Język programowania, w którym każde wywołanie funkcji / blok odbywa się w osobnym wątku? [Zamknięte]

26

Obecnie tworzę język programowania dla zabawy, w którym chodzi o to, że każde wywołanie funkcji / nowy blok (jeśli klauzule, pętle itp.) Będą działały w osobnym wątku. Zamiast tworzyć nowe wątki standardem powinno być to, że robi to automatycznie, a jeśli chcesz, aby działał w głównym wątku, musisz to określić.

Nie jestem zbyt dobrze poinformowany o wielowątkowym, równoległym programowaniu, ale znam podstawy (futures, bezpieczne wątki). Zastanawiam się więc, jak taki język mógłby wyglądać pod względem składni i czy w ogóle można zacząć? Celem nie jest uczynienie go „użytecznym”, lecz raczej zabawa i nauka.

(Przykro mi, jeśli jest to niewłaściwe miejsce do publikowania. Jeśli tak, z przyjemnością docenię, jeśli wskażecie mi właściwe miejsce, w którym dozwolone jest pytanie takie jak moje.)

Grimbox
źródło
17
Tworzenie wątków jest proste. Sztuczka z wielowątkowością polega na tym, że muszą ze sobą rozmawiać lub pracować z tymi samymi zasobami. Innymi słowy, to nie rozwidlenie jest trudne, to połączenia. Głównym problemem, który musisz rozwiązać, jest sposób, w jaki to kontrolujesz.
JimmyJames
20
IMO nie można tego zrobić bez poważnego rozciągnięcia zwykłej definicji słowa „funkcja” lub słowa „wątek”. Możesz przeczytać o aktorach, jeśli jeszcze ich nie znasz: en.wikipedia.org/wiki/Actor_model
Solomon Slow
9
Dbaj o wystarczającą dokładność, a przekonasz się, że procesory już automatycznie wykonują instrukcje równolegle, bez dodatkowego obciążenia twórcy oprogramowania. Zobacz Wykonywanie poza kolejnością i Procesor superskalarny .
8bittree
8
To właściwie brzmi trochę przerażająco. Chciałem wyjaśnić dlaczego, ale Karl Bielefeldt już to zrobił.
Mason Wheeler
1
Jaki paradygmat chcesz wspierać w swoim języku? Czy powinno to być konieczne czy funkcjonalne? Czy mówisz, że wszystkie instrukcje zostaną wykonane w tym samym czasie - wtedy / else-bloki wraz z tym, co nastąpi po nich?
Bergi

Odpowiedzi:

39

każde wywołanie funkcji / nowy blok (jeśli klauzule, pętle itp.) będą działać w osobnym wątku.

Dowiedz się więcej o kontynuacjach i stylu kontynuacji (i ich związku z wątkami lub coroutines). Sugeruję przeczytanie SICP i Lisp In Small Pieces . Również Pragmatics Programming Language daje użyteczny przegląd kilku języków i pomaga zaprojektować własny.

Dlatego zastanawiam się, jak taki język mógłby wyglądać pod względem składni

Składnia nie ma większego znaczenia dla odkrywania pomysłów . Semantyka ma znacznie większe znaczenie. Sugeruję na początku zastosować składnię typu S-expr (abyś mógł prototypować przy użyciu Scheme i jego wywołania / cc ) na początku.

Gdy twoje pomysły staną się bardziej jasne (po pewnym eksperymencie), możesz omówić je na temat lambda-the-ultimate , możesz zdefiniować bardziej seksowną składnię (która w rzeczywistości ma znaczenie, jeśli chcesz, aby ludzie adoptowali Twój język, a także liczy się jakość implementacji, implementacja próbki bezpłatnego oprogramowania, dokumentacja, biblioteka standardowa, interfejs funkcji zagranicznych itp.)

