nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 28 Mar 2024 06:20



Reply to topic  [ 7 posts ] 
Hopeless - перспективы параллельного программирования 
Author Message
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Подумал тут я (в очередной раз) про распараллеливание функциональных программ - почитал как это сделано в эрланге, поплевался... вобщем скорее всего будем считать, что удалённо (или просто в другом треде) можно вызвать любую публичную функцию любого модуля (который предварительно отпочкован через spawn) - при этом в отличие от локального вызова это будет выглядеть как асинхронная посылка сообщения без ожидания ответа (ответ придёт обратно путём удалённого же вызова некоторой функции, указанной при посылке):

dec spawn : string -> num; ! встроенная функция, которая запускает Hope-модуль (программу в виде файла .hop) как параллельный процесс (в будущем даже с возможностью запуска на другой машине в сети) и возвращает числовой идентификатор запущенного процесса

dec send : num # (alpha -> beta) # alpha # (beta -> gamma) -> bool; ! встроенная функция, которая осуществляет удалённый вызов некоторой функции (второй аргумент) предварительно запущенного в паралель модуля с известным числовым идентификатором (первый аргумент) с некоторыми аргументами (третий аргумент), кроме того должен быть указан "callback" (четвёртый аргумент) - локальная функция, которая будет вызвана, когда удалённая функция вернёт управление (либо сделать callback необязательным, но тогда придётся сделать две функции send без коллбека и sendx с коллбеком)

_________________
:dj: https://mastodon.social/@Shaos


Last edited by Shaos on 03 Apr 2010 17:19, edited 2 times in total.



29 Aug 2009 16:55
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Shaos wrote:
Подумал тут я (в очередной раз) про распараллеливание функциональных программ - почитал как это сделано в эрланге, поплевался... вобщем скорее всего будем считать, что удалённо (или просто в другом треде) можно вызвать любую публичную функцию любого модуля (который предварительно отпочкован через spawn) - при этом в отличие от локального вызова это будет выглядеть как асинхронная посылка сообщения без ожидания ответа (ответ придёт обратно путём удалённого же вызова некоторой функции, указанной при посылке):

dec spawn : string -> num; ! встроенная функция, которая запускает Hope-модуль (программу в виде файла .hop) как параллельный процесс (в будущем даже с возможностью запуска на другой машине в сети) и возвращает числовой идентификатор запущенного процесса

dec send : num # (alpha -> beta) # alpha # (beta -> gamma) -> bool; ! встроенная функция, которая осуществляет удалённый вызов некоторой функции (второй аргумент) предварительно запущенного в паралель модуля с известным числовым идентификатором (первый аргумент) с некоторыми аргументами (третий аргумент), кроме того должен быть указан "callback" (четвёртый аргумент) - локальная функция, которая будет вызвана, когда удалённая функция вернёт управление (либо сделать callback необязательным, но тогда придётся сделать две функции send без коллбека и sendx с коллбеком)


пример программы:

Code:
uses list;

dec get_reversed_list : list alpha -> num;
--- get_reversed_list(l) <= write(l); ! функцию write пока нельзя так юзать

dec remote_reverse : num # list alpha -> bool;
--- remote_reverse(i,l) <= sendx(i,reverse,l,get_reversed_list);

remote_reverse(spawn("list.hop"),[1,2,3,4,5]);


при вызове она должна напечатать [5,4,3,2,1]

_________________
:dj: https://mastodon.social/@Shaos


Last edited by Shaos on 03 Apr 2010 17:19, edited 1 time in total.



29 Aug 2009 17:53
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
с другой стороны предложенный подход неудобен - например как сводить вместе вычисленной на разных узлах? как ожидать когда все вычисления закончатся? вобщем надо делать иначе - удалённый вызов будет возвращать результат в место вызова, но при этом одновременно будут выполняться вызовы одного уровня (скажем внутри тюпла которым является например список аргументов любой функции):
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]

в этом примере одна половинка списка получается локально, а вторая путём отпочковывания параллельного процесса, причём конкатенация <> вызывается лишь в тот момент, когда оба результата готовы и доступны локально

