Я пишу многопоточное приложение на С++, где производительность имеет решающее значение. Мне нужно использовать много блокировок при копировании небольших структур между потоками, для этого я решил использовать спин-блокировки.
Я провел небольшое исследование и тестирование скорости и обнаружил, что большинство реализаций примерно одинаково быстры :
__asm {}
, используя что-то вроде этого кода , и он оценивает около 70 единиц времени, , но я не уверен, что был создан надлежащий барьер памяти.Изменить :Время, указанное здесь, — это время, необходимое двум потокам для блокировки и разблокировки спин-блокировки 1 000 000 раз.
Я знаю, что это не большая разница, но поскольку спин-блокировка — это активно используемый объект, можно подумать, что программисты договорились о самом быстром способе создания спин-блокировки. Однако поиск в Google приводит к множеству различных подходов. Я думаю, что этот вышеупомянутый метод был бы самым быстрым, если бы он был реализован с использованием встроенного ассемблера и с использованием инструкции CMPXCHG8B
вместо сравнения 32-битных регистров. Кроме того, необходимо учитывать барьеры памяти, это можно сделать с помощью LOCK CMPXHG8B (Я думаю?), что гарантирует «исключительные права» на общую память между ядрами. Наконец [некоторые предполагают], что для ожидание занятости должно сопровождаться NOP :REP , что позволит многопоточным процессорам Hyper -переключаться на другой поток, но я не уверен, правда это или нет. нет?
Из моего теста производительности -различных спин-блокировок видно, что особой разницы нет, но чисто в академических целях я хотел бы знать, какой из них самый быстрый. Однако, поскольку у меня очень ограниченный опыт работы с языком ассемблера -и с барьерами памяти, я был бы счастлив, если бы кто-нибудь мог написать код ассемблера для последнего примера, который я предоставил с LOCK CMPXCHG8B и соответствующими барьерами памяти в следующий шаблон:
__asm
{
spin_lock:
;locking code.
spin_unlock:
;unlocking code.
}