Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在c+中使用多线程进行快速排序+; 我在代码中使用多线程< /C> > C++实现了代码> > QuaskSux程序。p>_C++_Multithreading_Sorting_Synchronization_Quicksort - Fatal编程技术网

在c+中使用多线程进行快速排序+; 我在代码中使用多线程< /C> > C++实现了代码> > QuaskSux程序。p>

在c+中使用多线程进行快速排序+; 我在代码中使用多线程< /C> > C++实现了代码> > QuaskSux程序。p>,c++,multithreading,sorting,synchronization,quicksort,C++,Multithreading,Sorting,Synchronization,Quicksort,组合任务的方法是维护一个任务队列。每个 自由线程从公文包中选择一个任务,必要时执行它 生成新的子任务并将其放入公文包 但我不确定什么是对的!在我看来,在一个线程中,算法的运行速度比两个或四个线程快。我能把同步搞砸吗 谢谢任何人帮助我 代码: #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 使用名称空间std; //打印阵列 模板 无效打印(常量向量和arr) { 对于(大小i=0;i

组合任务的方法是维护一个任务队列。每个 自由线程从公文包中选择一个任务,必要时执行它 生成新的子任务并将其放入公文包

但我不确定什么是对的!在我看来,在一个
线程
中,算法的运行速度比两个或四个
线程
快。我能把同步搞砸吗

谢谢任何人帮助我

代码:

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
//打印阵列
模板
无效打印(常量向量和arr)
{
对于(大小i=0;icout影响性能的因素远不止你在这个问题上抛出了多少线程。其中

  • 您需要实际的并发性,而不仅仅是多个线程

  • 标准的快速排序具有很好的引用局部性,特别是当分区大小变小时,但您的技术会丢掉很多引用局部性,因为在每次分区时,对给定数组元素的责任很可能会被交换到不同的线程

  • 此外,互斥操作并不特别便宜,当分区变小时,您开始执行相当多与实际排序量相关的操作

  • 使用比物理内核更多的线程是没有意义的。四个线程可能不会太多,但这取决于您的硬件

以下是一些可以提高多线程性能的方法:

  • 在方法
    quick_sort()
    中,在实际排序过程中,不要像当前一样保持互斥锁
    q_互斥锁
    锁定(您使用的
    unique_lock
    构造函数锁定互斥锁,并且在
    unique_lock
    的生命周期内不会解锁它)

  • 对于小于某个阈值大小的分区,请切换到普通的递归技术。您必须进行测试以找到一个好的特定阈值;也许它需要可调

  • 在每个分区中,让每个线程只将其中一个子分区发布到公文包中;让它递归地处理另一个子分区——或者更好地说,迭代地处理。事实上,将它设置为您发布的较小的子分区,因为这样可以更好地限制公文包的大小


  • 你也可以考虑增加你运行测试的元素的数量。100000并不是那么多,你可能会看到较大的问题的不同的性能特征。1000000个元素对于现代硬件的测试并不完全是不合理的。

    在我看来,你应该捕获组合任务的行为。他进入了一个班级

    template <typename TASK, unsigned CONCURRENCY>
    class Portfolio {
        std::array<std::thread, CONCURRENCY> workers_;
        std::deque<TASK> tasks_;
        std::mutex m_;
        std::condition_variable cv_;
        std::atomic<bool> quit_;
        void work () {
            while (!quit_) {
                TASK t = get();
                if (quit_) break;
                t();
            }
        }
        TASK get () {
            std::unique_lock<std::mutex> lock(m_);
            while (tasks_.empty()) {
                cv_.wait(lock);
                if (quit_) return TASK();
            }
            TASK t = tasks_.front();
            tasks_.pop_front();
            if (!tasks_.empty()) cv_.notify_one();
            return t;
        }
    public:
        void put (TASK t) {
            std::unique_lock<std::mutex> lock(m_);
            tasks_.push_back(t);
            cv_.notify_one();
        }
        Portfolio ();
        ~Portfolio ();
    };
    
    不幸的是,这种制定并行快速排序的方法不太可能产生很大的加速。您要做的是并行化分区任务,这至少需要一个单线程计算过程(包括数据比较和交换),然后才能开始并行化


    首先将数组划分为
    工作大小
    子数组,对每个子数组并行执行快速排序,然后合并结果以创建排序向量可能会更快。

    Hm,这行
    唯一锁定
    是否将并行代码转换为连续的?ru上的问题也是一样。所以,我想指出at并行排序操作已经存在:嘿!你解决问题了吗?另外,他的快速排序算法总是在一个线程上运行,所以其他线程基本上什么也不做。谢谢你的建议!@Rakete1111那么如何修改代码以使其他线程获得收益呢?我不明白。@rekrut,我已将我的答案更新为address t他给出了1111分,谢谢你们的回答!!
    template <typename TASK, unsigned CONCURRENCY>
    class Portfolio {
        std::array<std::thread, CONCURRENCY> workers_;
        std::deque<TASK> tasks_;
        std::mutex m_;
        std::condition_variable cv_;
        std::atomic<bool> quit_;
        void work () {
            while (!quit_) {
                TASK t = get();
                if (quit_) break;
                t();
            }
        }
        TASK get () {
            std::unique_lock<std::mutex> lock(m_);
            while (tasks_.empty()) {
                cv_.wait(lock);
                if (quit_) return TASK();
            }
            TASK t = tasks_.front();
            tasks_.pop_front();
            if (!tasks_.empty()) cv_.notify_one();
            return t;
        }
    public:
        void put (TASK t) {
            std::unique_lock<std::mutex> lock(m_);
            tasks_.push_back(t);
            cv_.notify_one();
        }
        Portfolio ();
        ~Portfolio ();
    };
    
    template <typename T, unsigned WORK_SIZE, typename PORTFOLIO>
    QuickSortTask {
        std::reference_wrapper<PORTFOLIO> portfolio_;
        std::reference_wrapper<std::vector<T>> arr_;
        int start_;
        int end_;
    
        QuickSortTask (PORTFOLIO &p, std::vector<T> &a, int s, int e)
            : portfolio_(p), arr_(a), start_(s), end_(e)
            {}
    
        void operator () () {
            if ((end_ - start_) > WORK_SIZE) {
                int p = partition(arr_, start_, end_);
                portfolio_.put(QuickSortTask(portfolio_, arr_, start_, p-1));
                portfolio_.put(QuickSortTask(portfolio_, arr_, p+1, end_));
            } else {
                regular_quick_sort(arr_, start_, end_);
            }
        }
    };