У меня есть приложение, которое должно по существу оценивать обратную польскую запись математического выражения параллельно временам мая.Моя проблема в том, что я не вижу какого-либо выигрыша в производительности при использовании 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 нитями).По выводу отладки я вижу, что на самом деле создаются несколько потоков.Каждый поток получает определенный кусок цикла, но потоки не выполняются параллельно.Поток 0 вычисляет свой кусок цикла, затем поток 1 вычисляет свой кусок и так далее.Никакого параллельного выполнения вообще.Время выполнения точно такое, как если бы 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];
}
}
}
Странно, если я намеренно замедляю EvalRPNInParallel с ненужным циклом for, я действительно вижу параллельное выполнение EvalRPNInParallelкак я и ожидал.У кого-нибудь есть идея, почему я не вижу никакой выгоды от использования OpenMP her?
[update] Я также попробовал следующие конструкции 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