Шаблон, с которым я сталкивался несколько раз, - это тот, в котором список значений должен быть проверен путем сопоставления некоторого теста и проверки, прошел ли какой-либо или все элементы. Типичное решение - просто использовать удобные встроенные функции all
и any
.
Проблема в том, что они оцениваются в сериале. Во многих случаях было бы намного быстрее выполнять оценку параллельно с завершением процесса, если какой-либо поток найдет «False» для all
или «True» для any
. Я почти уверен, что поведение короткого замыкания не может быть реализовано с помощью Control.Parallel, поскольку оно требует межпроцессного взаимодействия, и я пока не понимаю достаточно близко к Control.Concurrent, чтобы реализовать это.
Это довольно распространенный паттерн в математике (например, Миллер-Рабин Прималити), поэтому я чувствую, что кто-то, возможно, уже нашел решение для этого, но по понятным причинам делает поиск в Google "параллельно или / и / любой / все в списке". haskell "не возвращает много релевантных результатов.
источник
unamb
библиотекойpthreads
в C или зелеными потоками в Haskell). Вы не запускаете несколько веб-серверов для обработки одновременных веб-запросов, вместо этого вы запускаете несколько потоков в одном процессе! То же относится и к параллелизму. Вы раскручиваете столько потоков, сколько имеете процессоров, и равномерно распределяете свою работу, таким образом заботясь о задачах, связанных с процессором. Попробуйте эту библиотеку, чтобы убедить себя github.com/lehins/haskell-schedulerОтветы:
Во многих реалистичных программах вы можете использовать параллельные стратегии для этой цели. Это потому, что, хотя нет явного механизма отмены ненужных вычислений, это будет происходить неявно при запуске сборщика мусора. В качестве конкретного примера рассмотрим следующую программу:
При этом используется стратегия параллельного списка для поиска
waldo = 0
(который никогда не будет найден) в выходных данных 100 потоков PRNG по 40 миллионов номеров в каждом. Скомпилируйте и запустите:и он привязывает четыре ядра к 16 секундам, в конце концов печатая
False
. Обратите внимание на статистику, что все 100 искр "преобразованы" и поэтому работают до завершения:Теперь измените
waldo
значение, которое можно найти раньше:и изменить,
main
чтобы сохранить поток в течение 10 секунд:Вы заметите, что он печатает
True
почти сразу, но 4 ядра остаются привязанными на 100% CPU (по крайней мере, на некоторое время), показывая, что ненужные вычисления продолжают работать и не закорачиваются, как вы, возможно, опасались.НО , все изменится, если вы заставите сборщик мусора после получения ответа:
Теперь вы увидите, что ЦП вскоре после печати переключается в режим ожидания
True
, а статистика показывает, что большинство вычислений были собраны мусором перед запуском:В реалистичных программах явное указание
performGC
не потребуется, поскольку GC будут выполняться регулярно, как само собой разумеющееся. Некоторые ненужные вычисления будут продолжать выполняться после того, как ответ найден, но во многих реалистичных сценариях доля ненужных вычислений не будет особенно важным фактором.В частности, если список большой и каждый отдельный тест элемента списка быстр, параллельные стратегии будут иметь отличную производительность в реальном мире и их легко внедрить в сделку.
источник