Cкорость работы InterlockedExchangeAdd и аналогов
Встретил в коде функцию InterlockedExchangeAdd и стало интересно, насколько быстро она работает.
Под катом - тесты и результаты.
Написал небольшой тестик, который 10млн раз делает InterlockedExchangeAdd.
for(int i = 0; i < CYCLES_COUNT; ++i)
{
InterlockedExchangeAdd (&l, 1);
}
Второй тест делает 10млн раз 2 вызова InterlockedExchangeAdd, третий - 3 вызова.
for(int i = 0; i < CYCLES_COUNT; ++i)
{
InterlockedExchangeAdd (&l, 1);
InterlockedExchangeAdd (&l2, 1);
InterlockedExchangeAdd (&l3, 1);
}
Четвертый тест использует CriticalSection для синхронизации доступа к переменной:
for(int i = 0; i < CYCLES_COUNT; ++i)
{
EnterCriticalSection(&cs);
l += 1;
LeaveCriticalSection(&cs);
}
Пятый тест использует критическую секцию и изменяет 4 переменных:
for(int i = 0; i < CYCLES_COUNT; ++i)
{
EnterCriticalSection(&cs);
l += 1;
l2 += 1;
l3 += 1;
l4 += 1;
LeaveCriticalSection(&cs);
}
Результаты (мс):
InterlockedAdd1: 183
InterlockedAdd2: 361
InterlockedAdd3: 575
EnterCriticalSection4: 383
EnterCriticalSection5: 392
Выводы:
InterlockedAdd примерно в 2 раза эффективнее, чем метод с критической секцией. Но, если вам надо изменить значение хотя бы 3-х переменных, то уже выгоднее использовать критическую секцию.
На двух переменных разницы почти нет.
При этом, если не использовать синхронизацию вообще, то операции с переменными работают во много-много раз быстрее.
Upd:
Сделал также тесты для intrinsic аналога функции InterlockedExchangeAdd - _InterlockedExchangeAdd. Она работает примерно в 2 раза быстрее!
Так что, если есть возможность, то лучше использовать intrinsic аналоги.