JP2019204387A - プログラム実行制御方法およびプログラム変換装置 - Google Patents
プログラム実行制御方法およびプログラム変換装置 Download PDFInfo
- Publication number
- JP2019204387A JP2019204387A JP2018100236A JP2018100236A JP2019204387A JP 2019204387 A JP2019204387 A JP 2019204387A JP 2018100236 A JP2018100236 A JP 2018100236A JP 2018100236 A JP2018100236 A JP 2018100236A JP 2019204387 A JP2019204387 A JP 2019204387A
- Authority
- JP
- Japan
- Prior art keywords
- function
- functions
- process barrier
- execution
- barrier
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Pending
Links
Images
Landscapes
- Devices For Executing Special Programs (AREA)
Abstract
【課題】データ競合しない関数群は複数のコアで並行実行可能としつつ、データ競合する関数対は時間分離して実行させる。【解決手段】プログラム変換装置22Aは、並行実行可能な関数列20を入力として、データ競合する関数対は時間分離して実行されるようにそれらの関数間にプロセスバリア30を挿入し、ロックフリー関数キューLFQ1を出力し、プロセスバリア30は、データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行をプロセスバリア30の位置で待機させるとともに、データ競合する前後の関数のうち、前の関数の実行が完了したかを監視する。【選択図】図1
Description
本発明は、マルチコアまたはメニーコアによるプログラムの並列実行を可能とするプログラム実行制御方法およびプログラム変換装置に関する。
半導体微細化技術が行き詰まり、クロック周期の高速化による性能改善から、多数のコアを1つのMPU(Micro Processing Unit)に搭載することによる性能改善が図られるようになり、多様な形態に適したメニーコアMPUがサーバや携帯端末用途などに販売されている。これらの用途では、シングルコアMPUを前提として設計され、データ分離(data separation)条件が成立する複数のアプリケーションをOS(Operating System)が並行実行制御することにより、メニーコアの性能を引き出す設計を前提としている。この並行実行制御では、OS内の共有リソースへのリード・ライトアクセスが発生するものの、既存の排他制御機構を用いて強制的に関数を逐次実行させることで時間分離(temporal separation)を図り、データ競合に起因したデータ整合性の不具合の回避に一定の成功を収めている。
しかし、長年、シングルコアを前提として設計、継承および派生開発されてきた制御ソフトウェアでは、グローバル変数に代表される共有リソースに関するアクセス競合が顕著である。そのため、前記のようなデータ分離を前提としたプログラム並行実行をすることができず、OSのサポートもない。データ競合を許容するプログラム並行実行は非決定的(non−deterministic)な実行後プログラム状態を導くため、デバッグ、テストおよび検証ができなくなる。
また、実際には、割込み処理負荷を分散させるために、複数のコアには設計時点で想定困難な計算負荷が発生する。そのため、関数毎のコア占有時間を用いて明示的に関数割当てをして最適化を図る設計手法でも、時間同期による制御不能無駄時間の上限が不定である限りは、最悪時応答時間の保証をすることも困難である。
従来技術では、タスク間依存関係の制約を考慮して、各コアに静的に割り当てたタスクの実行順序を明示的に制御する多様な方法があるが、2つの共通した課題がある。第1の課題は、コア数N(Nは2以上の整数)に比例してスケールしない共有リソースの使用を前提としている点である。第2の課題は、割込み処理などの外乱負荷のために、設計時点で最適化して決定した静的なタスク割当をして実現される無駄時間の抑制が図られず、最悪応答時間の保証ができない点である。
特許文献1には、逐次実行プログラムを構成する複数のマクロタスク間で制御依存性を分析し、並列実行可能なマクロタスクを各コアに割り当てて、Time−Triggered Scheduling(TTS、特許文献1中でスタティックスケジューリング)による時間分離を図る。しかし、これは前記第2の課題を抱えている。
特許文献1に加えて、特許文献2では、制御依存性がある複数のマクロタスクを束ねるプログラム変換機能を追加することを提案している。この技術は、マクロタスクが短時間で終わるため、TTS自体のオーバーヘッドが顕在化することへの対策であるが、依然として前記第2の課題を抱えている。
特許文献3は、明示的にプロセス間通信の機構を使い、タスク実行順序と実行開始時点を制御する方法が開示されている。しかし、この方法は、前記第1の課題を抱えている上、コア数やコア構成の変更に対して、設計資産をそのまま移管できず、再設計が必要になる。
特許文献4では、プログラム依存グラフ(PDG:Program Dependency Graph)に基づき、タスク投入の制御を行う方法が開示されている。このPDGはバリア同期を用いた手法であるが、競合が発生し得る関数を実行する度に全コアの同期待ちが発生するために、実行速度がコア数に対してスケールしない。
従来のソフトウェア開発手法における設計、デバッグ、テスト技法、カバレッジ基準および検証手法はすべて、多数の関数を逐次実行し、実行後プログラム状態の再現性および予測性が前提として成立することに依存している。
また、前記再現性および予測性は、制御ソフトウェアに要求される最悪時応答時間を保証するために必要な要件でもある。よって、プログラム並行実行の具体的な実現手段に寄らず、データ分離条件が成立する関数群は複数のコアで並行実行し、データ競合のために時間分離が必要となる関数対は逐次実行される並行実行制御機構が必要である。
特に、コア数の増加に対してスケールしないコア間通信機構に依存せず、設計時に想定困難な割込み負荷に適応して、各コアの計算待ち時間が動的に平準化され、最悪実行時間を保証できるような並列実行制御機構が求められていた。
また、前記再現性および予測性は、制御ソフトウェアに要求される最悪時応答時間を保証するために必要な要件でもある。よって、プログラム並行実行の具体的な実現手段に寄らず、データ分離条件が成立する関数群は複数のコアで並行実行し、データ競合のために時間分離が必要となる関数対は逐次実行される並行実行制御機構が必要である。
特に、コア数の増加に対してスケールしないコア間通信機構に依存せず、設計時に想定困難な割込み負荷に適応して、各コアの計算待ち時間が動的に平準化され、最悪実行時間を保証できるような並列実行制御機構が求められていた。
本発明は、上記事情に鑑みなされたものであり、その目的は、データ競合しない関数群は複数のコアで並行実行可能としつつ、データ競合する関数対は時間分離して実行させることが可能なプログラム実行制御方法およびプログラム変換装置を提供することにある。
上記目的を達成するため、第1の観点に係るプログラム実行制御方法は、並行実行可能な複数の関数が順々に登録されたロックフリー関数キューを保持し、前記ロックフリー関数キューは、データ競合する関数間に挿入されたプロセスバリアを含み、前記プロセスバリアは、前記データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行を前記プロセスバリアの位置で待機させる。
本発明によれば、データ競合しない関数群は複数のコアで並行実行可能としつつ、データ競合する関数対は時間分離して実行させることができる。
実施形態について、図面を参照して説明する。なお、以下に説明する実施形態は特許請求の範囲に係る発明を限定するものではなく、また、実施形態の中で説明されている諸要素及びその組み合わせの全てが発明の解決手段に必須であるとは限らない。
図1は、第1実施形態に係るプログラム変換方法およびプログラム実行制御方法を示すブロック図である。
図1において、プログラム変換装置22Aはプログラム変換処理を行う。計算機1Aはプログラム並行実行処理を行う。
図1において、プログラム変換装置22Aはプログラム変換処理を行う。計算機1Aはプログラム並行実行処理を行う。
まず、プログラム変換装置22Aのプログラム変換処理について説明する。
プログラム変換装置22Aは、関数列20を入力として、データ競合する関数対は時間分離して実行されるようにそれらの関数間にプロセスバリア30を挿入し、ロックフリー関数キューLFQ1を出力する。関数列20は、並行実行可能な複数の関数21を備える。図1では、関数列20が、関数[0]〜関数[4]を備える例を示した。プロセスバリア30は、データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行をプロセスバリア30の位置で待機させる。この時、プロセスバリア30は、データ競合する前後の関数のうち、前の関数の実行が完了したかを監視する。プロセスバリア30は、ロックフリー関数キューLFQ1に登録された関数を実行するN個のコアのうち1個のコアに関数の実行の完了を監視させることができる。
プログラム変換装置22Aは、関数列20を入力として、データ競合する関数対は時間分離して実行されるようにそれらの関数間にプロセスバリア30を挿入し、ロックフリー関数キューLFQ1を出力する。関数列20は、並行実行可能な複数の関数21を備える。図1では、関数列20が、関数[0]〜関数[4]を備える例を示した。プロセスバリア30は、データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行をプロセスバリア30の位置で待機させる。この時、プロセスバリア30は、データ競合する前後の関数のうち、前の関数の実行が完了したかを監視する。プロセスバリア30は、ロックフリー関数キューLFQ1に登録された関数を実行するN個のコアのうち1個のコアに関数の実行の完了を監視させることができる。
ロックフリー関数キューLFQ1の各関数には、自身の関数の処理終了を示す終了フラグ36が追加される。各関数は、自身の関数の処理が終了すると、自身の終了フラグをtrueに設定し、自身の関数の処理が終了してない場合、自身の終了フラグをfalseに設定する。処理が終了してない関数の終了フラグ36を予めfalseに初期化し、自身の関数の処理が終了すると、自身の終了フラグをtrueに設定するようにしてもよい。
プロセスバリア30は、データ競合する前後の関数のうち、後の関数の直前に配置する。例えば、関数[0]と関数[2]がデータ競合35Aを引き起こすものとすると、プロセスバリア30は、関数[2]の直前に挿入される。この時、プロセスバリア30には、監視対象として関数[0]が設定される。
また、データ競合する前後の関数において、監視対象となる前の関数とデータ競合する後の関数が複数ある場合、後の関数のうちの最前の関数に対してのみプロセスバリアが挿入される。例えば、関数[0]と関数[2]がデータ競合35Aを引き起こし、関数[0]と関数[4]がデータ競合35Bを引き起こすものとすると、プロセスバリア30は、関数[2]の直前にのみ挿入され、関数[4]の直前には挿入されない。
また、プロセスバリア30は、ロックフリー関数キューLFQ1に登録された関数[0]〜関数[4]をプロセスバリア30で区分けされた範囲に含まれる関数間ではデータ競合が発生しないようにする。例えば、プロセスバリア30の前の関数[0]と関数[1]との間ではデータ競合が発生しない。さらに、プロセスバリア30の後の関数[2]と関数[3]と関数[4]との間ではデータ競合が発生しない。
また、プロセスバリアで区分けされた区間に含まれる関数の個数が最大になるようにプロセスバリアの位置を設定することが好ましい。この時、データ競合が発生しない関数間には余計なプロセスバリアが挿入されないようにすることができる。
プログラム変換装置22Aは、データ競合判定部23Aおよびプロセスバリア挿入部24Aを備える。データ競合判定部23Aは、並行実行可能な関数間でデータ競合が発生するかどうかを判定する。プロセスバリア挿入部24Aは、データ競合が発生する関数間にプロセスバリア30を挿入する。データ競合は、前後の関数の少なくとも一方が共有データまたは共有リソースに更新処理を実行して引き起こされる競合である。データ競合として、関数対のいずれもWriteを実行するWrite/Write競合と、関数対の一方がReadを実行し、他方がWriteを実行するRead/Write競合を挙げることができる。
この時、関数[0]〜関数[4]は、グローバル変数に代表される共有データに対してリードまたはライトアクセスすることができる。共有リソースへのアクセスも同様に、参照(リード)または更新(ライト)アクセスに分類されるので、データ競合と共有リソース競合を明示的に区別する必要はない。
図2は、図1の関数間のデータ競合関係の一例を示す図である。
図2において、関数[0]〜関数[4]からアクセスされるグローバル変数var[0]〜var[5]が定義されているものとする。ここで、グローバル変数var[0]に対しては、関数[0]がRead、関数[2]がWrite、グローバル変数var[1]に対しては、関数[0]、関数[1]および関数[4]がRead、グローバル変数var[2]に対しては、関数[1]がWrite、グローバル変数var[3]に対しては、関数[0]および関数[4]がWrite、グローバル変数var[4]に対しては、関数[3]がRead、グローバル変数var[5]に対しては、関数[3]がWriteするものとする。
図2において、関数[0]〜関数[4]からアクセスされるグローバル変数var[0]〜var[5]が定義されているものとする。ここで、グローバル変数var[0]に対しては、関数[0]がRead、関数[2]がWrite、グローバル変数var[1]に対しては、関数[0]、関数[1]および関数[4]がRead、グローバル変数var[2]に対しては、関数[1]がWrite、グローバル変数var[3]に対しては、関数[0]および関数[4]がWrite、グローバル変数var[4]に対しては、関数[3]がRead、グローバル変数var[5]に対しては、関数[3]がWriteするものとする。
関数の実行順序により、実行後のプログラム状態が変わるのは、少なくとも一方の関数がライト(更新)アクセスをする場合である。この時、図1のデータ競合判定部23Aは、関数[0]と関数[2]との間でデータ競合35Aが発生し、関数[0]と関数[4]との間でデータ競合35Bが発生すると判定する。一方、両方の関数ともリード(参照)アクセスをする場合では、関数の実行順序によって実行後のプログラム状態が変わることはない。このため、関数[0]と関数[1]との間や、関数[1]と関数[4]との間にデータ競合が発生すると判定されることはない。
図3は、第1実施形態に係るプログラム変換方法を示すフローチャートである。
図3において、各関数がリード(参照)またはライト(更新)対象とする共有データまたは共有リソースを解析する(S01)。次に、完了未確認関数リストに関数[0]を登録し、k=1に初期化する(S02)。
図3において、各関数がリード(参照)またはライト(更新)対象とする共有データまたは共有リソースを解析する(S01)。次に、完了未確認関数リストに関数[0]を登録し、k=1に初期化する(S02)。
次に、完了未確認関数リストに登録された関数のうち、関数[k]とデータ競合(Write/Write競合またはRead/Write競合)する関数[q](0≦q<k)があるかどうか判断する(S03)。関数[k]とデータ競合する関数[q]がない場合、完了未確認関数リストに関数[k]を登録し(S04)、kを1だけインクリメントする(S05)。
一方、S03において関数[k]とデータ競合する関数[q]がある場合、k=Nかどうか判断する(S06)。Nはコア数である。図1の例では、N=4である。k=Nでない場合、監視対象関数=関数[q]とするプロセスバリアを関数[k]の直前に挿入する(S07)。監視対象関数は、終了フラグ36が監視対象とされる関数である。さらに、完了未確認関数リストから関数[q]を削除し、S05に進む。一方、S06においてk=Nの場合、処理を終了する。
ここで、監視対象関数=関数[q]とする1つ目のプロセスバリアを関数[k]の直前に挿入した場合、完了未確認関数リストから関数[q]を削除する。これにより、監視対象関数=関数[q]とする2つ目のプロセスバリアが、監視対象関数=関数[q]とする1つ目のプロセスバリアの後に挿入されないようにすることができる。
例えば、図1の関数[0]が完了未確認関数リストに登録されている時に、図2のデータ競合関係を参照することにより、関数[2]は関数[0]とデータ競合すると判断される。このため、監視対象関数=関数[0]とするプロセスバリア30が関数[2]の直前に挿入される。この時、完了未確認関数リストから関数[0]が削除される。このため、図2のデータ競合関係では、関数[4]は関数[0]とデータ競合する場合においても、図3のS03においては、完了未確認関数リストに登録された関数のうち、関数[4]とデータ競合する関数[0]はないと判断される。このため、監視対象関数=関数[0]とするプロセスバリアが関数[4]の直前に挿入されないようにすることができる。
ここで、監視対象関数=関数[0]とするプロセスバリア30を関数[2]の直前に挿入した場合、プロセスバリア30は、関数[2]の実行が開始される時は、関数[0]の実行が終了していることを保証することができる。このため、関数[2]の後の関数[4]の実行が開始される時においても、関数[0]の実行が終了していることを保証することができる。この結果、関数[4]が関数[0]とデータ競合する場合においても、関数[4]の直前にプロセスバリアが挿入されないようにして、不要なプロセスバリアの挿入を防止することができる。
次に、計算機1Aのプログラム並列実行処理について説明する。
図1において、計算機1Aは、ロックフリー関数キューLFQ1に基づいてプログラム並行実行を行う。計算機1Aには、複数のコア10〜13、入出力インターフェース14、DRAM15およびキャッシュ16が設けられている。計算機1Aは、入出力インターフェース14を介してセンサ17およびアクチュエータ18に接続されている。コアはCPUごとに設けるようにしてもよいし、1つのCPUに複数のコアが設けられていてもよい。DRAM15は、コア10〜13からアクセス可能な共有メモリとして用いることができる。この時、各コア10〜13は、入出力インターフェース14を介してDRAM15およびキャッシュ16にアクセスすることができる。センサ17は、車両の各部の状態を監視する。アクチュエータ18は、車両のパワートレイン系、操舵系および制動系などを駆動する。
図1において、計算機1Aは、ロックフリー関数キューLFQ1に基づいてプログラム並行実行を行う。計算機1Aには、複数のコア10〜13、入出力インターフェース14、DRAM15およびキャッシュ16が設けられている。計算機1Aは、入出力インターフェース14を介してセンサ17およびアクチュエータ18に接続されている。コアはCPUごとに設けるようにしてもよいし、1つのCPUに複数のコアが設けられていてもよい。DRAM15は、コア10〜13からアクセス可能な共有メモリとして用いることができる。この時、各コア10〜13は、入出力インターフェース14を介してDRAM15およびキャッシュ16にアクセスすることができる。センサ17は、車両の各部の状態を監視する。アクチュエータ18は、車両のパワートレイン系、操舵系および制動系などを駆動する。
DRAM15は、ロックフリー関数キューLFQ1を保持する。また、DRAM15は、各コア10〜13が実行する実行コードを保持することができる。ロックフリー関数キューLFQ1には、計算機1Aで並行実行可能な複数の関数が順々に登録される。ロックフリー関数キューLFQ1は複数用意することができ、コア10〜13のいずれかが、例えば、10msecの周期でDRAM15に順次ロードすることができる。なお、実装の都合により、ロックフリー関数キューLFQ1には、関数の実体の代わりに、関数の実体へのポインタを登録してもよい。
プロセスバリア30は、データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行をプロセスバリア30の位置で待機させる。この時、プロセスバリア30で区切られてない関数については複数のコア10〜13による並行処理が可能である。例えば、関数[0]と関数[1]については、コア10〜13による並行処理が可能である。また、関数[2]〜関数[4]についても、コア10〜13による並行処理が可能である。この時、プロセスバリア30は、データ競合する前後の関数のうち、前の関数の実行が完了したかを監視し、前の関数の実行が完了すると、後の関数を実行するコア10〜13の割り当てを許容する。
プロセスバリア30は、指定の関数の処理完了を確認するチェッカ関数32と、プロセスバリア30より後の関数の実行を待機させるリミッタ関数33とを備える。チェッカ関数32とリミッタ関数33とは1個ずつプロセスバリア30に設けられ、チェッカ関数32とリミッタ関数33とは対をなす。リミッタ関数33は、チェッカ関数32の直後に配置される。チェッカ関数32には、監視対象関数のリストが追加される。監視対象関数が複数ある場合は、それら全てのすべての監視対象関数をチェッカ関数32に登録する。図3では、チェッカ関数32として、プロセスバリア[0]_checker、監視対象関数=関数[0]が挿入され、リミッタ関数33としてプロセスバリア[0]_limiterが挿入された例を示した。
プロセスバリア30は、関数間のデータ競合に応じてロックフリー関数キューLFQ1に複数挿入することができる。これらのプロセスバリア30を区別するため、プロセスバリア30には、プロセスバリアID34が付される。この時、同じプロセスバリア30に所属するチェッカ関数32とリミッタ関数33は同じプロセスバリアID34を保持する。
チェッカ関数32は、指定の関数の処理完了を確認すると、チェッカ関数32と対となるリミッタ関数33をロックフリー関数キューLFQ1から削除する。各コア10〜13は、プロセスバリア30の処理時に関数の取得および実行を中断し、リミッタ関数33の削除後に、ロックフリー関数キューLFQ1から関数を取得して実行する処理を再開する。
ここで、指定の関数の実行の完了を監視するコアは、指定の関数を実行するコアとは別個に割り当てることができる。さらに、指定の関数を実行するコアと指定の関数の実行の完了を監視するコア以外の他のコアは、指定の関数の実行が完了するまで、プロセスバリア30に後続する関数の実行がプロセスバリア[0]_limiterにて阻止される。
ロックフリー関数キューLFQ1に登録されたエントリの取得に際しては、各コア10〜13は、ロックフリー関数キューLFQ1の先頭エントリの関数を読み取る。この時、各コア10〜13は、HEAD41とTAIL42という変数を参照することにより、先頭または最後の登録エントリの位置を知ることができる。HEAD41とTAIL42は、アクセスの高速化を図るために、キャッシュ16に保持させることができる。なお、HEAD41とTAIL42は、DRAM15が保持するようにしてもよい。そして、HEAD41のアクセス回数に応じてHEAD41がキャッシュ16に保持されるようにしてもよい。
mutex等の排他制御機構を用いることなくデータ競合を回避し、複数のコア10〜13がHEAD値とTAIL値を更新するには、HEAD値とTAIL値をアトミックに書き換え可能なCAS(compare−and−swap)命令を用いてロックフリー関数キューLFQ1をロックフリー化することができる。CAS命令の実行に成功したコア10〜13は、ロックフリー関数キューLFQ1の先頭エントリを取得し、HEAD値を次の登録エントリに進める。HEAD値に対するライトアクセス競合のために、CAS命令の実行に失敗したコア10〜13は、更新されたHEAD値に対して再度CAS命令を実行することで登録エントリを取得する。この時、複数のコア10〜13がHEAD値に同時にアクセスした場合においても、必ず1つのコアはCAS命令の実行に成功し、HEAD値に同時にアクセスした全てのコアがCAS命令の実行に失敗することはない。このため、コア数Nが有限である限りは、CAS命令の実行の失敗が際限なく何度も繰り返されるのを防止することができ、エントリ取得時の無駄時間を低減することができる。
このプロセスバリア30の導入により、ロックフリー関数キューLFQ1の処理に関与するコアの個数を固定する必要がなくなる。このため、各コアの実際の処理負荷に応じてロックフリー関数キューLFQ1の処理に割り当てるコアの個数を動的に変えることができ、計算負荷の平準化および最悪応答時間を保証することができる。
また、プロセスバリア30は、プロセスバリア30より前の全ての関数の実行が完了しなくても、監視対象関数の実行が完了すると、プロセスバリア30に後続する関数を実行させることができ、プロセスバリア30に後続する関数の実行の待ち時間を減らすことができる。
図4は、図1のロックフリー関数キューについてのプログラム実行制御方法を示すタイミングチャートである。なお、図1および図4の例では、並行実行される関数[0]および関数[1]において、監視対象関数である関数[0]が、監視対象関数でない関数[1]より早く終了した場合を示した。
図1および図4において、並行実行可能なコアがコア10〜12であるものとする。HEAD41は、ロックフリー関数キューLFQ1の先頭エントリとして関数[0]を示しているものとする。そして、コア10〜12がCAS命令を実行し、コア10がCAS命令の実行に成功したものとすると、コア10は、HEAD41が示す関数[0]を取得し、関数[0]を実行するとともに、HEAD41を次の登録エントリに進める(P10)。この時、HEAD41は、ロックフリー関数キューLFQ1の先頭エントリとして関数[1]を示す。
図1および図4において、並行実行可能なコアがコア10〜12であるものとする。HEAD41は、ロックフリー関数キューLFQ1の先頭エントリとして関数[0]を示しているものとする。そして、コア10〜12がCAS命令を実行し、コア10がCAS命令の実行に成功したものとすると、コア10は、HEAD41が示す関数[0]を取得し、関数[0]を実行するとともに、HEAD41を次の登録エントリに進める(P10)。この時、HEAD41は、ロックフリー関数キューLFQ1の先頭エントリとして関数[1]を示す。
次に、前回CAS命令の実行に失敗したコア11、12はCAS命令を再度実行し、コア11がCAS命令の実行に成功したものとすると、コア11は、HEAD41が示す関数[1]を取得し、関数[1]を実行するとともに、HEAD41を次の登録エントリに進める(P11)。この時、HEAD41は、ロックフリー関数キューLFQ1の先頭エントリとしてプロセスバリア[0]_checkerを示す。また、関数[0]と関数[1]は、コア10、11にて並行実行される。
次に、前回CAS命令の実行に失敗したコア12はCAS命令を再度実行し、コア12がCAS命令の実行に成功したものとすると、コア12は、HEAD41が示すプロセスバリア[0]_checkerを取得し、プロセスバリア[0]_checkerの処理を実行するとともに、HEAD41を次の登録エントリに進める(P12)。この時、HEAD41は、ロックフリー関数キューLFQ1の先頭エントリとしてプロセスバリア[0]_limiterを示す。
次に、コア10は、関数[0]の実行を完了したものとすると、関数[0]の終了フラグ36をtrueに設定し、CAS命令を実行する。そして、コア10は、CAS命令の実行に成功すると、HEAD41が示すプロセスバリア[0]_limiterを取得し、プロセスバリア[0]_limiterの処理を実行する(P13)。この時、コア10は、HEAD41を次の登録エントリに進めることなく、HEAD値をそのままにする。このため、HEAD41は、ロックフリー関数キューLFQ1の先頭エントリとしてプロセスバリア[0]_limiterを示したままとなる。プロセスバリア[0]_limiterの処理では、コア10は、ロックフリー関数キューLFQ1の先頭エントリを読み取り、その先頭エントリがプロセスバリア[0]_limiterである場合は、ロックフリー関数キューLFQ1の先頭エントリの読み取りを繰り返す。
プロセスバリア[0]_checkerの処理を実行しているコア12は、監視対象関数である関数[0]の終了フラグ36を監視し、関数[0]の終了フラグ36がfalseの場合は、関数[0]の終了フラグ36の監視を継続する。
一方、コア12は、関数[0]の終了フラグ36がtrueになると、プロセスバリア[0]_limiterをデキューし、プロセスバリア[0]_checkerの処理を終了する。この時、コア12は、HEAD41を次の登録エントリに進める。このため、HEAD41は、ロックフリー関数キューLFQ1の先頭エントリとして関数[2]を示す。
HEAD41が、ロックフリー関数キューLFQ1の先頭エントリとして関数[2]を示すと、ロックフリー関数キューLFQ1の先頭エントリがプロセスバリア[0]_limiterでなくなる。この時、プロセスバリア[0]_limiterの処理を実行しているコア10は、ロックフリー関数キューLFQ1の先頭エントリを読み取ると、その先頭エントリがプロセスバリア[0]_limiterでないため、プロセスバリア[0]_limiterの処理から抜け出し、プロセスバリア30を通過することができる。また、コア12がプロセスバリア[0]_limiterをデキューすることにより、コア11、12は、プロセスバリア30を通過することができる。
コア10、12は、プロセスバリア30を通過すると、CAS命令を実行する。そして、CAS命令が成功した順序に従ってコア10、12は関数[2]および関数[3]を取得し、関数[2]および関数[3]を並行実行する。この時、各コア10、12は、HEAD41の登録エントリをそれぞれ先に進める。このため、HEAD41は、ロックフリー関数キューLFQ1の先頭エントリとして関数[4]を示す。
コア11は、コア10、12が関数[2]および関数[3]を実行している間も、関数[1]の実行を継続する。そして、コア11は、関数[1]の実行が完了すると、CAS命令を実行する。コア11がCAS命令の実行に成功すると、コア11は、HEAD41が示す関数[4]を取得し、関数[4]を実行する。コア11が関数[1]の実行を完了した時には、プロセスバリア[0]_limiterはデキューされている。このため、コア11は、プロセスバリア30による待機時間なく、関数[1]の実行に引き続いて関数[4]を実行することができる。
上述した第1実施形態では、コア10による関数[0]の実行が完了すると、コア12によってプロセスバリア[0]_limiterがデキューされる。このため、コア10による関数[0]の実行が完了すると、コア11による関数[1]の実行が完了しなくても、コア10、12は関数[2]および関数[3]を実行することができる。このため、関数[2]および関数[3]の実行を開始するまでの待ち時間を短縮することができる。
なお、図4において、コア10が関数[0]の実行を完了し、関数[0]の終了フラグ36をtrueに設定した後、コア10がCAS命令の実行に成功する前に、コア12がプロセスバリア[0]_limiterをデキューした場合には、コア10は、プロセスバリア[0]_limiterの処理(P13)をスキップし、関数[3]を実行することができる。
さらに、CAS命令の実行に成功したコア10〜13がHEAD値で示される関数の実行を順次開始することで、データ競合しない関数群を並行実行しつつ、データ競合する関数対は時間分離して実行することができる。このため、ロックフリー関数キューLFQ1に登録された関数をコア10〜13が実行するためのスケジューリング調整を不要とすることができる。
また、関数を実行しているコアに割込みが入り、その関数の実行の完了が遅れる場合においても、他のコアは関数の取得および実行を継続することができる。このため、関数を実行しているコアに割込みが入った場合においても、他のコアに負荷分散することができ、外部デバイスからの割込み処理に対する応答時間の抑制と負荷平準化を図ることができる。
図5は、図1のロックフリー関数キューの実行中に割込みが入った時のプログラム実行制御方法を示すタイミングチャートである。
図5において、例えば、関数[1]を実行しているコア11に割込みが入り、コア11が割込み処理を実行するため、図4に示すように、コア11は関数[1]の実行の完了に引き続いて関数[4]を実行できないものとする。この場合においても、コア12が関数[2]の実行を完了すると、コア12は引き続いて関数[4]を実行することができる。このため、コア12は、コア11による割込み処理の完了を待たずに関数[4]の実行を開始することができ、割込み処理などの外乱負荷があった場合においても、最悪応答時間を保証することが可能となる。
図5において、例えば、関数[1]を実行しているコア11に割込みが入り、コア11が割込み処理を実行するため、図4に示すように、コア11は関数[1]の実行の完了に引き続いて関数[4]を実行できないものとする。この場合においても、コア12が関数[2]の実行を完了すると、コア12は引き続いて関数[4]を実行することができる。このため、コア12は、コア11による割込み処理の完了を待たずに関数[4]の実行を開始することができ、割込み処理などの外乱負荷があった場合においても、最悪応答時間を保証することが可能となる。
図6は、第1実施形態に係るプログラム実行制御方法を示すフローチャートである。
図6のS11において、各コア10〜13は、ロックフリー関数キューLFQ1が空か否かを判定する。ロックフリー関数キューLFQ1が空であれば処理を終了する。ロックフリー関数キューLFQ1が空でなければ、S12に進み、先頭エントリをロックフリー関数キューLFQ1から読み取る。読み取ったエントリがリミッタ関数でなければ、その先頭エントリを取得し、リミッタ関数であれば返り値falseを返す。この時、リミッタ関数を示していたHEAD値はそのまま維持し、HEAD値を次の登録エントリに進めない。
図6のS11において、各コア10〜13は、ロックフリー関数キューLFQ1が空か否かを判定する。ロックフリー関数キューLFQ1が空であれば処理を終了する。ロックフリー関数キューLFQ1が空でなければ、S12に進み、先頭エントリをロックフリー関数キューLFQ1から読み取る。読み取ったエントリがリミッタ関数でなければ、その先頭エントリを取得し、リミッタ関数であれば返り値falseを返す。この時、リミッタ関数を示していたHEAD値はそのまま維持し、HEAD値を次の登録エントリに進めない。
次に、S13において、各コア10〜13は、ロックフリー関数キューLFQ1から取得した関数がチェッカ関数32であるか判定し、チェッカ関数32である場合にはS17に進み、チェッカ関数22の処理102を実行する。チェッカ関数32でない場合にはS14に進み、各コア10〜13は、リミッタ関数33であるか判定する。リミッタ関数33である場合にはS20に進み、リミッタ関数33の処理101を実行する。リミッタ関数33でない場合には、各コア10〜13は、S15に進み、S12で取得した関数を実行する。次に、S16において、S15で実行した関数の終了フラグ36をtrueにセットし、S11に戻る。
チェッカ関数32の処理102において、S17では、監視対象関数の終了フラグ36を読み出し、終了フラグ36がtrueであるかを判定する。終了フラグ36がtrueでない場合、S17の処理を繰り返す。あるコアがチェッカ関数32の処理102を実行している時に、監視対象関数を処理する他のコアが監視対象関数の実行を完了すると、監視対象関数の実行を完了したコアは、監視対象関数の終了フラグ36をtrueに設定する。
監視対象関数の終了フラグ36が他のコアによりtrueに設定されると、チェッカ関数32の処理102を実行しているコアは、S17において、終了フラグ36がtrueであると判定し、S18に進む。なお、チェッカ関数32に複数の監視対象関数が登録されている場合、全ての監視対象関数の終了フラグ36がtrueである時に、S18に進む。S18では、チェッカ関数32の処理102を実行しているコアは、リミッタ関数33をデキューし、S19に進む。S19では、チェッカ関数32の処理102を実行しているコアは、チェッカ関数32の処理を終了してS11に戻る。
リミッタ関数33の処理101において、S20では、先頭エントリをロックフリー関数キューLFQ1から読み取る。次に、S21において、リミッタ関数33の処理101を実行しているコアは、S20で取得した関数が、S14のリミッタ関数33と同じプロセスバリアID34を持つリミッタ関数33であるかを判定する。なお、簡単のために、ロックフリー関数キューLFQ1のHEAD値を参照および比較してもよい。同じプロセスバリアID34を持つリミッタ関数33である場合はS20に戻り、ロックフリー関数キューLFQ1の先頭エントリの読み取りを繰り返す。
あるコアがリミッタ関数33の処理101を実行している時に、チェッカ関数32の処理102を実行しているコアがリミッタ関数33をデキューすると、ロックフリー関数キューLFQ1の先頭エントリは、同じプロセスバリアID34を持つリミッタ関数33でなくなる。このため、S21において、リミッタ関数33の処理101を実行しているコアは、S20で取得した関数が同じプロセスバリアID34を持つリミッタ関数33でないと判定し、S11に戻る。
これにより、チェッカ関数32が監視対象とする関数の実行が完了した時点でリミッタ関数33がデキューされ、S20で行っていたループ監視処理に伴う無駄時間がなくなることから、処理の高速化を図ることができる。また、関数処理に割り当てられるコアの個数の指定は必要でなくなる。ロックフリー関数キューLFQ1に登録された関数を処理している任意の時点で、そのロックフリー関数キューLFQ1に登録された関数を実行するコアを追加してもよいし、いくつかのコアを別のロックフリー関数キューの処理に再割当てしてもよい。
図7は、第2実施形態に係るプログラム変換方法およびプログラム実行制御方法を示すブロック図である。
図7において、プログラム変換装置22Bはプログラム変換処理を行う。計算機1Bはプログラム並行実行処理を行う。
図7において、プログラム変換装置22Bはプログラム変換処理を行う。計算機1Bはプログラム並行実行処理を行う。
まず、プログラム変換装置22Bのプログラム変換処理について説明する。
プログラム変換装置22Bは、並行実行可能な関数列20を入力として、データ競合する関数対は時間分離して実行されるようにそれらの関数間にプロセスバリア50を挿入し、ロックフリー関数キューLFQ2を出力する。プロセスバリア50は、データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行をプロセスバリア50の位置で待機させる。この時、プロセスバリア50は、データ競合する前後の関数のうち、前の関数の実行が完了したかを監視する。プロセスバリア50は、ロックフリー関数キューLFQ1に登録された関数を実行するN個のコアのうち(N−1)個以下のコアに関数の実行の完了を監視させることができる。
プログラム変換装置22Bは、並行実行可能な関数列20を入力として、データ競合する関数対は時間分離して実行されるようにそれらの関数間にプロセスバリア50を挿入し、ロックフリー関数キューLFQ2を出力する。プロセスバリア50は、データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行をプロセスバリア50の位置で待機させる。この時、プロセスバリア50は、データ競合する前後の関数のうち、前の関数の実行が完了したかを監視する。プロセスバリア50は、ロックフリー関数キューLFQ1に登録された関数を実行するN個のコアのうち(N−1)個以下のコアに関数の実行の完了を監視させることができる。
ロックフリー関数キューLFQ2の各関数には、自身の関数の処理終了を示す終了フラグ56が追加される。各関数は、自身の関数の処理が終了すると、自身の終了フラグをtrueに設定し、自身の関数の処理が終了してない場合、自身の終了フラグをfalseに設定する。
プロセスバリア50は、データ競合する前後の関数のうち、後の関数の直前に配置する。例えば、関数[0]と関数[2]がデータ競合35Aを引き起こすものとすると、プロセスバリア30は、関数[2]の直前に挿入される。この時、プロセスバリア50には、監視対象として関数[0]が設定される。
また、データ競合する前後の関数において、監視対象となる前の関数とデータ競合する後の関数が複数ある場合、後の関数のうちの最前の関数に対してのみプロセスバリアが挿入される。例えば、関数[0]と関数[2]がデータ競合35Aを引き起こし、関数[0]と関数[4]がデータ競合35Bを引き起こすものとすると、プロセスバリア50は、関数[2]の直前にのみ挿入され、関数[4]の直前には挿入されない。
プログラム変換装置22Bは、データ競合判定部23Bおよびプロセスバリア挿入部24Bを備える。データ競合判定部23Bは、並行実行可能な関数間でデータ競合が発生するかどうかを判定する。プロセスバリア挿入部24Bは、データ競合が発生する関数間にプロセスバリア50を挿入する。
図8は、第2実施形態に係るプログラム変換方法を示すフローチャートである。
図8において、各関数がリード(参照)またはライト(更新)対象とする共有データまたは共有リソースを解析する(S31)。
図8において、各関数がリード(参照)またはライト(更新)対象とする共有データまたは共有リソースを解析する(S31)。
次に、j=0、k=1から始めて関数[j]から関数[j+k]までの間でデータ競合(Write/Write競合またはRead/Write競合)する関数[q](j≦q<j+k)があるかどうか判断する(S32)。関数[j]から関数[j+k]までの間でデータ競合する関数[k]がない場合、kを1だけインクリメントし、S32の処理を繰り返す(S33)。
一方、S32において関数[j]から関数[j+k]までの間でデータ競合する関数[k]がある場合、j+k=Nかどうか判断する(S34)。j+k=Nでない場合、監視対象関数=関数[q]とするプロセスバリアを関数[j+k−1]の直後に挿入し、j=j+kかつk=1に設定して、S32に進む。一方、S34においてk=Nの場合、処理を終了する。
次に、計算機1Bのプログラム並列実行処理について説明する。
図7において、計算機1Bは、ロックフリー関数キューLFQ2に基づいてプログラム並行実行を行う。計算機1Bには、複数のコア10〜13、入出力インターフェース14、DRAM15およびキャッシュ16が設けられている。計算機1Bは、入出力インターフェース14を介してセンサ17およびアクチュエータ18に接続されている。
図7において、計算機1Bは、ロックフリー関数キューLFQ2に基づいてプログラム並行実行を行う。計算機1Bには、複数のコア10〜13、入出力インターフェース14、DRAM15およびキャッシュ16が設けられている。計算機1Bは、入出力インターフェース14を介してセンサ17およびアクチュエータ18に接続されている。
DRAM15は、ロックフリー関数キューLFQ2を保持する。ロックフリー関数キューLFQ2には、計算機1Bで並行実行可能な複数の関数が順々に登録される。プロセスバリア50は、データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行をプロセスバリア50の位置で待機させる。この時、プロセスバリア50で区切られてない関数については複数のコア10〜13による並行処理が可能である。例えば、関数[0]と関数[1]については、コア10〜13による並行処理が可能である。また、関数[2]〜関数[4]についても、コア10〜13による並行処理が可能である。この時、プロセスバリア50は、データ競合する前後の関数のうち、前の関数の実行が完了したかを監視し、前の関数の実行が完了すると、後の関数を実行するコア10〜13の割り当てを許容する。
プロセスバリア50は、並行実行可能なN−1個のチェッカ関数52と1個のリミッタ関数53とを備える。リミッタ関数53は、最後のチェッカ関数52の直後に配置される。例えば、並行実行可能なコアがコア10〜13であるものとすると、プロセスバリア50には、3個のチェッカ関数52と1個のリミッタ関数53が設けられる。この時、3個のチェッカ関数52は、4個のコア10〜13のうちいずれか3個のコアに割り当てることがきる。各チェッカ関数52は、指定の関数の処理完了を確認するまでプロセスバリア50より後の関数の実行をコアごとに待機させる。チェッカ関数52には、監視対象関数のリストが追加される。この時、N−1個のチェッカ関数52には、同一の監視対象関数が設定される。リミッタ関数23は、何も処理をせず終了する空関数である。
図7では、チェッカ関数52として、プロセスバリア[0]_checker[0]、プロセスバリア[0]_checker[1]およびプロセスバリア[0]_checker[2]が挿入され、リミッタ関数53としてプロセスバリア[0]_limiterが挿入された例を示した。さらに、プロセスバリア[0]_checker[0]、プロセスバリア[0]_checker[1]およびプロセスバリア[0]_checker[2]には、監視対象関数=関数[0]が設定されている例を示した。
プロセスバリア50は、関数間のデータ競合に応じてロックフリー関数キューLFQ2に複数挿入することができる。これらのプロセスバリア50を区別するため、プロセスバリア50には、プロセスバリアID54が付される。この時、同じプロセスバリア50に所属するチェッカ関数52とリミッタ関数53は同じプロセスバリアID54を保持する。
N−1個のうちのいずれか1個のチェッカ関数52が、指定の関数の処理完了を確認すると、チェッカ関数52と対となるリミッタ関数53をロックフリー関数キューLFQ2から削除する。各コア10〜13は、プロセスバリア50の処理時に関数の取得および実行を中断し、リミッタ関数53の削除後に、ロックフリー関数キューLFQ2から関数を取得して実行する処理を再開する。ここで、指定の関数を実行するコアX1以外のコアX2〜XNは、指定の関数の実行が完了するまで、プロセスバリア50に後続する関数の実行がプロセスバリア[0]_checker[0]〜プロセスバリア[0]_checker[N−2]にて阻止される。
例えば、HEAD41は、ロックフリー関数キューLFQ2の先頭エントリとして関数[0]を示しているものとする。そして、コア10〜13がCAS命令を実行し、コア10がCAS命令の実行に成功したものとすると、コア10は、HEAD41が示す関数[0]を取得し、関数[0]を実行するとともに、HEAD41を次の登録エントリに進める(P20)。この時、HEAD41は、ロックフリー関数キューLFQ2の先頭エントリとして関数[1]を示す。
次に、前回CAS命令の実行に失敗したコア11〜13はCAS命令を再度実行し、コア11がCAS命令の実行に成功したものとすると、コア11は、HEAD41が示す関数[1]を取得し、関数[1]を実行するとともに、HEAD41を次の登録エントリに進める(P21)。この時、HEAD41は、ロックフリー関数キューLFQ2の先頭エントリとしてプロセスバリア[0]_checker[0]を示す。また、関数[0]と関数[1]は、コア10、11にて並行実行される。
次に、前回CAS命令の実行に失敗したコア12、13はCAS命令を再度実行し、コア12がCAS命令の実行に成功したものとすると、コア12は、HEAD41が示すプロセスバリア[0]_checker[0]を取得し、プロセスバリア[0]_checker[0]の処理を実行するとともに、HEAD41を次の登録エントリに進める(P22)。この時、HEAD41は、ロックフリー関数キューLFQ2の先頭エントリとしてプロセスバリア[0]_checker[1]を示す。また、関数[0]と関数[1]とプロセスバリア[0]_checker[0]は、コア10〜12にて並行実行される。この時、コア12は、監視対象関数である関数[0]の終了フラグ56を監視し、関数[0]の終了フラグ56がfalseの場合は、関数[0]の終了フラグ56の監視を継続する。
次に、前回CAS命令の実行に失敗したコア13はCAS命令を再度実行し、コア13がCAS命令の実行に成功したものとすると、コア13は、HEAD41が示すプロセスバリア[0]_checker[1]を取得し、プロセスバリア[0]_checker[1]の処理を実行するとともに、HEAD41を次の登録エントリに進める(P23)。この時、HEAD41は、ロックフリー関数キューLFQ2の先頭エントリとしてプロセスバリア[0]_checker[2]を示す。また、関数[0]と関数[1]とプロセスバリア[0]_checker[0]とプロセスバリア[0]_checker[1]は、コア10〜13にて並行実行される。この時、コア13は、監視対象関数である関数[0]の終了フラグ56を監視し、関数[0]の終了フラグ56がfalseの場合は、関数[0]の終了フラグ56の監視を継続する。
次に、コア10は、関数[0]の実行を完了したものとすると、関数[0]の終了フラグ56をtrueに設定し、CAS命令を実行する。そして、コア10は、CAS命令の実行に成功すると、HEAD41が示すプロセスバリア[0]_checker[2]を取得し、プロセスバリア[0]__checker[2]の処理を実行するとともに、HEAD41を次の登録エントリに進める(P24)。この時、HEAD41は、ロックフリー関数キューLFQ2の先頭エントリとしてプロセスバリア[0]_limiterを示す。また、関数[1]とプロセスバリア[0]_checker[0]とプロセスバリア[0]_checker[1]とプロセスバリア[0]_checker[2]は、コア10〜13にて並行実行される。
この時、コア10は、監視対象関数である関数[0]の終了フラグ56を監視し、関数[0]の終了フラグ56がtrueになると、プロセスバリア[0]_limiterをデキューし、プロセスバリア[0]_checker[2]の処理を終了する。この時、コア12は、HEAD41を次の登録エントリに進める。このため、HEAD41は、ロックフリー関数キューLFQ2の先頭エントリとして関数[2]を示す。
コア12、13は、関数[0]の終了フラグ56がtrueになると、プロセスバリア[0]_checker[0]およびプロセスバリア[0]_checker[1]の処理を終了する。この時、コア12、13は、プロセスバリア[0]_limiterが既にデキューされているので、プロセスバリア[0]_limiterのデキューをスキップする。プロセスバリア[0]_limiterのデキューをスキップした場合は、HEAD41を次の登録エントリに進めないようにする。このため、HEAD41は、ロックフリー関数キューLFQ2の先頭エントリとして関数[2]を示したままとなる。
コア10、12、13は、プロセスバリア50を通過すると、CAS命令を実行する。そして、CAS命令が成功した順序に従ってコア10、12、13は関数[2]、関数[3]および関数[4]を取得し、関数[2]、関数[3]および関数[4]を並行実行する。この時、コア11は、コア10、12、13が関数[2]、関数[3]および関数[4]を実行している間も、関数[1]の実行を継続する。そして、コア11は、関数[1]の実行が完了すると、CAS命令を実行することができる。コア11が関数[1]の実行を完了した時には、プロセスバリア[0]_limiterはデキューされている。このため、コア11は、プロセスバリア50による待機時間なく、関数[1]の実行に引き続いて次の処理を実行することができる。
図9は、図1のプログラム変換装置のハードウェア構成例を示すブロック図である。
図9において、プログラム変換装置22Aには、プロセッサ101、通信制御デバイス102、通信インターフェース103、主記憶デバイス104、外部記憶デバイス105および出力インターフェース107が設けられている。プロセッサ101、通信制御デバイス102、通信インターフェース103、主記憶デバイス104および外部記憶デバイス105および出力インターフェース107は、内部バス106を介して相互に接続されている。主記憶デバイス104および外部記憶デバイス105は、プロセッサ101からアクセス可能である。
図9において、プログラム変換装置22Aには、プロセッサ101、通信制御デバイス102、通信インターフェース103、主記憶デバイス104、外部記憶デバイス105および出力インターフェース107が設けられている。プロセッサ101、通信制御デバイス102、通信インターフェース103、主記憶デバイス104および外部記憶デバイス105および出力インターフェース107は、内部バス106を介して相互に接続されている。主記憶デバイス104および外部記憶デバイス105は、プロセッサ101からアクセス可能である。
プロセッサ101は、プログラム変換装置22A全体の動作制御を司るハードウェアである。主記憶デバイス104は、例えば、SRAMまたはDRAMなどの半導体メモリから構成することができる。主記憶デバイス104には、プロセッサ101が実行中のプログラムを格納したり、プロセッサ101がプログラムを実行するためのワークエリアを設けたりすることができる。
外部記憶デバイス105は、大容量の記憶容量を有する記憶デバイスであり、例えば、ハードディスク装置やSSD(Solid State Drive)である。外部記憶デバイス105は、各種プログラムの実行ファイルやプログラムの実行に用いられるデータを保持することができる。外部記憶デバイス105には、データ競合判定プログラム105Aおよびプロセスバリア挿入プログラム105Bを格納することができる。データ競合判定プログラム105Aおよびプロセスバリア挿入プログラム105Bは、プログラム変換装置22Aにインストール可能なソフトウェアであってもよいし、プログラム変換装置22Aにファームウェアとして組み込まれていてもよい。
通信制御デバイス102は、外部との通信を制御する機能を有するハードウェアである。通信制御デバイス102は、通信インターフェース103を介してネットワーク109に接続される。ネットワーク109は、インターネットなどのWAN(Wide Area Network)であってもよいし、WiFiなどのLAN(Local Area Network)であってもよいし、WANとLANが混在していてもよい。入出力インターフェース107は、データ入出力機能を有するハードウェアである。
プロセッサ101がデータ競合判定プログラム105Aおよびプロセスバリア挿入プログラム105Bを主記憶デバイス104に読み出し、データ競合判定プログラム105Aおよびプロセスバリア挿入プログラム105Bを実行することにより、並行実行可能な関数間でデータ競合が発生するかどうかを判定し、データ競合が発生する関数間にプロセスバリアを挿入することができる。この時、プロセッサ101は、入出力インターフェース107を介し、プロセスバリア挿入前の関数列を取得し、その関数列の関数間にプロセスバリアが挿入されたロックフリー関数キューLFQ1を出力することができる。
ここで、データ競合判定プログラム105Aは、図1のデータ競合判定部23Aの機能を実現し、プロセスバリア挿入プログラム105Bは、図1のプロセスバリア挿入部24Aの機能を実現することができる。
なお、データ競合判定プログラム105Aおよびプロセスバリア挿入プログラム105Bの実行は、複数のプロセッサやコンピュータに分担させてもよい。あるいは、プロセッサ101は、ネットワーク109を介してクラウドコンピュータなどにデータ競合判定プログラム105Aおよびプロセスバリア挿入プログラム105Bの全部または一部の実行を指示し、その実行結果を受け取るようにしてもよい。
1A、1B 計算機、10〜13 コア、14 入出力インターフェース、15 DRAM、16 キャッシュ、17 センサ、18 アクチュエータ、LFQ1、LFQ2 ロックフリー関数キュー、20 関数列、22 プログラム変換装置、23 データ競合判定部、24 プロセスバリア挿入部、30 プロセスバリア、21、31 関数、32 チェッカ関数、33 リミッタ関数、34 プロセスバリアID、35A、35B データ競合、36 終了フラグ
Claims (15)
- 並行実行可能な複数の関数が順々に登録されたロックフリー関数キューを保持し、
前記ロックフリー関数キューは、データ競合する関数間に挿入されたプロセスバリアを含み、
前記プロセスバリアは、前記データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行を前記プロセスバリアの位置で待機させるプログラム実行制御方法。 - 前記プロセスバリアは、前記データ競合する前後の関数のうち、前の関数の実行が完了したかを監視し、前の関数の実行が完了すると、後の関数を実行するコアの割り当てを許容する請求項1に記載のプログラム実行制御方法。
- 前記プロセスバリアは、
指定の関数の処理完了を確認するチェッカと、
前記プロセスバリアより後の関数の実行を待機させるリミッタとを備え、
前記チェッカは、前記指定の関数の処理完了を確認すると、前記チェッカと対となる前記リミッタを前記ロックフリー関数キューから削除し、
前記コアは、
前記プロセスバリアの処理時に前記関数の取得および実行を中断し、
前記リミッタの削除後に、前記ロックフリー関数キューから前記関数を取得して実行する処理を再開する請求項2に記載のプログラム実行制御方法。 - 前記ロックフリー関数キューに登録された関数を実行するN(Nは2以上の整数)個のコアを備え、
前記データ競合する前後の関数のうち前の関数の実行するコアと、前記前の関数の実行が完了したかを監視するコアとは互いに異なる請求項2に記載のプログラム実行制御方法。 - 前記ロックフリー関数キューに登録された各関数は、自身の関数の処理が終了したかどうかを示すフラグを備える請求項2に記載のプログラム実行制御方法。
- 前記ロックフリー関数キューに登録された関数を前記プロセスバリアで区分けした各範囲に含まれる関数間では前記データ競合が発生しない請求項2に記載のプログラム実行制御方法。
- 前記プロセスバリアで区分けされた区間に含まれる関数の個数が最大になるように前記プロセスバリアの位置を設定する請求項6に記載のプログラム実行制御方法。
- 前記データ競合する前後の関数において、前記監視対象となる前の関数とデータ競合する後の関数が複数ある場合、前記後の関数のうちの最前の関数に対してのみ前記プロセスバリアが挿入される請求項2に記載のプログラム実行制御方法。
- 並行実行可能な関数間でデータ競合が発生するかどうかを判定し、前記データ競合が発生する関数間にプロセスバリアを挿入する処理をプロセッサに実行させるプログラム変換装置であって、
前記プロセスバリアは、前記データ競合する前後の関数のうち、前の関数の実行が完了するまで、後の関数の実行を前記プロセスバリアの位置で待機させるプログラム変換装置。 - 前記データ競合は、前後の関数の少なくとも一方が共有データまたは共有リソースに更新処理を実行して引き起こされる競合である請求項9に記載のプログラム変換装置。
- 前記プロセスバリアは、前記データ競合する前後の関数のうち、前の関数の実行が完了したかを監視し、前の関数の実行が完了すると、後の関数を実行するコアの割り当てを許容する請求項9に記載のプログラム変換装置。
- 前記ロックフリー関数キューに登録された関数を前記プロセスバリアで区分けした各範囲に含まれる関数間では前記データ競合が発生しない請求項11に記載のプログラム変換装置。
- 前記プロセスバリアで区分けされた区間に含まれる関数の個数が最大になるように前記プロセスバリアの位置を設定する請求項12に記載のプログラム変換装置。
- 前記データ競合する前後の関数において、前記監視対象となる前の関数とデータ競合する後の関数が複数ある場合、前記後の関数のうちの最前の関数に対してのみ前記プロセスバリアが挿入される請求項11に記載のプログラム変換装置。
- 前記プロセスバリアは、
指定の関数の処理完了を確認するチェッカと、
前記プロセスバリアより後の関数の実行を待機させるリミッタとを備え、
前記チェッカは、前記指定の関数の処理完了を確認すると、前記チェッカと対となる前記リミッタを前記ロックフリー関数キューから削除する請求項11に記載のプログラム変換装置。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
JP2018100236A JP2019204387A (ja) | 2018-05-25 | 2018-05-25 | プログラム実行制御方法およびプログラム変換装置 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
JP2018100236A JP2019204387A (ja) | 2018-05-25 | 2018-05-25 | プログラム実行制御方法およびプログラム変換装置 |
Publications (1)
Publication Number | Publication Date |
---|---|
JP2019204387A true JP2019204387A (ja) | 2019-11-28 |
Family
ID=68727053
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
JP2018100236A Pending JP2019204387A (ja) | 2018-05-25 | 2018-05-25 | プログラム実行制御方法およびプログラム変換装置 |
Country Status (1)
Country | Link |
---|---|
JP (1) | JP2019204387A (ja) |
Cited By (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN113568665A (zh) * | 2020-04-29 | 2021-10-29 | 北京希姆计算科技有限公司 | 一种数据处理装置 |
-
2018
- 2018-05-25 JP JP2018100236A patent/JP2019204387A/ja active Pending
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN113568665A (zh) * | 2020-04-29 | 2021-10-29 | 北京希姆计算科技有限公司 | 一种数据处理装置 |
CN113568665B (zh) * | 2020-04-29 | 2023-11-17 | 北京希姆计算科技有限公司 | 一种数据处理装置 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US4604694A (en) | Shared and exclusive access control | |
US7818306B2 (en) | Read-copy-update (RCU) operations with reduced memory barrier usage | |
US7353346B2 (en) | Read-copy-update (RCU) operations with reduced memory barrier usage | |
KR100911796B1 (ko) | 하드웨어 지원을 갖는 다중 프로세서 및 다중 스레드 안전메시지 큐 | |
JP2500101B2 (ja) | 共用変数の値を更新する方法 | |
US7373640B1 (en) | Technique for dynamically restricting thread concurrency without rewriting thread code | |
US5274823A (en) | Interrupt handling serialization for process level programming | |
US9003420B2 (en) | Resolving RCU-scheduler deadlocks | |
US20120311606A1 (en) | System and Method for Implementing Hierarchical Queue-Based Locks Using Flat Combining | |
KR100902977B1 (ko) | 하드웨어 공유 시스템 및 방법 | |
US8359588B2 (en) | Reducing inter-task latency in a multiprocessor system | |
US6662364B1 (en) | System and method for reducing synchronization overhead in multithreaded code | |
US11645124B2 (en) | Program execution control method and vehicle control device | |
JP2019204387A (ja) | プログラム実行制御方法およびプログラム変換装置 | |
EP2144163A1 (en) | Method and system for synchronizing the execution of a critical code section | |
JP7346649B2 (ja) | 同期制御システムおよび同期制御方法 | |
Takada et al. | Real-time scalability of nested spin locks | |
US9619277B2 (en) | Computer with plurality of processors sharing process queue, and process dispatch processing method | |
JP2010026575A (ja) | スケジューリング方法およびスケジューリング装置並びにマルチプロセッサシステム | |
US11809219B2 (en) | System implementing multi-threaded applications | |
Strøm et al. | Hardware locks with priority ceiling emulation for a Java chip-multiprocessor | |
Zheng et al. | Interrupt Responsive Spinlock Mechanism Based on MCS for Multi-core RTOS | |
JP2019179416A (ja) | デッドロック回避方法、デッドロック回避装置 | |
JPH03288933A (ja) | データ資源に対するアクセスを制御する方法 |