Basile Starynkevitch
źródło
25
+1 za wzmiankę o tym, dlaczego składnia jest nieistotna. Kolejny +1, gdybym mógł za wyjaśnienie, dlaczego składnia jest bardzo ważna.
Jörg W Mittag
Dobra sugestia, ale aby omówić różne rzeczy na LtU, chciałbyś mieć konto i zdobycie go z mojego doświadczenia nie jest trywialne.
Mael
1
Powinieneś użyć puli wątków, aby zmniejszyć obciążenie. en.wikipedia.org/wiki/Thread_pool
shawnhcorey
37

Być może zainteresuje Cię lektura na temat badań równoległych danych Haskell . Jeśli szukasz w serwisie YouTube, Simon Peyton Jones wygłosił kilka interesujących rozmów na ten temat.

Jeśli dobrze pamiętam z jego przemówień, w czysto funkcjonalnym programowaniu, znalezienie okazji do tworzenia wątków jest prawie banalne. Jego głównym problemem w jego badaniach jest zbyt wiele, które są zbyt krótkotrwałe, tak że narzut związany z tworzeniem wątków i komunikowaniem ich wyników zasadniczo przewyższa zalety równoległości. Na przykład łatwo jest nauczyć kompilatora, aby obrócił 100 wątków do obliczeń sum $ fmap (+1) <100 length vector>, ale czy koszty ogólne sprawią, że będzie to opłacalne?

Sztuczka polega na konsolidowaniu wątków do korzystnych rozmiarów, bez nakładania na programistę obowiązku ręcznego oznaczania tego. Jest to trudny problem, który należy załamać, aby skutecznie korzystać z przyszłych komputerów z tysiącami rdzeni.

Karl Bielefeldt
źródło
8
Byłbym szczęśliwy, mogąc pracować ze staroświeckim komputerem z zaledwie setkami rdzeni ...
Hagen von Eitzen
8
Zwrócę uwagę na to, że w przypadku bardzo mocno równoległych danych robiliśmy już wiele równoległości bardzo skutecznie: procesory graficzne to w zasadzie 200-1000 rdzeni (nawet mają swoją własną hierarchię pamięci).
Delioth
4
@HagenvonEitzen: Azul Vega JCA (Java Compute Appliance) miał 16 procesorów z 54 rdzeniami, co daje w sumie 864 rdzenie, i nie była to żadna maszyna na poziomie badawczym lub prototypowa, ale prawdziwy produkt. Nie wypełnił też całego budynku, ani nawet całego pokoju, był urządzeniem wielkości biurka. I był dostępny 9 lat temu. Wspomniano już o GPU, była to jednak maszyna z 864 rdzeniami procesora ogólnego przeznaczenia .
Jörg W Mittag
3
Oczywiście, nie jest to powód, dla którego nie ma dzisiaj tych, masywnej dane równolegle GPU, ale już nie te masywne wielordzeniowych procesorów do komputerów stacjonarnych. Te pierwsze są komercyjnie opłacalne, te drugie nie, a to dlatego, że nie można ich skutecznie zaprogramować.
MSalters
@MSalters może potrzebujemy nieskończonej liczby małp? Lub programy kwantowe, które po prostu uruchamiają każdą możliwą operację na każdym kroku?
15

Właśnie to robi Erlang. Obsługuje ponowne dołączanie wątków głównie za pomocą kolejek. Jest to genialna koncepcja, ale początkowo trudno jest się otoczyć, jeśli twoje tło jest bardziej proceduralne. Bardzo polecam zajrzeć w to.

GenericJam
źródło
4

Najpierw polecam spojrzeć na PROMELA , język używany do opisu współbieżnego algorytmu, aby moduł sprawdzający model mógł brutalnie wymusić wszystkie możliwe wykonania w celu sprawdzenia, czy nie jest w stanie działać nieprawidłowo. (Programowanie równoległe jest notorycznie trudne do prawidłowego wykonania, dlatego takie techniki weryfikacji są ważne.) Nie uruchamia wszystkich konstrukcji w osobnych wątkach, ale ma raczej dziwną składnię i semantykę, ponieważ koncentruje się na niedeterministyce współbieżnych programów.

