Мова програмування, коли кожен виклик / блок функції виконується в окремому потоці? [зачинено]


26

Наразі я створюю мову програмування для розваги, де ідея полягає в тому, що кожен виклик функції / новий блок (якщо пропозиції, цикли тощо) будуть працювати в окремому потоці. Замість того, щоб створювати нові теми, стандарт повинен бути таким, що він робить це автоматично, і якщо ви хочете, щоб він запускався в основній темі, вам доведеться вказати це.

Я не так поінформований про багатопотокове паралельне програмування, але я знаю основи (Futures, об’єкти, безпечні для потоків). Тому мені цікаво, як така мова могла б виглядати синтаксисом мудрою і чи це взагалі можливо почати? Мета - не зробити його «корисним», це більше для задоволення від цього та досвіду навчання.

(Вибачте, якщо це неправильне місце для публікації. Якщо так, я б радий, якщо ви вкажете мене на потрібне місце, де дозволено таке питання, як моє.)


17
Створити нитки просто. Трюк з багатопотоковою ниткою полягає в тому, коли їм потрібно поговорити один з одним або працювати з тими ж ресурсами. Іншими словами, це не жорстке розгинання, це з'єднання. Основна проблема, яку потрібно вирішити, - це те, як ви це контролюєте.
JimmyJames

20
ІМО, ви не можете цього зробити, якщо серйозно не розтягнути звичайне визначення слова "функція" або слова "нитка". Ви можете прочитати про акторів, якщо ви ще не знайомі з ними: en.wikipedia.org/wiki/Actor_model
Соломон повільно

9
Отримайте дрібнозернисту інформацію, і ви побачите, що процесори вже паралельно вказують інструкції автоматично, не створюючи додаткового навантаження на розробника програмного забезпечення. Див. Розділ "Виконання поза замовленням" та " Надскалярний процесор" .
8bittree

8
Це насправді звучить жахливо. Я збирався пояснити чому, але Карл Білефельдт уже це зробив.
Мейсон Уілер

1
Яку парадигму ви хочете підтримати своєю мовою? Він повинен бути імперативним чи функціональним? Ви хочете сказати, що всі висловлювання виконувалися б одночасно - тодішні / інші блоки разом із тим, що відбувається після них?
Бергі

Відповіді:


39

кожен виклик функції / новий блок (якщо пропозиції, цикли тощо) працюватиме в окремому потоці.

Читайте набагато більше про продовження та стиль проходження продовження (та їхнє відношення до ниток чи розробок) Я пропоную прочитати SICP & Lisp In Small Pieces . Також Прагматика мови програмування дає корисний огляд кількох мов, і допоможе вам створити власну.

Тому мені цікаво, як така мова могла виглядати синтаксисом мудро

Синтаксис не має великого значення для вивчення ідей . Семантика має значення набагато більше. Я пропоную прийняти якийсь синтаксис типу S-expr (щоб ви могли спочатку прообразувати за допомогою Scheme та його call / cc ).

Після того, як ваші ідеї стануть більш чіткими (після деяких експериментів), ви можете обговорити їх на лямбда-остаточному , ви зможете визначити більш сексуальний синтаксис (що насправді має значення, якщо ви хочете, щоб люди сприйняли вашу мову, і що також має значення - якість впровадження, реалізація безкоштовного зразка програмного забезпечення, документація, стандартна бібліотека, інтерфейс іноземних функцій тощо)


25
+1 для згадки про те, чому синтаксис не має значення. Ще +1, якщо я міг би пояснити, чому синтаксис дуже важливий.
Йорг W Міттаг

Гарна пропозиція, але для обговорення матеріалів на LtU ви хочете отримати акаунт, і це не тривіально, щоб отримати його з мого досвіду.
Mael

1
Ви повинні використовувати пучок ниток, щоб зменшити накладні витрати. en.wikipedia.org/wiki/Thread_pool
shawnhcorey

37

Можливо, вам буде цікаво почитати про дослідження паралельних даних Haskell . Якщо ви шукаєте навколо YouTube, Саймон Пейтон Джонс також розказав цікаві розмови, пов'язані з цією темою.

Якщо я пригадую правильно з його розмов, у чистому функціональному програмуванні майже тривіально знайти можливості для створення тем. Його головна проблема в його дослідження , що мають занадто багато , що занадто недовговічні, так що накладні витрати створення потоків і передачі їх результати істотно переважує переваги паралелізму. Наприклад, легко навчити компілятора розкручувати 100 ниток для обчислення sum $ fmap (+1) <100 length vector>, але чи зробить це накладним?

Трюк тоді полягає в консолідації ниток на корисні розміри, не накладаючи тягар на програміста, щоб позначити це вручну. Це складна проблема, яку потрібно зламати, щоб ефективно використовувати майбутні ПК з тисячами ядер.


