Я экспериментирую со стандартными потоками С++. Я написал небольшой тест для проверки производительности и общей пропускной способности. Принцип заключается в том, чтобы запустить в один или несколько потоков цикл из 1 миллиарда итераций, время от времени делая небольшие паузы.
В первой версии я использовал счетчики в разделяемой памяти (то есть обычные переменные). Я ожидал следующего результата:
Sequential 1e+009 loops 4703 ms 212630 loops/ms 2 thrds:t1 1e+009 loops 4734 ms 211238 loops/ms 2 thrds:t2 1e+009 loops 4734 ms 211238 loops/ms 2 thrds:tt 2e+009 loops 4734 ms 422476 loops/ms manythrd tn 1e+009 loops 7094 ms 140964 loops/ms ... manythrd tt 6e+009 loops 7094 ms 845785 loops/ms
К сожалению, дисплей показал некоторые счетчики, как если бы они были неинициализированы!
Я мог бы решить эту проблему, сохранив конечное значение каждого счетчика в atomic<>
для последующего отображения. Однако я не понимаю, почему версия, основанная на простой разделяемой памяти, не работает должным образом: каждый поток использует свой собственный счетчик, так что условия гонок нет. Даже поток отображения обращается к счетчикам только после завершения счетных потоков. Использование volatile
тоже не помогло.
Может ли кто-нибудь объяснить мне это странное поведение (как будто память не обновлялась) и сказать, не пропустил ли я что-то?
Здесь общие переменные:
const int maxthread = 6;
atomic<bool> other_finished = false;
atomic<long> acounter[maxthread];
Вот код многопоточной функции:
void foo(long& count, int ic, long maxcount)
{
count = 0;
while (count < maxcount) {
count++;
if (count % 10000000 == 0)
this_thread::sleep_for(chrono::microseconds(1));
}
other_finished = true; // atomic: announce work is finished
acounter[ic] = count; // atomic: share result
}
Вот пример того, как я называю бенчмаркинг потоков:
mytimer.on(); // second run, two threadeds
thread t1(foo, counter[0], 0, maxcount); // additional thread
foo(counter[1], 1, maxcount); // main thread
t1.join(); // wait end of additional thread
perf = mytimer.off();
display_perf("2 thrds:t1", counter[0], perf); // non atomic version of code
display_perf("2 thrds:t2", counter[1], perf);
display_perf("2 thrds:tt", counter[0] + counter[1], perf);
counter
. - person nosid   schedule 27.06.2014