Я хотел научиться использовать C++ 11 std :: threads с VS2012, и я написал очень простую консольную программу на C++ с двумя потоками, которые просто увеличивают счетчик. Я также хочу проверить разницу в производительности при использовании двух потоков. Программа испытаний приведена ниже:C++ 11 std thread sumation with atomic very slow
#include <iostream>
#include <thread>
#include <conio.h>
#include <atomic>
std::atomic<long long> sum(0);
//long long sum;
using namespace std;
const int RANGE = 100000000;
void test_without_threds()
{
sum = 0;
for(unsigned int j = 0; j < 2; j++)
for(unsigned int k = 0; k < RANGE; k++)
sum ++ ;
}
void call_from_thread(int tid)
{
for(unsigned int k = 0; k < RANGE; k++)
sum ++ ;
}
void test_with_2_threds()
{
std::thread t[2];
sum = 0;
//Launch a group of threads
for (int i = 0; i < 2; ++i) {
t[i] = std::thread(call_from_thread, i);
}
//Join the threads with the main thread
for (int i = 0; i < 2; ++i) {
t[i].join();
}
}
int _tmain(int argc, _TCHAR* argv[])
{
chrono::time_point<chrono::system_clock> start, end;
cout << "-----------------------------------------\n";
cout << "test without threds()\n";
start = chrono::system_clock::now();
test_without_threds();
end = chrono::system_clock::now();
chrono::duration<double> elapsed_seconds = end-start;
cout << "finished calculation for "
<< chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
<< "ms.\n";
cout << "sum:\t" << sum << "\n";\
cout << "-----------------------------------------\n";
cout << "test with 2_threds\n";
start = chrono::system_clock::now();
test_with_2_threds();
end = chrono::system_clock::now();
cout << "finished calculation for "
<< chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
<< "ms.\n";
cout << "sum:\t" << sum << "\n";\
_getch();
return 0;
}
Теперь, когда я использую для счетчика только долго долго переменной (которая комментируется) Я получаю значение, которое отличается от правильного - 100000000 вместо 200000000. Я не уверен, почему это так, и я полагаю, что эти два потока меняют счетчик одновременно, но я не уверен, как это происходит на самом деле, потому что ++ - просто очень простая инструкция. Кажется, что потоки кэшируют переменную суммы в начале. Производительность составляет 110 мс с двумя потоками против 200 мс для одного потока.
Таким образом, правильный способ согласно документации - использовать std :: atomic. Однако сейчас производительность намного хуже для обоих случаев как около 3300 мс без потоков и 15820 мс с потоками. Каков правильный способ использования std :: atomic в этом случае?
Вы компилируете в режиме выпуска? –
Без атоматики ваша программа имеет неопределенное поведение. С атомикой это медленнее, потому что теперь у вас есть два потока, которые постоянно борются за одну и ту же переменную. Многопоточность является очень дорогостоящей и стоит только в определенных особых ситуациях. –
Он намного медленнее даже без потоков. Какой еще вариант я должен сделать, чтобы он работал правильно и быстро? –