web-dev-qa-db-ja.com

すべての関数呼び出し/ブロックが個別のスレッドで行われるプログラミング言語?

私は現在、楽しみのためにプログラミング言語を作成しています。ここでは、すべての関数呼び出し/新しいブロック(句、ループなど)が個別のスレッドで機能するという考えです。新しいスレッドを作成する代わりに、標準でそれを自動的に実行する必要があります。メインスレッドで実行する場合は、それを指定する必要があります。

私はマルチスレッドの並列プログラミングについては知らされていませんが、基本(未来、スレッドセーフオブジェクト)は知っています。したがって、私はそのような言語がどのように構文的に賢く見えるか、そしてそれが最初から可能かどうか疑問に思っていますか?目標は、それを「有用」にすることではありません。それは、それを楽しんで学習するためのものです。

(これが間違った投稿先である場合は申し訳ありません。そうである場合は、私のような質問が許可されている適切な場所を教えていただければ幸いです。)

26
Grimbox

すべての関数呼び出し/新しいブロック(if句、ループなど)は別のスレッドで機能します。

continuationscontinuation-passing style (およびそれらのスレッドまたはコルーチンとの関係)読むことをお勧めします [〜#〜] sicp [〜#〜]LISP In Small個 。また、Programming Language Pragmaticsは、いくつかの言語の有用な概要を提供し、独自の言語の設計に役立ちます。

したがって、私はそのような言語が構文上どのように見えるか疑問に思っています

ideasを探索する場合、構文はそれほど重要ではありません。 Semantics はさらに重要です。最初に S-expr のような構文を採用することをお勧めします(Schemeとその call/cc を使用してプロトタイプを作成できるようにするため)。

アイデアがより明確になったら(いくつかの実験を行った後) lambda-the-ultimate でそれらについて話し合うかもしれませんが、よりセクシーな構文を定義できます(実際に人々があなたの言語を採用したい場合、これは重要です、また、実装の品質、フリーソフトウェアのサンプル実装、ドキュメント、標準ライブラリ、外部関数インターフェイスなども重要です)

39

data parallel Haskell の研究について読むことに興味があるかもしれません。 YouTubeで検索すると、Simon Peyton Jonesがこのテーマに関連する興味深い講演を行っています。

純粋な関数型プログラミングで彼の講演を正しく思い出せば、スレッドを作成する機会を見つけることはほとんど簡単です。彼の研究における彼の主な問題は、短すぎて多すぎるため、スレッドの作成と結果の通信のオーバーヘッドが本質的にメリットを上回ることです並列処理の。たとえば、sum $ fmap (+1) <100 length vector>を計算するために100スレッドをスピンアップするようにコンパイラーに教えるのは簡単ですが、オーバーヘッドによって価値があるのでしょうか?

トリックは、プログラマーに負担をかけずにスレッドを有益なサイズに統合することです。数千のコアを持つ将来のPCを効果的に使用するためにクラックする必要のある難しい問題です。

37
Karl Bielefeldt

これはまさにErlangが行うことです。ほとんどの場合キューを使用して、スレッドの再結合を処理します。それは素晴らしい概念ですが、背景が手続き型言語の場合、最初に頭を回すのは少し難しいです。私はそれを調べることを強くお勧めします。

15
GenericJam

最初に、 [〜#〜] promela [〜#〜] を確認することをお勧めします。これは、モデルチェッカー可能なすべての実行をブルートフォースで実行して、不正な動作ができないことを確認できます。 (並行プログラミングは悪名高い難しいそのため、このような検証手法が重要です。)すべての構成要素を個別のスレッドで実行するわけではありませんが、構文が奇妙であり、セマンティクスは、その焦点が並行プログラムの非決定性であるためです。

より抽象的に言えば、 π-calculus は、並列計算をモデル化するための美しいアプローチです。 Robin Milner著の本Communicating and Mobile Systems:The Pi Calculusを入手しない限り、頭を動かすのは困難です。これは、「共有メモリにアクセスする複数のスレッド」というより広い意味での並列計算について考えるのに役立ちました。条件付きステートメント、「goto」などが、より単純で自然に並列なプリミティブからどのように構築できるかは非常に興味深いです。

構文に関して...これを解決する最良の方法は、いくつかのサンプルプログラムを書くことです。配列を並べ替えるプログラムを作成するか、複数のサーバーに同時にpingして、どれが最も速く応答するかを報告するか、並列に迷路を解こうとするか、そうではありません。これを行っている間、構文から欠落しているものが明らかになり、それらを追加できます。いくつかを追加したら、それらに共通点があるかどうかを考えてください。共通点がある場合は、複数の目的に役立つ簡単なアプローチを見つけることができます。

4
Artelius

同様のプロジェクトが過去に試みられてきました。古典を読んでアイデアを略奪することをお勧めします。 (すべてのリンクはウィキペディアに移動します)

  • nity この言語は、並列プログラミングを教えるために使用されました。実際に実装されたとは思いません。構文はいくぶん不可解ですが、基本的には不明な順序で実行されるステートメントのコレクションがあり、実行する必要がなくなるまで繰り返し実行されます。これはあなたが求めるものに最も近いです。

  • Occam この言語は実際に使用するために設計されましたが、実際に使用されることはありません。ここにキーワードPARがあります。これは、ステートメントのリストを並行して実行する必要があることを意味します。

  • Erlang 別の現実世界の言語。これは通信会社のエリクソンが使用しており、かなりの支持を得ています。彼らは、並列処理を実用的で使いやすいものにするために多くの努力を重ねてきました。

  • Google GO これは私の束のお気に入りです。概念的にはErlangとほとんど同じですが、構文が優れており、その背後にGoogleの重みがあります。何が間違っているのでしょうか?

警告で終了します:並列処理を正しく行うのは非常に困難です。最近のプログラムのほとんどのバグは、それを取得した結果です間違った。本当に行ってよろしいですか?

4
Stig Hemmer

それは可能ですが、考えられるすべてのアプリケーションの99 +%には役立ちません。ロジックは典型的にはシーケンスバウンドであり、フローです。ステップごとに問題の解決策に到達し、ステップの順序は重要です。これは、主に1つのステップの出力が次のステップの入力になるためです。

いくつかのケースでは、互いに独立して実行できる多くのタスクがありますが、通常は、それらを並行して実行する前に順次セットアップする方が安価です。

したがって、あなたの時間は、お気に入りのプログラミング言語でマルチスレッド機能を使用する方法を学習することに費やす方が良いと思います。

3
Martin Maat

そのようなプログラミング言語ではありませんが、 [〜#〜] vhdl [〜#〜] を確認する必要があります。これは、デジタル回路を説明するために使用されます。デジタル回路は、特にシリアルで実行するように指示しない限り、すべてを並列で実行します。それはあなたにあなたの言語をどのように設計するか、そしてそれがどんな種類の論理に適しているかもしれないかの両方の考えを与えるかもしれません。

2
OnePie

Clojureは、いくつかのアイデアを検討する価値があります。

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

ここにいくつかの考えがあります:独立して実行できる計算の単位をタスクと呼びます:1.タスクは独立しているので同時に実行できます2.異なるタスクは異なるリソースを必要とし、実行に異なる時間がかかります3.したがって、タスクはスケジュールされるべきですスループットを最大化します。4。スケジューラとして機能する唯一のプログラムはオペレーティングシステムです。

アップルグランドセントラルディスパッチのようなものは、そのようなスケジューラを提供する試みです。

上記は、タスクの実行の責任が必ずしもプログラミング言語の責任ではないことを意味します。

もう1つは、並列システムのプログラミングの負担をできるだけ減らすことです。これを行う唯一の方法は、プログラムから何かを行う方法の指定を削除することです。プログラムは何をすべきかを指定するだけで、残りは自動的に行われます。

上記はおそらく、動的言語とジャストインタイムのコンパイルが進むべき道であることを意味します。

2
foobar

あなたが探しているものは暗黙的な並列処理と呼ばれ、Sun/Oracleの Fortress など、この概念を探求した言語があります。とりわけ、それは(潜在的に)並列にループを実行します。

残念ながら、それは 廃止されました とそこには多くのデッドリンクがありますが、Googleを一生懸命に使用している場合、そこにまだいくつかのPDFが浮遊しています。足りる:

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 (ペイウォール)

注目に値するのは、スレッドの作成と開始はコストがかかる傾向があるため、通常、すべてのステートメント/式に対して実際のスレッドを開始することは望ましくないということです。代わりに、 スレッドのプールを必要な作業を投稿します 。しかし、それは実装の詳細です。

2
gustafc

これは、C++で非常に簡単にシミュレートできます。 「すべての」*関数呼び出しが_std::future_によって実装されていることを確認してください。戻り値の処理は、将来的に.get()を呼び出すだけで実行されます。

したがって、C++にコンパイルして言語のプロトタイプを作成できます。これにより、構文がどのようになるかがわかります。主な違いは、呼び出しポイント(入力引数が提供される場所)と戻りポイント(関数の出力が使用される場所)を分離することです。

(*)「すべての関数」と言いますが、関数として数えるかどうかはあなた次第です。 memsetは組み込み関数ですか、それとも関数ですか?整数の割り当て、またはユーザー定義型の割り当ては関数呼び出しですか?

0
MSalters