Вопрос по c++, c, x86-64, thread-synchronization, multithreading – Насколько быстрым является неоспоримый замок?

9

И насколько она быстрее / медленнее по сравнению с неоспоримой атомарной переменной (такой как атомарная операция C ++). Кроме того, насколько медленнее оспариваемые атомные переменные по сравнению с неоспоримой блокировкой? Архитектура, над которой я работаю, - x86-64.

@ edA-qamort-ora-y Как автор другого вопроса, я могу сказать, что они одинаковы. Другой вопрос может бытьphrased иначе (с точки зрения накладных расходов), но на самом деле он спрашивал: «Насколько быстрее, чем блокировка, является атомарной операцией?» & # x201D; Konrad Rudolph
возможный дубликатOverhead of using locks instead of atomic intrinsics Konrad Rudolph
@KonradRudolph, я вижу, что вопросы похожи, но не совсем так. Этот более сфокусирован на фундаментальных затратах на операции, а второй - на накладные расходы двух подходов к алгоритму. На самом деле я бы ответил на них несколько иначе. edA-qa mort-ora-y

Ваш Ответ

3   ответа
5

проект на GitHub с целью измерения этого на разных платформах. К сожалению, после моей магистерской диссертации у меня никогда не было времени, чтобы заняться этим, но, по крайней мере, есть элементарный код.

Он измеряет pthreads и OpenMP блокировки по сравнению с__sync_fetch_and_add внутренняя.

Из того, что я помню, мы ожидали довольно большой разницы между блокировками и атомарными операциями (~ на порядок), но реальная разница оказалась очень маленькой.

Тем не менее, измерение сейчас в моей системе дает результаты, которые отражают мое первоначальное предположение, а именно, что (независимо от того, используется ли pthreads или OpenMP), атомарные операции выполняются примерно в пять раз быстрее, а одна операция блокировки с приращением занимает около 35 нс (это включает получение блокировки , выполняя приращение и освобождая блокировку).

3

зависит также от системы. Атомарные переменные не могут быть оспорены так же, как блокировка (даже если вы используетесемантика приобретенного выпуска), то есть весь смысл атомарности, он блокирует шину для распространения хранилища (в зависимости от режима барьера памяти), но это деталь реализации.

Однако, большинство блокировок пользовательского режима просто заключены в атомные операции, см.этот статья Intel, в которой приводятся некоторые данные о высокопроизводительных масштабируемых блокировках с использованием атомарных операций под x86 и x64 (по сравнению с Windows & apos;CriticalSection замки, к сожалению, нет статистики дляSWR блокировок, но всегда нужно профилировать для своей собственной системы / среды).

«Атомные переменные не могут быть оспорены так же, как блокировка» - если два потока (на разных ядрах) забивают одну и ту же атомную переменную, то это, безусловно, оспаривается? Затем дело за архитектурой / реализацией зависит от того, действительно ли соревнование замедляет ход событий. Возможно, вы могли бы сравнить его с двумя потоками на разных ядрах, использующими одну и ту же неатомарную переменную, чтобы понять, занимает ли в некотором смысле атомная синхронизация какое-то время.
@SteveJessop, определенно. Два ядра, использующие одну и ту же переменную, вызовут чрезмерную синхронизацию этой переменной. В этот момент вы связаны задержкой / пропускной способностью шины кеша.
@Necrolis: конечно, механизм совершенно другой, но я думаю, что спрашивающий вправе называть все такие вещи «раздорами». Если мой код задерживается в ожидании выхода другого кода, то мы продолжаем, независимо от того, какой механизм :-)
@ edA-qamort-ora-y: и проблема потенциально запутана на архитектурах, подобных x86, из-за связного кэша. Итак, как вы говорите, забивание одного и того же места является своего рода спором, даже если этоisn't атомная переменная. Я не уверен, знает ли спрашивающий это, но я думаю, что это является мешающим фактором, если вы решите выяснить, какова «стоимость»; имеет оспариваемый атомный прирост. Вы можете сравнить его с атомарными инкрементами в одном потоке или с оспариваемым неатомарным инкрементом (так называемая гонка данных) и прийти к совершенно другим представлениям о том, что такое «атомная конкуренция». расходы.
@SteveJessop: вы могли бы назвать это так, но, IMO, все это сделано по-другому, поэтому вы действительно не можете поместить его в ту же категорию, что и повтор-ожидание-вращение для уже полученной блокировки.
14

что именно означает скорость, очень неопределенно, потому что она во многом зависит от того, что именно вы делаете (даже не связанного с самой операцией).

Вот некоторые цифры от AMD 64-битного Phenom II X6 3,2 ГГц. Я также запускаю это на чипах Intel, и время сильно варьируется (опять же, в зависимости от того, что именно делается).

GCC__sync_fetch_and_add, который был бы полностью огороженным атомным дополнением, имеет в среднем 16 нс, с минимальным временем 4 нс. Минимальное время, вероятно, ближе к истине (хотя даже там у меня есть немного накладных расходов).

Непревзойденный мьютекс pthread (через повышение) составляет 14 нс (что также является его минимумом). Обратите внимание, что это также слишком мало, поскольку время фактически увеличится, если что-то еще заблокировало мьютекс, но сейчас это не оспаривается (так как это приведет к синхронизации кэша).

Неудачный try_lock равен 9 нс.

У меня нет простой старой версии atomic inc, поскольку на x86_64 это обычная операция обмена. Вероятно, близко к минимально возможному времени, поэтому 1-2 нс.

Вызов notify без условной переменной для условной переменной составляет 25 нс (если что-то ожидает около 304 нс).

Однако, поскольку все блокировки вызывают определенные гарантии упорядочения ЦП, объем памяти, который вы изменили (независимо от того, что умещается в буфере хранилища), изменит время, необходимое для выполнения таких операций. И, очевидно, если у вас когда-нибудь возникнут разногласия по поводу мьютекса, это ваше худшее время. Любой возврат к ядру Linux может длиться сотни наносекунд, даже если на самом деле переключение потоков не происходит. Обычно это происходит, когда атомарные блокировки не выполняются, поскольку они никогда не связаны с какими-либо вызовами ядра: ваша средняя производительность также является вашей наихудшей. Разблокировка мьютекса также влечет за собой дополнительные издержки, если есть ожидающие потоки, тогда как атомарный не будет.

ПРИМЕЧАНИЕ. Выполнение таких измерений чревато проблемами, поэтому результаты всегда сомнительны. Мои тесты пытаются минимизировать отклонения, фиксируя скорость процессора, устанавливая привязку процессора к потокам, не запуская другие процессы и усредняя по большим наборам результатов.

Да, на Linux. Не оспариваемый означает, что он не касается системного вызова, хотя, таким образом, futex фактически не задействован в этом случае (не оспариваемый в библиотеке NPTL разрешается полностью в пространстве пользователя без системного вызова).
Спасибо за цифры! Какую платформу вы тестировали? говоря "pthread mutex" не говорит много, поскольку то, что это означает, полностью зависит от реализации. Поскольку время близко к атомарному добавлению, я предполагаю, что это GNU / Linux, так что вы используете futex?
На мой взгляд, «Футекс»is целое число, так что оно задействовано, но все, что нужно, - это атомный инкремент «фьютекс»; (то есть целое число)

Похожие вопросы