Я пытаюсь использовать новые потоки C++ 11, но мой простой тест имеет ужасную многоядерность. В качестве простого примера эта программа добавляет некоторые квадратные случайные числа.Почему этот код C++ 11, содержащий rand() медленнее с несколькими потоками, чем с одним?
#include <iostream>
#include <thread>
#include <vector>
#include <cstdlib>
#include <chrono>
#include <cmath>
double add_single(int N) {
double sum=0;
for (int i = 0; i < N; ++i){
sum+= sqrt(1.0*rand()/RAND_MAX);
}
return sum/N;
}
void add_multi(int N, double& result) {
double sum=0;
for (int i = 0; i < N; ++i){
sum+= sqrt(1.0*rand()/RAND_MAX);
}
result = sum/N;
}
int main() {
srand (time(NULL));
int N = 1000000;
// single-threaded
auto t1 = std::chrono::high_resolution_clock::now();
double result1 = add_single(N);
auto t2 = std::chrono::high_resolution_clock::now();
auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
std::cout << "time single: " << time_elapsed << std::endl;
// multi-threaded
std::vector<std::thread> th;
int nr_threads = 3;
double partual_results[] = {0,0,0};
t1 = std::chrono::high_resolution_clock::now();
for (int i = 0; i < nr_threads; ++i)
th.push_back(std::thread(add_multi, N/nr_threads, std::ref(partual_results[i])));
for(auto &a : th)
a.join();
double result_multicore = 0;
for(double result:partual_results)
result_multicore += result;
result_multicore /= nr_threads;
t2 = std::chrono::high_resolution_clock::now();
time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
std::cout << "time multi: " << time_elapsed << std::endl;
return 0;
}
Собран с 'г ++ -std = C++ 11 -pthread test.cpp' на Linux и 3core машины, типичный результат
time single: 33
time multi: 565
Так многопоточный версия больше на порядок медленнее. Я использовал случайные числа и sqrt, чтобы сделать пример менее тривиальным и подверженным оптимизации компилятора, поэтому у меня нет идей.
редактировать:
- Эта проблема весы для больших N, так что проблема не короткое время выполнения
- Время создания темы не проблема. Исключая его, это не меняет результат значительно
Ничего себе, я нашел проблему. Это был действительно rand(). Я заменил его эквивалентом C++ 11, и теперь он отлично работает. Всем спасибо!
Невозможно воспроизвести. Какой уровень оптимизации вы используете? –
Вы измеряете алгоритм + ** время создания потоков, которое медленное из-за системных вызовов **. Переместите таймер после создания потоков и затем выполните потоки. – deepmax
'rand()' обычно не является функцией защиты от нескольких протекторов. Используйте 'rand_r()'. –