|
nedoPC.orgElectronics hobbyists community established in 2002 |
|
|
Page 1 of 1
|
[ 7 posts ] |
|
Hopeless - перспективы параллельного программирования
Author |
Message |
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22589 Location: Silicon Valley
|
Подумал тут я (в очередной раз) про распараллеливание функциональных программ - почитал как это сделано в эрланге, поплевался... вобщем скорее всего будем считать, что удалённо (или просто в другом треде) можно вызвать любую публичную функцию любого модуля (который предварительно отпочкован через spawn) - при этом в отличие от локального вызова это будет выглядеть как асинхронная посылка сообщения без ожидания ответа (ответ придёт обратно путём удалённого же вызова некоторой функции, указанной при посылке):
dec spawn : string -> num; ! встроенная функция, которая запускает Hope-модуль (программу в виде файла .hop) как параллельный процесс (в будущем даже с возможностью запуска на другой машине в сети) и возвращает числовой идентификатор запущенного процесса
dec send : num # (alpha -> beta) # alpha # (beta -> gamma) -> bool; ! встроенная функция, которая осуществляет удалённый вызов некоторой функции (второй аргумент) предварительно запущенного в паралель модуля с известным числовым идентификатором (первый аргумент) с некоторыми аргументами (третий аргумент), кроме того должен быть указан "callback" (четвёртый аргумент) - локальная функция, которая будет вызвана, когда удалённая функция вернёт управление (либо сделать callback необязательным, но тогда придётся сделать две функции send без коллбека и sendx с коллбеком)
Last edited by Shaos on 03 Apr 2010 17:19, edited 2 times in total.
|
29 Aug 2009 16:55 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22589 Location: Silicon Valley
|
пример программы:
при вызове она должна напечатать [5,4,3,2,1]
Last edited by Shaos on 03 Apr 2010 17:19, edited 1 time in total.
|
29 Aug 2009 17:53 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22589 Location: Silicon Valley
|
с другой стороны предложенный подход неудобен - например как сводить вместе вычисленной на разных узлах? как ожидать когда все вычисления закончатся? вобщем надо делать иначе - удалённый вызов будет возвращать результат в место вызова, но при этом одновременно будут выполняться вызовы одного уровня (скажем внутри тюпла которым является например список аргументов любой функции):
| | | | Code: dec spawn : string -> num; dec call : num # (alpha->beta) # alpha -> beta; call(spawn("list.hop"),reverse,[6,7,8,9,10]) <> call(spawn("list.hop"),reverse,[1,2,3,4,5]) > [10,9,8,7,6,5,4,3,2,1]
| | | | |
в вышеприведённом примере отпочковываются два параллельных процесса list.hop в которых одновременно вызываются функции reverse - конкатенация списков (оператор <>) осуществляется только если оба результата получены P.S. а может spawn и не нужен? все равно у нас нету никакого контекста, создавать тред и держать его вечно нет смысла - достаточно создавать тред лишь непосредственно в момент удалённого вызова - можно call переименовать в spawn в этом случае: | | | | Code: dec spawn : string # (alpha->beta) # alpha -> beta; spawn("list.hop",reverse,[6,7,8,9,10]) <> spawn("list.hop",reverse,[1,2,3,4,5]) > [10,9,8,7,6,5,4,3,2,1]
| | | | |
на тот конец передаётся имя файла, который уже должен там быть физически - имя нужно чтобы без проблем загрузить его (если он ещё не загружен) и запустить нужную функцию P.P.S. по идее на этой стороне мы можем и внутри определить откуда взялась эта функция - надо сырцы хопа поизучать повнимательнее, но вроде можно - т.е. передачей имени файла озаботится ядро хопа и программисту об этом думать ненадо: | | | | Code: dec spawn : (alpha->beta) # alpha -> beta; reverse([6,7,8,9,10]) <> spawn(reverse,[1,2,3,4,5]) > [10,9,8,7,6,5,4,3,2,1]
| | | | |
в этом примере одна половинка списка получается локально, а вторая путём отпочковывания параллельного процесса, причём конкатенация <> вызывается лишь в тот момент, когда оба результата готовы и доступны локально
|
29 Aug 2009 18:39 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22589 Location: Silicon Valley
|
| | | | Shaos wrote: с другой стороны предложенный подход неудобен - например как сводить вместе вычисленной на разных узлах? как ожидать когда все вычисления закончатся? вобщем надо делать иначе - удалённый вызов будет возвращать результат в место вызова, но при этом одновременно будут выполняться вызовы одного уровня (скажем внутри тюпла которым является например список аргументов любой функции): | | | | Code: dec spawn : string -> num; dec call : num # (alpha->beta) # alpha -> beta; call(spawn("list.hop"),reverse,[6,7,8,9,10]) <> call(spawn("list.hop"),reverse,[1,2,3,4,5]) > [10,9,8,7,6,5,4,3,2,1]
| | | | |
в вышеприведённом примере отпочковываются два параллельных процесса list.hop в которых одновременно вызываются функции reverse - конкатенация списков (оператор <>) осуществляется только если оба результата получены P.S. а может spawn и не нужен? все равно у нас нету никакого контекста, создавать тред и держать его вечно нет смысла - достаточно создавать тред лишь непосредственно в момент удалённого вызова - можно call переименовать в spawn в этом случае: | | | | Code: dec spawn : string # (alpha->beta) # alpha -> beta; spawn("list.hop",reverse,[6,7,8,9,10]) <> spawn("list.hop",reverse,[1,2,3,4,5]) > [10,9,8,7,6,5,4,3,2,1]
| | | | |
на тот конец передаётся имя файла, который уже должен там быть физически - имя нужно чтобы без проблем загрузить его (если он ещё не загружен) и запустить нужную функцию | | | | |
ещё один из вариантов распараллеливания - отпочковывание процесса, который становится полностью независимым - например в случае сервера - по приходу нового запроса необходимо отпочковать тред по его обработке, в то время как основной тред продолжает ждать остальные запросы
с другой стороны нет смысла переписывать сишную программу с форками на функциональный язык (как сделали к примеру создатели хаскеля) - функциональный подход должен быть несколько иным - отпочковыая некую функцию как тред, мы должны указать сокет как источник входных данных, кроме того выходные данные не интересуют родительский тред - они должны уйти обратно в сокет - клиенту:
tcp_listen(8000,function);
запускаем TCP-слушателя на порту 8000, который по приходу запроса вызовет функцию function перенаправив поток из сокета в список - аргумент функции и возврат функции отправит обратно в сокет, после чего тред закроет
также можно подумать насчёт межпроцессного взаимодействия посредством каналов или ещё чего-нибудь...
|
03 Sep 2009 20:16 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22589 Location: Silicon Valley
|
Есть идея объединить оба варианта - сделать возможным вызов spawn как синхронно, так и асинхронно (причем с вызовом коллбека либо без оного, если результат работы отпочкованного процесса не интересен родительскому процессу - как в случае с listen - т.е. уже три варианта):
в последнем случае указываем не только функцию, которую надо вызвать, но и имя hop-модуля P.S. в будущем в строке - идентификаторе модуля можно будет не только модуль указывать, но и адрес узла, на котором это должно быть выполнено (при статической и заранее известной структуре сети) P.P.S. кстати адрес может быть не конкретный, а типа индекса из списка адресов, передаваемых в hopeless при запуске: 0 - текущая система (localhost), 1 - первый адрес из списка, 2 - второй и т.д., например "1:test.hop" P.P.P.S. вариант сервера тогда будет выглядеть примерно так:
|
05 Sep 2009 21:11 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22589 Location: Silicon Valley
|
подумалось тут, что синхронный вызов spawn не так уж и бессмысленен - например можно запустить удалённо фунцию map:
spawn("field",map,(lambda x => x*x,[1,2,3,4,5]));
при этом вызывающий модуль не будет просто висеть и ждать когда же удалённый конец возведет в квадрат весь список - на самом деле вызывающий модуль будет по одному передавать на тот конец элементы списка и в ответ, опять же по одному, получать результаты (потому как у нас ленивые вычисления) и вокруг этого уже можно строить какую-то разумную параллельную логику
|
05 Apr 2010 20:19 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22589 Location: Silicon Valley
|
Суть моего подхода в том, что ленивые списки используются в качестве каналов передачи данных между процессами (т.е. никаких других абстракций для каналов создавать больше ненадо)
|
20 Apr 2010 19:07 |
|
|
|
Page 1 of 1
|
[ 7 posts ] |
|
Who is online |
Users browsing this forum: No registered users and 100 guests |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|