在 OpenMP 线程中充分私有化数据

Posted

技术标签:

【中文标题】在 OpenMP 线程中充分私有化数据【英文标题】:Adequately privatizing data in OpenMP threads 【发布时间】:2018-06-06 18:52:04 【问题描述】:

据我所知,以下玩具代码没有任何用处:

#include <iostream>

#include "omp.h"

using namespace std;

class OtherClass 

   public:

   OtherClass() 
      cout << "hi\n";
   

   int GetNumber(int input) 
      int i, num;
      int *tmp;

      tmp = new int[100];

      tmp[0] = 0;
      for (i=1;i<100;i++) 
         tmp[i] = (input*tmp[i-1]+1)%5;
      
      num = tmp[input];

      delete[] tmp;

      return num;
   

   ~OtherClass() 
      cout << "bye\n";
   

;


class MainClass 

   public:

   int *myarray;

   MainClass(int numcells) 
      myarray = new int[numcells];
   

   ~MainClass() 
      delete[] myarray;
   

;


int main() 

   int i;

#define NUMELEMS 100

   MainClass *mc = new MainClass(NUMELEMS);
   OtherClass *oc = new OtherClass();

#pragma omp parallel private(i)
    
#pragma omp for
   for (i=0; i<NUMELEMS; i++ ) 
      mc->myarray[i] = oc->GetNumber(omp_get_thread_num()+1);
   
    // end of omp parallel

   for (i=0; i<NUMELEMS; i++) 
      cout << mc->myarray[i] << "\n";
   

   delete mc;
   delete oc;


但它说明了我在处理真实代码时出现的一个问题。即,我想知道OtherClass:GetNumber 中的数组tmptmp 如何填充的细节并不重要;我只是在输入一些代码来生成一些“有趣”的数字,这些数字会因线程而异。我的问题是,tmp 是否充分保护了可能正在运行的各种线程?线程在初始化、访问和删除它时是否可能会相互绊倒?例如,一个线程是否会按照另一个线程的定义访问tmp?或者一个线程可能会在另一个线程可以访问它之前删除tmp?如果需要修改,谁能告诉我应该如何修改代码?

顺便说一句,这段代码运行良好。但我想知道在更复杂、更大的代码中会发生什么。

【问题讨论】:

【参考方案1】:

您的代码非常安全。

GetNumber 中发生的任何事情都完全是一个线程本地的,没有变量或指针转义。准确地说,变量tmp 是每个线程私有的——其他线程看不到它。因此,每个线程分配的tmp指向的数据对任何其他线程都是不可见的。

也就是说 - 如果代码是真实代码的任何指示,我强烈建议使用更少的 new / delete 并在堆栈上放置更多的对象。它使对代码的推理变得更加容易——尤其是涉及线程。

【讨论】:

非常感谢。不要以为我可以对新/删除做太多事情。这不是我的代码。谢谢。 @bob 如果您确实需要进行内存分配,请确保您使用的是线程感知内存分配器。 infoworld.com/article/3201285/software/… 似乎是一个有用的起点。 @JimCownie 非常感谢您的提示。会调查的。

以上是关于在 OpenMP 线程中充分私有化数据的主要内容,如果未能解决你的问题,请参考以下文章

C++:OpenMP 中的私有静态变量

OpenMP 的全局变量

如果共享堆栈或数据变量,OpenMP 是不是会将它们移动到堆中?

如何使用多线程处理缓存的数据结构(例如 openmp)

使用 OpenMP 线程重新初始化向量是不是更快?

在动态 DLL 中使用线程私有变量?