Я вижу, что вопрос был повторно активирован наградой, теперь я спрашиваю, каково практическое использование yield
. Приведу пример из своего опыта.
Как мы знаем, yield
заставляет вызывающий поток отказаться от процессора, на котором он работает, чтобы можно было запланировать запуск другого потока. Это полезно, когда текущий поток на данный момент завершил свою работу, но хочет быстро вернуться в начало очереди и проверить, не изменилось ли какое-либо условие. Чем это отличается от переменной условия? yield
позволяет потоку намного быстрее вернуться в рабочее состояние. При ожидании переменной условия поток приостанавливается и должен ждать, пока другой поток не подаст сигнал о том, что он должен продолжить.yield
в основном говорит: «разрешите запуск другого потока, но позвольте мне очень быстро вернуться к работе, поскольку я ожидаю, что что-то изменится в моем состоянии очень и очень быстро». Это намекает на интенсивное вращение, когда условие может быстро измениться, но приостановка потока приведет к значительному снижению производительности.
Но хватит болтовни, вот конкретный пример: параллельный узор волнового фронта. Базовым примером этой проблемы является вычисление отдельных «островков» единиц в двумерном массиве, заполненном нулями и единицами. «Остров» - это группа ячеек, которые примыкают друг к другу по вертикали или горизонтали:
1 0 0 0
1 1 0 0
0 0 0 1
0 0 1 1
0 0 1 1
Здесь у нас есть два островка единиц: верхний левый и нижний правый.
Простое решение - сделать первый проход по всему массиву и заменить значения 1 увеличивающимся счетчиком так, чтобы к концу каждая 1 была заменена своим порядковым номером в старшем порядке строк:
1 0 0 0
2 3 0 0
0 0 0 4
0 0 5 6
0 0 7 8
На следующем шаге каждое значение заменяется минимумом между ним и значениями соседей:
1 0 0 0
1 1 0 0
0 0 0 4
0 0 4 4
0 0 4 4
Теперь мы можем легко определить, что у нас есть два острова.
Часть, которую мы хотим запустить параллельно, - это этап, на котором мы вычисляем минимумы. Не вдаваясь в подробности, каждый поток получает строки с чередованием и полагается на значения, вычисленные потоком, обрабатывающим строку выше. Таким образом, каждый поток должен немного отставать от потока, обрабатывающего предыдущую строку, но также должен успевать за разумное время. Более подробная информация и реализация представлены мной в этом документе . Обратите внимание на использование , sleep(0)
которое более или менее С эквивалентом yield
.
В этом случае yield
использовалось, чтобы заставить каждый поток по очереди приостанавливаться, но поскольку поток, обрабатывающий соседнюю строку, тем временем продвигался бы очень быстро, переменная условия оказалась бы катастрофическим выбором.
Как видите, yield
это довольно мелкая оптимизация. Использование его в неправильном месте, например, ожидание в условиях, которые редко меняются, приведет к чрезмерному использованию ЦП.
Извините за долгий лепет, надеюсь, я ясно выразился.