Як правило, функціональне програмування не передбачає швидших програм. Це полегшує паралельне та паралельне програмування. Для цього є два основні ключі:
- Уникнення змінних станів, як правило, зменшує кількість речей, які можуть помилитися в програмі, а тим більше в паралельній програмі.
- Уникнення примітивів синхронізації із спільною пам'яттю та синхронізації на основі блокування на користь концепцій вищого рівня, як правило, спрощує синхронізацію між потоками коду.
Одним з відмінних прикладів пункту №2 є те, що в Хаскеллі ми чітко відрізняємо детермінований паралелізм від недетермінованої одночасності . Немає кращого пояснення, ніж цитувати чудову книгу Саймона Марлоу Паралельне та паралельне програмування в Хаскеллі (цитати з розділу 1 ):
Паралельна програма є один , який використовує безліч обчислювальних апаратних засобів (наприклад, кілька процесорних ядер) для виконання обчислень більш швидко. Мета - досягти відповіді раніше, делегуючи різні частини обчислень різним процесорам, які виконують одночасно.
Навпаки, паралельність - це технологія програмування програми, в якій є кілька потоків управління. Концептуально нитки управління виконуються "одночасно"; тобто користувач бачить їх ефекти переплетеними. Незалежно від того, чи вони насправді виконують одночасно чи ні, це детальна інформація про реалізацію; паралельна програма може виконуватись на одному процесорі через перемежоване виконання або на декількох фізичних процесорах.
На додаток до цього, Марлоу згадує також вимір детермінізму :
Пов'язане розмежування між детермінованими та недетермінованими моделями програмування. Модель детермінованого програмування - це така модель, в якій кожна програма може дати лише один результат, тоді як модель недетермінованого програмування допускає програми, які можуть мати різні результати, залежно від певного аспекту виконання. Моделі одночасного програмування обов'язково не детерміновані, оскільки вони повинні взаємодіяти із зовнішніми агентами, які викликають події в непередбачувані часи. Однак недетермінізм має деякі помітні недоліки: Програми стають значно складнішими для перевірки та обґрунтування.
Для паралельного програмування ми хотіли б використовувати детерміновані моделі програмування, якщо це можливо. Оскільки мета полягає в тому, щоб швидше дійти до відповіді, ми швидше не ускладнюємо нашу програму важче налагоджувати процес. Детерміноване паралельне програмування є найкращим з обох світів: тестування, налагодження та міркування можна проводити в послідовній програмі, але програма працює швидше, додаючи більше процесорів.
У Хаскеллі паралелізм та паралельність функціонують навколо цих понять. Зокрема, те, що інші мови об'єднуються в один набір функцій, Haskell розбивається на дві:
- Детерміновані особливості та бібліотеки для паралелізму .
- Недетерміновані функції та бібліотеки для одночасності .
Якщо ви просто намагаєтеся прискорити чистий, детермінований обчислення, детермінований паралелізм часто полегшує справи. Часто ви просто робите щось подібне:
- Напишіть функцію, яка створює список відповідей, кожний з яких обчислювати дорого, але не сильно залежать один від одного. Це Haskell, тому списки ліниві - значення їх елементів фактично не обчислюються, поки споживач цього не вимагає.
- Використовуйте бібліотеку " Стратегії", щоб паралельно споживати елементи списку результатів вашої функції по декількох ядрах.
Я фактично зробив це з однією з моїх програм проекту іграшок кілька тижнів тому . Паралелізовувати програму було тривіально - головне, що я мав зробити, це фактично додати код, який говорить "паралельно обчислювати елементи цього списку" (рядок 90), і я отримав майже лінійне збільшення пропускної здатності в деякі мої дорожчі тестові випадки.
Моя програма швидша, ніж якби я перейшов із звичайними багатопотоковими утилітами на основі блокування? Я дуже сумніваюся в цьому. Акуратна річ у моєму випадку отримала стільки ударів від такого маленького долара - мій код, мабуть, дуже неоптимальний, але, оскільки це так просто паралелізувати, я отримав велику швидкість роботи з набагато меншими зусиллями, ніж правильне профілювання та оптимізація, і немає ризику перегонів. І це, я б сказав, головний спосіб функціонального програмування дозволяє писати "швидші" програми.