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.)
Odpowiedzi:
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.
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.)
źródło
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.
źródło
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.
źródło
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.
źródło
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ć?
źródło
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.
źródło
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.
źródło
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.
źródło
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.
źródło
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
memset
jest nieodłączną funkcją? Czy przypisanie liczb całkowitych lub przypisanie typów zdefiniowanych przez użytkownika jest wywołaniem funkcji?źródło