递归深度切断策略:并行快速排序

Recursion Depth Cut Off Strategy: Parallel QuickSort

本文关键字:并行 快速排序 策略 深度 递归      更新时间:2023-10-16

我实现了一个并行快速排序算法。为了避免过多并行线程的开销,我有一个截断策略,当向量大小小于特定阈值时,将并行算法转换为顺序算法。然而,现在我试图设置基于递归深度的切断策略。也就是说,当达到一定的递归深度时,我希望我的算法变成顺序的。我使用了下面的代码,但它不起作用。我不知道该怎么做。什么好主意吗?

template <class T>
void ParallelSort::sortHelper(typename vector<T>::iterator start, typename vector<T>::iterator end, int level =0) //THIS IS THE QUICKSoRT INTERFACE
{
  static int depth =0;
  const int insertThreshold = 20;
  const int threshold = 1000;
  if(start<end)
  {
    if(end-start < insertThreshold) //thresholf for insert sort
    {
      insertSort<T>(start, end);
    }
    else if((end-start) >= insertThreshold && depth<threshold) //threshhold for non parallel quicksort
    {
      int part = partition<T>(start,end);
      depth++;
      sortHelper<T>(start, start + (part - 1), level+1);
      depth--;
      depth++;
      sortHelper<T>(start + (part + 1), end, level+1);
      depth--;
    }
    else
    {
      int part = partition<T>(start,end);
      #pragma omp task
      {
        depth++;
        sortHelper<T>(start, start + (part - 1), level+1);
        depth--;
      }
      depth++;
      sortHelper<T>(start + (part + 1), end, level+1);
      depth--;
    }
  }
}

我尝试了静态变量depth和非静态变量level,但它们都不起作用。注:以上剪切仅取决于depth。包含level以显示所尝试的两种方法

从两个线程写入static depth会使您的代码执行未指定的行为,因为这些写入操作没有指定。

当它发生时,你正在传递level,这是你的递归深度。在每个级别上,您将线程数量增加一倍——因此级别上的限制等于6(例如)最多对应于2^6个线程。你的代码只有一半是并行的,因为partition代码发生在主线程中,所以你可能会有少于理论的最大线程数同时运行。

template <class T>
void ParallelSort::sortHelper(typename vector<T>::iterator start, typename vector<T>::iterator end, int level =0) //THIS IS THE QUICKSoRT INTERFACE
{
  const int insertThreshold = 20;
  const int treeDepth = 6; // at most 2^6 = 64 tasks
  if(start<end)
  {
    if(end-start < insertThreshold) //thresholf for insert sort
    {
      insertSort<T>(start, end);
    }
    else if(level>=treeDepth) // only 2^treeDepth threads, after which we run in sequence
    {
      int part = partition<T>(start,end);
      sortHelper<T>(start, start + (part - 1), level+1);
      sortHelper<T>(start + (part + 1), end, level+1);
    }
    else // launch two tasks, creating an exponential number of threads:
    {
      int part = partition<T>(start,end);
      #pragma omp task
      {
        sortHelper<T>(start, start + (part - 1), level+1);
      }
      sortHelper<T>(start + (part + 1), end, level+1);
    }
  }
}

好了,我明白了。这是我犯的一个愚蠢的错误。

当堆栈大小大于某个阈值时,算法应该返回到顺序代码,而不是小于。这样做解决了问题,并给了我一个加速。