OpenMP:堆腐败的原因,任何人?

Jac*_*cob 2 c c++ dll openmp visual-c++-2005

编辑:我可以运行相同的程序两次,同时没有任何问题 - 如何使用OpenMP或其他方法复制它?

这是问题的基本框架.

//Defined elsewhere
class SomeClass
{
public:
  void Function()
  {
    // Allocate some memory
    float *Data;
    Data = new float[1024];

    // Declare a struct which will be used by functions defined in the DLL
    SomeStruct Obj;
    Obj = MemAllocFunctionInDLL(Obj);

    // Call it
    FunctionDefinedInDLL(Data,Obj);

    // Clean up
    MemDeallocFunctionInDLL(Obj);
    delete [] Data;        
  }
}

void Bar()
{
   #pragma omp parallel for
   for(int j = 0;j<10;++j)
   {
     SomeClass X;
     X.Function();
   }
}
Run Code Online (Sandbox Code Playgroud)

我已经验证,当尝试释放某些内存时MemDeallocFunctionInDLL(),_CrtIsValidHeapPointer()断言失败.

这是因为两个线程都在写入同一个内存吗?

所以要解决这个问题,我认为我会SomeClass私有化(这对我来说完全陌生,所以任何帮助都会受到赞赏).

void Bar()
{
   SomeClass X;
   #pragma omp parallel for default(shared) private(X)
   for(int j = 0;j<10;++j)
   {         
     X.Function();
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,当它试图失败分配在一开始的内存Data.

注意:如果需要,我可以对DLL进行更改

注意:没有完美运行#pragma omp parallel for

编辑:现在Bar看起来像这样:

void Bar()
{
   int j
   #pragma omp parallel for default(none) private(j)
   for(j = 0;j<10;++j)
   {
     SomeClass X;         
     X.Function();
   }
}
Run Code Online (Sandbox Code Playgroud)

仍然没有运气.

min*_*ang 5

查看MemAllocFunctionInDLL,FunctionDefinedInDLL,MemDeallocFunctionInDLL是线程安全的或可重入的.换句话说,这些函数是做静态变量还是共享变量?在这种情况下,您需要确保这些变量不会被其他线程损坏.

没有omp-for的事实很好可能意味着你没有正确地编写一些函数来保证线程安全.

我想看看Mem(Alloc | Dealloc)FunctionInDLL中使用了哪种内存分配/自由函数.

补充:我很确定你在DLL中的函数不是线程安全的.您可以同时运行此程序而不会出现问题.是的,它应该没问题,除非你的程序使用系统范围的共享资源(例如全局内存或进程间的共享内存),这是非常罕见的.在这种情况下,线程中没有共享变量,因此您的程序运行正常.

但是,在mutithreads中调用这些函数(这意味着在单个进程中)会导致程序崩溃.这意味着线程之间存在一些共享变量,并且它可能已被破坏.

这不是OpenMP的问题,只是一个多线程的bug.解决这个问题可能很简单.请查看DLL函数是否可以安全地被许多线程并发调用.

如何私有化静态变量

假设我们有这样的全局变量:

static int  g_data;
static int* g_vector = new int[100];
Run Code Online (Sandbox Code Playgroud)

私有化只不过是为每个线程创建私有副本.

int  g_data[num_threads];
int* g_vector[num_threads];
for (int i = 0; i < num_threads; ++i)
  g_vector[i] = new int[100];
Run Code Online (Sandbox Code Playgroud)

然后,对这些变量的任何引用都是

// Thread: tid
g_data[tid] = ...
.. = g_vector[tid][..]
Run Code Online (Sandbox Code Playgroud)

是的,这很简单.但是,这种代码可能存在错误的共享问题.但是,虚假共享是表现的问题,而不是正确性.

首先,尝试私有化任何静态和全局变量.然后,检查它的正确性.接下来,看看你会得到的加速.如果加速是可扩展的(比如在四核上快3.7倍),那么它没关系.但是,在低速加速的情况下(例如四核上加速2倍),您可能会看到错误的共享问题.要解决错误共享问题,您只需在数据结构中添加一些填充.