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)
仍然没有运气.
查看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倍),您可能会看到错误的共享问题.要解决错误共享问题,您只需在数据结构中添加一些填充.