Intel рекомендует использовать инструкции PAUSE
только тогда, когда спин-петля очень короткая.
Как я понял из ваших вопросов, ожидания в вашем случае очень длинные. В этом случае спин-петли не рекомендуются.
Вы написали, что у вас есть «поток, который продолжает сканировать некоторые места (например, очередь) для получения новых узлов».
В этом случае Intel рекомендует использовать функции API синхронизации вашей операционной системы. Например, вы можете создать событие, когда новый узел появится в очереди, и просто подождать этого события, используя WaitForSingleObject(Handle, INFINITE)
. Очередь вызовет это событие всякий раз, когда появится новый узел.
Согласно Руководству по оптимизации Intel, инструкция PAUSE
обычно используется с программными потоками, выполняющимися на двух логических процессорах, расположенных в одном и том же ядре процессора, ожидающих снятия блокировки. Такие короткие циклы ожидания имеют тенденцию длиться от десятков до нескольких сотен циклов (то есть 20-500 циклов ЦП), поэтому с точки зрения производительности выгоднее ждать, занимая ЦП, чем уступать ОС.
500 циклов ЦП на процессоре Core i7 7700K с частотой 4500 МГц составляет 0,0000001 секунды, т. Е. 1/10000000-ая секунда: этот цикл 500 циклов ЦП может делать 10 миллионов раз в секунду.
Как видите, эта PAUSE
инструкция предназначена для действительно коротких периодов времени.
С другой стороны, каждый вызов функции API, такой как Sleep (), требует больших затрат на переключение контекста, которое может составлять более 10000 циклов; он также несет стоимость переходов от кольца 3 к кольцу 0, что может составлять 1000+ циклов.
Если потоков больше, то доступны ядра процессора (умноженные на функцию гиперпоточности, если таковые имеются), и поток переключится на другой в середине критической секции, ожидая, когда критическая секция из другого потока может действительно нужно looong , по крайней мере, 10000+ циклов, поэтому инструкция PAUSE
будет бесполезной.
Пожалуйста, смотрите эту статью для получения дополнительной информации:
Когда ожидается, что цикл ожидания будет длиться тысячи и более циклов, это
предпочтительнее уступить операционной системе, вызвав одну из функций API синхронизации ОС, например WaitForSingleObject в ОС Windows.
В заключение: в вашем сценарии инструкция PAUSE
не будет лучшим выбором, так как ваше время ожидания велико, в то время как PAUSE
предназначен для очень коротких циклов. PAUSE составляет всего 131 такт SkyWell или более поздних процессоров. Например, на Intel Core i7-7700K CPU @ 4,20 ГГц Kaby Lake это всего лишь 31,19 нс.
На более ранних процессорах, таких как Haswell, у меня около 9 циклов. На Intel Core i5-4430 @ 3GHz это 2,81 нс. Таким образом, для длинных циклов лучше отказаться от управления другими потоками, используя функции API синхронизации ОС, чем занимать ЦП с циклом PAUSE
.