Минимальное время, которое поток может приостановить в Linux - PullRequest
8 голосов
/ 10 сентября 2011

В моем приложении потоки должны приостанавливаться на очень короткое время (100 секунд тактов). Один из способов сделать паузу - вызвать nanosleep, но я полагаю, что это требует системного вызова ядра. Теперь я хочу сделать паузу, не заходя в ядро.

Обратите внимание, что у меня достаточно ядер для запуска моих потоков, и я привязываю каждый поток к отдельному ядру, так что даже инструкция, которая может ненадолго остановить ядро, будет хорошей. Я использую x86. Я просто хочу, чтобы нить остановилась во время паузы. Я не хочу занятого цикла или системного вызова ядра. Можно ли сделать это? Какое минимальное время я могу приостановить поток?

Ответы [ 6 ]

7 голосов
/ 10 сентября 2011

_mm_pause в цикле ожидания ожидания - это путь.

К сожалению, предоставляемая им задержка может меняться для каждого семейства процессоров:

http://siyobik.info/main/reference/instruction/PAUSE

Пример использования GCC в Linux:

#include <xmmintrin.h>

int main (void) {
    _mm_pause();
    return 0;
}

Компиляция с включенным MMX:

gcc -o moo moo.c  -march=native

Также вы всегда можете просто использовать встроенный ассемблер:

__asm volatile ("pause" ::: "memory");

Снекоторые инженеры Intel могут посчитать это полезным для определения стоимости паузы:

Команда NOP может находиться в диапазоне от 0,4 до 0,5 такта, а инструкция PAUSE может занимать 38-40 часов.

http://software.intel.com/en-us/forums/showthread.php?t=48371

1 голос
/ 10 сентября 2011

Почему бы тебе просто не подождать? Вы можете в цикле многократно вызывать инструкцию rdtsc, чтобы получить счетчик тактов, а затем просто остановиться, если разница превышает 100 тактов.

Я предполагаю, что это для торговой системы, для которой это обычная техника

0 голосов
/ 10 сентября 2011

Вообще говоря, для такой короткой задержки я бы подумал, что системный вызов не практичен, потому что издержки системного вызова + планирование + переключение контекста и обратно будут намного больше, чем ваша пауза, как вы, кажется, думаете. уже быть в курсе.

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

Да, вращение, подобное этому, действительно тратит впустую энергию, и если вы работаете на ЦП с несколькими аппаратными потоками, как обычно подразумевает многоядерный, вы также без необходимости извлекаете слоты выполнения из других потоков, но если у вас нет очень системный вызов с очень низкими издержками и механизм планировщика и таймер высокого разрешения, я бы сказал, что это невозможно.

0 голосов
/ 10 сентября 2011

Ваша единственная надежда получить точную синхронизацию - это использование timer_create и получение истечения таймера по сигналу, я думаю. С расписанием в реальном времени.

Я не уверен, для чего это может быть полезно, так как вы не можете выполнить какой-либо ввод-вывод в таком маленьком временном окне, и поэтому не должно иметь значения, если ваш код выполняется 1000 раз с промежутком в 100 нс между каждым запуском или 1000 раз вместе с пробелом 100 мс в конце.

0 голосов
/ 10 сентября 2011

Это зависит от того, что вы подразумеваете под паузой. Если с помощью паузы вы хотите остановить поток на короткий промежуток времени, это может сделать только ОС.

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

0 голосов
/ 10 сентября 2011

нет - это невозможно.Либо звоните sleep или select - ядру;или иметь цикл, чтобы тратить время.

...