(57)【要約】【課題】プログラムの実行速度を向上させること。【解決手段】複数の文を内包した一又は複数のループ処理５０ａ、５０ｂを有するソースコード５０を取得する取得部４１と、前記ソースコード５０における複数の文の依存関係を維持しながら、ループ処理５０ａ、５０ｂを複数に分割する分割部４３と、分割後の二つのループ処理５１ｃ、５１ｄの各々が内包する二つの文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ二つの文におけるデータ構造の個数がメモリフェッチストリーム数を超えない場合には、二つの文の依存関係を維持しながら二つのループ処理５１ｃ、５１ｄを融合し、上記個数がメモリフェッチストリーム数を超える場合には融合をしない融合処理部４４とを有する情報処理装置２１による。【選択図】図１０
2020126395.tif 000002
【特許請求の範囲】
【請求項１】
複数の文を内包した一又は複数のループ処理を有するソースコードを取得する取得部と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する分割部と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない融合処理部と、
を有することを特徴とする情報処理装置。
【請求項２】
前記融合処理部は、依存関係がある二つの前記文が複数組存在する場合には、分割前の前記ループ処理において前記文が位置するネストの深さを前記二つの文の各々について求めると共に、求めた前記深さのうちの大きい方の値を複数の前記組の各々に対して特定して、特定した前記値が大きい組から順に前記融合を行うことを特徴とする請求項１に記載の情報処理装置。
【請求項３】
前記融合処理部は、二つの前記文が依存関係を有しておらず、かつ同一の前記データ構造を含む場合には、前記二つの文の各々を内包する前記ループ処理同士を融合することを特徴とする請求項１に記載の情報処理装置。
【請求項４】
複数の文を内包した一又は複数のループ処理を有するソースコードを取得する処理と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する処理と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない処理と、
をコンピュータに実行させるための情報処理プログラム。
【請求項５】
複数の文を内包した一又は複数のループ処理を有するソースコードを取得する処理と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する処理と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない処理と、
をコンピュータが実行することを特徴とする情報処理方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、情報処理装置、情報処理プログラム、及び情報処理方法に関する。
【背景技術】
【０００２】
プログラムの実行速度を速める手法の一つにループ分割がある。ループ分割は、プログラムにループ処理が含まれている場合に、そのループ処理を複数個に分割する手法である。これにより、一つのループ処理に含まれる文の数が減るため、当該ループ処理を実行するときのキャッシュミスを低減でき、ひいてはプログラムの実行速度を向上させることができる。
【０００３】
プログラムのコード量が多い場合にはループ分割を手動で行うは困難であり、その場合にはコンパイラによってループ分割を行うことが多い。
【０００４】
しかしながら、コンパイラは、プログラムを実行するプロセッサのハードウェアの構造を考慮することなくループ分割を行うため、そのプロセッサが実行速度を速めるのに最適なプログラムを出力するとは限らない。
【先行技術文献】
【特許文献】
【０００５】
【特許文献１】特開２０１５−１９４８８１号公報
【特許文献２】特開２０００−３４７８７９号公報
【発明の概要】
【発明が解決しようとする課題】
【０００６】
一側面によれば、本発明は、プログラムの実行速度を向上させることを目的とする。
【課題を解決するための手段】
【０００７】
一側面によれば、複数の文を内包した一又は複数のループ処理を有するソースコードを取得する取得部と、前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する分割部と、前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない融合処理部とを有する情報処理装置が提供される。
【発明の効果】
【０００８】
一側面によれば、プログラムの実行速度を向上させることができる。
【図面の簡単な説明】
【０００９】
【図１】図１は、ループ分割について説明するための図である。
【図２】図２は、ターゲットマシンのハードウェア構成図である。
【図３】図３は、調査に使用したプログラムについて示す図である。
【図４】図４は、プログラムの実行速度の調査結果を示す図である。
【図５】図５は、本実施形態に係る情報処理装置のハードウェア構成図である。
【図６】図６は、本実施形態に係る情報処理装置の機能を示す機能構成図である。
【図７】図７は、本実施形態における入力ソースコードの一例を示す図である。
【図８】図８は、本実施形態に係るグラフ作成部が作成するグラフについて説明するための図である。
【図９】図９は、本実施形態に係るグラフと分割処理済ソースコードとを示す図である。
【図１０】図１０は、本実施形態に係るグラフと出力ソースコードとを示す図である。
【図１１】図１１は、本実施形態に係る情報処理装置について示すフローチャート（その１）である。
【図１２】図１２は、本実施形態に係る情報処理装置について示すフローチャート（その２）である。
【図１３】図１３は、本実施形態の例における入力ソースコードを示す図である。
【図１４】図１４は、本実施形態の例における入力ソースコードとグラフとを示す図である。
【図１５】図１５は、本実施形態の例における分割処理済ソースコードとグラフとを示す図である。
【図１６】図１６は、本実施形態の例における出力ソースコードとグラフとを示す図である。
【発明を実施するための形態】
【００１０】
本実施形態の説明に先立ち、本願発明者が検討した事項について説明する。
図１は、ループ分割について説明するための図である。
【００１１】
図１の例では、C言語で記述されたソースコード１に対してループ分割を行う場合を想定している。そのソースコード１には三つの文「Stmt0」、「Stmt1」、「Stmt2」を含むforループによって一つのループ処理１ａが実行される。このループ処理１ａを分割するパターンは複数ある。これらのパターンのうちの二つをソースコード２及びソースコード３に示す。
【００１２】
ソースコード２は、ソースコード１のforループを三つに分割し、その各々で文「Stmt0」、「Stmt1」、「Stmt2」を実行するソースコードである。この場合には、各forループに対応した三つのループ処理２ａ〜２ｃが実行されることになる。
【００１３】
一方、ソースコード３は、ソースコード１のforループを二つに分割し、二つのループ処理３ａ、３ｂを実行する場合のソースコードである。この例では、文「Stmt0」がループ処理３ａで実行され、文「Stmt1」と文「Stmt2」が別のループ処理３ｂで実行される。
【００１４】
このように、ループ処理１ａを分割して得られるソースコードには、ループ処理の個数が異なる二つのソースコード２、３がある。分割後のループ処理の個数は分割の粒度とも呼ばれ、分割後のループ処理の個数が多いほど粒度は小さいと言い、その個数が少ないほど粒度は大きいと言う。図１の例では、ソースコード２のループ分割の粒度はソースコード３のそれよりも小さい。
【００１５】
プログラムの実行速度はループ分割の粒度に依存する。例えば、ループ分割の粒度を小さくして一つのループ処理に含まれる文の数を少なくすれば、そのループ処理を実行する際のキャッシュミスを低減できる。その一方で、一つのプログラムに多量のループ処理が含まれてしまうため、ループ処理から抜けるための条件分岐命令の個数が増え、かえってプログラムの実行速度が低下してしまう。
【００１６】
実行速度を向上させるのに最適な分割の粒度は、プログラムを実行するターゲットマシンのハードウェアの構造に依存する。これについて以下に説明する。
【００１７】
図２は、ターゲットマシン１０のハードウェア構成図である。
【００１８】
ターゲットマシン１０は、サーバやPC(Personal Computer)等の計算機であって、プロセッサ１１とメインメモリ１５とを有する。
【００１９】
このうち、プロセッサ１１は、データのプリフェッチ機能を備えたハードウェアであって、演算部１２、データキャッシュメモリ１３、及びバッファメモリ１４を備える。
【００２０】
このうち、演算部１２は、算術演算や論理演算を行うALU(Arithmetic Logic Unit)と各種のレジスタとを備えた回路素子である。また、データキャッシュメモリ１３は、演算部１２で使用するデータを保持するSRAM(Static Random Access Memory)等のメモリである。
【００２１】
そして、バッファメモリ１４は、メインメモリ１５からデータキャッシュメモリ１３に転送されるデータを決定するために用いられるハードウェアであり、メインメモリ１５とデータキャッシュメモリ１３の間に設けられる。
【００２２】
そのバッファメモリ１４には複数のブロック１４ａ〜１４ｄが設けられる。ブロック１４ａ〜１４ｄは、データキャッシュメモリ１３に転送されるデータのアドレスやアクセスの規則性を保持するために割り当てられる記憶領域の単位である。以下ではブロック１４ａ〜１４ｄの個数のことをメモリフェッチストリーム数と呼ぶ。図２の例では、メモリフェッチストリーム数は４である。
【００２３】
一方、メインメモリ１５は、演算部１２で使用するデータや命令を記憶したDRAM(Dynamic Random Access Memory)等のハードウェアである。
【００２４】
このようなターゲットマシン１０においては、演算部１２におけるプログラム実行に先立ち、プログラム実行に必要なデータをメインメモリ１５からデータキャッシュメモリ１３に転送するプリフェッチを行う。これにより、プログラムがデータを参照するのに要する時間を短縮でき、プログラムの実行速度を向上できる。
【００２５】
そのプリフェッチで各ブロック１４ａ〜１４ｄに割り当てられるデータは実行時に決定される。ここでは、プログラム中に含まれる個々の配列に異なるブロック１４ａ〜１４ｄを割り当てる場合を想定する。例えば、プログラムに二つの配列「A」、「B」がある場合を考える。この場合は、配列「A」のアドレスやアクセスの規則性を格納するために一つのブロック１４ａが割り当てられ、配列「B」のアドレスやアクセスの規則性を格納するのに別のブロック１４ｂが割り当てられる。
【００２６】
大抵のプログラムでは、ループ処理の内部に配列がある場合、そのループ処理を実行するときに配列の各要素をアドレス順に参照することが多い。配列の各要素はアドレスが連続しているため、このように配列要素をデータキャッシュメモリ１３にプリフェッチしておくことでプログラムの実行時間を早めることができる。
【００２７】
但し、一つのループ処理に含まれる配列の個数がメモリフェッチストリーム数を超えると、それら全ての配列のアドレスやアクセスの規則性を同時にバッファメモリ１４に格納することができなくなる。そのため、ループ処理の実行時にバッファメモリ１４からアドレスやアクセスの規則性の追い出しが頻繁に発生し、プリフェッチが実行できず、プログラムの実行速度が遅くなる。
【００２８】
これを確かめるため、本願発明者は、ループ処理に含まれる配列の個数が２〜２６個の相異なるプログラムを２５個用意し、これらのプログラムの処理速度を調査した。
図３は、調査に使用したプログラムについて示す図である。
【００２９】
図３に示すように、例えば配列の個数が２個のプログラムSC2では、一つのforループの中に二つの配列「A1」、「A2」が含まれる。また、配列の個数が３個のプログラムSC3では、一つのforループの中に三つ配列「A1」、「A2」、「A3」が含まれる。配列の個数が４〜２６個のプログラムSC4〜SC26もこれと同様に作成した。
【００３０】
このようなプログラムをターゲットマシン１０で実行する場合には、前述のようにforループの実行時に各配列のアドレスやアクセスの規則性がブロック１４ａ〜１４ｄのそれぞれに格納される。例えば、プログラムSC2のforループを実行する場合には、ブロック１４ａに配列「A1」のアドレスやアクセスの規則性が格納され、ブロック１４ｂに配列「A2」のアドレスやアクセスの規則性が格納される。
【００３１】
本願発明者は、これらのプログラムSC2〜SC26の実行速度を調査した。その調査結果を図４に示す。
【００３２】
図４の横軸は、プログラムSC2〜SC26に含まれる配列の個数を示す。例えば、配列の個数が３の場合は、配列の個数が３個のプログラムSC3を実行した場合を指す。
【００３３】
また、図４の縦軸は、プロセッサが１秒当たりに処理をしたデータ量を示す。
【００３４】
なお、この調査では、プログラムを実行するプロセッサとしてARM thunder X2 CN9975を使用した。
【００３５】
図４に示すように、配列の個数が８個を超えるとデータの処理量が大きく低下する。これは、このプロセッサのメモリフェッチストリーム数が８であるためと考えられる。
【００３６】
以上の結果から、プログラムの実行速度を向上させるには、一つのループ処理に含まれる配列の個数をメモリフェッチストリーム数以下とするのが好ましいことが明らかとなった。
【００３７】
以下に、プログラムの実行速度を向上させ得る本実施形態について説明する。
【００３８】
（本実施形態）
本実施形態では、以下のようにしてソースコードに含まれるループ処理を分割し、一つのループ処理に含まれる配列の個数がメモリフェッチストリーム数を超えないようにする。
【００３９】
[ハードウェア構成]
図５は、本実施形態に係る情報処理装置のハードウェア構成図である。
【００４０】
この情報処理装置２１は、ループ分割を行うためのPC等の計算機であって、記憶部２２、メインメモリ２３、プロセッサ２４、入力部２５、及び表示部２６を備える。これらの各部はバス２７によって相互に接続される。
【００４１】
このうち、記憶部２２は、例えばHDD(Hard Disk Drive)やSSD(Solid State Drive)等の二次記憶装置であり、本実施形態に係る情報処理プログラム３０を記憶する。情報処理プログラム３０は、入力されたソースコードをループ分割し、分割後のソースコードを出力するコンパイラである。
【００４２】
なお、その情報処理プログラム３０をコンピュータが読み取り可能な記録媒体２８に記録させておき、プロセッサ２４に記録媒体２８の情報処理プログラム３０を読み取らせるようにしてもよい。
【００４３】
そのような記録媒体２８としては、例えばCD-ROM(Compact Disc - Read Only Memory)、DVD(Digital Versatile Disc)、及びUSB(Universal Serial Bus)メモリ等の物理的な可搬型記録媒体がある。また、フラッシュメモリ等の半導体メモリやハードディスクドライブを記録媒体２８として使用してもよい。これらの記録媒体２８は、物理的な形態を持たない搬送波のような一時的な媒体ではない。
【００４４】
更に、公衆回線、インターネット、及びLAN(Local Area Network)等に接続された装置に情報処理プログラム３０を記憶させておき、プロセッサ２４が情報処理プログラム３０を読み出して実行するようにしてもよい。
【００４５】
一方、メインメモリ２３は、DRAM等のようにデータを一時的に記憶するハードウェアであって、その上に前述の情報処理プログラム３０が展開される。
【００４６】
プロセッサ２４は、自装置の各部を制御したり、メインメモリ２３と協働して情報処理プログラム３０を実行したりするCPU(Central Processing Unit)等のハードウェアである。
【００４７】
入力部２５は、キーボードやマウス等の入力デバイスである。ユーザがこれらの入力デバイスを操作することにより、情報処理プログラム３０でコンパイルするソースファイルを指定したり、コンパイル後の出力ソースファイルの出力先が指定されたりする。
【００４８】
また、表示部２６は、情報処理プログラム３０の実行時にユーザが使用する様々なコマンドを表示する液晶ディスプレイ等の表示デバイスである。なお、以下では情報処理装置２１が情報処理プログラム３０を実行する場合を例にして説明するが、ターゲットマシン１０（図２参照）が情報処理プログラム３０を実行することにより以下の各処理や機能を実現してもよい。
【００４９】
[機能構成]
図６は、本実施形態に係る情報処理装置２１の機能を示す機能構成図である。
【００５０】
図６に示すように、情報処理装置２１は、取得部４１、グラフ作成部４２、分割部４３、及び融合処理部４４を備える。これらの各部は、プロセッサ２４とメインメモリ２３が協働して前述の情報処理プログラム３０を実行することにより実現される。
【００５１】
このうち、取得部４１は、コンパイルの対象となる入力ソースコードを取得する機能ユニットであり、例えば図７に示す入力ソースコード５０を取得する。
図７は、入力ソースコード５０の一例を示す図である。
【００５２】
入力ソースコード５０は、図２のターゲットマシン１０で実行するためのC言語で記述されたプログラムであり、複数のforループを有する。以下では、これらのforループのうち最も外側のforループで実行される処理をループ処理と呼ぶ。図７の例では、第１のループ処理５０ａと第２のループ処理５０ｂがループ処理の例となる。
【００５３】
このうち、第１のループ処理５０ａは複数の文「Stmt0」、「Stmt1」、「Stmt2」を内包しており、これらの文を一つのforループで繰り返し実行する。また、第２のループ処理５０ｂは、入れ子の関係にある二つのforループで実現されるネストの深さが２のループ処理であり、複数の文「Stmt3」、「Stmt4」を内包する。
【００５４】
なお、ここでは入力ソースコード５０に複数のループ処理５０ａ、５０ｂが含まれている場合を例にしているが、一つのループ処理に複数の文を含む入力ソースコード５０を用いてもよい。
【００５５】
更に、入力ソースコード５０を記述する言語はC言語に限定されず、C++やFortranによって入力ソースコード５０を記述してもよい。また、for文に代えてwhile文によりループを記述してもよい。
【００５６】
グラフ作成部４２（図６参照）は、依存解析によりこの入力ソースコード５０に含まれる複数の文の各々の依存関係を求め、その依存関係に基づいてグラフを作成する。
そのグラフについて図８を参照しながら説明する。
【００５７】
図８は、入力ソースコード５０を用いてグラフ作成部４２が作成するグラフGについて説明するための図である。
【００５８】
グラフGは、入力ソースコード５０に含まれる文「Stmt0」、「Stmt1」、「Stmt2」、「Stmt3」、「Stmt4」の各々をノードNとする有向グラフである。また、ノードNの値は、そのノードNに対応した文が位置するネストの深さである。例えば、文「Stmt3」は、ループ処理５０ｂにおいて二つのfor文の内側にあり、ネストの深さが２のところに位置しているため、文「Stmt3」に対応するノードNの値は２となる。文「Stmt4」についても同様である。一方、「Stmt0」、「Stmt1」、「Stmt2」の各々の文は、ループ処理５０ａにおいて一つのfor文の内側にあり、ネストの深さが１のところに位置しているため、これらの文に対応するノードNの値は１となる。
【００５９】
また、グラフ作成部４２は、フロー依存、出力依存、及び逆依存のいずれかの依存関係を有する二つの文の組を特定し、これらの文に対応するノードN間にエッジEを設ける。
【００６０】
図８の例では、以下のような依存関係がある場合を想定している。
文「Stmt1」と文「Stmt3」：フロー依存
文「Stmt3」と文「Stmt4」：出力依存
文「Stmt0」と文「Stmt1」：双方向に依存
文「Stmt2」：依存関係なし
【００６１】
この場合には、文「Stmt1」と文「Stmt3」のそれぞれに対応する二つのノードNの間にエッジEが設けられる。また、そのエッジEの向きは、入力ソースコード５０における文の出現順とする。よって、このエッジEの向きは、文「Stmt1」から文「Stmt3」に向かう方向となる。
【００６２】
同様に、文「Stmt3」と文「Stmt4」のそれぞれに対応する二つのノードNの間にも、文「Stmt3」から文「Stmt4」に向かう方向のエッジEが設けられる。
【００６３】
一方、相互に依存関係がある文「Stmt0」と文「Stmt1」との間には、双方向を向いたエッジFを設ける。例えば、文「Stmt0」が文「Stmt1」の結果を参照し、かつ文「Stmt1」が文「Stmt0」の結果を参照する場合に、これらの文は相互に依存関係を有することになる。
【００６４】
また、他の文と依存関係がない文「Stmt2」については、その文「Stmt2」と同じ配列を含む他の文との間に仮想的なエッジKを設ける。ここでは、文「Stmt0」と文「Stmt2」とが同一の配列を含むものとする。なお、この仮想的なエッジKの向きも、入力ソースコード５０における文の出現順とする。
【００６５】
分割部４３（図６参照）は、このグラフGを参照することにより、入力ソースコード５０に含まれるループ処理５０ａ、５０ｂを、各文の依存関係を維持する分割のうちで分割後のループ処理の個数が最大となるように分割する。
その分割方法について図９を参照して説明する。
【００６６】
図９は、前述のグラフGと、ループ処理を分割した分割処理済ソースコード５１とを示す図である。
【００６７】
図９に示されるように、分割処理済ソースコード５１は、ループ処理を分割したことで入力ソースコード５０よりもループ処理の個数が増えており、第１〜第４のループ処理５１ａ〜５１ｄを有する。どのようにループ処理を分割するかは、分割部４３がグラフGを参照することで以下のように決定する。
【００６８】
例えば、グラフGに示されるように、文「Stmt1」と文「Stmt3」は、それらを結ぶエッジEが一方向を向いており、その向きで規定される出現順を保つ限り、異なるループ処理で実行しても実行結果は変わらない。よって、分割部４３は、エッジEの向きを参照して文「Stmt1」と文「Stmt3」の出現順を特定し、その出現順が変わらないように文「Stmt1」と文「Stmt3」をそれぞれ異なるループ処理５１ａ、５１ｃに内包させる。文「Stmt3」と文「Stmt4」との組、及び文「Stmt0」と文「Stmt3」との組についても同様である。
【００６９】
一方、文「Stmt0」と文「Stmt1」は、それらを結ぶエッジFの向きが双方向となっている。この場合は、前述のように文「Stmt0」と文「Stmt1」は相互に依存関係を有しているため、これらの文を別々のループ処理で実行したのでは分割前と実行結果が変わってしまう。よって、分割部４３は、グラフGを参照して得られたエッジFの向きが双方向となっている場合には、そのエッジFの両端の文を同一のループ処理に内包させる。図９の例では、文「Stmt0」と文「Stmt1」が同じループ処理５１ａに内包される。
【００７０】
以上により、文「Stmt0」、「Stmt1」、「Stmt2」、「Stmt3」、「Stmt4」の各々の依存関係を維持する複数の分割のうち、分割後のループ処理５１ａ〜５１ｄの個数が最大となる分割処理済ソースコード５１が得られることになる。
【００７１】
融合処理部４４（図９参照）は、このように分割部４３がループ処理を分割した後に、ループ処理を融合して最終的な出力ソースコードを出力する。その融合方法について図１０を参照して説明する。
【００７２】
図１０は、前述のグラフGと出力ソースコード５２を示す図である。
【００７３】
出力ソースコード５２は、融合処理部４４が分割処理済ソースコード５１のループ処理５１ａ〜５１ｄの一部を融合することにより得られたソースコードであり、この例では第１〜第３のループ処理５２ａ〜５２ｃを有する。
【００７４】
ループ処理５１ａ〜５１ｄのうちのどれを融合するかは、メモリフェッチストリーム数nと各文に含まれる配列に依存する。そこで、以下では、文「Stmt0」と文「Stmt2」のそれぞれに含まれる配列が「A0」のみであり、文「Stmt1」に含まれる配列が「A1」のみであるとする。また、文「Stmt3」に含まれる配列が「A3」のみであり、文「Stmt4」に含まれる配列が「A4」のみであるとする。
【００７５】
また、簡単のためにメモリフェッチストリーム数nは２であるとする。
【００７６】
この場合、メモリフェッチストリーム数nを超えた個数の配列が一つのループ処理に含まれていると、前述のようにバッファメモリ１４からアドレスやアクセスの規則性が追い出されるため、そのループ処理の実行速度が低下する。
【００７７】
例えば、ループ処理５１ａ、５１ｂを融合して「Stmt0」、「Stmt1」、「Stmt2」の各文を一つのforループで実行すると、そのforループに三つの配列「A0」、「A1」、「A2」が含まれてしまい、配列の個数がn（＝２）を超えてしまう。
【００７８】
よって、融合処理部４４は、ループ処理５１ａ、５１ｂを融合の対象とはしない。
【００７９】
一方、ループ処理５１ｃ、５１ｄを融合し、文「Stmt3」と文「Stmt4」とを一つのforループで実行しても、そのforループに含まれる配列の個数は２となり、メモリフェッチストリーム数n（＝２）を超えない。
【００８０】
したがって、融合処理部４４は、これらのループ処理５１ｃ、５１ｄを融合して新しいループ処理５２ｃとする。この場合、融合前に文「Stmt3」と文「Stmt4」が位置していたネストの深さはいずれも２であるため、融合後のループ処理５２ｃにおいてもこれらの文「Stmt3」、「Stmt4」のネストの深さは２となる。
【００８１】
深いネストを有するループ処理を二つに分割したままにしておくと、ループ処理から抜けるための条件分岐命令を各ループ処理で独立に実行する必要があり、実行命令数が増えてプログラムの実行時間が長くなってしまう。よって、ループ処理５１ｃ、５１ｄのようにネストが深い処理同士を融合することで、条件分岐命令の数を大きく削減でき、融合による実行時間の短縮化の効果が大きくなる。
【００８２】
そこで、融合処理部４４は、グラフGのノードNの値が表すネストの深さを参照し、その深さに基づいて融合する二つのループ処理を決定する。例えば、融合処理部４４は、エッジE、Kの両端の二つのノードNの各々の値のうちで大きい方の値を求め、当該値が大きなエッジE、Kから順にループ処理を融合する。
【００８３】
また、融合処理部４４は、文「Stmt3」と文「Stmt4」の各々に対応したノードNの間のエッジEの向きを参照し、その向きが表す出現順にループ処理５２ｃに文「Stmt3」と文「Stmt4」とを並べる。これにより、融合後のループ処理５２ｃにおいても各文「Stmt3」、「Stmt4」の依存関係が維持され、入力ソースコード５０と同じ実行結果が出力される出力ソースコード５２を得ることができる。
【００８４】
[フローチャート]
次に、本実施形態に係る情報処理方法について説明する。
図１１及び図１２は、本実施形態に係る情報処理方法について示すフローチャートである。
【００８５】
まず、ステップＳ１において、取得部４１が入力ソースコード５０（図７参照）を取得する。
【００８６】
次に、ステップＳ２に移り、グラフ作成部４２が、入力ソースコード５０に含まれる複数の文の依存解析を行い、その解析結果に基づいて図８に示したグラフGを作成する。
【００８７】
続いて、ステップＳ３に移り、グラフ作成部４２がグラフGに仮想的なエッジKを追加する。前述のように、そのエッジKは、依存関係がないものの同一の配列を含む文に対応したノードN間に設けられる。
【００８８】
次いで、ステップＳ４に移り、分割部４３が、入力ソースコード５０に含まれるループ処理５０ａ、５０ｂの各々を複数に分割する。これにより、図９に示したように、複数のループ処理５１ａ〜５１ｄを有する分割処理済ソースコード５１を生成する。
【００８９】
この分割は、前述のように各文の依存関係を維持する分割のうちで分割後のループ処理５１ａ〜５１ｄの個数が最大となるように行われる。これにより、分割により得られるループ処理の個数が増えるため、後で融合するループ処理の組の候補を増やすことができる。
【００９０】
続いて、ステップＳ５に移り、融合処理部４４が、メモリフェッチストリーム数nを取得する。例えば、融合処理部４４は、ユーザが入力部２５から入力したメモリフェッチストリーム数nを取得してもよいし、コンパイラの依存解析によりメモリフェッチストリーム数nを取得してもよい。
【００９１】
次に、ステップＳ６に移り、融合処理部４４が、エッジEの両端のノードNのうちで大きい方の値Dを、全てのエッジEについて特定する。その値Dは、前述のように、エッジEの両端に対応する二つの文が位置するネストうち、深い方の深さを表す。そこで、以下では、値DのことをエッジEのネストの深さDとも呼ぶ。
【００９２】
同様に、融合処理部４４は、仮想的なエッジKに対してもその値Dを特定する。
【００９３】
そして、融合処理部４４が、複数のエッジE、Kのうちで値Dが最大のものを選択する。
【００９４】
続いて、ステップＳ７に移り、選択したエッジE、Kの両端の各々の文を内包する二つのループ処理を融合すると、融合後のループ処理に含まれる配列の個数がメモリフェッチストリーム数nを超えるかを融合処理部４４が判断する。
【００９５】
ここで、超える（ＹＥＳ）と判断された場合には、ステップＳ８に移り、そのエッジE、Kを次の選択候補から外す。そして、ステップＳ６からやり直す。
【００９６】
一方、ステップＳ７において超えない（ＮＯ）と判断された場合には、図１２のステップＳ９に移る。ステップＳ９では、融合処理部４４が、ステップＳ６で選択したエッジE、Kの両端の各々の文を内包する二つのループ処理を融合する。
【００９７】
次に、ステップＳ１０に移り、融合処理部４４が、ステップＳ９で融合したエッジE、Kを次の選択候補から外す。
【００９８】
続いて、ステップＳ１１に移り、融合処理部４４が、選択可能なエッジE、Kがないかどうかを判断する。ここで、残っていない（ＹＥＳ）と判断された場合には、ステップＳ１２に移り、融合処理部４４が図１０の出力ソースコード５２を出力する。
【００９９】
一方、残っている（ＮＯ）と判断された場合にはステップＳ６からやり直す。
【０１００】
以上により、本実施形態に係る情報処理装置の基本ステップを終了する。
【０１０１】
この後は、出力ソースコード５２を他のコンパイラでコンパイルすることにより、図２のターゲットマシン１０で実行可能なバイナリファイルを作成する。
【０１０２】
上記した本実施形態によれば、ステップＳ７、Ｓ９において、一つのループ処理が内包する配列の個数がメモリフェッチストリーム数nを超えないように、二つの文の各々を内包する二つのループ処理同士を融合する。
【０１０３】
そのため、図２のバッファメモリ１４からアドレスやアクセスの規則性が頻繁に追い出されるのを抑制でき、プログラムの実行速度が向上するという技術的な効果が得られる。
【０１０４】
更に、このようにループ処理同士を融合することでループ処理を抜け出すための条件分岐命令の個数が減り、プログラムの実行速度を更に向上させることができる。
【０１０５】
しかも、ステップＳ６において、複数のエッジEのうちでネストの深さDが最大のものを選択するため、ネストが深いループ処理から順に融合が行われる。これにより、ネストが深く条件分岐命令を多く含むループ処理から優先的に減らすことができ、融合による実行時間の短縮化の効果が大きくなる。
【０１０６】
また、ステップＳ３において依存関係がない二つの文の間に仮想的なエッジを追加するため、依存関係がない二つの文の各々を含むループ処理も融合の候補とすることができる。そして、これらのループ処理を実際に融合することにより、条件分岐命令の削減による実行時間の短縮化の効果を得ることができる。
【０１０７】
特に、HPC(High Performance Computing)向けのプログラムではループ処理が内包する文の個数が膨大になる傾向がある。よって、そのようなプログラムに対して本実施形態のようにループ処理を自動的に分割や融合をすることで開発者の負担を減らすことができる。
【０１０８】
次に、更に詳細なソースコードを用いた具体的な例について説明する。
【０１０９】
図１３は、本例で使用する入力ソースコードを示す図である。
【０１１０】
この例ではC言語で記述された入力ソースコード６０を使用する。その入力ソースコード６０はネスト構造の二つのforループを有しており、このうちの外側のforループによってループ処理６０ａが実行される。そして、そのループ処理６０ａには４個の配列A、B、C、Dが含まれる。
【０１１１】
なお、以下では、ソースコード６０に含まれる文を、その文と同一行のコメント文で特定する。例えば、コメント文「Stmt0」は、文「A[i] = alpha;」を指すものとする。
【０１１２】
そして、前述の図１１及び図１２のフローチャートに従い、この入力ソースコード６０に対して情報処理装置２１が以下の各処理を行う。
【０１１３】
まず、取得部４１が入力ソースコード６０を取得し（ステップＳ１）、次いでグラフ作成部４２がグラフGを作成する（ステップＳ２）。
【０１１４】
図１４は、入力ソースコード６０とグラフGとを示す図である。
【０１１５】
図１４に示されるように、入力ソースコード６０の各文には次のような依存関係がある。
【０１１６】
文「Stmt0」と文「Stmt2」：配列「A」によるフロー依存
文「Stmt1」と文「Stmt3」：配列「B」によるフロー依存
文「Stmt2」と文「Stmt3」：配列「C」による出力依存
文「Stmt3」と文「Stmt4」：依存関係なし
【０１１７】
この依存関係に従い、グラフ作成部４２がグラフGを作成する。
【０１１８】
そのグラフGは、前述のように各文をノードNとする有向グラフであって、各文が位置するネストの深さがそのノードNの値となる。
【０１１９】
例えば、文「Stmt2」は、ループ処理６０ａにおいて二つのfor文の内側にあり、ネストの深さが２のところに位置しているため、文「Stmt2」に対応するノードNの値は２となる。また、文「Stmt0」は、ループ処理６０ａにおいて一つのfor文の内側にあり、ネストの深さが１のところに位置しているため、文「Stmt0」に対応するノードNの値は１となる。
【０１２０】
更に、依存関係がある二つの文の各々に対応した二つのノードNの間にはエッジEが設けられ、入力ソースコード６０における各文の出現順を表す向きがそのエッジEに付与される。
【０１２１】
例えば、前述のように文「Stmt1」と文「Stmt3」は、配列「B」によるフロー依存を有するため、これらの文に対応したノードNの間にはエッジEが設けられる。また、入力ソースコード６０においては先に文「Stmt1」が出現してその後に文「Stmt3」が出現するため、文「Stmt1」から文「Stmt3」に向かう方向の向きがそのエッジEに付与される。
【０１２２】
続いて、グラフ作成部４２が、このグラフGに仮想的なエッジKを追加する（ステップＳ３）。
【０１２３】
前述のように、仮想的なエッジKは、同一の配列を含む依存関係がない二つの文の間に設けられる。この例では、文「Stmt3」と文「Stmt4」とは依存関係を有していないものの、同一の配列「B」を含む。よって、文「Stmt3」と文「Stmt4」の各々に対応するノードNの間に仮想的なエッジKが設けられる。
【０１２４】
次に、分割部４３が、このグラフGを参照してループ処理６０ａを複数に分割する。
【０１２５】
図１５は、分割により得られた分割処理済ソースコード６１とグラフGとを示す図である。
【０１２６】
前述のように、ループ処理の分割は、複数の文の依存関係を維持する分割のうちで、分割後のループ処理の個数が最大となるように行われる。この例では、文「Stmt0」、「Stmt1」、「Stmt2」、「Stmt3」、「Stmt4」のうちで相互の依存関係を有する組み合わせがないため、一つのループ処理が一つの文のみを内包するようにしても各々の文の依存関係は維持される。よって、ループ処理６０ａは、各々が一つの文のみを内包する第１〜第５のループ処理６１ａ〜６１ｅに分割される。
【０１２７】
次に、融合処理部４４が、メモリフェッチストリーム数nを取得する（ステップＳ５）。この例では、メモリフェッチストリーム数nは２とする。
【０１２８】
次いで、融合処理部４４が、全ての複数のエッジE、Kのうちでネストの深さDが最も深いものを選択する（ステップＳ６）。この例では、全てのエッジE、Kにおいて深さDが２となるため、全てのエッジE、Kが選択されることになる。
【０１２９】
そして、融合処理部４４が、一つのループ処理に含まれる配列の個数がメモリフェッチストリーム数n（＝２）を超えないように、各エッジE、Kの両端の文を内包するループ処理同士を融合する（ステップＳ７〜Ｓ１０）。
【０１３０】
図１６は、このように融合して得られた出力ソースコード６２とグラフGとを示す図である。
【０１３１】
図１６に示すように、その出力ソースコード６２には第１〜第３のループ処理６２ａ〜６２ｃが含まれる。
【０１３２】
このうち、第１のループ処理６２ａは、文「Stmt0」を内包する第１のループ処理６１ａと文「Stmt2」を内包する第３のループ処理６１ｃとを融合して得られたループ処理である。その第１のループ処理６２ａに含まれる配列は「A」と「C」であるため、第１のループ処理６２ａに含まれる配列の個数は２となり、メモリフェッチストリーム数n（＝２）を超えない。
【０１３３】
また、第２のループ処理６２ｂは、文「Stmt1」を内包する第２のループ処理６１ｂと文「Stmt3」を内包する第４のループ処理６１ｄとを融合して得られたループ処理である。その第２のループ処理６２ｂにおいても、二つの配列「B」、「Ｃ」のみが含まれており、配列の個数はメモリフェッチストリーム数n（＝２）を超えない。
【０１３４】
一方、第３のループ処理６１ｃと第４のループ処理６１ｄとを融合してしまうと、融合後のループ処理には「A」、「B」、「C」の三つの配列が含まれてしまい、配列の個数がメモリフェッチストリーム数n（＝２）を超えてしまう。よって、融合処理部４４は、第３のループ処理６１ｃと第４のループ処理６１ｄとを融合しない。同様の理由により、第４のループ処理６１ｄと第５のループ処理６１ｅも融合しない。
【０１３５】
よって、融合処理部４４は選択可能なエッジはないと判断し（ステップＳ１１）、この出力ソースコード６２を出力する。
【０１３６】
以上により、入力ソースコード６０を用いた場合の処理を終える。
【０１３７】
上記した例によれば、出力ソースコード６２における第１〜第３のループ処理６２ａ〜６２ｃの各々に含まれる配列の個数がメモリフェッチストリーム数を超えない。そのため、ターゲットマシン１０において各ループ処理６２ａ〜６２ｃを実行する際に、バッファメモリ１４からアドレスやアクセスの規則性が追い出されるのを抑制でき、プログラムの実行速度を向上することができる。
【０１３８】
しかも、図１５の分割処理済ソースコード６１における各ループ処理６１ａ〜６１ｅの一部を融合することで、ループ処理を抜け出すための条件分岐命令の個数を減らしてプログラムの実行速度を更に向上させることができる。
【０１３９】
以上、本実施形態について詳細に説明したが、本実施形態は上記に限定されない。
【０１４０】
例えば、図１３の入力ソースコード６０における配列「A」、「B」、「C」、「D」に代えて、アドレスが連続した要素を含むデータ構造を入力ソースコード６０に記述してもよい。そのようなデータ構造がループ処理６０ａに記述されていると、プログラム実行時にそのデータ構造の各要素がアドレス順に読み出される可能性が高い。よって、そのデータ構造をバッファメモリ１４（図２参照）にプリフェッチすることで、配列の場合と同様にプログラムの実行速度を向上させることが可能となる。
【０１４１】
以上説明した各実施形態に関し、更に以下の付記を開示する。
（付記１）  複数の文を内包した一又は複数のループ処理を有するソースコードを取得する取得部と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する分割部と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない融合処理部と、
を有することを特徴とする情報処理装置。
（付記２）  前記融合処理部は、依存関係がある二つの前記文が複数組存在する場合には、分割前の前記ループ処理において前記文が位置するネストの深さを前記二つの文の各々について求めると共に、求めた前記深さのうちの大きい方の値を複数の前記組の各々に対して特定して、特定した前記値が大きい組から順に前記融合を行うことを特徴とする付記１に記載の情報処理装置。
（付記３）  前記融合処理部は、二つの前記文が依存関係を有しておらず、かつ同一の前記データ構造を含む場合には、前記二つの文の各々を内包する前記ループ処理同士を融合することを特徴とする付記１に記載の情報処理装置。
（付記４）  前記分割部は、相互に依存関係がある複数の前記文を含む前記ループ処理を分割しないことを特徴とする付記１に記載の情報処理装置。
（付記５）  複数の前記文の各々をノードとする有向グラフであって、依存関係を有する二つの前記文の各々に対応する二つの前記ノードの間にエッジを有すると共に、前記ソースコードにおける前記文の出現順を表す向きが前記エッジに付与されたグラフを生成するグラフ作成部を更に有し、
前記融合処理部は、二つの前記ノードの間に前記エッジが存在する場合には、前記二つのノードの各々に対応した二つの前記文の各々を内包する二つの前記ループ処理を融合すると共に、前記融合後の前記ループ処理の内部において、前記エッジの向きが表す順序に前記二つの文を並べることを特徴とする付記１に記載の情報処理装置。
（付記６）  前記ノードの値は、当該ノードに対応する前記文が前記ソースコードの前記ループ処理において位置するネストの深さであり、
前記融合処理部は、前記エッジが複数存在する場合には、前記エッジの両端の二つの前記ノードの各々に対応した二つの前記文の各々について前記値を求めると共に、求めた前記値のうちの大きい方の前記値を各々の前記エッジに対して特定し、特定した前記値が大きい前記エッジから順に前記融合を行うことを特徴とする付記５に記載の情報処理装置。
（付記７）  前記データ構造は配列であることを特徴とする付記１に記載の情報処理装置。
（付記８）  前記分割部は、分割後の前記ループ処理の個数が最大となるように、前記ループ処理を分割することを特徴とする付記１に記載の情報処理装置。
（付記９）  複数の文を内包した一又は複数のループ処理を有するソースコードを取得する処理と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する処理と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない処理と、
をコンピュータに実行させるための情報処理プログラム。
（付記１０）  複数の文を内包した一又は複数のループ処理を有するソースコードを取得する処理と、
前記ソースコードにおける複数の前記文の依存関係を維持しながら、前記ループ処理を複数に分割する処理と、
前記分割後の二つの前記ループ処理の各々が内包する二つの前記文が、アドレスが連続した要素を含むデータ構造を複数有しており、かつ前記二つの文における前記データ構造の個数がメモリフェッチストリーム数を超えない場合には、前記二つの文の依存関係を維持しながら前記二つのループ処理を融合し、前記個数が前記メモリフェッチストリーム数を超える場合には前記融合をしない処理と、
をコンピュータが実行することを特徴とする情報処理方法。
【符号の説明】
【０１４２】
１、２、３…ソースコード、１０…ターゲットマシン、１１…プロセッサ、１２…演算部、１３…データキャッシュメモリ、１４…バッファメモリ、１４ａ〜１４ｄ…ブロック、１５…メインメモリ、２１…情報処理装置、２２…記憶部、２３…メインメモリ、２４…プロセッサ、２５…入力部、２６…表示部、２７…バス、２８…記録媒体、３０…情報処理プログラム、４１…取得部、４２…グラフ作成部、４３…分割部、４４…融合処理部、５０…入力ソースコード、５０…入力ソースコード、５０ａ、５０ｂ…第１、第２のループ処理、５１…分割処理済ソースコード、５１ａ〜５１ｄ…第１〜第４のループ処理、５２…出力ソースコード、５２ａ〜５２ｃ…第１〜第３のループ処理、６０…入力ソースコード、６０ａ…ループ処理、６１…分割処理済ソースコード、６１ａ〜６１ｅ…第１〜第５のループ処理、６２…出力ソースコード、６２ａ〜６２ｂ…第１〜第３のループ処理、E、F、K…エッジ、G…グラフ、N…ノード。
【図１】
2020126395.tif 000003
【図２】
2020126395.tif 000004
【図３】
2020126395.tif 000005
【図４】
2020126395.tif 000006
【図５】
2020126395.tif 000007
【図６】
2020126395.tif 000008
【図７】
2020126395.tif 000009
【図８】
2020126395.tif 000010
【図９】
2020126395.tif 000011
【図１０】
2020126395.tif 000012
【図１１】
2020126395.tif 000013
【図１２】
2020126395.tif 000014
【図１３】
2020126395.tif 000015
【図１４】
2020126395.tif 000016
【図１５】
2020126395.tif 000017
【図１６】
2020126395.tif 000018