c++ - 如何将矩阵提升为具有多个线程的幂?

标签 c++ multithreading c++11 matrix stdthread

我正在尝试将矩阵提升为多线程的幂,但我不太擅长线程。我还从键盘输入线程数,该数字在 [1,矩阵高度] 范围内,然后我执行以下操作:

unsigned period = ceil((double)A.getHeight() / threadNum);
unsigned prev = 0, next = period;
for (unsigned i(0); i < threadNum; ++i) {
        threads.emplace_back(&power<long long>, std::ref(result), std::ref(A), std::ref(B), prev, next, p);

        if (next + period > A.getHeight()) {
            prev = next;
            next = A.getHeight();
        }
        else {
            prev = next;
            next += period;
        }
    }

我很容易用多个线程将一个矩阵乘以另一个矩阵,但这里的问题是一旦完成了 1 步,例如我需要将 A 提高到 3 次方,A^2 就是那个步骤,在该步骤之后我必须等待所有线程完成,然后再继续执行 A^2*A。我怎样才能让我的线程等待呢?我正在使用 std::thread 的。

在发布第一个回复后,我意识到我忘记提及我只想创建这些线程一次,而不是为每个乘法步骤重新创建它们。/p>

最佳答案

我建议使用 condition_variable .

算法是这样的:

  1. 为 N 个线程将矩阵拆分为 N 个部分。

  2. 每个线程计算单次乘法所需的结果子矩阵。

  3. 然后它使用 fetch_add 递增原子 threads_finished 计数器并等待共享条件变量。

  4. 最后一个完成的线程 (fetch_add()+1 == thread count),通知所有线程,它们现在可以继续处理。

  5. 利润。

编辑: 这是如何停止线程的示例:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <algorithm>
#include <atomic>

void sync_threads(std::condition_variable & cv, std::mutex & mut, std::vector<int> & threads, const int idx) {
    std::unique_lock<std::mutex> lock(mut);
    threads[idx] = 1; 
    if(std::find(threads.begin(),threads.end(),0) == threads.end()) {
        for(auto & i: threads)
            i = 0;
        cv.notify_all();
    } else {
        while(threads[idx])
            cv.wait(lock);
    }
}

int main(){

    std::vector<std::thread> threads;

    std::mutex mut;
    std::condition_variable cv;

    int max_threads = 10;
    std::vector<int> thread_wait(max_threads,0);

    for(int i = 0; i < max_threads; i++) {
        threads.emplace_back([&,i](){
                std::cout << "Thread "+ std::to_string(i)+" started\n";
                sync_threads(cv,mut,thread_wait,i);
                std::cout << "Continuing thread " + std::to_string(i) + "\n";
                sync_threads(cv,mut,thread_wait,i);
                std::cout << "Continuing thread for second time " + std::to_string(i) + "\n";

            });
    }

    for(auto & i: threads)
        i.join();
}

有趣的部分在这里:

void sync_threads(std::condition_variable & cv, std::mutex & mut, std::vector<int> & threads, const int idx) {
    std::unique_lock<std::mutex> lock(mut); // Lock because we want to modify cv
    threads[idx] = 1; // Set my idx to 1, so we know we are sleeping
    if(std::find(threads.begin(),threads.end(),0) == threads.end()) {
        // I'm the last thread, wake up everyone
        for(auto & i: threads)
            i = 0;
        cv.notify_all();
    } else { //I'm not the last thread - sleep until all are finished
        while(threads[idx]) // In loop so, if we wake up unexpectedly, we go back to sleep. (Thanks for pointing that out Yakk)
            cv.wait(lock);
    }
}

关于c++ - 如何将矩阵提升为具有多个线程的幂?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29560248/

相关文章:

c++ - 概念难度 c++ Deck of Cards

c++ - QList 内部函数模板

c++ - 流操纵器如何工作?

linux - socket编程中的线程问题

c# 调用Monitor.Pulse()时抛出对象同步错误

c++ - c++ 11线程的段错误(核心转储)

c++ - 为什么不使用 #define 来隐藏 unique_ptr 丑陋在这里工作?

android - 如何在 Android 中使用 std::stoul 和 std::stoull?

c++ - 读取 16 位 DPX 像素数据

python - 在 PyQt 中启动 new QThread() 时传递参数