我正在尝试将矩阵提升为多线程的幂,但我不太擅长线程。我还从键盘输入线程数,该数字在 [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 .
算法是这样的:
为 N 个线程将矩阵拆分为 N 个部分。
每个线程计算单次乘法所需的结果子矩阵。
然后它使用
fetch_add
递增原子threads_finished
计数器并等待共享条件变量。最后一个完成的线程 (fetch_add()+1 == thread count),通知所有线程,它们现在可以继续处理。
- 利润。
编辑: 这是如何停止线程的示例:
#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/