(19)【発行国】日本国特許庁(JP)
(12)【公報種別】特許公報(B2)
(11)【特許番号】
(24)【登録日】2023-02-13
(45)【発行日】2023-02-21
(54)【発明の名称】情報処理装置、情報処理プログラム、及び情報処理方法
(51)【国際特許分類】
G06F 8/41 20180101AFI20230214BHJP
【FI】
G06F8/41 130
(21)【出願番号】P 2019017824
(22)【出願日】2019-02-04
【審査請求日】2021-11-09
(73)【特許権者】
【識別番号】000005223
【氏名又は名称】富士通株式会社
(74)【代理人】
【識別番号】100087480
【氏名又は名称】片山 修平
(72)【発明者】
【氏名】津金 佳祐
【審査官】多賀 実
(56)【参考文献】
【文献】特開2014-228891(JP,A)
【文献】特開2004-326760(JP,A)
【文献】米国特許第06058266(US,A)
【文献】本川 敬子 外3名,「ストリーム数とリユースを考慮したループ分配方式」,情報処理学会研究報告,社団法人情報処理学会,2007年09月09日,第2007巻, 第88号,pp.27-32
(58)【調査した分野】(Int.Cl.,DB名)
G06F 8/41
(57)【特許請求の範囲】
【請求項1】
複数の文を内包した一又は複数のループ処理を有するソースコードを取得する取得部と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する分割部と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない融合処理部と、
複数の前記文の各々をノードとする有向グラフであって、依存関係を有する二つの前記文の各々に対応する二つの前記ノードの間にエッジを有すると共に、前記ソースコードにおける前記文の出現順を表す向きが前記エッジに付与されたグラフを生成するグラフ作成部と、を有し、
前記融合処理部は、二つの前記ノードの間に前記エッジが存在する場合には、前記二つのノードの各々に対応した二つの前記文の各々を内包する二つの前記ループ処理を融合すると共に、前記融合後の前記ループ処理の内部において、前記エッジの向きが表す順序に前記二つの文を並べることを特徴とする情報処理装置。
【請求項2】
前記融合処理部は、依存関係がある二つの前記文が複数組存在する場合には、分割前の前記ループ処理において前記文が位置するネストの深さを前記二つの文の各々について求めると共に、求めた前記深さのうちの大きい方の値を複数の前記組の各々に対して特定して、特定した前記値が大きい組から順に前記融合を行うことを特徴とする請求項1に記載の情報処理装置。
【請求項3】
前記融合処理部は、二つの前記文が依存関係を有しておらず、かつ同一の前記データ構造を含む場合には、前記二つの文の各々を内包する前記ループ処理同士を融合することを特徴とする請求項1に記載の情報処理装置。
【請求項4】
前記メモリフェッチストリーム数は、キャッシュメモリと第2のメモリとの間に配されたブロックの個数に等しく、各ブロックには各データ構造のアドレスが格納されることを特徴とする請求項1に記載の情報処理装置。
【請求項5】
前記融合処理部は、依存関係がある二つの文の複数の組のうち、ノードが示すネストの深さが大きい組から順にループ処理を融合することを特徴とする請求項1に記載の情報処理装置。
【請求項6】
複数の文を内包した一又は複数のループ処理を有するソースコードを取得する処理と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する処理と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない処理と、
複数の前記文の各々をノードとする有向グラフであって、依存関係を有する二つの前記文の各々に対応する二つの前記ノードの間にエッジを有すると共に、前記ソースコードにおける前記文の出現順を表す向きが前記エッジに付与されたグラフを生成する処理と、をコンピュータに実行させ、
二つの前記ノードの間に前記エッジが存在する場合には、前記二つのノードの各々に対応した二つの前記文の各々を内包する二つの前記ループ処理を融合すると共に、前記融合後の前記ループ処理の内部において、前記エッジの向きが表す順序に前記二つの文を並べる、情報処理プログラム。
【請求項7】
複数の文を内包した一又は複数のループ処理を有するソースコードを取得する処理と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する処理と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない処理と、
複数の前記文の各々をノードとする有向グラフであって、依存関係を有する二つの前記文の各々に対応する二つの前記ノードの間にエッジを有すると共に、前記ソースコードにおける前記文の出現順を表す向きが前記エッジに付与されたグラフを生成する処理と、をコンピュータが実行し、
二つの前記ノードの間に前記エッジが存在する場合には、前記二つのノードの各々に対応した二つの前記文の各々を内包する二つの前記ループ処理を融合すると共に、前記融合後の前記ループ処理の内部において、前記エッジの向きが表す順序に前記二つの文を並べる、情報処理方法。
【発明の詳細な説明】
【技術分野】
【0001】
本発明は、情報処理装置、情報処理プログラム、及び情報処理方法に関する。
【背景技術】
【0002】
プログラムの実行速度を速める手法の一つにループ分割がある。ループ分割は、プログラムにループ処理が含まれている場合に、そのループ処理を複数個に分割する手法である。これにより、一つのループ処理に含まれる文の数が減るため、当該ループ処理を実行するときのキャッシュミスを低減でき、ひいてはプログラムの実行速度を向上させることができる。
【0003】
プログラムのコード量が多い場合にはループ分割を手動で行うは困難であり、その場合にはコンパイラによってループ分割を行うことが多い。
【0004】
しかしながら、コンパイラは、プログラムを実行するプロセッサのハードウェアの構造を考慮することなくループ分割を行うため、そのプロセッサが実行速度を速めるのに最適なプログラムを出力するとは限らない。
【先行技術文献】
【特許文献】
【0005】
【文献】特開2015-194881号公報
【文献】特開2000-347879号公報
【発明の概要】
【発明が解決しようとする課題】
【0006】
一側面によれば、本発明は、プログラムの実行速度を向上させることを目的とする。
【課題を解決するための手段】
【0007】
一側面によれば、複数の文を内包した一又は複数のループ処理を有するソースコードを取得する取得部と、前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する分割部と、前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない融合処理部と、複数の前記文の各々をノードとする有向グラフであって、依存関係を有する二つの前記文の各々に対応する二つの前記ノードの間にエッジを有すると共に、前記ソースコードにおける前記文の出現順を表す向きが前記エッジに付与されたグラフを生成するグラフ作成部と、を有し、前記融合処理部は、二つの前記ノードの間に前記エッジが存在する場合には、前記二つのノードの各々に対応した二つの前記文の各々を内包する二つの前記ループ処理を融合すると共に、前記融合後の前記ループ処理の内部において、前記エッジの向きが表す順序に前記二つの文を並べる情報処理装置が提供される。
【発明の効果】
【0008】
一側面によれば、プログラムの実行速度を向上させることができる。
【図面の簡単な説明】
【0009】
【
図1】
図1は、ループ分割について説明するための図である。
【
図2】
図2は、ターゲットマシンのハードウェア構成図である。
【
図3】
図3は、調査に使用したプログラムについて示す図である。
【
図4】
図4は、プログラムの実行速度の調査結果を示す図である。
【
図5】
図5は、本実施形態に係る情報処理装置のハードウェア構成図である。
【
図6】
図6は、本実施形態に係る情報処理装置の機能を示す機能構成図である。
【
図7】
図7は、本実施形態における入力ソースコードの一例を示す図である。
【
図8】
図8は、本実施形態に係るグラフ作成部が作成するグラフについて説明するための図である。
【
図9】
図9は、本実施形態に係るグラフと分割処理済ソースコードとを示す図である。
【
図10】
図10は、本実施形態に係るグラフと出力ソースコードとを示す図である。
【
図11】
図11は、本実施形態に係る情報処理装置について示すフローチャート(その1)である。
【
図12】
図12は、本実施形態に係る情報処理装置について示すフローチャート(その2)である。
【
図13】
図13は、本実施形態の例における入力ソースコードを示す図である。
【
図14】
図14は、本実施形態の例における入力ソースコードとグラフとを示す図である。
【
図15】
図15は、本実施形態の例における分割処理済ソースコードとグラフとを示す図である。
【
図16】
図16は、本実施形態の例における出力ソースコードとグラフとを示す図である。
【発明を実施するための形態】
【0010】
本実施形態の説明に先立ち、本願発明者が検討した事項について説明する。
図1は、ループ分割について説明するための図である。
【0011】
図1の例では、C言語で記述されたソースコード1に対してループ分割を行う場合を想定している。そのソースコード1には三つの文「Stmt0」、「Stmt1」、「Stmt2」を含むforループによって一つのループ処理1aが実行される。このループ処理1aを分割するパターンは複数ある。これらのパターンのうちの二つをソースコード2及びソースコード3に示す。
【0012】
ソースコード2は、ソースコード1のforループを三つに分割し、その各々で文「Stmt0」、「Stmt1」、「Stmt2」を実行するソースコードである。この場合には、各forループに対応した三つのループ処理2a~2cが実行されることになる。
【0013】
一方、ソースコード3は、ソースコード1のforループを二つに分割し、二つのループ処理3a、3bを実行する場合のソースコードである。この例では、文「Stmt0」がループ処理3aで実行され、文「Stmt1」と文「Stmt2」が別のループ処理3bで実行される。
【0014】
このように、ループ処理1aを分割して得られるソースコードには、ループ処理の個数が異なる二つのソースコード2、3がある。分割後のループ処理の個数は分割の粒度とも呼ばれ、分割後のループ処理の個数が多いほど粒度は小さいと言い、その個数が少ないほど粒度は大きいと言う。
図1の例では、ソースコード2のループ分割の粒度はソースコード3のそれよりも小さい。
【0015】
プログラムの実行速度はループ分割の粒度に依存する。例えば、ループ分割の粒度を小さくして一つのループ処理に含まれる文の数を少なくすれば、そのループ処理を実行する際のキャッシュミスを低減できる。その一方で、一つのプログラムに多量のループ処理が含まれてしまうため、ループ処理から抜けるための条件分岐命令の個数が増え、かえってプログラムの実行速度が低下してしまう。
【0016】
実行速度を向上させるのに最適な分割の粒度は、プログラムを実行するターゲットマシンのハードウェアの構造に依存する。これについて以下に説明する。
【0017】
図2は、ターゲットマシン10のハードウェア構成図である。
【0018】
ターゲットマシン10は、サーバやPC(Personal Computer)等の計算機であって、プロセッサ11とメインメモリ15とを有する。
【0019】
このうち、プロセッサ11は、データのプリフェッチ機能を備えたハードウェアであって、演算部12、データキャッシュメモリ13、及びバッファメモリ14を備える。
【0020】
このうち、演算部12は、算術演算や論理演算を行うALU(Arithmetic Logic Unit)と各種のレジスタとを備えた回路素子である。また、データキャッシュメモリ13は、演算部12で使用するデータを保持するSRAM(Static Random Access Memory)等のメモリである。
【0021】
そして、バッファメモリ14は、メインメモリ15からデータキャッシュメモリ13に転送されるデータを決定するために用いられるハードウェアであり、メインメモリ15とデータキャッシュメモリ13の間に設けられる。
【0022】
そのバッファメモリ14には複数のブロック14a~14dが設けられる。ブロック14a~14dは、データキャッシュメモリ13に転送されるデータのアドレスやアクセスの規則性を保持するために割り当てられる記憶領域の単位である。以下ではブロック14a~14dの個数のことをメモリフェッチストリーム数と呼ぶ。
図2の例では、メモリフェッチストリーム数は4である。
【0023】
一方、メインメモリ15は、演算部12で使用するデータや命令を記憶したDRAM(Dynamic Random Access Memory)等のハードウェアである。
【0024】
このようなターゲットマシン10においては、演算部12におけるプログラム実行に先立ち、プログラム実行に必要なデータをメインメモリ15からデータキャッシュメモリ13に転送するプリフェッチを行う。これにより、プログラムがデータを参照するのに要する時間を短縮でき、プログラムの実行速度を向上できる。
【0025】
そのプリフェッチで各ブロック14a~14dに割り当てられるデータは実行時に決定される。ここでは、プログラム中に含まれる個々の配列に異なるブロック14a~14dを割り当てる場合を想定する。例えば、プログラムに二つの配列「A」、「B」がある場合を考える。この場合は、配列「A」のアドレスやアクセスの規則性を格納するために一つのブロック14aが割り当てられ、配列「B」のアドレスやアクセスの規則性を格納するのに別のブロック14bが割り当てられる。
【0026】
大抵のプログラムでは、ループ処理の内部に配列がある場合、そのループ処理を実行するときに配列の各要素をアドレス順に参照することが多い。配列の各要素はアドレスが連続しているため、このように配列要素をデータキャッシュメモリ13にプリフェッチしておくことでプログラムの実行時間を早めることができる。
【0027】
但し、一つのループ処理に含まれる配列の個数がメモリフェッチストリーム数を超えると、それら全ての配列のアドレスやアクセスの規則性を同時にバッファメモリ14に格納することができなくなる。そのため、ループ処理の実行時にバッファメモリ14からアドレスやアクセスの規則性の追い出しが頻繁に発生し、プリフェッチが実行できず、プログラムの実行速度が遅くなる。
【0028】
これを確かめるため、本願発明者は、ループ処理に含まれる配列の個数が2~26個の相異なるプログラムを25個用意し、これらのプログラムの処理速度を調査した。
図3は、調査に使用したプログラムについて示す図である。
【0029】
図3に示すように、例えば配列の個数が2個のプログラムSC2では、一つのforループの中に二つの配列「A1」、「A2」が含まれる。また、配列の個数が3個のプログラムSC3では、一つのforループの中に三つ配列「A1」、「A2」、「A3」が含まれる。配列の個数が4~26個のプログラムSC4~SC26もこれと同様に作成した。
【0030】
このようなプログラムをターゲットマシン10で実行する場合には、前述のようにforループの実行時に各配列のアドレスやアクセスの規則性がブロック14a~14dのそれぞれに格納される。例えば、プログラムSC2のforループを実行する場合には、ブロック14aに配列「A1」のアドレスやアクセスの規則性が格納され、ブロック14bに配列「A2」のアドレスやアクセスの規則性が格納される。
【0031】
本願発明者は、これらのプログラムSC2~SC26の実行速度を調査した。その調査結果を
図4に示す。
【0032】
図4の横軸は、プログラムSC2~SC26に含まれる配列の個数を示す。例えば、配列の個数が3の場合は、配列の個数が3個のプログラムSC3を実行した場合を指す。
【0033】
また、
図4の縦軸は、プロセッサが1秒当たりに処理をしたデータ量を示す。
【0034】
なお、この調査では、プログラムを実行するプロセッサとしてARM thunder X2 CN9975を使用した。
【0035】
図4に示すように、配列の個数が8個を超えるとデータの処理量が大きく低下する。これは、このプロセッサのメモリフェッチストリーム数が8であるためと考えられる。
【0036】
以上の結果から、プログラムの実行速度を向上させるには、一つのループ処理に含まれる配列の個数をメモリフェッチストリーム数以下とするのが好ましいことが明らかとなった。
【0037】
以下に、プログラムの実行速度を向上させ得る本実施形態について説明する。
【0038】
(本実施形態)
本実施形態では、以下のようにしてソースコードに含まれるループ処理を分割し、一つのループ処理に含まれる配列の個数がメモリフェッチストリーム数を超えないようにする。
【0039】
[ハードウェア構成]
図5は、本実施形態に係る情報処理装置のハードウェア構成図である。
【0040】
この情報処理装置21は、ループ分割を行うためのPC等の計算機であって、記憶部22、メインメモリ23、プロセッサ24、入力部25、及び表示部26を備える。これらの各部はバス27によって相互に接続される。
【0041】
このうち、記憶部22は、例えばHDD(Hard Disk Drive)やSSD(Solid State Drive)等の二次記憶装置であり、本実施形態に係る情報処理プログラム30を記憶する。情報処理プログラム30は、入力されたソースコードをループ分割し、分割後のソースコードを出力するコンパイラである。
【0042】
なお、その情報処理プログラム30をコンピュータが読み取り可能な記録媒体28に記録させておき、プロセッサ24に記録媒体28の情報処理プログラム30を読み取らせるようにしてもよい。
【0043】
そのような記録媒体28としては、例えばCD-ROM(Compact Disc - Read Only Memory)、DVD(Digital Versatile Disc)、及びUSB(Universal Serial Bus)メモリ等の物理的な可搬型記録媒体がある。また、フラッシュメモリ等の半導体メモリやハードディスクドライブを記録媒体28として使用してもよい。これらの記録媒体28は、物理的な形態を持たない搬送波のような一時的な媒体ではない。
【0044】
更に、公衆回線、インターネット、及びLAN(Local Area Network)等に接続された装置に情報処理プログラム30を記憶させておき、プロセッサ24が情報処理プログラム30を読み出して実行するようにしてもよい。
【0045】
一方、メインメモリ23は、DRAM等のようにデータを一時的に記憶するハードウェアであって、その上に前述の情報処理プログラム30が展開される。
【0046】
プロセッサ24は、自装置の各部を制御したり、メインメモリ23と協働して情報処理プログラム30を実行したりするCPU(Central Processing Unit)等のハードウェアである。
【0047】
入力部25は、キーボードやマウス等の入力デバイスである。ユーザがこれらの入力デバイスを操作することにより、情報処理プログラム30でコンパイルするソースファイルを指定したり、コンパイル後の出力ソースファイルの出力先が指定されたりする。
【0048】
また、表示部26は、情報処理プログラム30の実行時にユーザが使用する様々なコマンドを表示する液晶ディスプレイ等の表示デバイスである。なお、以下では情報処理装置21が情報処理プログラム30を実行する場合を例にして説明するが、ターゲットマシン10(
図2参照)が情報処理プログラム30を実行することにより以下の各処理や機能を実現してもよい。
【0049】
[機能構成]
図6は、本実施形態に係る情報処理装置21の機能を示す機能構成図である。
【0050】
図6に示すように、情報処理装置21は、取得部41、グラフ作成部42、分割部43、及び融合処理部44を備える。これらの各部は、プロセッサ24とメインメモリ23が協働して前述の情報処理プログラム30を実行することにより実現される。
【0051】
このうち、取得部41は、コンパイルの対象となる入力ソースコードを取得する機能ユニットであり、例えば
図7に示す入力ソースコード50を取得する。
図7は、入力ソースコード50の一例を示す図である。
【0052】
入力ソースコード50は、
図2のターゲットマシン10で実行するためのC言語で記述されたプログラムであり、複数のforループを有する。以下では、これらのforループのうち最も外側のforループで実行される処理をループ処理と呼ぶ。
図7の例では、第1のループ処理50aと第2のループ処理50bがループ処理の例となる。
【0053】
このうち、第1のループ処理50aは複数の文「Stmt0」、「Stmt1」、「Stmt2」を内包しており、これらの文を一つのforループで繰り返し実行する。また、第2のループ処理50bは、入れ子の関係にある二つのforループで実現されるネストの深さが2のループ処理であり、複数の文「Stmt3」、「Stmt4」を内包する。
【0054】
なお、ここでは入力ソースコード50に複数のループ処理50a、50bが含まれている場合を例にしているが、一つのループ処理に複数の文を含む入力ソースコード50を用いてもよい。
【0055】
更に、入力ソースコード50を記述する言語はC言語に限定されず、C++やFortranによって入力ソースコード50を記述してもよい。また、for文に代えてwhile文によりループを記述してもよい。
【0056】
グラフ作成部42(
図6参照)は、依存解析によりこの入力ソースコード50に含まれる複数の文の各々の依存関係を求め、その依存関係に基づいてグラフを作成する。
そのグラフについて
図8を参照しながら説明する。
【0057】
図8は、入力ソースコード50を用いてグラフ作成部42が作成するグラフGについて説明するための図である。
【0058】
グラフGは、入力ソースコード50に含まれる文「Stmt0」、「Stmt1」、「Stmt2」、「Stmt3」、「Stmt4」の各々をノードNとする有向グラフである。また、ノードNの値は、そのノードNに対応した文が位置するネストの深さである。例えば、文「Stmt3」は、ループ処理50bにおいて二つのfor文の内側にあり、ネストの深さが2のところに位置しているため、文「Stmt3」に対応するノードNの値は2となる。文「Stmt4」についても同様である。一方、「Stmt0」、「Stmt1」、「Stmt2」の各々の文は、ループ処理50aにおいて一つのfor文の内側にあり、ネストの深さが1のところに位置しているため、これらの文に対応するノードNの値は1となる。
【0059】
また、グラフ作成部42は、フロー依存、出力依存、及び逆依存のいずれかの依存関係を有する二つの文の組を特定し、これらの文に対応するノードN間にエッジEを設ける。
【0060】
図8の例では、以下のような依存関係がある場合を想定している。
文「Stmt1」と文「Stmt3」:フロー依存
文「Stmt3」と文「Stmt4」:出力依存
文「Stmt0」と文「Stmt1」:双方向に依存
文「Stmt2」:依存関係なし
【0061】
この場合には、文「Stmt1」と文「Stmt3」のそれぞれに対応する二つのノードNの間にエッジEが設けられる。また、そのエッジEの向きは、入力ソースコード50における文の出現順とする。よって、このエッジEの向きは、文「Stmt1」から文「Stmt3」に向かう方向となる。
【0062】
同様に、文「Stmt3」と文「Stmt4」のそれぞれに対応する二つのノードNの間にも、文「Stmt3」から文「Stmt4」に向かう方向のエッジEが設けられる。
【0063】
一方、相互に依存関係がある文「Stmt0」と文「Stmt1」との間には、双方向を向いたエッジFを設ける。例えば、文「Stmt0」が文「Stmt1」の結果を参照し、かつ文「Stmt1」が文「Stmt0」の結果を参照する場合に、これらの文は相互に依存関係を有することになる。
【0064】
また、他の文と依存関係がない文「Stmt2」については、その文「Stmt2」と同じ配列を含む他の文との間に仮想的なエッジKを設ける。ここでは、文「Stmt0」と文「Stmt2」とが同一の配列を含むものとする。なお、この仮想的なエッジKの向きも、入力ソースコード50における文の出現順とする。
【0065】
分割部43(
図6参照)は、このグラフGを参照することにより、入力ソースコード50に含まれるループ処理50a、50bを、各文の依存関係を維持する分割のうちで分割後のループ処理の個数が最大となるように分割する。
その分割方法について
図9を参照して説明する。
【0066】
図9は、前述のグラフGと、ループ処理を分割した分割処理済ソースコード51とを示す図である。
【0067】
図9に示されるように、分割処理済ソースコード51は、ループ処理を分割したことで入力ソースコード50よりもループ処理の個数が増えており、第1~第4のループ処理51a~51dを有する。どのようにループ処理を分割するかは、分割部43がグラフGを参照することで以下のように決定する。
【0068】
例えば、グラフGに示されるように、文「Stmt1」と文「Stmt3」は、それらを結ぶエッジEが一方向を向いており、その向きで規定される出現順を保つ限り、異なるループ処理で実行しても実行結果は変わらない。よって、分割部43は、エッジEの向きを参照して文「Stmt1」と文「Stmt3」の出現順を特定し、その出現順が変わらないように文「Stmt1」と文「Stmt3」をそれぞれ異なるループ処理51a、51cに内包させる。文「Stmt3」と文「Stmt4」との組、及び文「Stmt0」と文「Stmt3」との組についても同様である。
【0069】
一方、文「Stmt0」と文「Stmt1」は、それらを結ぶエッジFの向きが双方向となっている。この場合は、前述のように文「Stmt0」と文「Stmt1」は相互に依存関係を有しているため、これらの文を別々のループ処理で実行したのでは分割前と実行結果が変わってしまう。よって、分割部43は、グラフGを参照して得られたエッジFの向きが双方向となっている場合には、そのエッジFの両端の文を同一のループ処理に内包させる。
図9の例では、文「Stmt0」と文「Stmt1」が同じループ処理51aに内包される。
【0070】
以上により、文「Stmt0」、「Stmt1」、「Stmt2」、「Stmt3」、「Stmt4」の各々の依存関係を維持する複数の分割のうち、分割後のループ処理51a~51dの個数が最大となる分割処理済ソースコード51が得られることになる。
【0071】
融合処理部44(
図9参照)は、このように分割部43がループ処理を分割した後に、ループ処理を融合して最終的な出力ソースコードを出力する。その融合方法について
図10を参照して説明する。
【0072】
図10は、前述のグラフGと出力ソースコード52を示す図である。
【0073】
出力ソースコード52は、融合処理部44が分割処理済ソースコード51のループ処理51a~51dの一部を融合することにより得られたソースコードであり、この例では第1~第3のループ処理52a~52cを有する。
【0074】
ループ処理51a~51dのうちのどれを融合するかは、メモリフェッチストリーム数nと各文に含まれる配列に依存する。そこで、以下では、文「Stmt0」と文「Stmt2」のそれぞれに含まれる配列が「A0」のみであり、文「Stmt1」に含まれる配列が「A1」のみであるとする。また、文「Stmt3」に含まれる配列が「A3」のみであり、文「Stmt4」に含まれる配列が「A4」のみであるとする。
【0075】
また、簡単のためにメモリフェッチストリーム数nは2であるとする。
【0076】
この場合、メモリフェッチストリーム数nを超えた個数の配列が一つのループ処理に含まれていると、前述のようにバッファメモリ14からアドレスやアクセスの規則性が追い出されるため、そのループ処理の実行速度が低下する。
【0077】
例えば、ループ処理51a、51bを融合して「Stmt0」、「Stmt1」、「Stmt2」の各文を一つのforループで実行すると、そのforループに三つの配列「A0」、「A1」、「A2」が含まれてしまい、配列の個数がn(=2)を超えてしまう。
【0078】
よって、融合処理部44は、ループ処理51a、51bを融合の対象とはしない。
【0079】
一方、ループ処理51c、51dを融合し、文「Stmt3」と文「Stmt4」とを一つのforループで実行しても、そのforループに含まれる配列の個数は2となり、メモリフェッチストリーム数n(=2)を超えない。
【0080】
したがって、融合処理部44は、これらのループ処理51c、51dを融合して新しいループ処理52cとする。この場合、融合前に文「Stmt3」と文「Stmt4」が位置していたネストの深さはいずれも2であるため、融合後のループ処理52cにおいてもこれらの文「Stmt3」、「Stmt4」のネストの深さは2となる。
【0081】
深いネストを有するループ処理を二つに分割したままにしておくと、ループ処理から抜けるための条件分岐命令を各ループ処理で独立に実行する必要があり、実行命令数が増えてプログラムの実行時間が長くなってしまう。よって、ループ処理51c、51dのようにネストが深い処理同士を融合することで、条件分岐命令の数を大きく削減でき、融合による実行時間の短縮化の効果が大きくなる。
【0082】
そこで、融合処理部44は、グラフGのノードNの値が表すネストの深さを参照し、その深さに基づいて融合する二つのループ処理を決定する。例えば、融合処理部44は、エッジE、Kの両端の二つのノードNの各々の値のうちで大きい方の値を求め、当該値が大きなエッジE、Kから順にループ処理を融合する。
【0083】
また、融合処理部44は、文「Stmt3」と文「Stmt4」の各々に対応したノードNの間のエッジEの向きを参照し、その向きが表す出現順にループ処理52cに文「Stmt3」と文「Stmt4」とを並べる。これにより、融合後のループ処理52cにおいても各文「Stmt3」、「Stmt4」の依存関係が維持され、入力ソースコード50と同じ実行結果が出力される出力ソースコード52を得ることができる。
【0084】
[フローチャート]
次に、本実施形態に係る情報処理方法について説明する。
図11及び
図12は、本実施形態に係る情報処理方法について示すフローチャートである。
【0085】
まず、ステップS1において、取得部41が入力ソースコード50(
図7参照)を取得する。
【0086】
次に、ステップS2に移り、グラフ作成部42が、入力ソースコード50に含まれる複数の文の依存解析を行い、その解析結果に基づいて
図8に示したグラフGを作成する。
【0087】
続いて、ステップS3に移り、グラフ作成部42がグラフGに仮想的なエッジKを追加する。前述のように、そのエッジKは、依存関係がないものの同一の配列を含む文に対応したノードN間に設けられる。
【0088】
次いで、ステップS4に移り、分割部43が、入力ソースコード50に含まれるループ処理50a、50bの各々を複数に分割する。これにより、
図9に示したように、複数のループ処理51a~51dを有する分割処理済ソースコード51を生成する。
【0089】
この分割は、前述のように各文の依存関係を維持する分割のうちで分割後のループ処理51a~51dの個数が最大となるように行われる。これにより、分割により得られるループ処理の個数が増えるため、後で融合するループ処理の組の候補を増やすことができる。
【0090】
続いて、ステップS5に移り、融合処理部44が、メモリフェッチストリーム数nを取得する。例えば、融合処理部44は、ユーザが入力部25から入力したメモリフェッチストリーム数nを取得してもよいし、コンパイラの依存解析によりメモリフェッチストリーム数nを取得してもよい。
【0091】
次に、ステップS6に移り、融合処理部44が、エッジEの両端のノードNのうちで大きい方の値Dを、全てのエッジEについて特定する。その値Dは、前述のように、エッジEの両端に対応する二つの文が位置するネストうち、深い方の深さを表す。そこで、以下では、値DのことをエッジEのネストの深さDとも呼ぶ。
【0092】
同様に、融合処理部44は、仮想的なエッジKに対してもその値Dを特定する。
【0093】
そして、融合処理部44が、複数のエッジE、Kのうちで値Dが最大のものを選択する。
【0094】
続いて、ステップS7に移り、選択したエッジE、Kの両端の各々の文を内包する二つのループ処理を融合すると、融合後のループ処理に含まれる配列の個数がメモリフェッチストリーム数nを超えるかを融合処理部44が判断する。
【0095】
ここで、超える(YES)と判断された場合には、ステップS8に移り、そのエッジE、Kを次の選択候補から外す。そして、ステップS6からやり直す。
【0096】
一方、ステップS7において超えない(NO)と判断された場合には、
図12のステップS9に移る。ステップS9では、融合処理部44が、ステップS6で選択したエッジE、Kの両端の各々の文を内包する二つのループ処理を融合する。
【0097】
次に、ステップS10に移り、融合処理部44が、ステップS9で融合したエッジE、Kを次の選択候補から外す。
【0098】
続いて、ステップS11に移り、融合処理部44が、選択可能なエッジE、Kがないかどうかを判断する。ここで、残っていない(YES)と判断された場合には、ステップS12に移り、融合処理部44が
図10の出力ソースコード52を出力する。
【0099】
一方、残っている(NO)と判断された場合にはステップS6からやり直す。
【0100】
以上により、本実施形態に係る情報処理装置の基本ステップを終了する。
【0101】
この後は、出力ソースコード52を他のコンパイラでコンパイルすることにより、
図2のターゲットマシン10で実行可能なバイナリファイルを作成する。
【0102】
上記した本実施形態によれば、ステップS7、S9において、一つのループ処理が内包する配列の個数がメモリフェッチストリーム数nを超えないように、二つの文の各々を内包する二つのループ処理同士を融合する。
【0103】
そのため、
図2のバッファメモリ14からアドレスやアクセスの規則性が頻繁に追い出されるのを抑制でき、プログラムの実行速度が向上するという技術的な効果が得られる。
【0104】
更に、このようにループ処理同士を融合することでループ処理を抜け出すための条件分岐命令の個数が減り、プログラムの実行速度を更に向上させることができる。
【0105】
しかも、ステップS6において、複数のエッジEのうちでネストの深さDが最大のものを選択するため、ネストが深いループ処理から順に融合が行われる。これにより、ネストが深く条件分岐命令を多く含むループ処理から優先的に減らすことができ、融合による実行時間の短縮化の効果が大きくなる。
【0106】
また、ステップS3において依存関係がない二つの文の間に仮想的なエッジを追加するため、依存関係がない二つの文の各々を含むループ処理も融合の候補とすることができる。そして、これらのループ処理を実際に融合することにより、条件分岐命令の削減による実行時間の短縮化の効果を得ることができる。
【0107】
特に、HPC(High Performance Computing)向けのプログラムではループ処理が内包する文の個数が膨大になる傾向がある。よって、そのようなプログラムに対して本実施形態のようにループ処理を自動的に分割や融合をすることで開発者の負担を減らすことができる。
【0108】
次に、更に詳細なソースコードを用いた具体的な例について説明する。
【0109】
図13は、本例で使用する入力ソースコードを示す図である。
【0110】
この例ではC言語で記述された入力ソースコード60を使用する。その入力ソースコード60はネスト構造の二つのforループを有しており、このうちの外側のforループによってループ処理60aが実行される。そして、そのループ処理60aには4個の配列A、B、C、Dが含まれる。
【0111】
なお、以下では、ソースコード60に含まれる文を、その文と同一行のコメント文で特定する。例えば、コメント文「Stmt0」は、文「A[i] = alpha;」を指すものとする。
【0112】
そして、前述の
図11及び
図12のフローチャートに従い、この入力ソースコード60に対して情報処理装置21が以下の各処理を行う。
【0113】
まず、取得部41が入力ソースコード60を取得し(ステップS1)、次いでグラフ作成部42がグラフGを作成する(ステップS2)。
【0114】
図14は、入力ソースコード60とグラフGとを示す図である。
【0115】
図14に示されるように、入力ソースコード60の各文には次のような依存関係がある。
【0116】
文「Stmt0」と文「Stmt2」:配列「A」によるフロー依存
文「Stmt1」と文「Stmt3」:配列「B」によるフロー依存
文「Stmt2」と文「Stmt3」:配列「C」による出力依存
文「Stmt3」と文「Stmt4」:依存関係なし
【0117】
この依存関係に従い、グラフ作成部42がグラフGを作成する。
【0118】
そのグラフGは、前述のように各文をノードNとする有向グラフであって、各文が位置するネストの深さがそのノードNの値となる。
【0119】
例えば、文「Stmt2」は、ループ処理60aにおいて二つのfor文の内側にあり、ネストの深さが2のところに位置しているため、文「Stmt2」に対応するノードNの値は2となる。また、文「Stmt0」は、ループ処理60aにおいて一つのfor文の内側にあり、ネストの深さが1のところに位置しているため、文「Stmt0」に対応するノードNの値は1となる。
【0120】
更に、依存関係がある二つの文の各々に対応した二つのノードNの間にはエッジEが設けられ、入力ソースコード60における各文の出現順を表す向きがそのエッジEに付与される。
【0121】
例えば、前述のように文「Stmt1」と文「Stmt3」は、配列「B」によるフロー依存を有するため、これらの文に対応したノードNの間にはエッジEが設けられる。また、入力ソースコード60においては先に文「Stmt1」が出現してその後に文「Stmt3」が出現するため、文「Stmt1」から文「Stmt3」に向かう方向の向きがそのエッジEに付与される。
【0122】
続いて、グラフ作成部42が、このグラフGに仮想的なエッジKを追加する(ステップS3)。
【0123】
前述のように、仮想的なエッジKは、同一の配列を含む依存関係がない二つの文の間に設けられる。この例では、文「Stmt3」と文「Stmt4」とは依存関係を有していないものの、同一の配列「B」を含む。よって、文「Stmt3」と文「Stmt4」の各々に対応するノードNの間に仮想的なエッジKが設けられる。
【0124】
次に、分割部43が、このグラフGを参照してループ処理60aを複数に分割する。
【0125】
図15は、分割により得られた分割処理済ソースコード61とグラフGとを示す図である。
【0126】
前述のように、ループ処理の分割は、複数の文の依存関係を維持する分割のうちで、分割後のループ処理の個数が最大となるように行われる。この例では、文「Stmt0」、「Stmt1」、「Stmt2」、「Stmt3」、「Stmt4」のうちで相互の依存関係を有する組み合わせがないため、一つのループ処理が一つの文のみを内包するようにしても各々の文の依存関係は維持される。よって、ループ処理60aは、各々が一つの文のみを内包する第1~第5のループ処理61a~61eに分割される。
【0127】
次に、融合処理部44が、メモリフェッチストリーム数nを取得する(ステップS5)。この例では、メモリフェッチストリーム数nは2とする。
【0128】
次いで、融合処理部44が、全ての複数のエッジE、Kのうちでネストの深さDが最も深いものを選択する(ステップS6)。この例では、全てのエッジE、Kにおいて深さDが2となるため、全てのエッジE、Kが選択されることになる。
【0129】
そして、融合処理部44が、一つのループ処理に含まれる配列の個数がメモリフェッチストリーム数n(=2)を超えないように、各エッジE、Kの両端の文を内包するループ処理同士を融合する(ステップS7~S10)。
【0130】
図16は、このように融合して得られた出力ソースコード62とグラフGとを示す図である。
【0131】
図16に示すように、その出力ソースコード62には第1~第3のループ処理62a~62cが含まれる。
【0132】
このうち、第1のループ処理62aは、文「Stmt0」を内包する第1のループ処理61aと文「Stmt2」を内包する第3のループ処理61cとを融合して得られたループ処理である。その第1のループ処理62aに含まれる配列は「A」と「C」であるため、第1のループ処理62aに含まれる配列の個数は2となり、メモリフェッチストリーム数n(=2)を超えない。
【0133】
また、第2のループ処理62bは、文「Stmt1」を内包する第2のループ処理61bと文「Stmt3」を内包する第4のループ処理61dとを融合して得られたループ処理である。その第2のループ処理62bにおいても、二つの配列「B」、「C」のみが含まれており、配列の個数はメモリフェッチストリーム数n(=2)を超えない。
【0134】
一方、第3のループ処理61cと第4のループ処理61dとを融合してしまうと、融合後のループ処理には「A」、「B」、「C」の三つの配列が含まれてしまい、配列の個数がメモリフェッチストリーム数n(=2)を超えてしまう。よって、融合処理部44は、第3のループ処理61cと第4のループ処理61dとを融合しない。同様の理由により、第4のループ処理61dと第5のループ処理61eも融合しない。
【0135】
よって、融合処理部44は選択可能なエッジはないと判断し(ステップS11)、この出力ソースコード62を出力する。
【0136】
以上により、入力ソースコード60を用いた場合の処理を終える。
【0137】
上記した例によれば、出力ソースコード62における第1~第3のループ処理62a~62cの各々に含まれる配列の個数がメモリフェッチストリーム数を超えない。そのため、ターゲットマシン10において各ループ処理62a~62cを実行する際に、バッファメモリ14からアドレスやアクセスの規則性が追い出されるのを抑制でき、プログラムの実行速度を向上することができる。
【0138】
しかも、
図15の分割処理済ソースコード61における各ループ処理61a~61eの一部を融合することで、ループ処理を抜け出すための条件分岐命令の個数を減らしてプログラムの実行速度を更に向上させることができる。
【0139】
以上、本実施形態について詳細に説明したが、本実施形態は上記に限定されない。
【0140】
例えば、
図13の入力ソースコード60における配列「A」、「B」、「C」、「D」に代えて、アドレスが連続した要素を含むデータ構造を入力ソースコード60に記述してもよい。そのようなデータ構造がループ処理60aに記述されていると、プログラム実行時にそのデータ構造の各要素がアドレス順に読み出される可能性が高い。よって、そのデータ構造をバッファメモリ14(
図2参照)にプリフェッチすることで、配列の場合と同様にプログラムの実行速度を向上させることが可能となる。
【0141】
以上説明した各実施形態に関し、更に以下の付記を開示する。
(付記1) 複数の文を内包した一又は複数のループ処理を有するソースコードを取得する取得部と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する分割部と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない融合処理部と、
を有することを特徴とする情報処理装置。
(付記2) 前記融合処理部は、依存関係がある二つの前記文が複数組存在する場合には、分割前の前記ループ処理において前記文が位置するネストの深さを前記二つの文の各々について求めると共に、求めた前記深さのうちの大きい方の値を複数の前記組の各々に対して特定して、特定した前記値が大きい組から順に前記融合を行うことを特徴とする付記1に記載の情報処理装置。
(付記3) 前記融合処理部は、二つの前記文が依存関係を有しておらず、かつ同一の前記データ構造を含む場合には、前記二つの文の各々を内包する前記ループ処理同士を融合することを特徴とする付記1に記載の情報処理装置。
(付記4) 前記分割部は、相互に依存関係がある複数の前記文を含む前記ループ処理を分割しないことを特徴とする付記1に記載の情報処理装置。
(付記5) 複数の前記文の各々をノードとする有向グラフであって、依存関係を有する二つの前記文の各々に対応する二つの前記ノードの間にエッジを有すると共に、前記ソースコードにおける前記文の出現順を表す向きが前記エッジに付与されたグラフを生成するグラフ作成部を更に有し、
前記融合処理部は、二つの前記ノードの間に前記エッジが存在する場合には、前記二つのノードの各々に対応した二つの前記文の各々を内包する二つの前記ループ処理を融合すると共に、前記融合後の前記ループ処理の内部において、前記エッジの向きが表す順序に前記二つの文を並べることを特徴とする付記1に記載の情報処理装置。
(付記6) 前記ノードの値は、当該ノードに対応する前記文が前記ソースコードの前記ループ処理において位置するネストの深さであり、
前記融合処理部は、前記エッジが複数存在する場合には、前記エッジの両端の二つの前記ノードの各々に対応した二つの前記文の各々について前記値を求めると共に、求めた前記値のうちの大きい方の前記値を各々の前記エッジに対して特定し、特定した前記値が大きい前記エッジから順に前記融合を行うことを特徴とする付記5に記載の情報処理装置。
(付記7) 前記データ構造は配列であることを特徴とする付記1に記載の情報処理装置。
(付記8) 前記分割部は、分割後の前記ループ処理の個数が最大となるように、前記ループ処理を分割することを特徴とする付記1に記載の情報処理装置。
(付記9) 複数の文を内包した一又は複数のループ処理を有するソースコードを取得する処理と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する処理と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない処理と、
をコンピュータに実行させるための情報処理プログラム。
(付記10) 複数の文を内包した一又は複数のループ処理を有するソースコードを取得する処理と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する処理と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない処理と、
をコンピュータが実行することを特徴とする情報処理方法。
【符号の説明】
【0142】
1、2、3…ソースコード、10…ターゲットマシン、11…プロセッサ、12…演算部、13…データキャッシュメモリ、14…バッファメモリ、14a~14d…ブロック、15…メインメモリ、21…情報処理装置、22…記憶部、23…メインメモリ、24…プロセッサ、25…入力部、26…表示部、27…バス、28…記録媒体、30…情報処理プログラム、41…取得部、42…グラフ作成部、43…分割部、44…融合処理部、50…入力ソースコード、50…入力ソースコード、50a、50b…第1、第2のループ処理、51…分割処理済ソースコード、51a~51d…第1~第4のループ処理、52…出力ソースコード、52a~52c…第1~第3のループ処理、60…入力ソースコード、60a…ループ処理、61…分割処理済ソースコード、61a~61e…第1~第5のループ処理、62…出力ソースコード、62a~62b…第1~第3のループ処理、E、F、K…エッジ、G…グラフ、N…ノード。