Idąc bardziej abstrakcyjnie, rachunek π jest pięknym podejściem do modelowania obliczeń równoległych. Trudno się oderwać, dopóki nie dostaniesz książki Robin Milner Communicating and Mobile Systems: The Pi Calculus . Pomogło mi to myśleć o obliczeniach równoległych w szerszym znaczeniu tego słowa, że ​​„wiele wątków ma dostęp do pamięci współdzielonej”. Interesujące jest, w jaki sposób instrukcje warunkowe, „gotos” itd. Mogą być budowane z prostszych, naturalnie równoległych prymitywów.

Jeśli chodzi o składnię ... najlepszym sposobem na rozwiązanie tego problemu jest napisanie przykładowych programów. Napisz program do sortowania tablicy lub jednoczesnego pingowania kilku serwerów i zgłaszania, który z nich reaguje najszybciej, lub spróbuj rozwiązać labirynt równolegle lub cokolwiek. Podczas gdy to robisz, rzeczy, których brakuje w twojej składni, staną się widoczne i będziesz mógł je dodać. Po dodaniu kilku rzeczy, zadaj sobie pytanie, czy mają one coś wspólnego, a jeśli tak, to może znajdziesz prostsze podejście, które może służyć wielu celom.

Artelius
źródło
4

Podobne projekty próbowano w przeszłości. Sugeruję lekturę na temat klasyków, aby zdobywać pomysły. (Wszystkie linki prowadzą do Wikipedii)

  • Jedność Ten język był / jest używany do nauczania programowania równoległego. Nie sądzę, żeby to zostało faktycznie wdrożone. Składnia jest nieco tajemnicza, ale w zasadzie masz kolekcję instrukcji, które wykonują się w nieznanej kolejności i wielokrotnie, dopóki nie będzie już nic więcej do zrobienia. To jest najbliższe temu, o co prosisz.

  • Occam Ten język został zaprojektowany do faktycznego używania, ale tak naprawdę nigdy go nie złapał. Tutaj jest słowo kluczowe PAR, co oznacza, że ​​lista instrukcji powinna być wykonywana równolegle.

  • Erlang Kolejny język świata rzeczywistego. Ten jest używany przez firmę telekomunikacyjną Ericsson i ma dość następujące. Włożyli wiele pracy w uczynienie równoległości praktyczną i użyteczną.

  • Google GO To moja ulubiona z tej grupy. Koncepcyjnie podobnie jak Erlang, ale z lepszą składnią i ciężarem Google za tym. Co może źle pójść?

Chciałbym zakończyć ostrzeżeniem: bardzo trudno jest uzyskać równoległość. Większość błędów we współczesnych programach jest spowodowana błędem . Czy na pewno chcesz się tam wybrać?

Stig Hemmer
źródło
Żadne przestępstwo skierowane do jakiegokolwiek języka, którego nie ma na mojej liście. Po prostu moja wiedza jest ograniczona.
Stig Hemmer
3

Jest to możliwe, ale nie byłoby przydatne dla ponad 99% wszystkich możliwych do pomyślenia aplikacji. Logika jest typowo związana z sekwencją, jest przepływem. Krok po kroku dochodzisz do rozwiązania problemu, a kolejność kroków ma znaczenie, głównie dlatego, że dane wyjściowe z jednego kroku będą wprowadzane do następnego.

W nielicznych przypadkach masz wiele zadań, które można wykonać niezależnie od siebie, zazwyczaj taniej jest ustawić je sekwencyjnie, zanim zaczną działać równolegle.

Myślę więc, że lepiej spędzić czas na nauce korzystania z funkcji wielowątkowości w ulubionym języku programowania.

