我有一个想要的简单例子:
#include "vector"
#include "omp.h"
#include <ctime>
#include "windows.h"//just for Sleep
class MyItem
{
public:
MyItem()
{
}
void createChildren()
{
Sleep(10);
int childCount = (rand()%5);
if(childCount>3) //25% of chance of having 4 children 75% of having no children
{
for(int i=0; i<childCount;i++)
children.push_back(MyItem());
}
}
std::vector<MyItem> children;
};
double calculateTree()
{
srand(0);
std::vector<MyItem> toMakePartition;
for(int i=0;i<250;i++)
toMakePartition.push_back(MyItem());
size_t totalSize = toMakePartition.size();
int currentDone = 0;
clock_t begin = clock();
while (currentDone < totalSize)
{
omp_set_num_threads(omp_get_num_procs());
#pragma omp parallel for schedule(dynamic)
for (int index = currentDone; index < totalSize; index++)
{
toMakePartition[index].createChildren();
#pragma omp critical
{
for(int i=0; i<toMakePartition[index].children.size();i++)
toMakePartition.push_back(toMakePartition[index].children[i]);
currentDone++;
totalSize = toMakePartition.size();
}
}
printf("STEP DONE, currentDone %i totalSize %i\n", currentDone, (int)totalSize);
}
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
printf("TOTAL TIME %f\n",(float)elapsed_secs);
return elapsed_secs;
}
使用OpenMP可以在1.368秒内运行它,这还不错,但是有点次优,让我解释一下原因:
我将其作为输出
STEP DONE,当前完成250总大小374 STEP DONE,当前完成374 totalSize 478 STEP DONE,当前完成478 totalSize 586 STEP DONE, 当前完成586总大小630步骤完成,当前完成630总大小654 步骤完成,当前完成654总大小686步骤完成,当前完成686 totalSize 750 STEP DONE,当前完成750 totalSize 810 STEP DONE, currentDone 810总计大小846 STEP DONE,currentDone 846总计大小902 步骤完成,当前完成902总大小934步骤完成,当前完成934 总计966步骤已完成,当前已完成966总计982步骤已完成, currentDone 982 totalSize 982
这意味着for是使用每个线程的totalSize的先前值执行的,并且只有在for循环结束并再次评估while循环时才更新,我知道这根据OpenMP的工作原理是有意义的,但是,如果我可以在for循环中更新它,那可能会特别好,因为在我的实际情况下,某些分支可能花费其他分支时间的x1000,我认为这是不可能的,但是也许有些人可以给我一个提示,以评估另一个可能改善这里。
我正在使用MSVS 2017,因此无法执行OpenMP任务。
谢谢。