Каковы компромиссы между "занятым ожиданием" и "сном"? - PullRequest
21 голосов
/ 10 июля 2009

Это продолжение моего предыдущего вопроса

Как работает режим блокировки в сокетах unix / linux?

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

Но тогда может ли это быть эффективный способ в реальном времени, скажем, жесткие / твердые приложения в реальном времени? Поскольку процесс не разблокирован, когда условие разблокирования выполнено, скорее, когда планировщик передаст ему свой срез ЦП, и условие разблокирования является истинным.

Как будто вы хотите адаптивное решение, я не считаю, что «спин-блокировки» или «занятые ожидания» являются правильным способом сделать это, срезы ЦП тратятся впустую, и система в целом перестает отвечать на запросы или может плохо -responsive.

Может кто-нибудь, пожалуйста, проясните эти противоречивые мысли.

Ответы [ 6 ]

39 голосов
/ 10 июля 2009

Переход в режим сна до тех пор, пока планировщик не разбудит вас, является нормальным / предпочтительным занятием.

Спиннинг (альтернативный способ ожидания без сна) менее обычен и имеет следующие эффекты:

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

  • Может прекратить вращаться в тот самый момент, когда происходит то, чего вы ждете (потому что вы постоянно проверяете это событие, и вам не нужно тратить время на то, чтобы разбудить, потому что ты уже проснулся)

  • Не вызывает проблем с процессором, необходимых для перехода в спящий режим и для повторного пробуждения

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

4 голосов
/ 10 июля 2009

A Spin Lock сжигает ЦП и путь опрашиваемого ресурса для непрерывной траты ресурсов, пока нужное событие не происходит.

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

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

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


Я думаю, что J-16 указывает на то, что спящий (заблокированный) поток оставляет свой код и пространство данных неиспользованным в заблокированном состоянии. Это может привести к тому, что система освободит ресурсы (например, кэши данных / кода), которые затем необходимо будет пополнить при освобождении блока. Следовательно, в зависимости от условий, блок может привести к большему расходу ресурсов.
Это также действительное примечание, и его следует проверить при разработке и реализации.
Но в большинстве случаев блокировка обычно лучше, чем спин-блокировки.

1 голос
/ 08 января 2011

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

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

Другой сценарий, который я могу придумать для принудительного переключения контекста, выглядит следующим образом:

while(condition)
    sleep(0);
0 голосов
/ 25 октября 2009

// Адаптированный исходный код ASPI ...

    DWORD startStopUnit (HANDLE handle, BOOL bLoEj, BOOL bStart)
    {
       DWORD  dwStatus;
       HANDLE heventSRB;
       SRB_ExecSCSICmd s;





    //here
       heventSRB = CreateEvent (NULL, TRUE, FALSE, NULL);

       memset (&s, 0, sizeof (s));

       s.SRB_Cmd = SC_EXEC_SCSI_CMD;
       s.SRB_HaID = 0;
       s.SRB_Target = 0;
       s.SRB_Lun = 0;
       s.SRB_Flags = SRB_EVENT_NOTIFY;
       s.SRB_SenseLen = SENSE_LEN;
       s.SRB_CDBLen = 6;
       s.SRB_PostProc = (LPVOID) heventSRB;
       s.CDBByte[0] = 0x1B;
       s.CDBByte[4] |= bLoEj ? 0x02 : 0x00;
       s.CDBByte[4] |= bStart ? 0x01 : 0x00;

       ResetEvent (heventSRB);
       dwStatus = SPTISendASPI32Command (handle,(LPSRB) & s);
       if (dwStatus == SS_PENDING)
         {
//and here, don´t know a better way to wait for something to finish without processor cicles
        WaitForSingleObject (heventSRB, DEFWAITLEN);
         }
       CloseHandle (heventSRB);

       if (s.SRB_Status != SS_COMP)
         {
    printf("Erro\n");
        return SS_ERR;
         }

       printf("nao Erro\n");
       return s.SRB_Status;
    }
0 голосов
/ 12 июля 2009

Я постараюсь быть на месте, так как здесь представлено достаточно объяснений с помощью других ответов, и да, извлекая уроки из всех этих ответов, я думаю, что будет полная картина. ---

По моему мнению, компромисс между Отзывчивость и пропускная способность системы.

Отзывчивость - можно рассматривать с двух точек зрения

  • по всей отзывчивости системы и
  • отзывчивость конкретного или отдельного процесса

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

И, конечно же, для конкретного процесса или отзывчивости на процесс мы рассмотрим модель «занятое ожидание / спин-блокировка».

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

Я думаю, что лучше всего - разработать систему с учетом скорости реагирования на процесс, не влияя на общую скорость реакции и пропускную способность, - путем реализации планировщика на основе приоритетов с учетом вопросов инверсии приоритетов, если сложность вас не беспокоит:).

0 голосов
/ 10 июля 2009

Прежде всего, у вас неправильное представление:

Блокировка звонков - это не «ожидание занятости» или «спин-блокировки». Блокирующие вызовы являются спящими - это означает, что ЦП будет работать над другой задачей, процессор не будет потрачен впустую

По вашему вопросу о блокировке звонков

Блокировка вызовов проще - их легко понять, легче разработать, легче отладить.

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

Это компромисс - более быстрое развитие и ремонтопригодность? или масштабируемость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...