Оптимизировать Буддхаброт
В настоящее время я работаю над собственной реализацией "Буддхаброт". Пока я использую std::thread
-Класс из C++11 для одновременной работы через следующую итерацию:
void iterate(float *res){
//generate starting point
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(-1.5,1.5);
double ReC,ImC;
double ReS,ImS,ReS_;
unsigned int steps;
unsigned int visitedPos[maxCalcIter];
unsigned int succSamples(0);
//iterate over it
while(succSamples < samplesPerThread){
steps = 0;
ReC = distribution(generator)-0.4;
ImC = distribution(generator);
double p(sqrt((ReC-0.25)*(ReC-0.25) + ImC*ImC));
while (( ((ReC+1)*(ReC+1) + ImC*ImC) < 0.0625) || (ReC < p - 2*p*p + 0.25)){
ReC = distribution(generator)-0.4;
ImC = distribution(generator);
p = sqrt((ReC-0.25)*(ReC-0.25) + ImC*ImC);
}
ReS = ReC;
ImS = ImC;
for (unsigned int j = maxCalcIter; (ReS*ReS + ImS*ImS < 4)&&(j--); ){
ReS_ = ReS;
ReS *= ReS;
ReS += ReC - ImS*ImS;
ImS *= 2*ReS_;
ImS += ImC;
if ((ReS+0.5)*(ReS+0.5) + ImS*ImS < 4){
visitedPos[steps] = int((ReS+2.5)*0.25*outputSize)*outputSize + int((ImS+2)*0.25*outputSize);
}
steps++;
}
if ((steps > minCalcIter)&&(ReS*ReS + ImS*ImS > 4)){
succSamples++;
for (int j = steps; j--;){
//std::cout << visitedPos[j] << std::endl;
res[visitedPos[j]]++;
}
}
}
}
Так что в основном я работаю в каждом потоке так долго, что я сгенерировал достаточно траекторий достаточной длины, которая, как ожидается, занимает одинаковое время в каждом потоке.
Но у меня действительно есть ощущение, что эта функция может быть мне неоптимизирована, поскольку ее код очень хорошо читается. Кто-нибудь может придумать какие-нибудь модные оптимизации? Когда дело доходит до компиляции, я просто использую:g++ -O4 -std=c++11 -I/usr/include/OpenEXR/ -L/usr/lib64/ -lHalf -lIlmImf -lm buddha_cpu.cpp -o buddha_cpu
Так что любые намеки на сокращение еще нескольких цифр / сек будут очень полезны. Также любые ссылки на дальнейшую литературу приветствуются.
1 ответ
Вы это проверяли? -O4
быстрее чем -O2
? Выше О2 не уверен. Кроме того, если этот сборник только для вас, попробуйте -march=native
, Это позволит использовать преимущества вашей конкретной архитектуры ЦП, но полученный двоичный файл может привести к сбою с SIGSEV на старых / разных машинах.
Вы не показали ни одной темы, если я правильно вижу. Убедитесь, что ваши потоки не записывают в память места одной и той же строки кэша. Запись областей памяти в одну и ту же строку кэша из разных потоков заставляет ядра ЦП синхронизировать свой кэш - это огромное снижение производительности.