如何从不同的线程,OpenMP,C ++写入文件

时间:2017-09-22 07:06:15

标签: c++ parallel-processing openmp

我使用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;
         }

如果两个线程同时尝试写入文件,则数据会混淆。 我怎么能解决这个问题?

2 个答案:

答案 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上注册线程,......),除非您可以重用先前在线程池中创建的某些线程...)。在决定是否要并行化时,请考虑这一点。有时,非并行计算可能会更快......