LINUX.ORG.RU

Приоритеты потоков


0

1

Диспозиция такая: есть два потока, один рисует данные opengl'ем, второй в фоне грузит куски данных. Реализована, соответственно, очередь запросов, защищённая мутексом:

// Главный поток
{
  while (1) {
    pthread_mutex_lock(mutex);
    ...
    отрисовка_данных(dataset);
    ...
    queue.push_back(request);
    ...
    pthread_mutex_unlock(mutex);  /* 1 */
  }
}

// Рабочий поток:
{
  pthread_mutex_lock(mutex);
  while (!die_flag) {
    while (queue.empty())
      pthread_cond_wait(condvar, mutex);
    request = queue.pop_front();
    pthread_mutex_unlock(mutex);

    data = долгая_обработка_куска_данных(request);

    pthread_mutex_lock(mutex);
    dataset.push_back(data);
  }
  pthread_mutex_unlock(mutex);
}

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

На деле же происходит следующая неприятая вещь: первый поток после рендеринга и добавления нескольких запросов в очередь вызывает pthread_mutex_unlock (/* 1 */) и не возвращается из неё 0.1 секунды, за которые второй поток и ухитряется обработать аж десяток кусков данных, соответственно, отображение в главном потоке заметно лагает. Насколько я понимаю, получается так потому что у первого потока, успевшего за время рендеринга пожрать циклов CPU, понижается приоритет, а т.к. второй поток это время спал, он вытесняет первый пока не догонит его по использованию CPU. Вставка sched_yield во второй поток помогает, но сейчас используется два потока, и лаги, хоть и менее заметны, всё ещё присутствуют. Как я понимаю, несколько рабочих потоков будут просто переключаются друг на друга, но не на главный.

Собственно вопрос: как избавиться от лагов? Я так понимаю, приоритеты потокам выставлять не очень хорошо потому что условиях нехватки CPU (т.е. 1 ядро занятое на 100%) поток с меньшим приоритетом будет голодать, а значит данные грузиться не будут. В идеале нужно чтобы главный поток не вытеснялся более чем на 0.01 сек, но при этом чтобы CPU с другими потоками получал поровну.

★★★★★
Ответ на: комментарий от ly

>>> В таких случаях полностью dyntick-ядро начинает будить процесс «не раз в в тик», а каждую микросекунду (или как там запрошено).

Выглядит, мягко говоря, неправдоподобно.

Я про другое говорю - когда вызывают usleep/select/poll(1) чтобы чуть-чуть подождать (в цикле), предполагая что планировщик запустит

Ну то есть консенсус: будить процесс раз в микросекунду технически невозможно.

Если ядро будет полностью верным dynitick-ам, то процесс будет «засыпать» на 1 us, и получиться а-ля busy-loop.

Никто не гарантирует процессам SCHED_OTHER того, что они проснутся точно после запрошенного времени, так что ядру нет необходимости быть «верным» чему-то.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

В целом согласен, да ядро не может много чего гарантировать и даже для SCHED_FIFO.

Но с микросекундой тут другой случай, получается что процесс нужно будить всегда... А если не будить, то получаются обычные тики. Наверное до «2.8» так и останется «прореживатель» ;-(

ly
()
Ответ на: комментарий от ly

> Но с микросекундой тут другой случай,

С микросекунлой будет занятое ожидание еще многие годы.

А если не будить, то получаются обычные тики.

??

tailgunner ★★★★★
()
Ответ на: комментарий от ly

> Наверное до «2.8» так и останется «прореживатель»

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

idle ★★★★★
()
Ответ на: комментарий от ly

> либо повсеместном поклонении jiffies в ядре.

1) jiffies обновляются и в случае с dyntick

2) Это не поклонение, это текущий способ измерять время, работать с таймерами, etc.

Дак я про то и говорил, что после экспериментов Инго subj превратился в прореживатель тиков.

А что, было по-другому?

Есть hrtimers. Задача - возможность работы с таймеринтервалами меньше 1/HZ.

Есть dynamick ticks. Задача - не генерировать timer interrupt, если без него «можно обойтись»

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.