gpt4 book ai didi

c++ - OpenMP 线程似乎串行执行

转载 作者:搜寻专家 更新时间:2023-10-31 01:57:30 28 4
gpt4 key购买 nike

我有一个应用程序,它基本上应该并行计算数学表达式的反向波兰表示法。我的问题是我在使用 OpenMP 时没有看到任何性能提升。 (我使用的是 VS2008,设置了/openmp 编译器选项。)

我的主循环是这样的:

int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
int nThreadID;
omp_set_num_threads(nMaxThreads);

#pragma omp parallel for schedule(static) private(nThreadID)
for (i=0; i<nBulkSize; ++i)
{
nThreadID = omp_get_thread_num();
printf("Thread %d Idx %d start",nThreadID, i);
results[i] = EvalRPNInParallel(i, nThreadID);
printf(" -- %d Idx %d end\n",nThreadID, i);
}

printfs 仅用于调试目的,以查看是否正在发生任何并行操作(应该将它们混合在 4 个线程之间)。从调试输出中我可以看到确实产生了多个线程。每个线程都获得循环的特定 block ,但线程似乎没有并行执行。线程 0 正在计算它的循环 block ,然后线程 1 计算它的 block ,依此类推。没有任何并行执行。执行时间就像 openmp 甚至没有激活一样。EvalRPNInParallel 是一个进行 RPN 计算的成员函数。我没有在这个函数中使用任何锁、互斥体 omp 障碍。

double Foo::EvalRPNInParallel(int nOffset, int nThreadID) const
{
double *Stack = &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / 4);
for (const SToken *pTok = m_pRPN; ; ++pTok)
{
switch (pTok->Cmd)
{
case cmADD: --sidx; Stack[sidx] += Stack[1+sidx]; continue;
case cmSUB: --sidx; Stack[sidx] -= Stack[1+sidx]; continue;
case cmMUL: --sidx; Stack[sidx] *= Stack[1+sidx]; continue;
case cmVAR: Stack[++sidx] = *(pTok->Val.ptr + nOffset); continue;
// ...
// ...
// ...
case cmEND: return Stack[m_nFinalResultIdx];
}
}
}

奇怪的是,如果我故意用不必要的 for 循环减慢 EvalRPNInParallel,我确实会看到 EvalRPNInParallel 的并行执行,正如我所期望的那样。有谁知道为什么我没有看到她使用 OpenMP 有任何好处?

[更新]我还尝试了以下 openMP 构造,但都没有显示任何并行执行:

int nIterationsPerThread = nBulkSize/nMaxThreads;
#pragma omp parallel for private(nThreadID, j, k) shared(nMaxThreads, nIterationsPerThread) ordered
for (i=0; i<nMaxThreads; ++i)
{
for (j=0; j<nIterationsPerThread; ++j)
{
nThreadID = omp_get_thread_num();
k = i*nIterationsPerThread + j;
printf("Thread %d Idx %d start",nThreadID, k);
results[k] = ParseCmdCodeBulk(k, nThreadID);
printf(" -- %d Idx %d end\n",nThreadID, k);
}
}

使用部分:

#pragma omp parallel shared(nBulkSize) private(nThreadID, i)
{
#pragma omp sections nowait
{
#pragma omp section
for (i=0; i<(nBulkSize/2); ++i)
{
nThreadID = omp_get_thread_num();
printf("Thread %d Idx %d start",nThreadID, i);
results[i] = ParseCmdCodeBulk(i, nThreadID);
printf(" -- %d Idx %d end\n",nThreadID, i);
} // end of section

#pragma omp section
for (i=nBulkSize/2; i<nBulkSize; ++i)
{
nThreadID = omp_get_thread_num();
printf("Thread %d Idx %d start",nThreadID, i);
results[i] = ParseCmdCodeBulk(i, nThreadID);
printf(" -- %d Idx %d end\n",nThreadID, i);
} // end of section
}
} // end of sections

最佳答案

经典海森堡,观察一个线程会影响它的行为。 printf() 函数很慢,肯定比你的表达式计算器慢得多。并且必须获得一个锁以防止字符串中的字符与其他线程请求的控制台输出混合在一起。多个线程并发进入 EvalRPNInParallel 函数的可能性不是很大。顺便说一句,您无法通过诊断观察到这一点。

通常的建议适用,仅您测量代码三次以找出瓶颈所在后才优化您的代码。如果它花费的时间超过几微秒,我会感到惊讶。在那种情况下你无法获胜,启动线程已经花费了更长的时间。您为找到瓶颈所做的相同测量也会告诉您线程是否让您领先。

关于c++ - OpenMP 线程似乎串行执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5528998/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com