编辑:我可以同时运行相同的程序两次,同时没有任何问题 - 如何使用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();
}
}
我已经验证,当尝试通过MemDeallocFunctionInDLL()
释放某些内存时,_CrtIsValidHeapPointer()
断言失败。
这是因为两个线程都在写入同一个内存吗?
所以为了解决这个问题,我想我会SomeClass
私有(这对我来说完全不同,所以任何帮助都会受到赞赏)。
void Bar()
{
SomeClass X;
#pragma omp parallel for default(shared) private(X)
for(int j = 0;j<10;++j)
{
X.Function();
}
}
现在它在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();
}
}
仍然没有运气。
答案 0 :(得分:5)
签出MemAllocFunctionInDLL,FunctionDefinedInDLL,MemDeallocFunctionInDLL 线程安全或重入。换句话说,这些函数是做静态变量还是共享变量?在这种情况下,您需要确保这些变量不会被其他线程破坏。
没有omp-for的事实很好可能意味着你没有正确地编写一些函数来保证线程安全。
我想看看Mem(Alloc | Dealloc)FunctionInDLL中使用了哪种内存分配/自由函数。
已添加:我非常确定您在DLL中的函数不是线程安全的。您可以同时运行此程序而不会出现问题。是的,它应该没问题,除非你的程序使用系统范围的共享资源(例如全局内存或进程间的共享内存),这是非常罕见的。在这种情况下,线程中没有共享变量,因此您的程序运行正常。
但是,在 mutithreads 中调用这些函数(这意味着在单个进程中)会导致程序崩溃。这意味着线程之间存在一些共享变量,并且它可能已被破坏。
这不是OpenMP的问题,而只是一个多线程错误。解决这个问题可能很简单。请查看DLL函数是否可以安全地被许多线程并发调用。
如何私有化静态变量
假设我们有这样的全局变量:
static int g_data;
static int* g_vector = new int[100];
私有化只不过是为每个线程创建私有副本。
int g_data[num_threads];
int* g_vector[num_threads];
for (int i = 0; i < num_threads; ++i)
g_vector[i] = new int[100];
然后,对这些变量的任何引用都是
// Thread: tid
g_data[tid] = ...
.. = g_vector[tid][..]
是的,这很简单。但是,此类代码可能存在false sharing问题。但是,虚假共享是表现的问题,而不是正确性。
首先,尝试私有化任何静态和全局变量。然后,检查它的正确性。接下来,看看你会得到的加速。如果加速是可扩展的(比如在四核上快3.7倍),那么它没关系。但是,在低速加速的情况下(例如四核上加速2倍),您可能会看到错误的共享问题。要解决错误共享问题,您只需在数据结构中添加一些填充。
答案 1 :(得分:2)
而不是
delete Data
你必须写
delete [] Data;
无论您在哪里执行新[],请务必使用delete []。
看起来你的问题并不是针对openmp的。您是否尝试在不包含#pragma parallel的情况下运行应用程序?
答案 2 :(得分:2)
default(shared)表示所有变量在线程之间共享,这不是您想要的。将其更改为默认值(无)。
Private(X)将为每个线程制作一个X的副本,但是,它们都不会被初始化,因此不一定会执行任何构造。
我认为你的初始方法会更好,在Dealloc调用中放置一个断点,看看内存指针是什么以及它包含什么。您可以看到guard bytes来判断在单个调用结束时或线程之后是否覆盖了内存。
顺便说一下,如果你运行一次没有omp循环,我假设这个有效吗?