8
Я б уже радий працювати зі старовинним ПК з лише сотнями ядер ...
Hagen von Eitzen

8
Я хотів би зауважити, що для сильно паралельних даних, ми вже дуже ефективно проводили паралелізацію: GPU - це по суті 200-1000 основних машин (у них навіть є власна ієрархія пам'яті).
Delioth

4
@HagenvonEitzen: JCA Azul Vega JCA (Java Compute Appliance) мав 16 процесорів з 54 ядрами на загальну суму 864 ядра, і це була не якась дослідницька машина чи прототип, а справжній продукт. Він також не заповнив цілу будівлю або навіть цілу кімнату, це був прилад розміру на столі. І він був доступний 9 років тому. Графічні процесори вже згадувалися, однак це була машина з 864 ядрами центрального процесора загального призначення .
Йорг W Міттаг

3
Звичайно, є причина, чому у нас сьогодні є такі масивні графічні процесори, що мають паралельну передачу даних, але вже не такі масові багатоядерні процесори для настільних ПК. Перші є комерційно життєздатними, останні - ні, і це тому, що ви не змогли їх ефективно програмувати.
MSalters

@MSalters, можливо, нам просто потрібна нескінченна кількість мавп? Або програми Quantum, які просто виконують всі можливі операції на кожному кроці?

15

Саме цим займається Ерланг. Він обробляє повторно з'єднання ниток, переважно за допомогою черг. Це геніальна концепція, але трохи важко обернути голову спочатку, якщо ваш фон є більш мовою процедурного типу. Я настійно рекомендую вивчити це.


4

По-перше, я б рекомендував вам подивитися на PROMELA , мову, що використовується для опису паралельного алгоритму, щоб перевіряючий зразок міг змусити всі можливі виконання, щоб переконатися, що він нездатний до неправильної поведінки. (Одночасно програмування, як відомо, важко отримати правильно. Ось чому такі методи перевірки важливі.) Він не запускає всі конструкції в окремих потоках, але має досить незвичайний синтаксис та семантику, оскільки його фокус - недетермінізм одночасних програм.

Виходячи з більш абстрактних даних, π-обчислення - прекрасний підхід до моделювання паралельних обчислень. Важко обійтися, якщо ви не отримаєте книгу Робін Мілнер « Комунікаційні та мобільні системи: обчислення Pi» . Це допомогло мені подумати про паралельні обчислення в більш широкому розумінні, що "кілька потоків, що мають доступ до спільної пам'яті". Цікаво, як умовні висловлювання, "готос" тощо можна побудувати з більш простих, природно паралельних примітивів.

Що стосується синтаксису ... найкращий спосіб вирішити це - написати деякі зразкові програми. Напишіть програму, щоб сортувати масив, або паралельно пінг декількох серверів і повідомте, який з них відповідає найшвидше, або спробуйте вирішити лабіринт паралельно, чи що. Поки ви це робите, речі, які відсутні у вашому синтаксисі, стануть очевидними, і ви можете їх додати. Після того, як ви додали кілька речей, запитайте себе, чи є у них щось спільне, і якщо так, можливо, ви можете знайти простіший підхід, який може служити численним цілям.


4

Подібні проекти намагалися проводити і раніше. Я пропоную прочитати класику, щоб грабувати ідеї. (Усі посилання переходять до Вікіпедії)

  • Єдність Ця мова була / використовується для навчання паралельного програмування. Я не думаю, що це було реально реалізовано. Синтаксис дещо криптовалютний, але в основному у вас є колекція висловлювань, які виконуються в невідомому порядку і повторно, поки більше нічого не потрібно робити. Це найближче до того, що ви просите.

  • Occam Ця мова була розроблена для фактичного використання, але вона ніколи насправді не прижилася. Тут є ключове слово PAR, що означає, що список операторів повинен виконуватися паралельно.

  • Ерланг Ще одна реальна мова. Цей використовується телекомунікаційною компанією Ericsson і має досить наступне. Вони доклали багато роботи, щоб зробити паралелізм практичним та корисним.

  • Google GO Це моя улюблена група. Концептуально майже те саме, що Ерланг, але з кращим синтаксисом та вагою Google за ним. Що може помилитися?

Я хотів би завершити з попередженням: Паралелізм дуже важко отримати правильно. Більшість помилок у сучасних програмах є наслідком того, що вони помиляються . Ви впевнені, що хочете туди поїхати?


Ніякого правопорушення, не призначеного для будь-якої мови, що не в моєму списку. Просто мої знання обмежені.
Стиг Хеммер

3

Це можливо, але це не було б корисно для 99 +% усіх делікатних програм. Логіка типово пов'язана з послідовністю, вона є потоком. Крок за кроком ви досягаєте вирішення проблеми, і порядок дії має значення, головним чином тому, що вихід одного кроку буде введений для наступного.

У кількох випадках у вас багато завдань, які можна виконати незалежно одна від одної, як правило, дешево їх встановлювати послідовно, перш ніж пускати їх паралельно.

Отже, я думаю, що ваш час було б краще витратити на вивчення способів використання багатопотокових мов улюбленої мови програмування.


5
Це відмінна відповідь на інше питання; ОП не запитує про мудрість такої схеми, а лише про те, чи можна це зробити та як виглядатиме "синтаксис".
ПригніченийДаніель

9
Ті, хто цього не просять, найбільше потребують моєї мудрості. Якщо хтось запитує, чи можливо спуститися з пагорба в кошику для покупок, найкращою відповіддю буде не "Ви ставите! Не забудьте змастити ними колеса!". Це було б більше схоже на "Ну так, але ...".
Мартін Маат

Нагадує мені стару інструкцію з монтажу EIAO - Виконувати в будь-якому порядку . (А де це взагалі будь-який ключ?)

@MartinMaat ніхто не збирається вбивати себе, написавши мову програмування для розваги
user253751

2

Clojure, можливо, варто переглянути деякі ідеї.

http://clojure-doc.org/articles/language/concurrency_and_parallelism.html

Ось кілька думок: Якщо ми називаємо одиницю обчислення, яку можна виконати самостійно завданням: 1. Завдання незалежні, тому їх можна виконувати одночасно 2. Різні завдання потребують різних ресурсів і займають різні часи. Тому завдання потрібно планувати для максимальної пропускної здатності 4. Єдиною програмою, яка може виконувати функції планувальника, є операційна система

Такі речі, як яблучна грандіозна центральна відправка, - це спроба надати такого планувальника.

Сказане означає, що відповідальність за виконання завдань не обов'язково покладається на мову програмування.

Друга думка - максимально зменшити тягар програмування паралельних систем. Єдиний спосіб зробити це - видалити будь-яку специфікацію того, як щось робити з програми. Програма повинна вказувати лише те, що слід робити, а решта має відбуватися автоматично.

Сказане, мабуть, означає, що динамічні мови та своєчасна компіляція - це шлях.


2

Те, що ви шукаєте, називається неявним паралелізмом, і є мови, які досліджували цю концепцію, наприклад, фортеця Сонце / Оракул . Крім усього іншого, він (потенційно) запускає петлі паралельно.

На жаль, це було припинено, і там багато мертвих посилань, але ви все ще можете знайти кілька PDF-файлів, що плавають там, якщо ви досить гучно перебуваєте в Google:

https://www.eecis.udel.edu/~cavazos/cisc879-spring2008/papers/fortress.pdf (специфікація мови)

http://stephane.ducasse.free.fr/Teaching/CoursAnnecy/0506-Master/ForPresentations/Fortress-PLDITutorialSlides9Jun2006.pdf

http://www.oracle.com/technetwork/systems/ts-5206-159453.pdf

http://dl.acm.org/citation.cfm?id=1122972 (платня)

Варто зауважити, що ти зазвичай не хочеш запускати фактичний потік для кожного оператора / виразу, оскільки створення та запуск ниток, як правило, коштує дорого - натомість у тебе буде пул ниток, на який ви публікуєте біти роботи, які потребують виконання . Але це деталь реалізації.


1
+1 за маніпулювання фортецею ... Думка мені дуже сподобалась. Мені було дуже сумно, коли вони оголосили, що розвиток припинено ...
Roland Tepp

2

Хоча це не мова програмування як такої, слід поглянути на VHDL . Він використовується для опису цифрової схеми, яка, природно, робить все паралельно, якщо ви спеціально не скажете це робити серійно. Це може дати вам кілька ідей, як створити свою мову та якою логікою вона підходить.


0

Це можна легко імітувати в C ++. Просто переконайтесь, що "кожен" * виклик функції реалізовано a std::future. Поводження із поверненою вартістю просто здійснюється за допомогою заклику .get()до майбутнього.

Отже, ви можете прообразувати свою мову, компілюючи в C ++. Це також говорить нам про те, як виглядатиме синтаксис: головна відмінність полягає в тому, що ви відокремлюєте точку виклику (де надаються вхідні аргументи) від точки повернення (там, де використовується функція виводу).

(*) Я кажу "кожна функція", але саме від вас залежить від функції. Це memsetвластивість чи функція? Чи присвоєння цілих чисел або призначення визначених користувачем типів є викликом функції?


І якщо ви відкладаєте відповіді на запитання досить довго, зазвичай потреба у відповіді відпадає. Я думаю, що це називається "Ліниво існуюче".
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.