1

我正在努力使快速排序并行,线程是第一次尝试。非线程版本正确排序,但线程不正确(这并不奇怪)。我发现有趣的是,当我删除线程但保留 boost::bind 调用时它仍然不起作用。如果 boost::bind 不是我想要的,请提出建议。Bind 似乎是使我的函数与 boost 线程一起工作的最简单(或唯一)的方法。

void Quicksort( fVec &Array, const int Left, const int Right )
{
    if( Right <= Left )
        return;

    int pivot = Left;
    const int pivotNewIndex = Partition( Array, Left, Right, pivot );

    // These function calls make it work fine
    //Quicksort( Array, Left, pivotNewIndex - 1 );
    //Quicksort( Array, pivotNewIndex + 1, Right );

    // boost::bind calls only swaps one element, doesn't actually sort
    boost::bind( &Quicksort, Array, Left, pivotNewIndex - 1 )();
    boost::bind( &Quicksort, Array, pivotNewIndex + 1, Right )();

    // threaded version that doesn't work, same as above
    //boost::thread threadA( boost::bind( &Quicksort, Array, Left, pivotNewIndex - 1 ) );
    //threadA.join();
    //boost::thread threadB( boost::bind( &Quicksort, Array, pivotNewIndex + 1, Right ) );
    //threadB.join();
}
4

1 回答 1

7

Boost bind 或多或少地创建了一个仿函数,当被调用时,它将使用你想要的参数调用你想要的函数。在这种情况下,您正在创建仿函数但从不调用它。尝试:

boost::bind( &Quicksort, Array, Left, pivotNewIndex - 1 )();
boost::bind( &Quicksort, Array, pivotNewIndex + 1, Right )();

我猜第一个论点是什么搞砸了。我认为 bind 需要参数是可复制的,而引用不是真的,它可能正在创建一个副本并将引用传递给它,这就是为什么没有任何变化的原因。尝试:

boost::bind( &Quicksort, boost::ref(Array), Left, pivotNewIndex - 1 )();
boost::bind( &Quicksort, boost::ref(Array), pivotNewIndex + 1, Right )();

了解 fVec 是什么以及为什么不将指针传递给要排序的数组会有所帮助。

另请注意,这种线程化方法可能不会提供太多加速,因为当您获得非常小的排序时,启动和调度新线程的开销远大于收益(另外,您将创建大量线程,即坏的)。您真正想要的是一个线程池,它可以在某个最佳大小的块或更大的块上运行,并且具有固定数量的线程。当达到小于限制的大小时,它会依次执行所有操作(对于更小的尺寸,您显然希望从快速排序更改为插入排序)。

另请注意,您加入的顺序无论如何都会导致串行执行......您希望在启动两个线程后加入两个线程。

于 2008-11-08T07:31:43.417 回答