Зачем нам нужен 'seq' или 'pseq' с 'par' в Haskell? - PullRequest
30 голосов
/ 02 января 2011

Я пытаюсь понять, зачем нам нужны все части стандартного примера кода:

a `par` b `pseq` a+b

Почему следующего недостаточно?

a `par` b `par` a+b

Вышеприведенное выражение выглядит очень наглядно: попробуйте одновременно оценить a и b и вернуть результат a+b. Причина только в эффективности: вторая версия будет зажигаться дважды, а не один раз?

Как насчет следующей, более краткой версии?

a `par` a+b

Зачем нам нужно проверять b перед a+b, как в исходном стандартном коде?

Ответы [ 3 ]

30 голосов
/ 02 января 2011

Хорошо. Я думаю, что следующая статья отвечает на мой вопрос: http://community.haskell.org/~simonmar/papers/threadscope.pdf

В итоге проблема с

a `par` b `par` a+b 

и

a `par` a+b

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

Оригинальная версия

a `par` b `pseq` a+b

обеспечивает работу основного потока на b до a+b (иначе вместо этого началось бы вычислять a), что дает возможность искре a материализоваться в поток для параллельной оценки.

16 голосов
/ 02 января 2011
a `par` b `par` a+b 

вычислит a и b параллельно и вернет a + b , да.

Тем не менее, pseq там гарантирует, что и a, и b будут оценены до того, как a + b is.

См. эта ссылка для более подробной информации по этой теме.

6 голосов
/ 19 мая 2014

a `par` b `par` a+b создает искры как для a, так и для b, но a+b достигается немедленно, поэтому одно из искр вспыхивает (т.е. оно оценивается в основном потоке). Проблема заключается в эффективности, так как мы создали ненужную искру. Если вы используете это для реализации параллельного разделения и завоевания, накладные расходы ограничат ваше ускорение.

a `par` a+b кажется лучше, потому что он создает только одну искру. Однако попытка оценить a до b приведет к искре для a, а поскольку у b нет искры, это приведет к последовательной оценке a+b. Переключение порядка на b+a решило бы эту проблему, но как код это не навязывает порядок, и Haskell все равно может оценить это как a+b.

Итак, мы делаем a `par` b `pseq` a+b, чтобы форсировать оценку b в главном потоке, прежде чем пытаться оценить a+b. Это дает возможность возникновения искры a, прежде чем мы попытаемся оценить a+b, и мы не создали ненужных искр.

...