Я пытаюсь оптимизировать и распараллелить некоторый код, который выполняет моделирование в структурах графа со ссылками и узлами.Главная горячая точка - это такой цикл:
void ExecuteAll()
{
for(long i = TotalCount(); i >= 1; i--)
{
long k = linkOrder[i];
long link = firstLink[k];
if (link == 0)
continue;
double d = 0.;
for(; link != 0; link = nextLink[link])
{
long kk = getNode(link);
d += fak[link]*res[kk];
}
d += res[k];
double d2 = d/fak2[k];
res[k] = d2;
res2[k] += d2;
}
}
Я переработал это для работы с несколькими потоками, реализовав такой класс:
class myDemoClass
{
bool volatile *isDone;
public:
void ExecuteSlice()
{
for(long i = TotalCount() - mThreadIndex; i >= 1; i -= threadCount)
{
long k = linkOrder[i];
Execute(k);
}
}
void Execute(long k)
{
long link = firstLink[k];
if (link == 0)
{
isDone[k] = true;
return;
}
double d = 0.;
for(; link != 0; link = nextLink[link])
{
long kk = getNode(link);
for(int x = 0; ! isDone[kk]; x++)
{} // Wait until data is ready. Time too short for sleep or event
d += fak[link]*res[kk];
}
d += res[k];
double d2 = d/fak2[k];
res[k] = d2;
res2[k] += d2;
isDone[k] = true;
}
}
Я создаю экземпляр этого классадля каждого потока, где каждый поток работает со срезом всех значений для i
.Я ввел новый массив bool volatile *isDone
, так как я не должен использовать результаты необработанных узлов.Я попытался вставить сон или событие вместо цикла for(;...;){}
, но оказалось, что для этого состояния ожидания слишком короткие.
Кажется, это работает нормально.Только 10% всех вызовов Execute () должны входить в цикл ожидания, поскольку график все больше и больше разворачивается из начальной точки, и результаты верны.
Но, что удивительно, ощутимого увеличения производительности (или потери) нет) на 8-ядерном компьютере XEON при использовании нового кода с 8 потоками.Я знаю, что этот код не является оптимальным с точки зрения аннулирования кэша, в основном, поскольку isDone
и res
пишутся и читаются из нескольких ядер.Но в большинстве случаев разыменованные индексы довольно далеко друг от друга.График содержит около 1.000.000 узлов и ссылок.
Как я могу улучшить параллелизм этого кода?