Haskell:Руководство по параллельной структуре данных

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


Предположим, что наша параллельная структура данных представляет собой карту m, доступ к которой осуществляется как m[i]. Допустим также, что у нас есть две функции, f_easyи f_hard. f_easyработает быстро, f_hardзанимает много времени. Предположим, что аргументы f_easy/f_hardявляются элементами m.

(1)Если ваши транзакции выглядят примерно так m[f_easy(...)] = f_hard(...), используйте IORefс atomicModifyIORef. Лень гарантирует, что mбудет заблокирован только на короткое время, поскольку он обновляется с помощью преобразователя. Вычисление индекса эффективно блокирует структуру (, так как что-то будет обновлено, но мы пока не знаем, что ), но как только известно, что это за элемент, преобразователь по всей структуре перемещается только к преобразователю. над этим конкретным элементом, и тогда только этот конкретный элемент «заблокирован».

(2)Если ваши транзакции выглядят примерно так m[f_hard(...)] = f_easy(...)и не сильно конфликтуют, используйте много TVars. Использование IORefв этом случае эффективно сделает приложение однопоточным, так как вы не сможете вычислить два индекса одновременно (, поскольку во всей структуре будет неразрешенный преобразователь). TVarпозволяет вам обрабатывать два индекса одновременно, однако недостатком является то, что если две параллельные транзакции обращаются к одному и тому же элементу, и одна из них является записью, одна транзакция должна быть отменена, что приводит к пустой трате времени (. ], который мог быть использован в другом месте). Если это случается часто,вам может быть лучше с блокировками, которые приходят (через черную дыру)из IORef, но если этого не происходит очень часто, вы получите лучший параллелизм с TVars.

В основном, в случае (2), с IORefвы можете получить 100% эффективность (без лишней работы), но использовать только потоки 1.1, но с TVar, если у вас небольшое число конфликтов вы можете получить 80% эффективности, но использовать 10 потоков, так что вы все равно в конечном итоге в 7 раз быстрее, даже с потраченной впустую работой.

7
задан Robin Green 20 May 2018 в 13:37
поделиться