У меня есть довольно простой пример того, что я хочу:
#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;
}
Он работает за 1,386 секунды с OpenMP, и это неплохо, но немного неоптимально, позвольте мне объяснить, почему:
Я получаю это как вывод
STEP DONE, currentDone 250 всегоРазмер 374 STEP DONE, currentDone 374
totalSize 478 STEP DONE, currentDone 478 totalSize 586 STEP DONE,
currentDone 586 totalSize 630 STEP DONE, currentDone 630 totalSize 654
STEP DONE, currentDone 654 всегоРазмер 686 STEP DONE, currentDone 686
totalSize 750 STEP DONE, currentDone 750 totalSize 810 STEP DONE,
currentDone 810 totalSize 846 STEP DONE, currentDone 846 totalSize 902
STEP DONE, currentDone 902 totalSize 934 STEP DONE, currentDone 934
totalSize 966 STEP DONE, текущийDone 966 totalSize 982 STEP DONE,
currentDone 982 totalSize 982
это означает, что for выполняется с предыдущим значением totalSize для каждого потока, и он обновляется только после завершения цикла for и повторной оценки цикла while, я знаю, что это имеет смысл в зависимости от того, как работает OpenMP, но если бы я мог обновить его внутри для цикла, это было бы здорово, особенно потому, что в моем реальном случае некоторые ветви могли занимать x1000 времени других ветвей, я думаю, что это невозможно, но, возможно, некоторые из вас могут дать мне совет, чтобы оценить другую возможную улучшение здесь.
Кстати, я использую MSVS 2017, поэтому создание задач OpenMP не вариант.
Заранее спасибо.