_________________
:dj: https://mastodon.social/@Shaos


29 Aug 2009 18:39
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
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 перенаправив поток из сокета в список - аргумент функции и возврат функции отправит обратно в сокет, после чего тред закроет

также можно подумать насчёт межпроцессного взаимодействия посредством каналов или ещё чего-нибудь...

_________________
:dj: https://mastodon.social/@Shaos


03 Sep 2009 20:16
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Есть идея объединить оба варианта - сделать возможным вызов spawn как синхронно, так и асинхронно (причем с вызовом коллбека либо без оного, если результат работы отпочкованного процесса не интересен родительскому процессу - как в случае с listen - т.е. уже три варианта):
Code:
dec spawn : string # (alpha->beta) # alpha -> beta; ! синхронный запуск параллельного процесса
dec spawna : string # (alpha->beta) # alpha -> truval; ! асинхронный запуск параллельного процесса без возврата результата
dec spawnac : string # (alpha->beta) # alpha # string # (beta->gamma) -> truval; ! асинхронный запуск параллельного процесса с коллбеком

в последнем случае указываем не только функцию, которую надо вызвать, но и имя hop-модуля
P.S. в будущем в строке - идентификаторе модуля можно будет не только модуль указывать, но и адрес узла, на котором это должно быть выполнено (при статической и заранее известной структуре сети)
P.P.S. кстати адрес может быть не конкретный, а типа индекса из списка адресов, передаваемых в hopeless при запуске: 0 - текущая система (localhost), 1 - первый адрес из списка, 2 - второй и т.д., например "1:test.hop"
P.P.P.S. вариант сервера тогда будет выглядеть примерно так:
Code:
type socket == num;
type byte == num; ! ???
type bytes == list byte;
type port == num;
type ip4 == byte # byte # byte # byte;
dec tcp_socket : port -> socket;
dec udp_socket : port -> socket;
dec listen : socket -> bool;
dec ip4_accept : socket -> socket # ip4;
dec read : socket -> list(bytes);
dec write : socket # bytes -> num;
dec reads : socket -> list(string);
dec writes : socket # string -> num;
dec recvfrom : socket -> bytes # ip4;
dec sendto : socket # bytes # ip4 -> num;
dec recvsfrom : socket -> string # ip4;
dec sendsto : socket # string # ip4 -> num;
.....
dec server : port -> bool;
dec server_loop : socket -> bool;
dec process : socket # ip4 -> bool;
dec process_line : socket # string -> string;
--- server(port) <= let s==tcp_socket(port) in s!=0 and listen(s) and server_loop(s);
--- server_loop(s) <= spawna("this.hop",process,ip4_accept(s)) and server_loop(socket);
--- process(s,addr) <= writes(s,process_line(s,reads(s)));
--- process_line(s,"") <= ""; ! empty reads means end of connection
--- process_line(s,line) <= line <> process_line(s,reads(s)); ! send back the same thing

_________________
:dj: https://mastodon.social/@Shaos


05 Sep 2009 21:11
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
подумалось тут, что синхронный вызов spawn не так уж и бессмысленен - например можно запустить удалённо фунцию map:

spawn("field",map,(lambda x => x*x,[1,2,3,4,5]));

при этом вызывающий модуль не будет просто висеть и ждать когда же удалённый конец возведет в квадрат весь список - на самом деле вызывающий модуль будет по одному передавать на тот конец элементы списка и в ответ, опять же по одному, получать результаты (потому как у нас ленивые вычисления) и вокруг этого уже можно строить какую-то разумную параллельную логику

_________________
:dj: https://mastodon.social/@Shaos


05 Apr 2010 20:19
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Суть моего подхода в том, что ленивые списки используются в качестве каналов передачи данных между процессами (т.е. никаких других абстракций для каналов создавать больше ненадо)

_________________
:dj: https://mastodon.social/@Shaos


20 Apr 2010 19:07
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 7 posts ] 

Who is online

Users browsing this forum: No registered users and 18 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

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.