2

编辑:我可以同时运行同一个程序两次,没有任何问题 - 我如何使用 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();
   }
}

仍然没有运气。

4

3 回答 3

5

查看 MemAllocFunctionInDLL、FunctionDefinedInDLL、MemDeallocFunctionInDLL 是thread-safere-entrant。换句话说,这些函数是静态变量还是共享变量?在这种情况下,您需要确保这些变量不会被其他线程破坏。

没有 omp-for 的事实很好,这可能意味着您没有正确编写一些线程安全的函数。

我想看看在 Mem(Alloc|Dealloc)FunctionInDLL 中使用了什么样的内存分配/释放函数。

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

但是,在多线程中调用这些函数(这意味着在单个进程中)会使您的程序崩溃。这意味着线程之间存在一些共享变量,并且可能已损坏。

这不是 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][..]

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

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

于 2009-11-05T18:12:58.680 回答
2

代替

delete Data

你必须写

delete [] Data;

无论你在哪里做new [],一定要使用delete []。

看起来您的问题并非特定于 openmp。您是否尝试在不包含#pragma parallel 的情况下运行您的应用程序?

于 2009-11-05T17:00:29.607 回答
2

default(shared) 表示所有变量都在线程之间共享,这不是您想要的。将其更改为默认值(无)。

Private(X) 将为每个线程制作 X 的副本,但是,它们都不会被初始化,因此不一定会执行任何构造。

我认为您的初始方法会更好,在 Dealloc 调用中放置一个断点,然后查看内存指针是什么以及它包含什么。您可以看到保护字节来判断内存是在单个调用结束时还是在线程之后被覆盖。

顺便说一句,我假设如果您运行一次,没有 omp 循环,这可以工作?

于 2009-11-05T17:07:58.430 回答