Martin Maat
źródło
5
To doskonała odpowiedź na inne pytanie; OP nie pyta o mądrość takiego schematu, a jedynie o to, czy można to zrobić i jak wyglądałaby „składnia”.
DepressedDaniel
9
Ci, którzy o to nie proszą, najbardziej potrzebują mojej mądrości. Jeśli ktoś zapyta, czy można zjechać ze wzgórza wózkiem na zakupy, najlepszą odpowiedzią nie będzie: „Obstawiasz! Pamiętaj, aby nasmarować koła!”. To byłoby bardziej jak „No tak, ale ...”.
Martin Maat
Przypomina mi starą instrukcję języka asemblera EIAO - Wykonaj w dowolnej kolejności . (A gdzie to w
@MartinMaat nikt nie zamierza się zabić, pisząc język programowania dla zabawy
253751
2

Clojure może być wart pomysłów.

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

Oto kilka przemyślenia: Jeśli nazwiemy jednostkę obliczeniową, którą można wykonać niezależnie, zadanie: 1. Zadania są niezależne, więc można je uruchamiać jednocześnie 2. Różne zadania wymagają różnych zasobów i uruchomienia w różnym czasie 3. Dlatego zadania należy zaplanować dla maksymalnej przepustowości 4. Jedynym programem, który może działać jako program planujący, jest system operacyjny

Rzeczy takie jak wielka centralna wysyłka jabłek są próbą zapewnienia takiego harmonogramu.

Powyższe oznacza, że ​​odpowiedzialność za wykonywanie zadań niekoniecznie spoczywa na języku programowania.

Drugą myślą jest jak największe zmniejszenie obciążenia związanego z programowaniem systemów równoległych. Jedynym sposobem na to jest usunięcie jakiejkolwiek specyfikacji tego, jak coś zrobić z programu. Program powinien określać tylko, co należy zrobić, a reszta powinna nastąpić automatycznie.

Powyższe prawdopodobnie oznacza, że ​​dynamiczne języki i kompilacja w samą porę są już na dobrej drodze.

foobar
źródło
2

To, czego szukasz, nazywa się ukrytym paralelizmem i istnieją języki, które zgłębiły tę koncepcję, takie jak Forteca Sun / Oracle . Między innymi (potencjalnie) uruchamia równolegle pętle.

Niestety, zostało przerwane i jest tam wiele martwych linków, ale nadal możesz znaleźć kilka plików PDF, jeśli wystarczająco mocno google:

https://www.eecis.udel.edu/~cavazos/cisc879-spring2008/papers/fortress.pdf (specyfikacja języka)

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 (paywalled)

Warto zauważyć, że zazwyczaj nie chciałbyś zaczynać rzeczywistego wątku dla każdego wyrażenia / wyrażenia, ponieważ tworzenie i uruchamianie wątków bywa kosztowne - zamiast tego dysponujesz pulą wątków, do których publikujesz fragmenty pracy wymagające wykonania . Ale to szczegół implementacji.

gustafc
źródło
1
+1 za mantioning Fortress ... Bardzo podobała mi się idea języka. Byłem naprawdę smutny, kiedy ogłosili, że rozwój został przerwany ...
Roland Tepp
2

Chociaż nie jest to język programowania jako taki, powinieneś przyjrzeć się VHDL . Służy do opisu obwodów cyfrowych, które naturalnie robią wszystko równolegle, chyba że wyraźnie powiesz mu, żeby zrobiło to serio. Może dać ci kilka pomysłów, jak zaprojektować język i jaka logika może być odpowiednia.

OnePie
źródło
0

Można to łatwo symulować w C ++. Upewnij się tylko, że „każde” * wywołanie funkcji jest realizowane przez std::future. Obsługa zwracanej wartości odbywa się po prostu przez wywołanie .get()przyszłości.

Dlatego możesz prototypować swój język, kompilując do C ++. Mówi nam to również, jak wyglądałaby składnia: główna różnica polega na tym, że oddzielasz punkt wywoławczy (gdzie podano argumenty wejściowe) od punktu zwrotnego (gdzie używane jest wyjście funkcji).

(*) Mówię „każda funkcja”, ale to od Ciebie zależy, co liczy się jako funkcja. Czy memsetjest nieodłączną funkcją? Czy przypisanie liczb całkowitych lub przypisanie typów zdefiniowanych przez użytkownika jest wywołaniem funkcji?

MSalters
źródło
A jeśli odłożysz wystarczająco długo odpowiedź na pytanie, zwykle potrzeba odpowiedzi zniknie. Myślę, że nazywa się to „Lazy Existing”.