代码之家  ›  专栏  ›  技术社区  ›  Grey

我如何修改我的函数,只创建一个新线程而不是两个线程,并且仍然获得相同的排序结果?

  •  0
  • Grey  · 技术社区  · 7 年前

    我正在使用编写一个并行合并排序 pthreads .现在,我正在创建两个线程,每个线程对一半的数据进行排序。然后合并这两个线程的结果。但是,我正在尝试更改函数中的代码,改为只创建1个线程,而不修改函数的现有参数或返回类型。

    因此,我试图让函数先对一半的数据本身进行排序,然后只创建一个新线程(而不是两个)来对另一半进行排序。

    这是我为创建两个线程的函数编写的代码:

    // sort and return float array x, of length n
    // using merge sort
    void *pmerge_sort(void *args) {
    
      // unpack arguments
      Sort_args *sargs = (Sort_args *)args;
      float *x = sargs->x;
      int n = sargs->len;
    
      // if n < k, the array is sorted directly
      // using another sort algorithm
      int k = 100;
      if (n < k) {
        return(gsort(x, n));
      }
    
      // create 2 threads; each sorts half the data
      int m = ((float)n)/2.0;
    
      // pack arguments to recursive call
      Sort_args args1, args2;
      args1.x = x;
      args1.len = m;
      args2.x = &x[m];
      args2.len = n-m;
    
      int rc;
      pthread_t p1, p2;
      rc = pthread_create(&p1, NULL, pmerge_sort, (void *)&args1);  assert(rc == 0);
      rc = pthread_create(&p2, NULL, pmerge_sort, (void *)&args2);  assert(rc == 0);
    
      // merge the results from the threads
      float *x1, *x2;
      pthread_join(p1, (void **) &x1);
      pthread_join(p2, (void **) &x2);
      float *y = merge(x1, m, x2, n-m);
    
      // copy the result back to x and free y
      memcpy((void *)x, (void *)y, n*sizeof(float));
      free(y);
    
      return (void *)x;
    }
    

    如何进一步修改代码以仅创建一个新线程,但仍能获得与创建两个新线程的代码相同的排序结果?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Potato    7 年前

    如果要对父对象排序一半,对子对象排序第二个,则有一种可能的解决方案:

      int rc;  
      pthread_t p;
      rc = pthread_create(&p, NULL, pmerge_sort, (void *)&args1);  assert(rc == 0);
    
      // merge the results from the threads
      float *x1, *x2;
    
      // let worker thread finish first
      pthread_join(p, (void **) &x1);
    
      // then sort other half here
      x2 = (float*)(*pmerge_sort)((void *)&args2);
    
      // then merge
      float *y = merge(x1, m, x2, n-m);
    

    还有其他方法,我们可以重新安排工作方式并使用轮询。然而,这是满足您的需求所需的最简单/最小的更改。(更改针对第一个代码块)