У меня проблема с многопоточным кодом, когда я использую его на определенном сервере с 2-мя ЦП. Сервер работает на Windows 7 x64 с Bi-Xeon E5-2697Wv2 12 ядер 2,7 ГГц; ОЗУ 64 Гб (8X8 Гб 1866 МГц); материнская плата SuperMicro X9DAI. Мой исполняемый файл сгенерирован с использованием Visual Studio MSVC 2013 и многопоточным с использованием OpenMP.Производительность распределения памяти двух CPU
Теперь проблема заключается в том, что у меня есть более высокая производительность, используя 1 поток в сравнении 24 темы ... Эта проблема видна только на этом компьютере, и когда я прикрепил профилировщик (CodeXL) я получаю следующий результат:
- 1 поток: ~ 3% времени выполнения находится внутри malloc/free (~ 3/~ 2)
- 24 потока: ~ 64% времени выполнения находится внутри malloc/free (~ 33%/~ 31%)
Код сложный, и я не могу опубликовать пример, но в основном это код monte carlo, ther e - небольшое количество динамических распределений (фаза инициализации создает все необходимые данные), остается только одно динамическое распределение в начале одного события для хранения данных события. Код не содержит мьютексов, каждый поток работает без какой-либо связи, кроме как в начале и в конце вычисления.
Мои знания в архитектуре сервера и двух процессоров очень ограничены, и я хочу знать, есть ли что-то, что я могу сделать, чтобы избежать этой проблемы (опция BIOS?), Я предполагаю, что есть контроллер, который выбирает, какая ОЗУ ЦП будет и эта операция замедляется ...
Благодарим вас за чтение.
EDIT: Я написал небольшой тест, чтобы оценить снижение производительности таНос/бесплатно, вот код:
#include <omp.h>
#include <afx.h>
#include <vector>
#include <fstream>
#include <iostream>
#include <chrono>
// malloc allocation size tab
int allocSize[] =
{
4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072
};
int main()
{
// number max of thread
int nbThreadMax = omp_get_max_threads();
// malloc/free iteration per bench
unsigned int nbIteration = 1000000;
// Empty res tab
std::vector<double> emptyRes(16, 0.);
// Duration per thread
std::vector<std::vector<double>> avgDuration(nbThreadMax, emptyRes);
int nbThread = 1;
unsigned int idxt = 0;
while (nbThread <= nbThreadMax)
{
// Current bench result
std::vector<std::vector<double>> threadResult(nbThread, emptyRes);
std::cout << "Thread : " << nbThread << std::endl;
// Create parrallel region
#pragma omp parallel num_threads(nbThread)
{
int nt = omp_get_thread_num();
for (unsigned int i = 0; i < 16; ++i)
{
int allocationSize = allocSize[i];
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
for (unsigned int j = 0; j < nbIteration; ++j)
{
void* pData = malloc(allocationSize);
free(pData);
}
end = std::chrono::system_clock::now();
threadResult[nt][i] += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()/1000.;
}
}
// Sum
for (unsigned int i = 0; i < 16; ++i)
{
for (unsigned int j = 0; j <= idxt; ++j)
{
avgDuration[idxt][i] += threadResult[j][i];
}
// /!\ Normalize for one thread /!\
avgDuration[idxt][i] /= nbThread;
}
++idxt;
// Increase thread number (X2)
if (nbThread >= nbThreadMax)
break;
if (nbThread * 2 > nbThreadMax)
nbThread = nbThreadMax;
else
nbThread = nbThread * 2;
}
// Write results
{
std::ofstream ofs("resultats.csv");
ofs << "NbThread;";
for (unsigned int i = 0; i < 16; ++i)
{
ofs << allocSize[i] << ";";
}
ofs << std::endl;
int nbThread = 1;
for (unsigned int n = 0; n < idxt; ++n)
{
ofs << nbThread << ";";
for (unsigned int i = 0; i < 16; ++i)
{
ofs << avgDuration[n][i] << ";";
}
ofs << std::endl;
nbThread = nbThread * 2;
}
ofs.close();
}
}
Вот результат optained на моем сервере: malloc/free duration /thread malloc/free performance factor /thread
Есть ли такой результат, показывающий проблему, или это нормальное снижение производительности?
24 потока на 2 процессора? –
Нитки не являются святым Граалем исполнения. Особенно на машинах NUMA –
да 24 потока на 2 процессора, я не уверен, что у меня 8X8Gb для ОЗУ. Значит, ты имеешь в виду, что я ничего не могу сделать? – user3513887