我使用openMP来并行我的C ++程序。我的并行代码具有非常简单的形式
#pragma omp parallel for shared(a, b, c) private(i, result)
for (i = 0; i < N; i++){
result= F(a,b,c,i)//do some calculation
cout<<i<<" "<<result<<endl;
}
如果两个线程同时尝试写入文件,则数据会混淆。 我怎么能解决这个问题?
答案 0 :(得分:5)
OpenMP提供了pragma来帮助进行同步。 #pragma omp critical
只允许一个线程在任何时间执行附加语句(互斥关键区域)。 #pragma omp ordered
编译指示确保循环迭代线程按顺序进入区域。
// g++ -std=c++11 -Wall -Wextra -pedantic -fopenmp critical.cpp
#include <iostream>
int main()
{
#pragma omp parallel for
for (int i = 0; i < 20; ++i)
std::cout << "unsynchronized(" << i << ") ";
std::cout << std::endl;
#pragma omp parallel for
for (int i = 0; i < 20; ++i)
#pragma omp critical
std::cout << "critical(" << i << ") ";
std::cout << std::endl;
#pragma omp parallel for ordered
for (int i = 0; i < 20; ++i)
#pragma omp ordered
std::cout << "ordered(" << i << ") ";
std::cout << std::endl;
return 0;
}
示例输出(一般每次都不同):
unsynchronized(unsynchronized(unsynchronized(05) unsynchronized() 6unsynchronized() 1unsynchronized(7) ) unsynchronized(unsynchronized(28) ) unsynchronized(unsynchronized(93) ) unsynchronized(4) 10) unsynchronized(11) unsynchronized(12) unsynchronized(15) unsynchronized(16unsynchronized() 13unsynchronized() 17) unsynchronized(unsynchronized(18) 14unsynchronized() 19)
critical(5) critical(0) critical(6) critical(15) critical(1) critical(10) critical(7) critical(16) critical(2) critical(8) critical(17) critical(3) critical(9) critical(18) critical(11) critical(4) critical(19) critical(12) critical(13) critical(14)
ordered(0) ordered(1) ordered(2) ordered(3) ordered(4) ordered(5) ordered(6) ordered(7) ordered(8) ordered(9) ordered(10) ordered(11) ordered(12) ordered(13) ordered(14) ordered(15) ordered(16) ordered(17) ordered(18) ordered(19)
答案 1 :(得分:1)
问题是:您拥有所有线程尝试访问的单个资源。必须保护这些单个资源免受并发访问(线程安全资源也这样做,对您来说是透明的;顺便说一下:here是关于std :: cout的线程安全性的一个很好的答案)。您现在可以保护这个单一资源e。 G。使用std::mutex
。问题是,线程必须等待互斥锁,直到另一个线程再次返回。因此,如果F是非常复杂的函数,那么你只能从并行化中获益。
进一步的缺点:当线程并行工作时,即使使用互斥锁保护std :: in,结果也可以按任意顺序打印出来,具体取决于哪个线程可以提前运行。
如果我可以假设您希望在大于i的结果之前将F(... i)的结果用于较小的i,则要么完全放弃并行化,要么采用不同的方式:
提供一个大小为N
的数组,让每个线程将结果存储在那里(array[i] = f(i);
)。然后在单独的非并行循环中迭代数组。同样,如果F
是一个复杂函数(对于大N),这样做是值得的。
此外:请注意,也必须创建线程,这会导致某些开销(创建线程基础结构和堆栈,在OS上注册线程,......),除非您可以重用先前在线程池中创建的某些线程...)。在决定是否要并行化时,请考虑这一点。有时,非并行计算可能会更快......