"相互に接続された複数のプロセシングコアと、ストリームデスティネーションモジュールおよびストリームソースモジュールを定義するストリームを含むストリームドメインコードを記憶するメモリであって、前記ストリームソースモジュールは前記ストリームにデータ値を代入し、前記ストリームは前記ストリームソースモジュールから前記ストリームデスティネーションモジュールへとデータ値を伝える、メモリと、いつ前記データ値が前記ストリームデスティネーションモジュールに対して利用可能となるかを検出し、前記複数のプロセシングコアのうちの1つ上で実行されるよう前記ストリームデスティネーションモジュールをスケジュールする、ランタイムシステムと、を備える、プログラム可能なコアに基づく演算デバイス。前記ストリームドメインコードは、入力ストリームおよび出力ストリームを含むストリーム式を含み、前記ストリーム式により、データ値が前記入力ストリームから消費され、データ値が前記ストリーム式の前記出力ストリームにおいて作られる、請求項1に記載の装置。前記ストリーム式は、関数に対応する関数コールを含み、前記ストリーム式により、前記入力ストリームから取得された前記データ値を用いて関数がコールされ、前記関数コールにより返される結果は、前記関数コールと関連付けられた前記出力ストリームに代入される、請求項2に記載の装置。前記ストリームドメインコードは代入文を含み、前記代入文により、前記ストリーム式の前記出力ストリームは2つ前に宣言されたストリームのソースとなる、請求項2に記載の装置。前記ストリーム式は複数のストリーム式のうちの1つであり、前記複数のストリーム式のそれぞれは、対応する別個のプロセシングコア上で実行される、請求項2に記載の装置。前記ストリームドメインコードは、入力ストリームおよび出力ストリームを有するモジュールを含み、前記モジュールは前記入力ストリームからデータ値を消費し、前記出力ストリームにおいてデータ値を作る、請求項1に記載の装置。前記モジュールは複数のモジュールのうちの1つであり、各モジュールは、前記複数のプロセシングコアのうちの別個の1つ上で実行される、請求項6に記載の装置。前記モジュールはその本体内に第2のモジュールを含む、請求項6に記載の装置。前記モジュールは逐次的に実行されるスレッドドメインコードを含む、請求項6に記載の装置。前記出力ストリームは、前記モジュールに含まれる複数の出力ストリームのうちの1つである、請求項6に記載の装置。前記モジュールは、前記ストリームドメインコートに含まれるモジュール配列に編成された複数のモジュールのうちの1つのモジュールであり、前記モジュール配列は各モジュールへのアクセスを可能にする複数のインデックスを有する、請求項6に記載の装置。前記ストリームドメインコードは、複数の配列インデックスと関連付けられたストリームの配列を含み、前記ストリームの配列内の各ストリームは、ストリームソースの配列からストリームデスティネーションの配列へとデータ値を伝え、各ストリームは配列インデックスを介してアクセス可能である、請求項11に記載の装置。前記ストリーム配列内の前記ストリームのそれぞれは、前記モジュール配列の前記入力ストリームまたは前記モジュール配列の前記出力ストリームに結合された、請求項12に記載の装置。ストリームソースからストリームデスティネーションへとデータ値を伝えるマルチコアランタイムシステムをさらに含む、請求項1に記載の装置。前記ランタイムシステムは、プロセシングコア、ハードウェア、または再設定可能なハードウェアにより実行され得る、非一時的媒体上に記憶された1つまたは複数の命令で実装される、請求項14に記載の装置。前記マルチコアランタイムシステムは先入れ先出しキューを前記ストリームデスティネーションにおいて有する、請求項14に記載の装置。前記マルチコアランタイムシステムは前記先入れ先出しキューのオーバーフローを防ぐ、請求項16に記載の装置。各プロセシングコアに、実行されるべきゼロ個かまたはそれ以上のタスクを割り当てるランタイムシステムであって、各タスクは、ストリーム式または前記コンピュータプログラムに現れるスレッドドメインコードのインスタンスを実装する、ランタイムシステムと、前記プロセシングコアに割り当てられた前記タスクの実行を管理するタスクマネージャと、をさらに含む、請求項16に記載の装置。前記タスクマネージャは、各タスクの各入力ストリームに対する消費側カウントと、各タスクの各出力ストリームに対する作成側カウントと、実行される準備が整ったタスクの実行準備完了キューと、タスクが実行可能となるために有効化されることが要求されるタスク入力ストリームの個数を判定する各タスクに対する入力カウントと、タスクが実行可能となるために有効化されることが要求されるタスク出力ストリームの個数を判定する各タスクに対する出力カウントとを保持し、前記タスクマネージャは、ストリームソースにおける前記タスクから送信されたフォワードアクノレッジメントに応答して、入力ストリームの前記消費側カウントをインクリメントし、前記アクノレッジメントは、追加的なデータ値が、前記入力ストリームに関連付けられた前記先入れ先出しキューにすでに格納されていることを示すことと、ストリームデスティネーションにおける前記タスクから送信されたバックワードアクノレッジメントに応答して出力ストリームの前記作成側カウントをデクリメントし、前記アクノレッジメントは、データ値が、前記ストリームデスティネーションにおける前記入力ストリームに関連付けられた前記先入れ先出しキューからすでに除去されていることを示すことと、作成側カウントおよび消費側カウントの有効化を監視することと、有効化された消費側カウントの個数が前記タスク入力カウントに到達し、且つ有効化された作成側カウントの個数が前記タスク出力カウントに到達したとき、タスクを前記実行準備完了タスクキューに置くことと、タスクが前記実行準備完了タスクキューの先頭にあり、且つ前記プロセッサコアが利用可能であるとき、前記タスクを実行することと、ストリームアクセス命令によりブロックされたかまたはタイムアウトした前記タスクが実行を完了した場合に前記タスクの実行を停止することと、をさらに実行する、請求項18に記載の装置。前記タスクマネージャは、プロセシングコア、ハードウェア、または再設定可能なハードウェアにより実行され得る、非一時的媒体上に記憶された1つまたは複数の命令で実装される、請求項18に記載の装置。複数のプロセシングコアを含むコンピュータシステムをプログラムするための方法であって、前記複数のプロセシングコア上で実行されるコンピュータプログラムを提供し、前記コンピュータプログラムは、前記プロセシングコアのうちの1つに対応する少なくとも1つのストリームソースから、前記プロセシングコアのうちの他の1つに対応する少なくとも1つのストリームデスティネーションへと、データ値を伝えるストリームを含むストリームドメインコードを含むこと、を含む方法。前記ストリームドメインコードは、入力ストリームおよび出力ストリームを含むストリーム式を含み、前記ストリーム式により、データ値が前記入力ストリームから消費され、データ値が前記ストリーム式の前記出力ストリームにおいて作られる、請求項21に記載の方法。前記ストリーム式は、関数に対応する関数コールを含み、前記ストリーム式により、前記入力ストリームから取得された前記データ値を有する関数がコールされ、前記関数コールにより返される結果は、前記関数コールと関連付けられた前記出力ストリームに代入される、請求項22に記載の方法。前記ストリームドメインコードは代入文を含み、前記代入文により、前記ストリーム式の前記出力ストリームは2つ前に宣言されたストリームのソースとなる、請求項22に記載の方法。前記ストリーム式は複数のストリーム式のうちの1つであり、前記複数のストリーム式のそれぞれは、対応する別個のプロセシングコア上で実行される、請求項22に記載の方法。前記ストリームドメインコードは、入力ストリームおよび出力ストリームを有するモジュールを含み、前記モジュールは前記入力ストリームからデータ値を消費し、前記出力ストリームにおいてデータ値を作る、請求項21に記載の方法。前記モジュールは複数のモジュールのうちの1つであり、各モジュールは、前記複数のプロセシングコアのうちの別個の1つ上で実行される、請求項26に記載の方法。前記モジュールはその本体内に第2のモジュールを含む、請求項26に記載の方法。前記モジュールは逐次的に実行されるスレッドドメインコードを含む、請求項26に記載の方法。前記出力ストリームは、前記モジュールに含まれる複数の出力ストリームのうちの1つである、請求項26に記載の方法。前記モジュールは、前記ストリームドメインコートに含まれるモジュール配列に編成された複数のモジュールのうちの1つのモジュールであり、前記モジュール配列は各モジュールへのアクセスを可能にする複数のインデックスを有する、請求項26に記載の方法。前記ストリームドメインコードは、複数の配列インデックスと関連付けられたストリームの配列を含み、前記ストリームの配列内の各ストリームは、ストリームソースの配列からストリームデスティネーションの配列へとデータ値を伝え、各ストリームは配列インデックスを介してアクセス可能である、請求項31に記載の方法。前記ストリーム配列内の前記ストリームのそれぞれは、前記モジュール配列の前記入力ストリームまたは前記モジュール配列の前記出力ストリームに結合された、請求項32に記載の方法。ストリームソースからストリームデスティネーションへとデータ値を伝えるマルチコアランタイムシステムを介して、コンピュータプログラムの実行を管理することをさらに含む、請求項21に記載の方法。前記ランタイムシステムは、プロセシングコア、ハードウェア、または再設定可能なハードウェアにより実行され得る、非一時的媒体上に記憶された1つまたは複数の命令で実装される、請求項34に記載の方法。前記マルチコアランタイムシステムは先入れ先出しキューを前記ストリームデスティネーションにおいて有する、請求項34に記載の方法。前記マルチコアランタイムシステムは前記先入れ先出しキューのオーバーフローを防ぐ、請求項36に記載の方法。実行されるべきゼロ個かまたはそれ以上のタスクを各プロセシングコアに割り当て、各タスクは、ストリーム式または前記コンピュータプログラムに現れるスレッドドメインコードのインスタンスを実装することと、タスクマネージャにより前記プロセシングコアに割り当てられた前記タスクの実行を管理することと、をさらに含む、請求項36に記載の方法。前記タスクマネージャは、各タスクの各入力ストリームに対する消費側カウントと、各タスクの各出力ストリームに対する作成側カウントと、実行される準備が整ったタスクの実行準備完了キューと、タスクが実行可能となるために有効化されることが要求されるタスク入力ストリームの個数を判定する各タスクに対する入力カウントと、タスクが実行可能となるために有効化されることが要求されるタスク出力ストリームの個数を判定する各タスクに対する出力カウントとを保持し、前記タスクマネージャは、さらに、ストリームソースにおける前記タスクから送信されたフォワードアクノレッジメントに応答して、入力ストリームの前記消費側カウントをインクリメントし、前記アクノレッジメントは、追加的なデータ値が、前記入力ストリームに関連付けられた前記先入れ先出しキューにすでに格納されていることを示すものであることと、ストリームデスティネーションにおける前記タスクから送信されたバックワードアクノレッジメントに応答して出力ストリームの前記作成側カウントをデクリメントし、前記アクノレッジメントは、データ値が、前記ストリームデスティネーションにおける前記入力ストリームに関連付けられた前記先入れ先出しキューからすでに除去されていることを示すものであることと、作成側カウントおよび消費側カウントの有効化を監視することと、有効化された消費側カウントの個数が前記タスク入力カウントに到達し、且つ有効化された作成側カウントの個数が前記タスク出力カウントに到達したとき、タスクを前記実行準備完了タスクキューに置くことと、タスクが前記実行準備完了タスクキューの先頭にあり、且つ前記プロセッサコアが利用可能であるとき、前記タスクを実行することと、ストリームアクセス命令によりブロックされたかまたはタイムアウトした前記タスクが実行を完了した場合に前記タスクの実行を停止することと、をさらに行う、請求項38に記載の方法。前記タスクマネージャは、プロセシングコア、ハードウェア、または再設定可能なハードウェアにより実行され得る、非一時的媒体上に記憶された1つまたは複数の命令で実装される、請求項38に記載の方法。前記先入れ先出しキューは前記コンピュータプログラムに指定された初期値により初期化される、請求項36に記載の方法。前記ストリームドメインコードは、識別子がストリームを指すことを示すキーワードを含む、請求項21に記載の方法。前記ストリームドメインコードは、第1クラスの地位に高められたストリームを含み、それにより、前記ストリームは、識別子、関数の入力パラメータ、関数の出力パラメータ、式中のパラメータ、または、式の出力となるよう拘束される、請求項21に記載の方法。前記関数および式は異なるプロセシングコア上で実行される、請求項43に記載の方法。前記ストリームは、複数のストリームソースから少なくとも1つのストリームデスティネーションへとデータ値を伝え、前記複数のストリームソースにより前記ストリームに代入された前記データ値は、各デスティネーションに到達する前に交互配置される、請求項21に記載の方法。前記ストリームドメインコードは擬似的定数ストリームを参照し、前記擬似的定数ストリームは、ストリームソースから、前記擬似的定数ストリームに関連付けられた型の少なくとも1つのデータ値を記憶するストリームデスティネーションへとデータ値を伝えるものであり、前記ストリームデスティネーションにおけるタスクは、ストリームソースに挿入された新規データ値が前記ストリームデスティネーションへ伝えられるまで、前記少なくとも1つのデータ値を記憶する前記ストリームデスティネーションを使用および再使用する、請求項21に記載の方法。1つの例によれば、プログラム可能なコアに基づく演算デバイスが開示される。係る演算デバイスは、相互に接続された複数のプロセシングコアを備える。メモリは、ストリームデスティネーションモジュールおよびストリームソースモジュールを定義するストリームを含むストリームドメインコードを記憶する。ストリームソースモジュールはデータ値をストリームに代入し、ストリームは、ストリームソースモジュールからストリームデスティネーションモジュールへとデータ値を伝える。ランタイムシステムは、いつデータ値がストリームデスティネーションモジュールに対して利用可能となるかを検出し、複数のプロセシングコアのうちの1つ上で実行されるようストリームデスティネーションモジュールをスケジュールする。本発明の追加的な態様は、図面を参照してなされる様々な実施形態の詳細な説明を鑑みると、当業者に明らかとなるであろう。なお、図面の簡単な説明は以下で提供される。適応的演算エンジンおよび適応的演算機械図1は、1つの演算モデル例を使用するマルチプロセッサシステムの1例を示すブロック図である。本明細書において適応的演算エンジンACE100と称される装置100は、好適には、集積回路として、または他の追加的な構成品を有する集積回路の1部分として具体化される。模範的な実施形態において、および、以下でより詳細に論じられるように、ACE100は、図示したマトリックス150A~マトリックス150N等の1つまたは複数の再設定可能なマトリックスまたはノード150と、マトリックス相互接続ネットワーク110とを備える。模範的な実施形態において、および以下でより詳細に論じられるように、マトリックス150Aおよびマトリックス150B等の1つまたは複数のマトリックス150は、コントローラ120として機能するよう構成され、一方、マトリックス150Cおよびマトリックス150D等の他のマトリックスは、メモリ140として機能するよう構成される。様々なマトリックス150およびマトリックス相互接続ネットワーク110は、フラクタルサブユニットとして、ともに実装され得、このフラクタルサブユニットは数個から1000個のノードの規模となり得る。好適な実施形態において、ACE100は、再設定可能マトリックス150、コントローラ120、およびメモリ140間における信号発信および他の伝送のために、または他の入力/出力I/O機能のために、従来の典型的な別個のデータ、DMA、ランダムアクセス、構成、および命令バスを利用しない。むしろ、データ、制御、および設定の情報は、マトリックス相互接続ネットワーク110を利用して、これらのマトリックス150間で伝送される。なお、このマトリックス相互接続ネットワーク110は、コントローラ120およびメモリ140として設定されたこれらのマトリックス150を含む再設定可能なマトリックス150間における任意の所与の接続を提供するよう、リアルタイムで設定および再設定が可能である。メモリ140として機能するよう設定されたマトリックス150は、固定メモリ要素の演算要素以下で説明するを利用して任意の所望の方法または模範的な方法で実装されてもよく、ACE100内に含まれるか、もしくは他のIC内あるいはICの1部分の内部に組み込まれてもよい。模範的な実施形態において、メモリ140はACE100の内部に含まれ、好適には、低電力消費型ランダムアクセスメモリRAM:randomaccessmemoryである演算要素から構成され得るが、フラッシュ、DRAM、SRAM、MRAM、ROM、EPROM、またはE2PROM等の他の任意の形態のメモリの演算要素から構成されてもよい。模範的な実施形態において、メモリ140は好適には、特には図示しないダイレクトメモリアクセスDMA:directmemoryaccessエンジンを含む。コントローラ120は、好適には、適応的有限状態機械FSM:finitestatemachine、縮小命令セットRISC:reducedinstructionsetプロセッサ、以下に説明する2種類の機能を実行する能力を有するコントローラまたは他の装置もしくはICとして設定されたマトリックス150Aおよびマトリックス150Bを用いて実装される。代替的には、これらの機能は従来のRSCまたは他のプロセッサを利用して実装され得る。カーネル制御と称される第1制御機能は、マトリックス150AのカーネルコントローラKARCとして図示され、マトリックス制御と称される第2制御機能は、マトリックス150BのマトリックスコントローラMARCとして図示される。コントローラ120のカーネルおよびマトリックスの制御機能は、様々なマトリックス150の設定可能性および再設定可能性を参照して、および本明細書においてシルバーウェアモジュールと称される結合されたデータ、設定、および制御情報の模範的な形態を参照して、以下で詳細に説明される。図1のマトリックス相互接続ネットワーク110は、サブセットの相互接続ネットワーク図示せずを備える。これらの相互接続ネットワークは、ブール相互接続ネットワーク、データ相互接続ネットワーク、および本明細書において集合的および一般的に相互連結interconnect、相互接続interconnection単数または複数、相互接続ネットワークinterconnectionnetwork単数または複数、またはネットワークと称される他のネットワークまたは相互接続方式を含み、当該技術分野において一般に知られるように、FPGA相互接続ネットワークまたはスイッチングファブリックを利用する等のさらに多様な様式で実装され得る。模範的な実施形態において、様々な相互接続ネットワークは、例えば米国特許第5,218,240号、米国特許第5,336,950号、米国特許第5,245,227号、および米国特許第5,144,166号において説明されるように実装される。これらの様々な相互接続ネットワークは、コントローラ120、メモリ140、様々なマトリックス150、演算ユニットまたはノード、および演算要素の間で選択可能スイッチング可能な接続を提供し、それにより、本明細書で一般に設定情報と称される設定信号に応答して、またはその制御下で、本明細書で説明される設定および再設定を行うための物理的基盤が提供される。加えて、様々な相互接続ネットワーク110、210、240、および220は、任意形態の従来のまたは個別の入力/出力バス、データバス、DMA、RAM、設定および命令バスに代わって、コントローラ120、メモリ140、様々なマトリックス150、および、演算ユニット、構成品、および要素間における、選択可能なまたはスイッチング可能な、データ、入力、出力、制御、および設定経路を提供する。しかし、様々な相互接続ネットワークの、または様々な相互接続ネットワーク内における、スイッチングまたは選択の操作は当該技術分野において周知の方法で実装され得るが、本発明に係る相互接続ネットワークの設計およびレイアウトが以下に詳細に説明するように新しく新規であることは指摘されるべきである。例えば、様々なレベルの相互接続が、様々なレベルのマトリックス、演算ユニット、および要素に対応して提供される。マトリックス150のレベルにおいては、従来技術のFPGA相互接続と比較すると、所与のエリアにおける接続能力がより低いマトリックス相互接続ネットワーク110は、より制限され且つ豊富さがより低く、そのために、キャパシタンスが低減され、動作スピードが増加する。しかし、特定のマトリックスまたは演算ユニット内においては、相互接続ネットワークは、顕著に濃度が高く豊富であるため、狭いまたは近接した参照の局所性においては、より高い適応および再設定の能力を有し得る。様々なマトリックスまたはノード150は、再設定可能および異種である。すなわち、一般に、所望の設定に応じて、再設定可能なマトリックス150Aは、一般に、再設定可能なマトリックス150Bからマトリックス150Nとは異なり、再設定可能なマトリックス150Bは、一般に、再設定可能なマトリックス150Aおよびマトリックス150Cからマトリックス150Nとは異なり、再設定可能なマトリックス150Cは、一般に、再設定可能なマトリックス150A、マトリックス150B、マトリックス150Dからマトリックス150Nとは異なり、以下同様に異なる。様々な再設定可能なマトリックス150はそれぞれ、一般に、異なる、または多様な混合の、適応的且つ再設定可能なノードまたは演算ユニットを含み、次いでノードは、一般に、異なった、または多様な混合の、様々な方法で適応的に接続、設定、および再設定され得ることにより、様々な相互接続ネットワークを通して様々な機能を実行する、固定の、特定用途向けの演算構成品および要素を含む。多様な内部設定および再設定に加えて、様々なマトリックス150は、マトリックス相互接続ネットワーク110を通して他のマトリックス150のそれぞれに対して、高レベルで接続、設定、および再設定され得る。ACEアーキテクチャの詳細は、上記で参照した関連する特許出願において見出され得る。並列演算モデルを使用し得る適応的演算機械160の他の例が図2に示される。この例における適応的演算機械160は、ネットワーク162を介してともに接続された32個の異種リーフノード180を有する。ネットワーク162は、1群のネットワーク入力ポート164、1群のネットワーク出力ポート168、省略可能なシステムインターフェースポート170、外部メモリインターフェース172、および内部メモリインターフェース174に接続された単一のルート164を有する。スーパーバイザーノードまたはKノード178もルート164に接続される。ノード180は、それぞれが、4進木182等の4進木にグループ化される。4進木182等の4進木は、それぞれが単一の親ノードおよび最大4個の子ノード180に接続された、5ポートのスイッチ要素184を用いて実装される。このスイッチ要素は、公正なラウンドロビン調停方式を実装し、性能増強のためにマルチレベルの先読みを有するパイプラインを提供する。この例において、全経路の幅は一定51ビットであるが、ネットワークのバンド幅を増強するために、Leisersonのファットツリーのスタイルで、木が上昇するにつれて経路を広げるためのオプションが利用可能である。この例において、ネットワーク162上のすべてのトラフィックは、図3のネットワークワード188に示すように、51ビットネットワークワードの形態である。ネットワークワード188は、ルートフィールド190、セキュリティビット192、サービスフィールド194、補助フィールド196、およびペイロードフィールド198を有する。ルートフィールド190は、ネットワークワード188の宛先アドレスである。ルートフィールド190における上位2ビットはチップIDである。セキュリティビット192は、設定メモリに対するピーク読み出しおよびポーク書き込みを可能にする。セキュリティビット192は、Kノード178により送信されるワードに対してのみ設定される。サービスフィールド194はサービス種類を定義し、補助フィールド196はサービス種類に依存する。サービスフィールド194はポイントトゥポイントPTPを含む16のサービス種類のうちの1つを定義する。なお、このPTPは、データおよびPTPアクノレッジメントを流すことに関し、PTPアクノレッジメントは、データに対するフロー制御をサポートし、宛先ノードにおける消費側カウントまたは製作側カウントをインクリメントまたはデクリメントさせるものである。ノードラッパー図4は、図1のACEアーキテクチャまたは図2のACMアーキテクチャにおける異質ノードと同種ネットワークとの間のインターフェースを示す。このインターフェースは、各ノードに対して共通の入力および出力の機構を提供するために用いられるため、ノードラッパーと称される。ノードの実行ユニットおよびメモリは、ノードラッパーを介して、ネットワークおよび制御ソフトウェアに対して接続され、それにより、均一で一貫したシステムレベルのプログラミングモデルが提供される。この例において、ノード180はメモリ210および実行ユニット212を備える。ノードラッパーの詳細は、上記で参照した関連する特許出願に見出され得る。好適な実施形態において、各ノードラッパーは、ハードウェアタスクマネージャHTM:hardwaretaskmanager200を備える。ノードラッパーは、データディストリビュータ202、省略可能なダイレクトメモリアクセスDMAエンジン204、およびデータアグリゲータ206も備える。HTMは、ノードプロセッサおよびリソースの実行または使用をそれぞれ調整する。HTMは、タスクリストを処理し、実行準備完了キューを作成することにより、これを行う。HTMは、図2のKノード178と称される専用ノードまたは制御ノード図示せずにより設定および管理される。しかし他のHTM制御手法も使用され得る。図4におけるノードラッパーは、ノード180を、その内部構造または機能に関わらず、図2における適応的演算機械160のすべての他のノードまたは図1における適応的演算エンジン100と、外観において同等にする。ノードラッパーはまた、タスク管理およびネットワーク相互作用に関連する無数の活動を処理しなければならない状況から実行ユニット212を解放する。とりわけ、ノードラッパーは、図2のネットワークワード188等の受信するネットワークワードのそれぞれを1つのクロックサイクル内で適正な方法で処理する機能を担当する。図4における実行ユニット212は、タスク実行機能を担当するタスクはモジュールインスタンスと同等である。実行ユニット212はデジタルシグナルプロセッサDSP:digitalsignalprocessor、縮小命令セットRISCプロセッサ、ドメイン固有プロセッサ、特定用途集積回路ASIC:application-specificintegratedcircuit、または再設定可能FPGAファブリックを含み得る。その形態に関わらず、実行ユニット212は、標準的インターフェースを通してノードラッパーと相互作用する。ノードメモリ210は、ノードラッパーおよび実行ユニット212の両方に対してアクセス可能である。ノードメモリ210は、受信するストリーミングデータをノードラッパーが格納し且つそのデータを実行ユニット212がアクセスする位置にある。ノード自体のメモリ210は、典型的には、実行ユニット212が出力データを送信する位置にはない。メモリアクセスを最小限とするために、出力データは、通常は、そのデータを要求しているノード、すなわち消費側ノード単数または複数に直接的に送信される。ノードメモリ210は、タスクパラメータを記憶するためにも用いられ、一時的作業用記憶領域として、タスクに対して利用可能である。ノード180がストリーミングデータの消費側であると同時に作成側である図2のACM160等のマルチノードシステムにおいては、作成速度と消費速度とが一致することが望ましい。1つのノード上の作成側タスクは、他のノード上の消費側タスクが対処可能であるよりも、より高いかまたはより低い速度で、データを作成し得る。作成側が、消費側が処理可能な速度よりも高い速度でデータを送信するならば、データはやがて失われる。作成側が、消費側が対処可能な速度よりも低い速度でデータを送信するならば、消費側はデータに対して飢餓状態となり、その結果、消費側は無駄に座して追加的なデータを待つことを余儀なくされ得る。ACM160は、ポイントトゥポイントプロトコルおよび図4のノードラッパーを介して、タスク管理、フロー制御、および負荷分散のための均一且つ一貫した機構を提供する。タスク管理により、タスクが十分な入力データを有し且つタスクにより生成されたデータを消費側ノード単数または複数において収容する十分なスペースが存在する場合にのみタスクが実行状態となることが確実なものとなる。フロー制御により、作成側タスクが、短すぎる時間内に多すぎるデータにより消費側タスクを圧倒しないことが保証される。負荷分散は、作成側タスクがデータをいくつかの代替的な消費側ノード間に分散することを可能にし、その結果、作成側タスクはより高い速度で動作することが可能となる。ストリーミングデータは、図5に示すポイントトゥポイントチャンネルポイントトゥポイントストリーム250を介して、ノード180ポイント間で転送される。ポイントトゥポイントチャンネル等の各PTPチャンネルは、作成側ノード252、作成側タスク254、出力ポート256、消費側ノード258、入力ポート260、入力バッファ262、および消費側タスク264を含む。作成側タスク254は、作成側ノード252の実行ユニット上で実行され、タスク活性化毎に有限サイズブロックのPTPデータを製作する。データのブロックは、一連のPTPワードとしてPTPチャンネル250上で送信される。ブロックの送信は、図5においてタスクとして示される。作成側ノード252上の出力ポート256は、作成側タスク254と関連付けられる。消費側タスク264は、消費側ノード258上の入力ポートを介して、PTPチャンネル252からPTPデータを受信する。消費側ノード258のノードメモリ内の循環型入力バッファ262は、受信するPTPデータを記憶する。消費側タスク264等の消費側タスクは、タスクの活性化図5のタスク2毎に、消費側ノード258の実行ユニット上で実行され、循環型入力バッファ262に存在する有限量のPTPデータを消費する。データは、作成側タスク254が、図6に示す50ビットポイントトゥポイントワード270を作成側ノード252のノードラッパーへと伝送すると、PTPチャンネル252上で伝えられる。ポイントトゥポイントワード270は、図3のネットワークワード188と同一のフィールドを有し、同じ要素/フィールドには図5の要素番号と同じ要素番号が付される。ポイントトゥポイントワード270は、ルートフィールド190においてノードワード272、補助フィールド196においてポートワード274、およびペイロードフィールド198においてデータワード276を含む。この例において、第51番目のビット、すなわちセキュリティビット192は、図2のネットワーク162により後に追加される。図4のノードラッパー等のノードラッパーは、次いで、PTPワードを、図5における消費側ノード258に伝送するために、パケット交換ネットワークに渡す。PTPワード270の8ビットルートフィールド190は、図5におけるノード258等の消費側ノードのノードワード272の形でアドレスを提供する。ポートワード274は、消費側ノードの入力ポートのうちのどの入力ポートにデータが宛てられているかを指示する、補助フィールド196の下位5ビットを含む。PTPワードが消費側ノードに到達すると、ノードラッパーは、ペイロードフィールド198における32ビットのデータワード176を、指示された入力ポートに関連付けられた循環型入力バッファに格納する。このようにして伝送が完了する。ACM160は、タスク管理、フロー制御、および負荷分散のための機構を備える。各入力ポートと関連付けられた入力バッファが存在する。入力および出力の両方のポートと関連付けられた、2の補数の符号付きカウントも存在する。入力ポートに関しては、カウントは消費側カウントと称される。なぜなら、このカウントは、関連するタスクにより消費されるために利用可能である、そのポートの入力バッファにおけるデータ量を反映するからである。消費側カウントは、その値が非負である場合、すなわちその符号ビットが0である場合、有効化される。有効化された消費側カウントは、関連する入力バッファが、関連するタスクの活性化により要求される最小量のデータを有することを示す。システム初期化時または再設定時に、消費側カウントは、典型的には-Cにリセットされる。なお、Cはタスク活性化毎に要求される32ビットワードの最少個数である。出力ポートに関しては、カウントは作成側カウントと称される。なぜなら、このカウントは、関連するタスクにより作成されたデータを受け入れるために、下流側入力バッファにおいて利用可能なスペースの量を反映するためである。作成側カウントは、その値が負である場合、すなわちその符号ビットが1である場合、有効化される。有効化された作成側カウントは、下流側関連入力バッファが、関連するタスクの活性化毎に作成されるデータの最大量を収容するために利用可能なスペースを有することを示す。システム初期化時または再設定時に、作成側カウントは、典型的にはP-S-1にリセットされる。なお、Pはタスク活性化毎に作成される32ビットワードの最大個数、Sは32ビットワードにおける下流側入力バッファのサイズである。消費側カウントおよび作成側カウントの両方は、典型的には負の値に初期化され、それにより、消費側カウントは開始時において無効状態にあり、一方、作成側カウントは開始時において有効状態にある。この初期状態は、入力バッファが通常はシステム初期化/再設定時において空き状態であるという事実を反映するものである。消費側カウントおよび作成側カウントは、フォワードアクノレッジメントおよびバックワードアクノレッジメントの形の借方のシステムにより更新される。両種のアクノレッジメントは、図7に示すアクノレッジメントネットワークワード280等のネットワークワードである。アクノレッジメントネットワークワード280は、図3のネットワークワード188と同一のフィールドを有し、同じ要素/フィールドは同一の要素番号が付される。アクノレッジメントネットワーク280ワードは、タスク活性化の最終ステップとしてタスクにより送信される。両方の場合において、ペイロードフィールド198は、4個のサブフィールド、すなわち、アクノレッジメント種類サブフィールド2821ビット、ポートサブフィールド284、3タスクサブフィールド286、およびAck値サブフィールド288、を有する。タスクが各活性化の終了時にタスクが実行する一連のアクノレッジメントが、以下に説明される。タスクの各出力ポートに対して、消費側入力ポートおよび消費側タスクを指定するフォワードアクノレッジメントが消費側ノードに送信される。Ack値は、タスクが消費側入力ポートに送信したPTPワードの個数である。出力ポートおよびタスクを指定するバックワードアクノレッジメント自己ackは、タスクが存在するノードに送信される。Ack値は、タスクが出力ポートを介して送信したPTPワードの個数である。タスクの各入力ポートに対して、作成側出力ポートおよび作成側タスクを指定するバックワードアクノレッジメントは、作成側ノードに送信される。Ack値は、タスクが、入力ポートのバッファから消費した32ビットワードの個数にマイナス符号を付した値である。入力ポートおよびタスクを示すフォワードアクノレッジメント自己ackは、タスクが存在するノードに送信される。Ack値は、タスクが入力ポートのバッファから消費した32ビットワードの個数にマイナス符号を付した値である。ハードウェアタスクマネージャ図4に示すハードウェアタスクマネージャ200は、受信するアクノレッジメントに応答して消費側カウントおよび作成側カウントを更新する機能を担当するノードラッパーの1部分である。ハードウェアタスクマネージャ200はまた、これらのカウントの符号ビットを監視し、カウントの適切な組が有効化されるとタスクを起動する。この最後の任務は、ポートではなくタスクと関連付けられた2つの符号付きカウント、すなわちタスク入力カウントおよびタスク出力カウントを用いて満足される。タスクの入力出力カウントは、有効化されたタスク消費側作成側カウントの個数を反映する。タスクカウントはその値が非負である場合、有効化される。タスクは、その入力カウントおよび出力カウントの両方が有効化されると、有効化され、実行のために利用可能となる。受信するアクノレッジメントは、様々なカウントを更新し、それによりタスクは以下のように起動される。フォワードアクノレッジメントが受信されると、指定されたポートが入力ポートとして解釈され、Ack値が、対応する消費側カウントに加えられる。消費側カウントが、無効状態から有効状態へと有効状態から無効状態へと遷移すると、指定されたタスクの入力カウントは、1だけインクリメントデクリメントされる。バックワードアクノレッジメントが受信されると、指定されたポートが出力ポートとして解釈され、Ack値が、対応する作成側カウントに加えられる。作成側カウントが、無効状態から有効状態へと有効状態から無効状態へと遷移すると、指定されたタスクの出力カウントは、1だけインクリメントデクリメントされる。バックワードアクノレッジメントまたはフォワードアクノレッジメントが受信され、指定されたタスクの入力カウントおよび出力カウントの両方が有効化されると、そのタスクは、もし実行準備完了キュー上にない場合は、実行準備完了キュー上に置かれる。タスクは、キューの先頭に到達すると起動される。これらの動作は、タスクに対する始動規則を具体化する。これらにより、タスクは実行準備完了キューに置かれることとなり、最終的に十分な個数の消費側カウントおよび十分な個数の作成側カウントが有効化されると、タスクは実行される。これらの十分な個数の具体的数値は、タスクの入力カウントおよび出力カウントの初期値により決定される。IOが、タスクに関連付けられた入力出力ポートの個数であり、ICInitialOCInitialがタスクの入力出力カウントの初期値であり、且つ、上述のように全部の消費側カウントが最初無効状態にあり全部の作成側カウントが最初有効状態にあると仮定すると、タスクは、I個の消費側カウントうちの-ICInitiail個が有効状態にあり、O個の作成側カウントうちO-OCInitial個が有効状態にある場合、始動する。例えば、I=4に対して、ICInitial=-1であるならば、4個の消費側カウントのうち1個が有効化されなければならない。ICInitial=-2であるならば、4個の消費側カウントのうち2個が有効化されなければならない。ICInitial=-3であるならば、4個の消費側カウントのうち3個が有効化されなければならない。ICInitial=-4であるならば、4個の消費側カウントのうち4個が有効化されなければならない。O=4に対して、OCInitial=3であるならば、4個の作成側カウントのうち1個が有効化されなければならない。OCInitial=2であるならば、4個の作成側カウントのうち2個が有効化されなければならない。OCInitial=1であるならば、4個の作成側カウントのうち3個が有効化されなければならない。OCInitial=0であるならば、4個の作成側カウントのうち4個が有効化されなければならない。図1におけるACE100および図2におけるACM200等のマルチプロセッサシステムのプログラミングは、ストリームCプログラム言語と称され得るものを用いてなされ得る。ストリームCモジュールストリームCプログラムにおいては、並行処理を表現するための機構は1つのみ存在する。その機構とは、すなわち、プログラムのモジュールおよびモジュールのようなストリーム式の並行演算を用いることである。シンタックス的には、モジュールは、C関数と極めて類似するが、セマンティクス的には、モジュールと関数とは異なる。C関数サブルーチンは、コールされたときにのみ、動作を始める。コールされると、制御は、通常は入力引数とともに、C関数に渡される。次いで、C関数はタスク/演算を実行し、終了すると、出力結果とともに制御を返す。C関数とは異なり、モジュールはコールされることがなく、また制御は、モジュールに渡されることも、モジュールから返されることもない。代わって、モジュールは、他のモジュールおよび外部世界との進行中の相互作用を、入力ポートおよび出力ポートを通して実行する。これらのポートを通して、モジュールは入力値のストリームを受け取り、出力値のストリームを発行する。モジュールプロトタイプのシンタックスはC関数プロトタイプのシンタックスと、3つの例外を除いて、同じである。第1に、キーワードstreamがモジュールプロトタイプに先行する。このキーワードは、各モジュール入力およびモジュール出力が、個別の値とではなく、指定された型の値のストリームと関連付けられていることを、コンパイラ/リンカに伝える。第2に、モジュールが複数の主力ストリームを有することを可能にするために、モジュールの戻り値型は、シンタックスにおいて入力パラメータリストと同一である、括弧で囲まれたリストにより置き換えられ得る。第3に、配列の概念をモジュールへと拡張するために、角括弧で囲まれた配列インデックスのリストは、モジュール名の直後および入力引数リストの直前に挿入され得る。モジュール配列については以下で論じる。以下の式、streamintmoduleAint,int;streamint,intmoduleBint,int;は、モジュール宣言の2つの例である。パラメータ名はここでは省略される。なぜなら、パラメータ名はモジュール宣言においては不要であるモジュール定義またはモジュールインスタンス化とは対比的にためである。しかしパラメータ名はプログラマの自由裁量により通常は記憶の一助として、入力に対して、および複数の出力が存在する場合には、出力に対しても、含まれ得る。例えば、2つの宣言は、次のように表現され得る。streamintmoduleAinta,intb;streamintx,intymoduleBinta,intb;第1の宣言は、moduleAが2つの入力ストリームを有し、その両方が整数型であること、および単一の出力ストリームを有し、これもまた整数型であることを示す。第2の宣言は、moduleBが2つの入力ストリームを有し、その両方が整数型であること、および2つの出力ストリームを有し、これらもまた整数型であることを示す。C関数の定義と同様に、モジュールの定義は、波括弧{および}で囲まれた本体を有する。C関数の定義の場合と同様に、各モジュール入力および出力が複数ある場合は、各出力モジュールは識別子が割り当てられる。以下は、モジュール定義の2つの例である。streamintmoduleAinta,int,b{//モジュール本体}streamintx,intymoduleBinta,intb{//モジュール本体}モジュールインスタンス化は、C関数コールに対するモジュールにおける対応物である。関数コールと同様に、モジュールインスタンス化は、モジュールがどこで用いられるかである。これら2種類の表現のシンタックスは同様であるが、セマンティクスは異なる。Cコードの1部分は、以下のように表現され得る。intx,y;intFint,int;...intz=F4,x5y;第1の文がxおよびyが正数であることを宣言する一方で、第2の文はFが2つの整数パラメータと、1つの整数の結果とを有する関数であることを宣言する。最後の文が、関数コールF4,x5yを含む代入文であり、関数F4,x5yは、2つの引数、すなわちFの2つのパラメータに対応する、式4および式x5yを有する。この部分的コードのストリーム版は、以下のようになる。streamintx,y;streamintFint,int;...streamintz=F4,x5y;このストリーム版において、これらの文のそれぞれにおいては、streamというキーワードが先頭にある。シンタックスが変化しているために、セマンティクスにおいても劇的な変化が生じている。個別の値に代わって、値のストリームが用いられる。したがって、第1の文は、xおよびyが整数ストリームであることを宣言する一方、第2の文は、Fが、2つの整数ストリーム入力および整数ストリーム出力を有するモジュールであることを宣言する。最後の文は、モジュールインスタンス化F4,x5yを含む代入文である。このF4,x5yは、2つの引数、すなわちFの2つのパラメータに対応する、ストリーム式4およびストリーム式x5yを有する。関数コールの場合は、代入z=F4,x5yが実行される毎、式4および式4,x5yが評価され、その結果生じた2つの値がパラメータとしてコール時に関数Fへと供給される。一定時間経過後、Fが値を返す。モジュールインスタンス化の場合は、代入文z=F4,x5yが実行されることもなく、また関数Fがコールされることもない。代わって、システム初期化時、ストリームCプログラムが実行を始める直前に、関数Fのインスタンスが作成インスタンス化され、それにより、インスタンスは、その2つの入力ポート上で整数のストリームを受け取ること、およびその出力ポート上で整数のストリームを作成することの準備が完了する。プログラム実行が開始されると、Fのインスタンスは、プログラム終了時まで、動作状態が保持されるすなわちFのインスタンスは永続的である。この簡単な例は、ストリームCにおいて相互作用するモジュールの集団を作成するために用いられる一般的な機構を示すものである。各モジュールのインスタンス化により、別個のモジュールインスタンスがシステム初期化時に作成される。ひとたび作成インスタンス化されると、モジュールインスタンスは、その入力ポート上で値のストリームを受け取ること、およびその出力ポート上で値のストリームを作成することの準備が完了する。さらに、プログラム実行が開始されると、モジュールインスタンスは、プログラム終了時まで、動作状態を保持する。複数の出力ポートを有するモジュールのインスタンス化の一般的な形は以下の通りである。<識別子リスト><モジュール識別子><式リスト>入力引数が式であるのに対し、出力引数は識別子である。これらの識別子は、名称がない出力ストリームに名称を与えるよう機能する。上記のストリーム代入文は、名称zをF4,x5yの名称がない出力ストリームに割り当てることにより、同じ役割を果たす。例えば、streamintw,x,y,z;streamint,intFint,int;...w,z=F4,x5y;前述のように、Fは2つの整数ストリーム入力を有するが、前の例とは対比的に、このFは2つの整数ストリーム出力を有する。これら2つの出力ストリームは、識別子w,zのリストとしてFのインスタンス化時に現れる。なお、これは、2つの出力ストリームに名称wおよびzを与えるよう機能する。モジュール本体内部の文は、2つのカテゴリー、すなわち、ストリームのみに関与するストリーム文と、Cの文の全範囲を含む他に、スレッドをストリームから読み出すこととスレッドをストリームに書き込むこととを可能にする文を含むスレッド文と、に分類される。各モジュールのインスタンス化により、別個のモジュールインスタンスがシステム初期化時に作成されるため、ストリームCにおいては、モジュールが、その本体内において、またはサブモジュールの本体内において、モジュール自体のインスタンス化を有することはできない。換言すると、モジュール参照の循環性は不可能である。この禁止は、無限個のモジュールインスタンスのインスタンス化という困難なタスクを回避することを支援する。ストリームCモジュールにおいて、制御を返すという概念は存在せず、したがってリターン文は適さない。モジュールにおいて、出力値はモジュールの出力ストリームに単に挿入される。しかし、それを行うためには、出力ストリームは名称を有さなければならない。括弧で囲まれた名称を有する出力ストリームのリストを有するモジュールに対しては、それは問題ではない。しかし、モジュールプロトタイプがモジュールの出力ストリームの型のみを提供する場合は、問題となる。その場合、モジュールの本体内のコードは、ストリームドメインにおいてもまたはスレッドドメインにおいても、キーワードoutをデフォルトモジュール出力ストリームの名称として用いることができる。この用法は、以下の部分的コードにおいて例示される。streamintmoduleAinta,intb{...out=ab;...関数がプログラムの演算ビルディングブロックを提供するのに対して、モジュール、およびモジュールと提携するストリームは、ストリームCプログラムに典型的な相互作用網および並行動作のための枠組を提供する。モジュールは値のストリームを処理するが、そのことにより、モジュールがストリーム内の個々の値にアクセスすることおよびこれらの値を関数に提供することが不可能となるわけではない。同様に、モジュールは、関数の出力値にアクセスすること、およびその値をストリームに挿入することも可能である。一方、関数はモジュールを参照することができない。なぜなら、関数内には係る相互作用のための機構が存在しないためである。能力におけるこの非対称性により、関数がプログラムヒエラルキー上でより低いレベルにある一方、モジュールはより高いレベルにあることがわかる。モジュールと関数との違いが実質的である一方で、モジュールと関数とが同様である1つの領域が存在する。それは、モジュールおよび関数の両方が副作用をサポートする点である。すなわち、モジュールおよび関数の両方が、それぞれの入力ポートおよび出力ポートとは独立的に、外部データ構造を操作し得る。これは、モジュールが副作用を有し得るスレッドを含み得る事実に由来する。図8Aは、モジュール300と、モジュール300に対してデータ/制御を提供するいくつかゼロ個からN個の入力ストリーム302と、次のモジュール/関数に対してデータ/制御を提供するいくつかゼロ個からN個の出力ストリーム304とを含む、一般的なモジュールを示す。出力ストリームを有さないモジュールはシンクであり、入力ストリームを有さないストリームはソースである。図8Bは、2つのモジュール、すなわちモジュールA300およびモジュールB310を示す図であり、各モジュールは、入力ストリーム302および312と、出力ストリーム304および314とを有する。モジュールA300の出力ストリーム304はモジュールB310の入力ストリーム312に接続される。モジュールA300は、CPUコア308上で実行されるようマッピングされ、モジュールB310は第2のCPUコア318上で実行されるようマッピングされる。コア308、318、および328は、図2のノード180と同様である。図8Cは、モジュールA300およびモジュールB310をCPUコア308等の同一のCPUコアにマッピングすることを示す図である。この事例において、モジュール300および310は、任意の他の別個の制御スレッドのように動作する。第2コア318上で実行されるオペレーティングシステムは、モジュール300および310を、プリエンプティブマルチタスキングに基づいてスケジューリングするか、または完了/解放まで実行し得る。両方のモジュール300および310および入力/出力ストリーム302、312、および304、314は、永続的であるすなわち、これらは処理実行準備完了状態に留まるため、演算を実行するための十分な入力ストリームデータの、および出力ストリームが演算されたデータを伝達することができる十分なスペースの、両方の利用可能性に基づいてモジュールをいつスケジュールするかに関する追加情報は、従来のオペレーティングシステムに提供されなければならない。多様な異なるアルゴリズムが、モジュールからコアへのマッピングを実行するために用いられ得る。これらのアルゴリズムは、キャッシュ近傍を含み得る。なお、キャッシュ近傍においては、最大個数のストリームを共有するモジュールは、共有されたDRAMに後続される共有されたL3キャッシュに後続される共有されたL2キャッシュに後続されるL1キャッシュを共有するコアに置かれる。これらのアルゴリズムは、物理近傍アルゴリズムも含み得る。なお、物理近傍アルゴリズムにおいては、最大個数のストリームを共有するモジュールは、互いに物理的に近接するコアに置かれる。例えば、アルゴリズムはダイから始まり、次いで、マザーボード上の集積回路へと、次いでラック上のマザーボードへと、次いで建物の同一階のラックへと、次いで地理的に近接する建物へと移行し得る。他のアルゴリズムは、次の利用可能なフリーであり得る。なお、そこにおいては、CPU使用率現在の使用率、または一定期間にわたる重み付き平均使用率または順番上次に利用可能なコアに基づく次の自由なコアに基づいて、モジュールがコアに割り当てられる。他のアルゴリズムは、予想負荷であり得る。なお、これは、評価された統計的サンプリングに基づいて、モジュールおよびコアを選択する。コア利用の実行平均が、モジュールを、最も負荷が軽いコアにロードするために用いられ得る。他のアルゴリズムは、ユーザによる指定である。なお、ここでは、ユーザ指定によるバーチャルコアIDが、全モジュールを物理コアID上に置くために用いられる。バーチャルコアIDの個数が物理的に利用可能なコアを越えると、複数のモジュールが、利用可能な物理コアにわたって均等にロードされる。図8Dは、モジュールA300に存在し、入力ストリーム302および出力ストリーム304において用いられ得る、様々なデータ構造330、332、および334を示す。メモリ/キャッシュまたはTLBのいずれかに存在し得るデータ構造330、332、および334は、シングルコアまたはマルチコアシステムが、入力ストリーム302等の入力ストリームから出力ストリーム304等の出力ストリームへとデータを搬送すること、入力ストリーム302をモジュールA300等のモジュールへと搬送すること、およびモジュールA300を出力ストリーム304へと入力することをスケジュールするために必要となる重要な情報を含む。各モジュールに対して、そのモジュールをユニークに識別し、そのモジュールに対するすべての入力ストリームをユニークに識別し、そのモジュールのすべての出力ストリームをユニークに識別し、入力ストリームおよび出力ストリームの接続方法をユニークに識別し、コアを識別し、モジュールが1つのコアから他のコアへとリロケートされるよう、すなわち仮想メモリを介してスワップアウトされるよう状態情報を保持する、情報が存在する。ストリームは動的にモジュールから追加または削除され得、モジュールは動的にコアから追加または削除され得る。ストリームストリームCプログラム言語におけるストリームという用語は、すべて同じデータ型であり且つ典型的に一定期間にわたって利用可能状態となる、一連のデータ値を指す。しかし、ストリームCにおいては、ストリームは、入力および出力のための枠組を遥かに越える機能を提供する。ストリームは、第1クラスのオブジェクト、すなわち変数の地位にほぼ匹敵する地位へと高められている。これは、ストリームが識別子と結合され得るすなわち、ストリームに名称が与えられ得ること、関数の入力パラメータすなわちモジュールの入力パラメータと結合され得ること、関数の出力すなわち、モジュールの入力パラメータと結合され得ること、式中のパラメータと結合され得ること、および式の出力と結合され得ることを意味する。ストリームは、単一のデータ型の値を、1つまたは複数のストリームソースから1つまたは複数のストリームデスティネーションへと伝える。この運搬がどのように遂行されるかについての正確な詳細は、実装に依存し、とりわけ、ストリームが単一の半導体ダイに限定されるかどうか、またはストリームが数メートルまたあるいは数千キロメートルにわたるかどうかに依存する。性能問題に対処する場合を除き、プログラマはこれらの詳細を考慮する必要はなく、4つのストリーム属性、すなわち、ストリーム型、ストリーム名、ストリームソース、およびストリームデスティネーションに関する、ストリームのこれらの側面のみを考慮すればよい。ストリーム型は、伝えられる値の型を示す。ポインタおよびtypedefにより定義されるデータ型を含む、Cの正当なデータ型であり得るストリーム型は、例えば、モジュール入力または出力パラメータとして現れることにより文脈により暗黙的に特定され得るか、または以下に説明するストリーム宣言を用いて明示的に特定され得る。ストリームソースは、値がストリームに置かれる位置である。可能なストリームソースは、モジュール定義の入力パラメータ、モジュールインスタンス化の出力、ストリーム式の出力、およびスレッド以下に説明するを含む。ストリームデスティネーションは、ストリームがそのポイントへと値を伝える位置である。可能なストリームデスティネーションは、モジュール定義の出力パラメータ、モジュールインスタンス化の入力引数、ストリーム式の入力、およびスレッドを含む。省略可能なストリーム名は、ストリームがモジュール入力またはモジュール出力として現れるときに、またはストリームがストリーム宣言において導入されるときに、ストリームに割り当てられる名称/識別子である。名称を有さないストリームの1つの例は、ストリーム割り当てにより名称が割り当てられていないストリーム式の出力ストリームである。ストリーム属性の概念は、関数Fの宣言およびモジュールMの部分的な定義を含む、以下の部分的コードにより示される。streamintFint,int;streamintzStrmMintxStrm,intyStrm{zStrm=xStrmyStrmFxStrm,yStrm;}ここでは、名称を有する3つのストリーム、すなわちxStrm、yStrm、およびzStrmが存在し、これらすべては、intのデータ型である。xStrmおよびyStrmは、それぞれが、モジュールMの入力パラメータである単一のソースを有する。xStrmおよびyStrmのデスティネーションは、それぞれ、Mの本体における代入式に現れる、xStrmおよびyStrmの2つのインスタンスにより表されるCにおいては、代入も式であることを想起されたい。これらのインスタンスは、代入式に対する入力を表す。したがって、xStrmおよびyStrmは、それぞれが単一のソースおよび2つのデスティネーションを有する。ストリームの式は、ストリームの式においては変数の代わりに入力ストリームが存在することを除いて、Cの式と同じである。ストリーム式は出力ストリームも有し、出力ストリームは、式評価からの結果を伝える。デフォルトにより、出力ストリームは名称を有さないが、ちょうど上記の代入で行ったように、ストリーム代入を用いることにより、名称を割り当てることが可能である。したがって、ストリーム式xStrmyStrmFxStrm,yStrmの出力ストリームは、ストリーム代入zStrm=xStrmyStrmFxStrm,yStrmにより、名称zStrmが割り当てられる。これら2つの式のうちのいずれかが、zStrmのソースであるとみなされ得る。zStrmのデスティネーションは、モジュールMの出力パラメータzStrmにより示されるモジュールMの出力ストリームである。streamintzStrmMintxStrm,intyStrmしたがって、xStrmは単一のソースおよび単一のデスティネーションを有する。ストリームの最も重要な属性は、ストリームが値を伝える際に果たす役割に関する。係る属性は4つ存在する。すなわち、a値は、ストリームソースにおけるか、またはinitialize関数を使用するシステム初期化時以外は、ストリームに入らない、b単一のソースにおいてストリームに入る値は、完全に時間順に整列される、cひとたびストリームに入ると、値はやがてはすべてのストリームデスティネーションに送達され、もしデスティネーションが複数存在する場合は、値の別個の複写が各デスティネーションに送達される、およびd単一ソースからの値は、値がストリームに入ったのと同一の順番ですなわち、ストリームにおいて値の飛び越しは存在しない、各ストリームデスティネーションにおいて受け取られる。これらの4つの属性が、ストリームが値の運搬について提供する唯一の保証である。これら4つの属性から論理的帰結として従わない任意の他の属性は、一般的なストリーム属性ではない。ストリームが義務を負うのは、ただ最終的に値を送達することのみである。したがって、ストリームのレイテンシ、すなわち値がストリームソースからストリームデスティネーションへと移動するに要する時間は不定である。事実、レイテンシは、時間に応じて、または同じストリームのソースデスティネーション対の間で、変動し得る。しかし、レイテンシが一定であるかまたは少なくとも限界を有することは、プログラミングモデルよりもむしろシステム実装により提供される保証に依存することにより達成され得る。例えば単一半導体ダイに限定されるソースデスティネーション対は、通常、そのレイテンシは限界を有する。また、上述の4つの属性は、ストリームの決定性および非決定性不確定性を暗示する。単一ソースを有するストリームに対しては、4つの属性は決定的なストリーム挙動を保証する。それは、値が単一ソースストリームに置かれる順番が、値がすべてのストリームデスティネーションに送達される順番を完全に決定することを意味する。しかし、複数のソースを有するストリームの場合、状況は大きく異なる。複数のストリームソースから生じる問題を示すために、以前のセクションに継続する以下の部分的コードの以下の適用を考慮してみるoutは単一出力モジュールのデフォルト出力ストリームである。intFint;streamintMintxStrm,intxStrm{out=xStrmxStrmFxStrm;}モジュールMの2つの入力パラメータは、同一のxStrmである。4つの属性から、モジュールMの第1の入力パラメータを通してxStrmに入った値は、xStrmの3つのデスティネーションのそれぞれにおいて、これらの値がストリームに入ったのと同じ順序で受け取られることとなる。モジュールMの第2の入力パラメータを通してxStrmに入った値は、xStrmの3つのデスティネーションのそれぞれにおいて、これらの値がストリームに入ったのと同じ順序で受け取られることとなる。このことは、2つのストリームの値は、xStrmのそれぞれのデスティネーションに到達する前に、合併または交互配置されることを意味する。どのように交互配置が実行されるかは、一般に、プログラムの構成により影響される。例えば、上記のプログラムの欠落部分は、パラメータ1とパラメータ2との値の間で正確な交互配置がされるように構成され得る。例えば、モジュールMの2つの入力パラメータストリームxStrmに到達する整数が、次の順序を有する場合、式out=xStrmxStrmFxStrmのxStrmの3つのデスティネーションのそれぞれに到着する順序は、という形になり得る。しかしながら、このようにプログラムにより課される決定性がいつも成り立つとは限らず、複数のストリームソースからの値が非決定的に交互配置される場合もある。さらに、ターゲットシステムによっては、これらの非決定的交互配置が、ストリームデスティネーション毎に異なり得る。したがって、例えば、モジュールMの2つの入力パラメータストリーム上に到達する値が上記の場合と同じである場合、xStrmの3つのデスティネーションに到達する順序は、という形で始まり得る。複数ソースストリームのデスティネーションにおける到着順序の非決定性は、単一ソースストリームのすべてのデスティネーションにわたる到着順序の一定性と対比的である。到着順序が一定である場合、以下の有用な表記を適用することが可能となる。単一ソースストリームssStrmおよび非負である整数iに対して、ssStrmiはssStrmのすべてのデスティネーションに現れる第i番目の値を示す。慣例的に、ssStrm0はすべてのデスティネーションに現れる第1の値を示す。値がストリームデスティネーションに到達すると、そのデスティネーションがモジュール定義またはモジュールインスタンス化入力引数である場合、その値は、モジュール境界の他方の側におけるストリームへと渡される。このように値は、移行状態に留まる。デスティネーションがストリーム式の入力またはスレッドである場合、値はFIFOキューに置かれる。移行状態に留まることを示すために、以下の部分的コードを示す。streamintmodule1int;streamintmodule2intxStrm{out=modulel1xStrm;}この部分的コードは、2つのモジュール、すなわちmodule1およびmodule2を含み、これら2つのモジュールのそれぞれは、単一の入力ストリームおよび単一の出力ストリームと、2つの名称を有するストリームxStrmおよびyStrm両方がmodule2の定義本体内に存在するとを有する。xStrmの唯一のデスティネーションすなわちmodule1xStrmは、module1のインスタンス化の入力引数である。このデスティネーションに到達する値は、module1の境界を単に通過し、module1の内部ストリームに達する。この状況は、yStrmの唯一のデスティネーションstreamintyStrmmodule2intxStrmに到達する値に対しても同じである。なぜなら、このデスティネーションはmodule2の出力パラメータであるため、到達する値はmodule2の境界を単に通過して、module2の外部にあるストリームに達する。他の例は、ストリームデスティネーションが以下の部分的コード等のストリーム式の入力である場合である。streamintFint,int;streamintMintxStrm,intyStrm{out=xStrmyStrmFxStrm,yStrm;}ストリーム式xStrmyStrmFxStrm,yStrmは、モジュールMの本体内にあり、このストリーム式は、xStrmの2つのデスティネーションと、yStrmの2つのデスティネーションとを含む。このストリーム式は2つの演算子およびと、関数Fとを含み、これらは普通のC構文である。このことは、この式を評価するためには、2つの演算子および関数Fが個々の値を供給されるべきであることを意味する。キューはストリームCのリンカ/ローダにより自動的に挿入され、ストリームCのランタイムにより管理される。ランタイムの任務の中には、キューが空き状態にあるときに信号を発すること、およびどのキューも確実にオーバーフローしないようにすることである。プログラマは特定の量を以下で説明するようにpragmaコマンドにより要求し得るが、各キューは関連するデータ型の少なくとも2つの値の容量を有することが保証される。この例のストリームにおいて、4つのキュー、すなわち4つのストリームデスティネーションストリーム式入力のそれぞれに対して1つのキュー、が存在する。これらのキューは、プログラマに対しては大半が不可視である。ひとたびストリームCプログラムが実行動作を開始すると、値がストリームに入る唯一の方法は、ストリームソースによる。より多くのストリームのうちの1つは、すでにストリーム中に含まれている値を要求する、有向サイクルdirectedcycleを形成し得る。最も簡単な係るサイクルは、xStrm=xStrmyStrmと等価であるxStrm=yStrmにおけるように、ストリーム代入の両辺にストリームが現れるときに生じる。図9Aはこの代入の第1の図的表現400である。なお、この代入においては、有向サイクルが、演算子の出力から同一の演算子の2つの入力のうちの1つに向かうフィードバック経路からなる。演算子が各入力ストリームからの値を消費して出力ストリーム上において値を作成することができないのは、この経路上において値が欠落しているためである。ゆえに、第2の図的表現402に示すように、値404が、実行の開始前に、フィードバック経路上に置かれない限り、演算子は決して始動することがない。他の問題は、1つの単一ソースストリームの、他の単一ソースストリームに対するオフセットの変化に関する。例えば、aStrmおよびbStrmの両方が、図9Bに図的に表現される、aStrmbStrm等の同一のモジュールまたはストリーム式に対する入力であり、そのモジュールまたは式が、これらのストリームから、対の形で、すなわちaStrmから1つの値およびbStrmから1つの値を消費する場合。aStrmnすなわち、aStrm上に第n番目に到達する値が、bStrmn2すなわち、bStrm上に第n2番目に到達する値と対になることが望まれる場合。したがって、aStrm0はbStrm2と、aStrm1はbStrm3と以下同様対となる。両方の問題に対するソリューンは、<ストリーム識別子>.initialize<値リスト>;の形を取る、ストリーム初期化文により提供される。ストリームCコンパイラ/リンカ/ローダがこの文と遭遇すると、ストリームCコンパイラ/リンカ/ローダは、FIFOキューを<ストリーム識別子>の各デスティネーションに挿入することデスティネーションがモジュール定義の出力パラメータである場合も、ストリーム文またはスレッドの入力引数である場合もと、そのキューのサイズを、Tデータ型の少なくともn1個の値を保持することができるよう設定することただし、nは<値リスト>中の値の個数であり、Tは<ストリーム識別子>のデータ型であると、<値リスト>中の値を、<値リスト>中の第1番目の値がキューの前部頭部に置かれる状態の順序でキューに置くこととを指示するものとして、この文を解釈する。例えば、図9Aにおいて、デッドロックを防ぐために、図的表現402において、値404が、フィードバック経路に、および、式出力にも、xStrm.initialize0;により挿入される。この文により、2つのFIFOキューが、xStrmの各デスティネーションに対して、作成されるフィードバック経路のデスティネーションにおけるキューは、前のセクションで説明したように、すでに挿入されている。xStrmがint型であると仮定すると、各ストリームのサイズは少なくとも2×sizeofintであり、システム初期化時においてint値0が各キューの先頭に位置する。このことは、図9Aにおけるフローチャート402において図示される。このようにxStrmが初期化され、代入xStrm=yStrmの出力は、となる。図9Bにおける第2の図的表現412におけるbStrmに対するaStrmのオフセットを変えることは、同様の方法で対処される。しかし、ここでは、2つの値がaStrmのFIFOキューに挿入される。なぜなら、bStrmに対して2つの値によりaStrmをオフセットすることが望まれ得るためである。このことは、1および2が、システム初期化時にaStrmのキューに挿入される2つの値414として選択された、以下のストリーム初期化文aStrm.initialize1,2;を用いることにより達成される。この初期化の結果は図9Bにおける表現412に図示される。このようにxStrmが初期化され、代入xStrm=yStrmの出力に現れる値は、となる。C変数の場合と同様に、特定のストリーム宣言は文脈上から、例えば、モジュール入力または出力パラメータとして現れることにより、暗黙的になされるが、すべてのストリームは使用の前に宣言されなければならない。明示的なストリーム宣言のシンタックスは、C変数宣言のシンタックスに従うが、この場合の宣言はキーワードstreamで始まる。stream<記憶クラス識別子>省略可能<型><識別子リスト>;記憶クラス識別子を有さないストリーム宣言の例を下にいくつか挙げる。streamintxStrm,yStrm;streamcharcStrm;streamdoubledStrm;5つのCにおける記憶クラス識別子、すなわち、auto、register、static、extern、およびtypedefのうち、ストリーム宣言においては、streamstaticintxStrm,yStrm;のように、staticのみが許可される。staticならびに非staticのストリーム宣言は、宣言が現れる文脈により決定される。係る文脈は3つ存在し、それぞれが、それぞれのスコープ規則を有する。それぞれの場合において、ストリーム宣言のスコープ規則は、変数宣言の対応物のスコープ規則と同じである。記憶クラス識別子を有さず且つモジュールの内部に現れるストリーム宣言に対しては、宣言スコープは、宣言からモジュールの終わりまで及ぶ。記憶クラス識別子を有さず且つモジュールおよび関数の外部に現れるストリーム宣言に対しては、宣言スコープはグローバルであり、すなわち、プログラム全体に対して可視である。static記憶クラス識別子を有し且つすべてのモジュールおよび関数の外部に現れるストリーム宣言に対しては、その宣言のスコープは、宣言から、宣言が現れるソースファイルの終わりまで及ぶ。変数には関係するがストリームには関係しない記憶クラス識別子に関するいくつかの宣言形態は、このリストに現れない。Cにおいては、auto記憶クラス識別子を用いて宣言された、またはまったく識別子を用いないで宣言された、これらの変数は、関数呼び出しの間では値を失う。ストリームはモジュール内においてのみ作用し、モジュールは呼び出されないためモジュールは常に動作状態にある、自動ストリームはそもそも無意味な概念である。したがって、auto記憶クラス識別子はストリーム宣言に適用されない。static識別子を用いて宣言され且つ関数の内部に現れる変数宣言は、宣言された変数が関数コール関数呼び出し間においてその値を保持することを示す。しかしモジュールの場合には、コールの概念が存在せず、したがって、static識別子はモジュール内部では無意味である。したがって、static識別子はモジュールスコープ内では用いられない。変数宣言に対して、extern記憶クラス識別子は、宣言および定義として働くグローバル変数のこれらの宣言と、単に宣言として働くグローバル変数の宣言とを区別することを支援する。しかしストリームの場合には、ストリーム宣言において記憶領域が決して除外されないため、宣言は決して定義にはならない。記憶領域は、以下のストリームFIFOのセクションにおいて説明されるように、ストリーム定義時においてのみ割り当てられる。registerおよびtypedefの記憶クラス識別子は、ストリームにおいてはまったく妥当性がなく、ストリーム宣言において現れることがない。ストリーム式は、通常のC式に対するストリームにおける対応物である。すべての変数に対して入力ストリームが取って代わること、および結果に対して出力ストリームが取って代わることは別として、これら2つの種類の式は極めて類似性が高い。式においては、変数と定数とが組み合わされて新しい値が作成されるが、一方、ストリーム式においては、ストリームと定数とが組み合わされて、新しいストリームが作られる。C式とストリーム式の構造はほぼ同一である。すべてのC演算子は、ストリーム式において有効な演算子である。同じ演算子の優先度が、C式とストリーム式との両方に当てはまる。C関数コールは、ちょうどC式で認められるのと同様に、ストリーム式においても認められる。単一の出力ストリームを有するモジュールのインスタンス化はストリーム式において認められ、関数コールと同様に取り扱われる。C式とストリーム式との間の相違点は、第1に、評価が行われる時点および方法にある。C式については、制御のスレッドが、式を含む文に到達した時点で、評価が行われる。その評価は、最初に、各変数をその現時点での値に置き換え、次いで、演算子の優先度にしたがって必要な演算を行うことにより、行われる。次いで、最後の演算により返される値が評価結果として供給される。C式の評価とは異なり、Cストリームプログラム言語におけるストリーム式の評価は、制御のスレッドには縛られない。代わって、ストリーム式は、便宜主義的に評価される。従来のように、評価は、演算子の優先度にしたがって必要な演算を行うことにより行われる。変数に対して値を置き換える代わりに、値は、式入力に属する各FIFOキューから消費ポップされる。FIFOキューは、ストリーム式の入力であるすべてのストリームデスティネーションにおいて挿入される。評価は便宜主義的である。なぜなら、式の各入力FIFOキューに少なくとも1つの値が存在するときは常に評価が行われるためである。従来のように、評価により作られる結果は、最後の演算により返された値である。しかし結果は、C式の場合とは異なる方法で対処される。C式に対しては、結果が代入される用法は、式の文脈により決定される。ストリーム式に対しては、結果は式の出力ストリーム式が代入かどうかに応じて、名称を持つ場合も持たない場合もあるに単に代入される。ストリーム式の1例が、xStrm、yStrm、およびzStrmがすべてint型のストリームである、以下の式xStrmyStrm5zStrmにおいて示され得る。これら3つのストリームに到達する値は、次のように始まる。すると、xStrmyStrm5zStrmの名称を有さない出力ストリームに代入される最初の3つの値は、以下のようになる。ストリーム式の中では、特にストリーム代入が注目される。係るストリーム代入には2つの型が存在し、第1の型は<ストリーム識別子>=<ストリーム式>の形を有する。そのCにおける対応物、すなわち変数への代入と同様に、この型のストリーム代入は副作用を有する。その出力ストリームに値を供給することに加えて、ストリーム代入は、右辺RHS:right-hand-side式の出力を左辺LHS:left-hand-sideのソースにし、そのプロセス中に、RHS式の出力ストリームを代入の出力ストリームとする。ストリーム代入は、RHS式の出力ストリームが名称を有さない場合は、その出力ストリームに名称も与える。より大きい式の部分式の出力ストリームに名称は必要ではないが、名称は、出力ストリームが任意の包含するsuper式superexpressionの外側のデスティネーションに宛てられなければならない場合は、不可欠となる。以下の部分的コートにおける式代入文は1つの例である。ストリーム式は、代入の場合もそれ以外の場合も、セミコロンが後尾に付されるとストリーム文となる。intFint,int;intGint;streamintMintxStrm,intyStrm{...out=FxStrm,GyStrm;...}式FxStrm,GyStrmおよび部分式GyStrmは、それぞれ、ストリーム文をストリーム式として有する。GyStrmの場合、出力ストリームは名称を有さない。なぜなら、ストリームのデスティネーションは、式の文脈から明らかであるためである。すなわち、デスティネーションはsuper式FxStrm,GyStrmにおける関数Fの第2の入力引数である。しかし、FxStrm,GyStrmの出力ストリームの場合は名称が必要となる。なぜなら、デスティネーションが式の外部にあるためである。その名称は、代入式out=FxStrm,GyStrmにおいて割り当てられる。この代入により、FxStrm,GyStrmの出力はzStrmのソースとなり、zStrmは単一のデスティネーション、モジュールMの出力パラメータを有する。ストリーム代入の第2の型は、<コンマで分割されたストリーム識別子のリスト>=<モジュールインスタンス化>の形を取る。この型は、複数出力モジュールの出力を複数の名称を有するストリームのソースにすることが望まれるときに生じる。例示すると、tapの第1の出力がintストリームxのソースであり、tapの第2の出力がintストリームyのソースである場合における、以下の複数出力モジュールstreamint,inttapint,int,int;である。これは、ストリーム代入intx,inty=taparg1,arg2,arg3;を用いて達成される。この代入により、モジュールのi番目の出力はi番目のストリームのソースとなり、モジュールの出力ストリームが名称を有さない場合には、その出力ストリームに名称が与えられる。モジュール本体内の文は、2つのカテゴリー、すなわち、スレッドおよびストリームに分類される。ストリーム文はストリームを取り扱うが、変数は取り扱わない。スレッド文は変数を取り扱い、いくつかの場合においては、ストリームも取り扱う。スレッドドメインにおける文は、大部分がC文であり、C文と同様に、本質的に命令的手続的であって、ステップ毎の手順を定義する。制御の逐次フロー多くの場合、スレッドと称されるは、係る手順と関連付けられ、文が実行される順序を支配する。それに対して、ストリーム文は宣言型である。係る文のそれぞれは、文中に現れるストリームについて宣言する。スレッドドメインにおいて存在するようなステップ毎の手順の概念は存在せず、したがって、モジュール本体内におけるストリーム文の順序は、1つの例外を除いて、重要ではない。変数は使用前に宣言される必要があるように、ストリームもまた使用前に宣言されなければならない。ストリームドメインの性質により、制御フローを取り扱うこれらのC文、特に、if-else、else-if、switch、for、while、do-while、break、continue、goto、およびreturnに対する対応物は存在しない。事実、ストリームドメインにおける唯一の文型は、C式文に対するストリームにおける対応物であり、Cにおけるように、最も一般的な式文は代入文である。ストリーム式文は、次の2つの形<ストリーム式>;stream<ストリーム式>;のうちの1つを有する。一方、ストリーム代入文は、次の2つの形<ストリーム識別子>=<ストリーム式>;stream<ストリーム識別子>=<ストリーム式>;<コンマで分割されたストリーム識別子のリスト>=<モジュールインスタンス化>のうちの1つを有する。モジュール、ストリームインスタンス化、ストリーム宣言、ストリーム式、およびストリーム文を使用する用途例は、デジタル信号処理において一般に使用される構文である有限インパルス応答FIR:finite-impulse-responseフィルタである。FIRフィルタは、離散型時間入力信号を離散型時間出力信号へと変換する。図10は、5タップFIRフィルタ500の図であり、図中、Xzは離散型時間入力502を、Yzは離散型時間出力504を表す。z-1と表記される、一連の単位遅延506は、それぞれが、受信する離散型時間信号を1クロックサイクルだけ遅延させる。それぞれが、受信する離散型時間信号に対して一定の係数hiを乗算する、一連の乗算器508。最後に、それぞれが、2つの受信信号を加算する、Σと表記された一連の加算器510。フィルタ500は5タップフィルタと称される。なぜなら、受信する離散型時間信号の5つの遅延されたバージョンのそれぞれが別個の係数を乗算され、結果として、5つの結果として生じた積が加算されるためである。離散型時間信号は、サンプルのストリームとして表される。乗算器508および加算器510のそれぞれはストリーム式として表される。単位遅延はストリームインスタンス化として表される。1つまたは複数の値を有するストリームを初期化することにより、値は、そのストリーム内で、第2のストリーム内の値に対して、オフセット遅延される。これは、UnitDelayモジュールの動作の基礎となる原理である。streamintUnitDelayintX{out=X;out.initialize0;}UnitDelayの本体において、ストリーム代入文out=X;により、UnitDelayの入力ストリームであるXは、UnitDelayのデフォルト出力ストリームであるoutのソースとなる。一方、ストリーム初期化文out.initialize0;は、システム初期化時に、値0をoutに挿入する。outにおけるこの初期値は、outにおける後続のすべての値を1つの値分だけオフセット遅延させる効果を有する。以下は、10、20、30、40、および50を任意に選択された5つのフィルタ係数として含む、図10におけるフィルタ500等の5タップFIRフィルタのストリームC実装である。streamintUnitDelayintX{out=X;out.initialize0;}streamintxOut,intyOuttapintxIn,intyIn,inth{xOut=UnitDelayxIn;yOut=yInhxOut;}streamintFIR5intX{intx2,inty2=tapX,10X,20;intx3,inty3=tapx2,y2,30;intx4,inty4=tapx3,y3,40;int,out=tapx4,y4,50;}この実装は並列性を示すが、明示的な並列性構文を用いることなく並列性が示されている。複数の名称を有するtapの出力の他は通常の逐次コードと類似するコードから、この並列性は現れたものである。変数に代わって、ここではストリームが存在する。FIR5の本体内におけるtapの4つインスタンス化のそれぞれは、式yInhxOutの、それ自身の複写を、3つの他のtapのインスタンス化と並列的に演算する。このことは、ストリーム式の便宜主義的な性質により、および新しい入力値がtapのインスタンス化のそれぞれへと継続的に到着することにより、可能となる。これらの新しい値は、FIR5の5つの内部ストリームにより供給される。Xは、FIR5の入力から第1のtapの入力へと値を伝える。x2およびy2は、第1のtapの出力から第2のtapの入力へと値を伝える。x3およびy3は、第2のtapの出力から第3のtapの入力へと値を伝える。x4およびy4は、第3のtapの出力から第4のtapの入力へと値を伝える。tapの各インスタンス化の入力hは、定数により置き換えられる。このことにより、ストリームCコンパイラはtapインスタンス化内のhのすべてのインスタンスを定数で置き換える。tapのインスタンス化により実行されるすべての演算により、FIR5入力値はFIR5出力値へと変換される。これらの最後の出力値が、FIR5のデフォルト出力ストリームにより供給される。outは、第4のtapの出力からFIR5の出力へと値を伝える。この実装は、多数のデジタル信号処理関数がどのようにストリームCにおいて取り扱われるかの1つの例である。上述のFIRフィルタ例においては、5つの係数すなわち10、20、30、40、50が、コンパイル時に既知である。しかしFIR5係数がコンパイル時に未知である場合、または係数が長い期間にわたって一定であるが、随時変更される場合は、他の技術を用いる必要がある。係る場合においては、これらの擬似的定数は、変化するため真の定数ではなく、また、ストリーム式またはスレッドにより消費FIFOキューからポップされないため、真のストリームではない。擬似的定数ストリームは、いくつかの面において通常のストリームに類似する。擬似的定数ストリームは、型と、1つまたは複数のソースと、1つまたは複数のデスティネーションと、名称とを有する。擬似的定数ストリームは、指定されたソースから指定されたデスティネーションへと指定された型を伝える。しかし、いくつかの点において、擬似的定数ストリームは通常のストリームとは異なる。通常のストリームがFIFOキューを有するのに対して、擬似的定数ストリームは、指定された型の1つの値のための記憶領域変数と関連付けられた記憶領域に極めて類似するを有する。係る記憶領域に存在する値は、ストリーム式またはスレッドによりアクセスされたときに、ポップされることも消費されることもなく、記憶領域内に留まり続ける。記憶された値は、新しい値がストリームソースのうちの1つからストリームに入ると、更新される。係るとき、新しい値は単に古い値を上書きする。この更新は典型的にはシステム動作とは非同期的になされるため、更新がストリームデスティネーションにおいて認識される時点は、一般に、非決定的である。擬似的定数ストリームの宣言は、システム初期化時に各ストリーム記憶位置に記憶される初期値を指定しなければならない。擬似的定数ストリームは、単独型の宣言においても、モジュールの入力または出力パラメータリストにおいても、以下のシンタックスconst<ストリーム型><ストリーム識別子>=<初期値>を用いて宣言される。通常は変数のみに対して適用される既存のCキーワードconstは、宣言されるストリームが擬似的定数ストリームであることを示すconstの使用は、新規キーワードの導入の手間を省く。これらの考えは、FIR5モジュールの以下の変更例において示される。ここでは、もとの例における5つの係数すなわち10、20、30、40、および50は、5つの擬似的定数ストリームh0、h1、h2、h3、およびh4により置き換えられる。システム初期化時にこれらのストリームに挿入される初期値はもとの係数と同一であるため、新しいFIR5は、もとと同一の係数で動作を開始する。しかし、新しいFIR5に関しては、これらの係数は、状況が許可するならば、更新され得る。streamintFIR5intX,constinth0=10,constinth1=20,constinth2=30,constinth3=40,constinth4=50,{intx2,inty2=tapX,h0X,h1;intx3,inty3=tapx2,y2,h2;intx4,inty4=tapx3,y3,h3;int,out=tapx4,y4,h4;}図11Aは、入力ストリーム604上の一連のFIFOバッファ602が強調されたモジュール600を示す。図11BおよびCは、FIFOバッファ602およびモジュール600を用いる、2つの追加の代替的な実装を示す。図11Bは、FIFOバッファ602が一連の出力ストリーム606上でのみ使用される状態を示す。図11Cは、FIFOバッファ602が入力ストリーム604および出力ストリーム606の両方上で使用される状態を示す。プログラマの観点からは、図11AからCに示す3つの図は同等である。性能の観点からは、図11Cにおけるように入力および出力にバッファを有することにより、モジュール600は、ストリームを受け取るモジュール600上の利用可能スペースを考慮することなく、スケジュールされることが可能となる。これは、追加的なメモリおよび別途のスケジュールステップのコストにより実現される。FIFOバッファ602は、実装に応じて、仮想メモリスペース上、物理メモリスペース上、および登録ファイルスペース上に存在し得る。図11Aにおけるような入力ストリームFIFOに対する高レベルのスケジューリングアルゴリズムの1例を以下に示す。a.次の場合、モジュールを実行するようスケジュールする{入力ストリーム単数または複数の入力FIFOにデータが存在する且つ現在のモジュールの出力ストリームに接続されたモジュールの入力ストリームFIFOに利用可能スペースが存在する}図10Bにおけるような出力ストリームFIFOに対する高レベルのスケジューリングアルゴリズムの1例を以下に示す。b.次の場合、モジュールを実行するようスケジュールする{現在のモジュールの入力ストリーム単数または複数に接続されたモジュールの出力ストリームFIFOにデータが存在する且つ出力ストリーム単数または複数のFIFOに利用可能スペースが存在する}図10Cにおけるような入力および出力ストリームFIFOに対する高レベルのスケジューリングアルゴリズムの1例を以下に示す。c.次の場合、モジュールを実行するようスケジュールする{入力ストリーム単数または複数の入力FIFOにデータが存在する且つ現在のモジュールの出力ストリームに接続されたモジュールの入力ストリームFIFOに利用可能スペースが存在するまたは出力ストリーム単数または複数のFIFOに利用可能スペースが存在する}スレッドスレッドは、ストリームCが完全且つ包括的な言語となるにあたり必要不可欠な能力を提供する。スレッドは、C関数すなわち、その入力が個別の値であり、その出力が単一の値である関数の本体内か、またはモジュールすなわち、その入力および出力が値のストリームである関数の本体内に、現れ得る。これら2種類のスレッドは、モジュールの本体内のスレッドがストリームCストリームにアクセスし得通常はストリームCストリームにアクセスする、その理由のために、通常は終了しないことを除いて、同じである。また、C関数の本体内のスレッドは、ストリームCストリームにアクセスせず、すべての良好な挙動を示すCスレッドと同様に、終了する。ストリームCスレッドの顕著な特性は、並列問題からの完全な乖離である。並列構文は存在せず、他のスレッドと直接的に相互作用することはなく、および新規スレッドは生成されない。したがって、ストリームCスレッドに関しては、ストリームCスレッドが複数スレッド環境で動作中であることを意識する必要がない。したがって、スレッドドメインで作業するプログラマは厳格に逐次的な問題に集中してよい。ストリームCにおける関数宣言および関数定義は、Cにおける対応物と同じシンタックスおよびセマンティクスを有する。ストリームCにおける関数コールに関しては、シンタックスおよびセマンティクスは、コールがa関数の本体に現れるか、またはbストリーム式に現れるかに依存する。同じ関数再帰関数の本体、または他の関数の本体におけるストリームC関数コールは、通常のC関数コールと同じシンタックスおよびセマンティクスを有する。ストリーム式におけるストリームC関数コールは、C関数コールと同じシンタックスを有するが、ただし、ストリームが関数コール引数における変数と置き換わる。係るコールのセマンティクスは同じであるが、通常の関数コールのセマンティクスとは同じでない。相違点は、関数の各評価コールがどのように行われるかに関する。さらに詳細には、相違点は、1関数コール引数に現れるパラメータストリームに対して値がどのように取得されるか、2関数コール出力のデスティネーション、および3制御がどのように取り扱われるか、に関する。Cにおいて、関数コールに現れる引数に現れるパラメータはすべて変数であり、係る関数入力変数に代入される値は、その変数の現在値である。ストリームCにおいては、ストリーム式関数コールの引数に現れるパラメータはすべてストリームであり、係る関数入力ストリームのそれぞれに代入される値は、a通常のストリームの場合は、ストリームデスティネーションにおけるFIFOキューからポップ消費される値である、またはb擬似的定数ストリームの場合は、そのストリームデスティネーションにおける現在の値である、のいずれかである。Cにおいて、関数コールにより変えられる値は、関数コール元に渡される。ストリームCにおいては、ストリーム式関数コールにより返される値は、関数コール出力ストリーム名称を有する場合も有さない場合もあるに代入される。ストリーム式そのものであるため、ストリーム式関数コールは常に出力ストリームを有する。出力値のデスティネーションは、ストリームのデスティネーションにより決定される。Cにおいて、関数は、制御のスレッドがその関数に対するコールと遭遇するとき、コールされる。ストリームCにおいては、ストリーム式関数コールは、制御スレッドに関わりなく評価されるすなわち、関数がコールされる。代わって、関数は、関数コールの通常の入力ストリームのそれぞれのFIFOキューに少なくとも1つの値が存在するときは常に便宜主義的にコールされる。擬似的定数入力ストリームは、値を供給する準備が常に整っており、したがって、関数コールまたはストリーム式の評価を決して妨げることはない。これら3つの相違点は別として、通常のC関数コールおよびストリーム式関数コールのセマンティクスは同じである。このことは、両方の場合においてスレッドに基づくセマンティクスが関数実行に適用されることを意味する。以下の関数GDCの定義およびモジュールGDC4を有するCストリームにおけるスレッドの1例が示され得る。intGCDinta,intb//再帰関数{ifa>=bab==0//スレッドの開始{returnb;}ifa<b{returnGCDb,a;//関数コール}returnGCDb,ab;//関数コール}streamintGCD4intw,intx,inty,intz//モジュール{out=GCDGCDw,x,GCDy,z;//3つの関数コールを有するストリーム式}再帰関数の古典的な例であるGCDは、2つの整数の最大公約数を返す。GCDは2つの整数入力aおよびbを有し、1つの整数結果を返す。GCD4は、4つの整数ストリーム入力すなわちw、x、y、およびzを有し、1つの整数ストリーム出力を有する。ストリーム式文out=GCDGCDw,x,GCDy,z;が、GCD4の本体内に存在し、ストリーム式GCDGCDw,x,GCDy,zがこの文の中に存在する。この式は、ストリームw、x、y、およびzのデスティネーションを含むため、これら4つのデスティネーションのそれぞれにおいてFIFOキューが存在する。これらのキューは、関数コールGCDw,xおよびGCDy,zが上述のように便宜主義的および並列的に評価実行されることを許可する。これらの2つのコールのように、GCDに対する第3のコールは、その2つの入力ストリームのFIFOキューから取得された入力値を用いて便宜主義的に実行される。これらの入力ストリームは、GCDに対する2つの他のコールの出力ストリームとして作られたものであり、そのために、これら2つのストリーム上のFIFOキューは、GCDに対する第3のコールが最初の2つのコールと並列的に実行されることを可能にする。この第3の関数コールの出力ストリームは、outへのストリーム代入により、GCD4の出力ストリームに宛てられる。図12におけるデータフロー図に表される、GCDに対する関数コールのこの構成は、4つの入力ストリームすなわちw、x、y、およびzからのデータが、3つの並列動作関数コールを通ってストリームされることを可能にし、その結果、それぞれの出力値が、i>=0であるいくつかの整数iに対してwi、xi、yi、およびziの最大公約数である、出力値のストリームが作成される。ストリームの観点からすると、どのようにモジュールが入力ストリーム値を出力トリーム値に変換するかは、重要ではない。重要であるのは、入力から出力への変換単数または複数および任意の副作用のみである。これまで挙げてきた例においては、これらの変換は、ストリーム式、すなわち特定用途用ハードウェア、再設定可能なハードウェア図1および図2における等の、逐次コードを実行するプロセッサまたは何らかの他の機構を用いて実装され得る式に関して表されてきた。これらの変換は、モジュールの本体内に存在する逐次コードとして明示的に表され得る。係るコードは、記憶されたプログラム逐次プロセッサstored-programsequentialprocessor上で実行され得、スレッドドメインと称され得るものの中に存在し得る。モジュールの本体は、排他的にストリームドメインまたはスレッドドメインにおける文を典型的には含むであろうが、しかし、このことにより、同じモジュール本体内において両種の文が排除されるわけではない。その場合、2つのドメインは、並んですなわち並列的に動作する。スレッドドメインのシンタックスおよびセマンティクスは、BrianW.KernighanおよびDennisM.Ritchie共著CProgrammingLanguage1978年により非公式に、およびISOのC規格ISO/IEC9899により公式に定義されるC言語のスーパーセットである。標準C言語に対する追加は、スレッドが、モジュール入力ストリーム、モジュール出力ストリーム、モジュール本体に対して内部にあるストリーム、またはグローバルストリームであれ、スレッドに対して可視であるこれらのストリームにアクセスすることを可能にする動作に関するものである。これらのストリームアクセス動作は、2つのカテゴリー、すなわちブロック型および非ブロック型に分類される。これらの動作を理解するために、ストリームにおける値のフローを規制するために用いられる機構、およびタスクタスクはモジュールインスタンスと等価であるを管理するための機構が、図4におけるノードラッパーを参照して説明したように重要である。フロー制御およびタスク管理は、ストリームCランタイムサポートシステムにより提供される重要なサービスである。フロー制御は、FIFOキューのオーバーフローすなわち、すでにフル状態であるキューにデータを書き込みことおよびFIFOキューのアンダーフローすなわち、空き状態のキューからデータを読み込みむことを防ぐ。タスク管理は、いつタスクが実行状態に置かれるか、いつかの場合においては、いつタスク実行が終了されるか、を制御する。ストリームCフロー制御システムおよびタスク管理システムにおいては、3つの重要な要素、すなわち消費側カウント、作成側カウント、およびタスクマネージャが存在する。整数消費側カウントは、通常の擬似的定数ではないストリームの各FIFOキューと関連付けられる。特定ストリームの特定スレッドによるすべての読み込みは、同一のFIFOキューをアクセスし、したがって、同一の消費側カウントにアクセスする。消費側カウントの符号ビットは、FIFOキューが空き状態であるかどうかを示す。1の符号ビット消費側カウントは負であるは、キューが空き状態であることを示す。0の符号ビット消費側カウントは非負であるは、キューが非空き状態であることを示す。整数作成側カウントは、各通常擬似的定数ではないストリームの各ソースと関連付けられる。作成側カウントの符号ビットは、このストリームソースに挿入された値を受け取るために下流側FIFOキューに利用可能スペースが存在するかどうかを示す。0の符号ビット作成側カウントは非負であるは、すべての下流側キューが、この出力ストリームにおいて値を受け取るためのスペースを有するとは限らないことを示す。1の符号ビット作成側カウントは負であるは、すべての下流側キューが、この出力ストリームにおいて値を受け取るためのスペースを有することを示す。図2におけるノード180等の各プロセシングコアは、実行を開始するに必要な入力データを含むすべてのリソースを有する、タスクの先入れ先出し実行準備完了キーを有する。各プロセシングコアは、タスクの実行を管理し、且つ必要な調節信号をタスク間に提供するタスクマネージャを有する。タスクマネージャは、データがFIFOキューにプッシュされた書き込まれたときに消費側カウントをインクリメントすることと、データがFIFOキューからポップされた消費されたときに消費側カウントをデクリメントすることと、スペースがデスティネーションFIFOキューにおいて利用可能となったことを示すためのバックワードアクノレッジメントを、ストリームソースへと送信することデフォルトは、各値が各FIFOキューから消費された後にバックワードアクノレッジメントを送信すると、を自動的に行う。タスクマネージャは、データがモジュールの出力ストリームに書き込まれた場合にそのストリームの作成側カウントをインクリメントすることと、モジュールの出力ストリームに対するバックワードアクノレッジメントが受け取られた場合にその出力ストリームの作成側カウントをデクリメントすることと、タスクが、入力データと、タスクが進行するために必要である任意の他の要求されるリソースと、を有する場合に、プロセシングコアの実行準備完了タスクキューにタスクを置くことと、も実行する。タスクマネージャは、タスクが実行準備完了タスクキューの先頭にあり且つ実行ユニットが利用可能である場合に、タスクを実行状態に置き、タスクが進行するために必要な入力データを有さない場合またはタスクがタイムアウトする場合に、タスクの実行を停止する。ブロック型ストリームアクセス演算は、モジュール本体に現れるスレッドが、モジュール入力ストリーム、モジュール出力ストリーム、モジュール本体に対して内部にあるストリーム、およびグローバルストリーム等の、スレッドに対して可視であるストリームにアクセスすることを可能にする。これらはストリームにアクセスするための好適な方法である。なぜなら、非ブロック型ストリームアクセス動作とは異なり、ブロック型ストリームアクセス動作は非決定性を生じさせないためである。係る演算のブロックおよび非ブロックは、プロセシングコアのタスクマネージャにより自動的に対処される。係る演算は3つあり、それぞれの演算はCにおける同様の演算にちなんで作られたものである。演算子>>は、ストリームFIFOキューから単一の値をポップ消費し、その値を変数に代入するために用いられる。演算子>>は<ストリーム識別子>>><変数識別子>;の形の文において用いられる。この文により、単一の値が左側のストリームからポップされ、右側の変数に代入される。しかし、ストリームに対するFIFOキューが、ストリームの消費側カウントの符号ビットにより示されるように空き状態である場合、文はブロックストールされ、キューが、ストリームの消費側カウントの符号ビットにより示されるように再び非空き状態となるまで、ブロック状態に保持される。演算子<<は、変数の現在の値をストリームに代入するために用いられる。演算子<<は、<ストリーム識別子><<<変数識別子>;の形の文において用いられる。この文により、右側の変数の値は左側のストリームに代入される。しかし、1つまたは複数の下流側キューが、ストリームソースにおける作成側カウントの符号ビットにより示されるように、係るデータを受け取るスペースを有さない場合、文は、ブロックストールされ、すべての下流側キューが、ストリームの作成側カウントの符号ビットにより示されるように再び値を受け取るスペースを有するようになるまで、ブロック状態に保持される。peek演算子は、ストリームFIFOキューの先頭における値を、ポップ消費せずに、取得するために用いられる。peek演算子は、<ストリーム識別子>.peekの形の式において用いられる。この式は、<ストリーム識別子>のFIFOキューの先頭における現在の値を返すが、キューから値をポップ消費しない。しかし、ストリームに対するFIFOキューが、ストリームの消費側カウントの符号ビットにより示されるように空き状態である場合、文は、ブロックストールされ、キューが、ストリームの消費側カウントの符号ビットにより示されるように再び非空き状態となるまで、ブロック状態に保持される。ブロック型のストリームアクセス演算子と同様に、非ブロック型ストリームアクセス演算は、モジュール本体に現れるスレッドが、モジュール入力ストリーム、モジュール出力ストリーム、モジュール本体に対して内部にあるストリーム、およびグローバルストリーム等の、スレッドに対して可視であるストリームにアクセスすることを可能にする。しかし、ブロック型演算とは異なり、非ブロック型演算は、典型的には、演算の結果に影響する競合状態に関与するものであり、したがって、非決定性を導入する。係る演算は2つある。<ストリーム識別子>.consumerCountの形の式は<ストリーム識別子>の消費側カウントを返す。なお、<ストリーム識別子>は、>>演算またはpeek演算を介して、スレッドにより読み込まれるストリームである。この式は、<ストリーム識別子>のFIFOキューが空き状態である場合に>>演算またはpeek演算を回避するために、<ストリーム識別子>の消費側カウント符号ビットをテストするために、主に用いられる。<ストリーム識別子>.producerCoutの形の式は、<ストリーム識別子>の作成側カウントを返す。なお、<ストリーム識別子>は<<演算を介して、スレッドにより書き込まれたストリームである。この式は、1つまたは複数の下流側キューが係る新しい値を受け取るスペースを有さない場合に、<<演算を回避するために、<ストリーム識別子>の作成側カウント符号ビットをテストするために、主に用いられる。モジュール本体内のスレッドが多数の異なる形を取り得るが、多くの変化例が、以下の典型的な形となるであろう。streamintmoduleAintstrm1,...,intstrmN{intvar1,...,varN,result;//変数を宣言whiletrue//永遠にループする{strm1>>var1;//入力ストリームから値を読み込むstrmN>>varN;//resultを算出するout<<result;//resultを出力ストリームに代入する}}ここでmoduleAは、1つまたは複数の入力ストリームと、単一の出力ストリームとを有するモジュールである。入力ストリームおよび出力ストリームのデータ型は、整数型へと任意選択される。moduleAの本体内のスレッドが最初に実行することは、各入力ストリームに対する値と、単一の出力ストリームに対する値とを宣言することである。次いでスレッドは、各反復がa各入力ストリームから値を読み込む消費すること、b結果を算出すること、およびc結果を出力ストリームに代入すること、を含む無限ループに入る。配列他の言語におけるのと同様に、配列は、データ要素の配列ばかりではなく、ストリーム配列およびモジュール配列もまた、ストリームCにおいて重要な役割を果たす。実際のデータ値の配列データ値の配列へのポインタではなくは、複数のストリーム上で並列的に伝えられる。ストリーム配列は、モジュールの配列とともに用いられるとき、特に有用である。ストリームCは、Cからデータ配列のためのシンタックスおよびセマンティクスを受け継ぐ。このことは、配列の名称が関数引数として用いられる場合、関数に渡される値は、配列の先頭の位置またはアドレスであり、配列要素は複写されないことを意味する。ストリーム入力引数およびモジュールの出力に対しても、同じことが成り立つ。例示のために、上述のGDC4モジュールが用いられ得る。streamintGCD4intw,intx,inty,intz//4つの整数引数を有する{//モジュールout=GCDGCDw,x,GCDy,z;}GCD4に4つの別個の整数ストリーム引数を供給する代わりに、各値が4つの整数の配列である単一のストリーム引数が供給される。GCD4は、以下のように変形されるであろう。streamintGCD4intwxyz//1つの配列引数を有するモジュール{out=GCDGCDwxyz[0],wxyz[1],GCDwxyz[2],wxyz[3];}C言語の規則によれば、GCD4の単一の引数はint型、すなわち整数へのポインタであり、この場合、4つの整数の配列における第1の整数である。GCD4の本体内のこれらの4つの整数は、標準的なC言語の演算子[]を用いてアクセスされる。C言語型のデータ配列をモジュールに供給することが、ストリームの文脈において配列を取り扱うための1つの方法である。いくつかの用途に関しては、モジュールに配列ポインタのストリームを供給することは、その用途に固有の並列性を十分に利用するためには不十分である。したがって、配列のストリームよりもむしろ、ストリームの配列は、データ値の配列へのポインタではなく、実際のデータ値の配列が、複数のストリーム上で並列的に伝えられることを可能にする。ストリーム配列の宣言は、2つの相違、すなわちキーワードstreamが宣言に先行すること、および配列のサイズがコンパイル時に既知でなければならないことを除き、通常のC言語の配列の宣言と同じである。この制限は、モジュールと同じくアプリケーション内のすべてのストリームがコンパイル時にインスタンス化されるので、必要である。ストリーム配列宣言の例を以下に挙げる。streamintarray1D[4];streamintarray2D[4][16];streamintarray3D[4][16][9];第1の宣言は、array1Dが4つの整数ストリームの1次元配列であることを宣言する。同様に、array2Dが64個の整数ストリームの2次元配列であること、およびarray3Dが576個の整数ストリームの3次元配列であることが宣言される。ストリーム配列の個々のストリームは、データ配列の個々の要素と同じ方法でアクセスされる。例えば、array3D[3][15][7]は、array3Dの576個のストリームのうちの1つを示す。ひとたびストリーム配列が宣言されると、配列全体、配列内のサブ配列、または配列内の個々のストリームは参照され得る。これらの3つの場合が以下の部分的コードにおいて例示される。streamintmoduleAint;//モジュール宣言streamintmoduleBint[4];//モジュール宣言streamintmoduleCint[3][4];//モジュール宣言streamintmoduleDintW[3][4]//モジュール定義{streamintX=moduleAW[2][0];//ストリーム式streamintY=moduleBW[2][0];//ストリーム式streamintZ=moduleCW;//ストリーム式}ここでは、moduleA、moduleB、およびmoduleCに対する宣言と、moduleDの部分的な定義が示される。これら4つのモジュールの入力型を以下に示す。moduleDの本体内のmoduleA、moduleB、およびmoduleCのインスタンス化に供給される入力引数を以下に示す。それぞれの場合において、モジュールインスタンス化引数型は、モジュール入力型と一致し、したがって各モジュールインスタンス化は、ストリームCの型づけの強い要件を満足する。ストリーム式内におけるストリーム配列の個々のストリームをアクセスすることも、この複素数乗算モジュール例に示すように、単純明快である。streamint[2]complexMultintX[2],intY[2]{out[0]=X[0]Y[0]-X[1]Y[1];out[1]=X[0]Y[1]X[1]Y[0];}ストリーム式内の演算子が並列的にアクティブであるため、ストリーム式X[0]Y[0]-X[1]Y[1]およびX[0]Y[1]X[1]Y[0]における4つの乗算、1つの加算、および1つの減算は、並列的に評価される。並列処理に対する最も普及している手法の1つであるデータ並列性は、同一のタスクが同一のデータ構造典型的には配列の異なる部分上で並列的に並行して実行される、並列性の1つの形態である。ストリームCにおいて、データ並列性は、モジュール配列によりサポートされる。モジュール配列は、その名称が暗示するように、モジュールの配列である。モジュール配列は、モジュール名と入力パラメータのリストとの間に角括弧で囲まれた配列次元を挿入することにより宣言される。以下はモジュール配列宣言の2つの例である。streamintmoduleA[3][4]int,int;streamint,intmodu1eB[3][4]int,int;両方の場合において、配列次元は3×4である。通常単独型モジュールの定義と同様に、モジュール配列の定義は波括弧{および}で囲まれた本体を有する。以下は、モジュール配列定義の2つの例である。第1の例は単一デフォルト出力ストリームを有し、それに対して、第2の例は名称を有する2つの出力ストリームを有する。streamintmoduleA[3][4]inta,intb{//モジュール本体}streamintx,intymoduleB[3][4]inta,intb{//モジュール本体}ひとたびモジュール配列が宣言宣言または定義されると、配列全体、配列内のサブ配列、または配列内の個々のモジュールは、データ配列およびストリーム配列と同じ方法で、ストリーム式内でインスタンス化され得る。moduleA[3][4]に対して、これら3つの場合が示される。モジュール配列の重要な属性は、モジュール配列がシステム初期化時にインスタンス化されるとき、顕著なものとなる。モジュール配列の各要素は、別個のモジュールインスタンス化として、インスタンス化される。その結果、すべての配列要素が並列的に動作することが可能となる。moduleA[3][4]がこの概念の1つの例である。モジュールがインスタンス化されると、moduleAの123×4個の別個のインスタンス化が作られ、それぞれのインスタンス化は、他の11個のインスタンス化と並列的に動作する。さらに、このインスタンス化の乗算は、moduleA[3][4]の各インスタンス化に当てはまる。したがって、moduleA[3][4]の3つのインスタンスが存在する場合、moduleAの363×12個の別個のインスタンス化が作られる。モジュール配列インスタンス化のパーソナル化は、インスタンス化がどのデータ上で演算されるかを決定する。インスタンス化は、各モジュールインスタンス化にそれ自体のユニークなデータをインスタンス化の入力ストリームを通して供給することにより、パーソナル化され得る。各モジュールインスタンス化が、その配列インデックスを、インデックス演算子を用いて特定することが可能となり、それにより、インスタンス化が、グローバル配列のそれ自体のユニークな部分にアクセスすることが可能となることにより、インスタンス化はパーソナル化され得る。ストリーム配列がモジュール配列の各要素にユニークなデータを供給するために用いられ得る第1タイプのパーソナル化が以下に示される。第2タイプのパーソナル化は、各配列モジュールの配列インデックスのインスタンス化がコンパイル時に既知であるという事実を利用する。これらのインデックスにアクセスするために、プログラマは、以下のシンタックスintindexintiで演算子を使用する。なお、式中、iはコンパイル時に定数へと評価される整数式である。コンパイル時に、indexiはインスタンス化の第1番目のインデックスと置き換えられる。iが配列境界外である場合、コンパイル時エラーまたはランタイムエラーが生じる。ストリーム配列およびモジュール配列は、ストリームCの特別な配列結合機能を用いてストリーム配列とモジュール配列とが結合されたときに、最大の有用性を発揮する。結合に対しては、3つの要件、すなわちaストリーム配列およびモジュール配列が同じ次元を有さなければならないこと、bストリーム配列がモジュール配列の入力または出力と接続結合されていなければならないこと、およびcストリーム配列型がモジュールの入力/出力型と一致しなければならないこと、が存在する。係る結合が生じると、ストリーム配列内の各個別ストリームは、同一のインデックスを有するモジュール配列の個々のモジュールの入力/出力ストリームに接続結合される。したがって、0<=i1<D1,0<=i2<D2...0<=in<Dnに対して、ストリーム配列S[D1][D2]...[Dn]がモジュール配列M[D1][D2]...[Dn]の入力/出力に結合されると、各個別ストリームS[i1][i2]...[in]は個別モジュールM[i1][i2]...[in]の入力/出力に接続される。以下は、1つのモジュール配列の出力および他のモジュール配列の入力に結合されたストリーム配列の例である。streamintmoduleA[3][2];//第1の結合されたモジュールstreamvoidmoduleB[3][2]int;//第2の結合されたモジュールstreamvoidparentModule{streamintcStrm[3][2];//結合されたストリームcStrm[][]=moduleA[][];//cStrmに結合されたmoduleAの出力moduleB[][]cStrm[][];//moduleBの入力に結合されたcStrm}ここで、moduleA[3][2]の出力ストリームはcStrm[3][2]に結合され、cStrm[3][2]はmoduleB[3][2]の入力ストリームに結合される。これらは正規の結合である。なぜなら、cStrm[3][2]、moduleA[3][2]、およびmoduleB[3][2]が、すべて同一の次元を有し、cStrm[3][2]が、moduleA[3][2]の出力およびmoduleB[3][2]の入力に接続され、cStrm[3][2]の型、moduleA[3][2]の出力型、およびmoduleB[3][2]の入力型がすべてintである、ためである。以下の表は、cStrm[3][2]の各個別ストリーム、すなわちa出力がストリームソースであるモジュール、bcStrm[3][2]における個別ストリーム、およびcインプットがストリームデスティネーションであるモジュールをリストする。PINGモジュールが他のモジュールに対して、そのモジュールが実行する特定の演算、副作用が完了したことを通知することが必要となる状況が存在する。例えば、モジュールがグローバルメモリ内のデータ構造に関する演算を実行するとき、おそらく同一のデータ構造に関する演算を実行する多数のモジュールのうちの1つとして、そのモジュールは、典型的には、演算が完了したため下流側の演算またはタスクが開始され得ることを下流側モジュールに通知する必要がある。これらの状況においては、値を返す必要はなく、特定のタスクが完了した信号を返すのみでよい。値ではなく信号が必要とされるこれらの状況に対して、ストリームCはpingデータ型を提供する。pingping型の値は、特性を有さず、互いに対して完全に区別がつかない。pingは、3つの演算子、すなわち、1タスクの同期を提供するjoin演算子、2>>ストリームアクセス演算子、および3<<ストリームアクセス演算子、とともに用いられる。第1の使用法はストリームのみに関するが、第2および第3の使用法は、ストリームおよびスレッドに関する。pingキーワードは、1つまたは複数のping型のストリームを宣言するときに用いられる。例えば、以下の式streampingpStrm0,pStrm1,pStrm2;は、pStrm0、pStrm1、およびpStrm2がping型のストリームであることを宣言する。pingキーワードは、streampingmoduleNameint,ping;のように、モジュール入力または出力がping型であることを宣言するモジュールプロトタイプ/定義にも用いられる。pingの第1の使用法はjoin演算子に関し、join演算子は、pingストリームと他の1つまたは複数のストリームとを繋いで、単一の出力ストリームを作る機能を有する。この演算子は、他のいくつかの演算モデルにおいて見られる接合演算rendezvousoperationと同様である。join演算子を含む式は、2つの形<pingストリーム配列>.join<pingストリーム>.join<ストリーム式>のうちの1つを取る。すべてのストリーム式と同様に、これらの形のうちの1つにおける式の各評価は、各入力ストリームから単一の値/pingを消費し、式の名称を有さない出力ストリーム上に単一の値/pingを作る。入力ストリームが空き状態値が存在しないである場合、すべての入力ストリームが少なくとも1つの値/pingを有するまで、評価はストールブロックされる。非ping式に対しては明示的なjoin演算は必要ない。なぜなら、join演算の効果はすでに式評価のセマンティクスにより包含されるためである。第1の型の式が評価されると、単一のpingがpingストリームの配列内の各ストリームから消費され、単一のpingが式の出力ストリーム上に発行される。第2の形の式が評価されると、<pingストリーム>からの単一のpingと、<ストリーム式>の評価とが消費される。このストリーム式<ストリーム式>は、pingを含む任意の型であり得る。<ストリーム式>の評価から得られる値は、join演算の出力ストリーム上に発行される。式がping型である場合、式は単一のpingに評価される。このように、pingストリームは、上述の>>演算子の場合と同じく、<pingストリーム>にpingが存在する場合にのみ評価の進行を許可する守衛として機能する。join演算の2つの形が図13Aおよび13Bに図示される。図13Aにおいては、サイズがnである1次元pingストリーム配列の個別ストリームが繋がれて、単一の名称を有さない出力pingストリームが作られる。図13Bにおいては、単一のpingストリームであるpingStrmが式exprと繋がれて、exprと同じ型を有する単一の名称を有さない出力ストリームが作られる。join演算の1例は、データ構造Xを含み得る。ただし、データ構造Xについて、2つの演算、すなわち演算Aおよび演算Bが行われる。これらの演算は、以下の要件、すなわちago信号に応答して実行される以外には、演算Aも演算Bも実行されないこと、bgo信号が受信されると、演算Aおよび演算Bが並列的に実行されること、およびc演算Aまたは演算Bのいずれかが開始される前に、直前のgo信号に応答して実行された両方の演算が完了していなければならないこと、を満足する。この問題に対する簡単なソリューションは、join演算の2つのインスタンスを用いることである。streampingmoduleApingpStrm{whiletrue{pStrm>>ping;//データ構造X上で演算Aを実行するout<<ping;}}streampingmoduleBpingpStrm{whiletrue{pStrm>>ping;//データ構造Xに関して演算Bを実行するout<<ping;}}streampingmoduleCpinggoStrm{streampingstartStrm=goStrm.joindoneStrm;streampingStrmA=moduleAstartStrm;streampingStrmB=moduleBstartStrm;streampingdoneStrm=StrmA.joinStrmB;doneStrm.initializeping;out=doneStrm;}moduleAおよびmoduleBは、それぞれ演算Aおよび演算Bをカプセル化する。それぞれは、ping毎に1つの演算を開始する入力pingストリームと、ping毎に1つの演算の完了を確認する出力pingストリームとを有する。moduleCはmoduleAおよびmoduleBの両方の1つのインスタンスを含み、goStrm入力pingストリームを介してgo信号を受け取る。moduleCにおける6つの文は以下の役割を果たす。streampingstartStrm=goStrm.joindoneStrm;は、goStrmとdoneStrmとを繋いで、startStrmを作る。このように、goStrmすなわちgo信号上にpingが存在し、doneStrm上にpingが存在するこれは、直前のgo信号に応答した演算Aおよび演算Bが完了したことを示す場合に、pingがstartStrmに代入される。streampingStrmA=moduleAstartStrm;は、startStrmをmoduleAの入力pingストリームに接続し、moduleAの出力pingストリームをStrmAに接続する。このことは、演算Aは、直前のgo信号に関連付けられた両方の演算が完了した後にのみ、go信号に応答して行われることを意味する。streampingStrmB=moduleBstartStrm;は直前の文と同様であり、この文は、直前のgo信号に関連付けられた両方の演算が完了した後にのみ、演算Bがgo信号に応答して行われることが確実になされるようにする。しかし、演算Aおよび演算Bが行われる順序に制限はない。換言すれば、演算Aおよび演算Bは並列的に行われる。streampingdoneStrm=StrmA.joinStrmB;はmoduleAの出力pingストリームであるStrmAと、moduleBの出力pingストリームであるStrmBとを繋ぐ。このように、直前のgo信号に応答して行われた両方の演算が完了したならば、pingがdoneStrmに代入される。doneStrm.initializeping;は、システム初期化時に単一のpingをdoneStrmに代入する。このことは、すべての以前の演算が、まったく存在せず、完了したことを示す。この文がなければ、moduleCはデッドロックし、演算はまったく行われないであろう。out=doneStrm;は、doneStrmをmoduleCのデフォルト出力ストリームであるoutに接続する。このストリーム上の各pingは、go信号に応答して行われた演算Aおよび演算Bが完了したことを確認する。moduleCの挙動は、moduleCの入力ポート上でgo信号pingとして総括され、その結果、以前の演算が完了した後にのみ、演算Aおよび演算Bはデータ構造Xに関して並列的に行われ得る。演算Aおよび演算Bの両方が完了すると、モジュールCはその出力ポート上で確認としてpingを送信する。pingStrm>>ping;式中、pingStrmはping型のストリームであるの形の文は、スレッドの実行をpingStrm内のpingと同期する機能を有する。この文がスレッドにおいて遭遇されると、単一のpingがpingStrmから読み出される消費される。pingStrmが空き状態すなわち、pingStrmにpingが存在しないである場合、この文は、pingが利用可能となるまで、ブロックストールされる。したがって、この文は、pingがpingStrmに存在するときにのみスレッドの進行を許可する守衛として機能する。この演算では変数は関与せず、>>通常は変数の存在が期待される演算子の右側には、キーワードpingのみが存在する。pingStrm<<ping;式中、pingStrmはping型のストリームであるの形の文は、スレッドが、特定の演算単数または複数が完了したことを関係者に知らせることを可能にする。この文がスレッドにおいて遭遇されると、単一のpingがpingStrmに書き込まれる代入される。上述の第1の文とは異なり、この文は決してブロックされない。pingが関与するこれらの2つの形のストリーム/スレッド相互作用が、以下の部分的コードにおいて例示される。streampingmoduleApingpStrm{//ループに入る前に初期化を行うwhiletrue{pStrm>>ping;//副作用を有する演算を行うout<<ping;}}moduleAは、単一の入力ポートおよび単一の出力ポートを有し、その両方がping型である。moduleA内には無限ループを含むスレッドが存在する。なお、この無限ループの各反復は、以下の文pStrm>>ping;により開始される。この文は、ループの反復を、モジュール入力ストリームpStrmにおけるpingと同期させる機能を有する。pStrmが空き状態であるとき、この文はブロックされ、pStrmが非空き状態であるとき、この文はpStrmから単一のpingを消費する。その文に続いて、必ず副作用を伴う活動に関連する文がある。副作用がないなら、modleAは操作不能と等価となるであろう。各反復の末尾には、次の文out<<ping;が存在する。なお、この文は、moduleAの標準出力ポートを通して、他のループ反復が完了したことを知らせる。完全にストリームドメイン内で作業するとき、join演算子は有用である。しかし、スレッド内で結合を行うことがより便利となる状況も存在し得る。例えば、スレッドstreampingpingStrm[32];内で、個別ストリームを結合することを考えてみる。それは、スレッド内でforループを埋め込むことにより達成され得る。forinti=0;i<32;i{pingStrm[i]>>ping;}このループは、1つのpingがpingStrm内の32個のストリームのそれぞれから消費されるまで、ブロックされる。pingStrm[].joinの出力ストリームに対応する出力ストリームは、文joinStrm<<ping;を有するforループに従うことにより、作られる。pingStrm[].joinの挙動を模倣するモジュールを作るために、これらの2つの部分的コードがwhiletrueループに埋め込まれ、そのループは、モジュールstreampingjoinArraypingpingStrm[32]{whiletrue{forinti=0;i<32;ipingStrm[i]>>ping;out<<ping;}}に代入される。埋め込まれたスレッドを有するモジュールは、pingStrm.joinexpr式中、exprは式であるの挙動を模倣するために用いられ得る。しかし、この場合、モジュールは、pingStrmに対する入力ストリームばかりではなく、exprの各入力ストリームに対する入力ストリームも必要とする。したがって、例えば、exprが式XYZ式中、X、Y、およびZは整数であるである場合、pingStrm.joinexprを実装するモジュールは、streampingjoinExprpingpingStrm,intX,intY,intZ{whiletrue{pingStrm>>ping;out<<XYZ;}}のようになるであろう。画素処理例は、同一のタスクが配列等の同一のデータ構造の異なる部分上で並列的に並行して実行される、並列性の1つの形態であるデータ並列性の実装におけるping、ストリーム配列、およびモジュール配列の使用を示す。この例は、モジュール配列およびモジュールからなる。externintxScaleFactor,yScaleFactor;streampingdoPixel[64][256]intbaStrm//本体は{//スレッドドメインにあるconstintx=xScaleFactorindex0;constinty=yScaleFactorindex1;intbaseAddress;whiletrue{baStrm>>baseAddress;//演算をbaStrm[x][y]および//その近傍に関して行うout<<ping;}}streamvoidparentModuleintbaStrm//本体は{//ストリームドメイン内にあるstreampingxStrm[64][256];streampingjStrm;jStrm.initializeping;xStrm[][]=doPixel[][]jStrm.joinbaStrm;jStrm=xStrm[][].join;}2次元モジュール配列doPixel[64][256]は、画素の2次元配列のサイズと一致するように作られている。doPixel[64][256]が動作する画素配列のベースアドレスは、入力ストリームbaStrmにより供給される。個別doPixelモジュール上の画素のx座標は、個別doPixelモジュールのxインデックスであるindex0セクション5.3参照にグローバル定数xScaleFactorを乗算することにより得られる。個別doPixelモジュール上の画素のy座標は、個別doPixelモジュールのyインデックスであるindex1にグローバル定数yScaleFactorを乗算することにより得られる。各画素の処理は、変数baStrmをbaStrmの現在値に設定することにより始まる。次いで、baStrm[x][y]およびその近傍について演算が行われる。処理が終わると、個別doPixelモジュールはpingを発行することにより完了を知らせる。parentModuleは、画素配列のベースアドレスを、doPixel[64][256]内の個別モジュールにブロードキャストする機能を担当する。このことは、以下の文xStrm[][]=doPixel[][]jStrm.joinbaStrm;によりなされる。ここで、doPixelの入力引数リスト内の式jStrm.joinbaStrmは、jStrmにpingが存在する場合にのみbaStrm内の値が通過することを許可する守衛として機能する。以下の文jStrm.initializeping;によりjStrmに挿入される初期pingは、まさに第1のベースアドレスが妨げられずに通過することを許可する。その後、pingは、以下の文jStrm=xStrm[][].join;ここで、xStrm[64][256]は、doPixel[64][256]内の個々のモジュールにより作られたpingストリームの配列であるにより、jStrmに挿入される。したがって、新しいpingは、doPixel[64][256]内のすべのモジュールが、pingを発行することにより、以前の演算の完了を知らせる場合にのみ、jStrmに挿入される。これにより、画素配列に関するすべての演算は、次の配列に関する演算が開始される前に、確実に完了することとなる。標準的Cデータ型よりもむしろpingを用いることに、大きい利点が存在する。Cデータ型を用いると、先入れ先出しFIFOが、Cデータ型ストリームのすべてのデスティネーション、すなわち、ストリームが式への入力となるすべての位置において、データ値に必要とされる。しかしpingは互いに対して区別がつかないため、pingストリームの各デスティネーションにおいて必要とされるものは、キューに入れられたpingの個数を知らせるカウンタのみである。これにより、データ値に対する先入れ先出しキューと比較して、コストが顕著に削減されることとなる。pragmaコマンドはストリームCコンパイラ/リンカ/ローダに対する指示である。指示pragmaInitializeCountm,p,nは、モジュールmからnの入力/出力ポートpの消費側/作成側カウントを初期化する。pragmaコマンドは、モジュール定義pragmaFwrdsAckValuem,s,nの直後に続かなければならない。この定義は、nを、モジュールmの出力ストリームsから開始されるポイントトゥポイント接続に対するフォワードアクノレッジメント値として指定する。pragmaコマンドは、モジュールmの出力ストリームsから開始されるポイントトゥポイント接続に対するバックワードアクノレッジメント値としてnを指定するモジュール定義pragmaBwrdsAckValuem,s,nの直後に続かなければならない。pragmaコマンドは、モジュール定義の直後に続かなければならない。上述の概念のいくつかの利点例は、スレッドおよびマルチスレッド、すなわち、複数スレッドの並列実行のサポートである。また、SIMD、MIDM、命令レベル、タスクレベル、データ並列性、データフロー、およびSystolic等の並列性のすべての形態が表現可能である。決定的挙動がデフォルトである。非決定性は、プログラムに必要な場合にのみ明示的に追加される。なぜなら、ソフトウェアテストの容易性および信頼性をより効果的なものとするものは、逐次プログラミングの中にあるためである。上述した概念は、明示的な並列的構文を有さない。並列性は、普通の逐次コードに、少なくともシンタックスの面で、類似するストリームドメインにおけるコードから抜け落ちてしまう。したがって、スレッドドメインで作業するプログラマは厳格にシーケンシャル問題に集中してよい。プログラミングモデルは、モデルに基づく設計およびモデルに基づくテストに役立ち、プロセシングコアの任意の個数に応じて拡大縮小する。プログラミングモデルは、プロセシングコアを隔てる距離がナノメートル単位の場合にも千キロメートル単位の場合にも、等しく適用可能である。フォアグラウンドまたはバックグラウンドのタスクは存在せず、ただタスクのみが存在し、割込またはメッセージ引き渡しも存在せず、ただストリームのみが存在する。本発明は、本発明に係る特定の実施形態に関して説明してきたが、これらの実施形態は単に例示に過ぎず、本発明を限定するものではない。例えば、任意の種類の処理ユニット、機能的回路または、1つまたは複数のユニットの集合、および/またはメモリ、I/O素子、その他等のリソースがノードに含まれ得る。ノードは、簡単なレジスタでもよく、または、デジタル信号処理システム等のように、より複雑なものであってもよい。本明細書に説明したものではなく、他の種類のネットワークまたは相互接続方式も用いられ得る。本発明の特徴または態様は、好適な実施形態に関して本明細書で説明された適合システム以外のシステムにおいても達成され得る。"