我遇到了一个相当令人沮丧的OpenMP问题:似乎如果OpenMP在代码中的某个地方以并行模式使用(对于多个线程),那么动态内存分配/解除分配即使在非代码的并行部分。这是一个示例程序(只是说明):
int main()
{
#pragma omp parallel
{
// Just to get OpenMP going
}
double wtime0, wtime;
wtime0 = omp_get_wtime();
double **stuff;
const int N = 1000000;
stuff = new double*[N];
for (int i=0; i < N; i++) stuff[i] = new double;
for (int i=0; i < N; i++) *(stuff[i]) = sqrt(i);
for (int i=0; i < N; i++) delete[] stuff[i];
delete[] stuff;
wtime = omp_get_wtime() - wtime0;
cout << "Total CPU time: " << wtime << endl;
}
当我在笔记本电脑上使用一个线程(英特尔酷睿2双核处理器)运行此代码时,我的CPU时间为0.093。另一方面,如果我用两个线程运行它,CPU时间增加到0.13。指针分配越多,差异就越大。在上面的代码中,如果我用一个简单的数组替换“stuff”,例如
double stuff2[N];
for (int i=0; i < N; i++) stuff2[i] = sqrt(i);
然后没有差异。有人可以告诉我为什么在分配/取消分配指针时存在这个问题,即使它不是并行完成的?这是一个问题的原因是因为在我正在使用的实际代码中,动态内存分配是必不可少的。有些部分可以通过并行运行来加速,但是(有两个线程而不是一个线程),这远远超过了内存分配/解除分配大大减慢的事实,即使在非并行部分也是如此。如果具有丰富OpenMP经验的人可以告诉我如何解决这个问题,我将非常感激。 (最糟糕的情况是,我可以使用MPI,但如果可以在OpenMP中解决,我会很喜欢它。)
提前感谢您的帮助。
答案 0 :(得分:2)
是的,这是可以接受的。通常,应该避免在多线程环境中进行天真的动态分配,因为那里存在单个锁。支持MT的分配器提供了更好的性能,在分配繁重的情况下应该是首选。 这就是为什么我总是嘲笑这里只使用向量或字符串或共享指针作为类成员而不让用户指定分配策略的代码。