(19)【発行国】日本国特許庁(JP)
(12)【公報種別】特許公報(B2)
(11)【特許番号】
(24)【登録日】2023-06-13
(45)【発行日】2023-06-21
(54)【発明の名称】クラス生成プログラム及びクラス生成方法
(51)【国際特許分類】
G06F 9/455 20180101AFI20230614BHJP
【FI】
G06F9/455 100
(21)【出願番号】P 2021562209
(86)(22)【出願日】2019-12-02
(86)【国際出願番号】 JP2019046992
(87)【国際公開番号】W WO2021111496
(87)【国際公開日】2021-06-10
【審査請求日】2022-04-13
(73)【特許権者】
【識別番号】000005223
【氏名又は名称】富士通株式会社
(74)【代理人】
【識別番号】100087480
【氏名又は名称】片山 修平
(72)【発明者】
【氏名】栗原 康志
(72)【発明者】
【氏名】川上 健太郎
(72)【発明者】
【氏名】齋藤 盛幸
【審査官】三坂 敏夫
(56)【参考文献】
【文献】特開2010-186468(JP,A)
【文献】米国特許出願公開第2008/0141012(US,A1)
【文献】中西 悠 他,コードの性能可搬性を提供するSIMD向け共通記述方式,情報処理学会論文誌 第48巻 No.SIG13(ACS19),日本,社団法人情報処理学会,2007年08月15日,第48巻 第SIG 13(ACS 19)号,第95頁-第105頁,ISSN:0387-5806
【文献】井上 拓 他,SIMD命令を用いるUTF-8文字列デコード処理の高速化,情報処理学会論文誌 論文誌トランザクション 2008 Nobember[CD-ROM],日本,社団法人情報処理学会,2008年11月15日,第1頁-第8頁,ISSN:1882-7772
(58)【調査した分野】(Int.Cl.,DB名)
G06F 9/448-9/455
(57)【特許請求の範囲】
【請求項1】
ベクトルレジスタに関する第1の書式を表す第1のクラスと、前記ベクトルレジスタに関する第2の書式を表すと共に前記第1のクラス
の機能を継承した第2のクラスと、
前記第2のクラスのインスタンスを前記第1のクラスのメンバ変数として指定する際に利用される符号、前記ベクトルレジスタに含まれる要素を指定する際に利用される符号、又は前記ベクトルレジスタのリストを指定する際に利用される符号である字句とを対応付けて記憶した記憶部を参照して、相互に対応する前記第1のクラス、前記第2のクラス、及び前記字句を取得する処理と、
取得した前記字句に応じて、取得した前記第2のクラスのインスタンスを生成する第1のコードと、前記字句を多重定義する第2のコードのいずれかを、取得した前記第1のクラスの内部に生成する処理と、
をコンピュータに実行させるためのクラス生成プログラム。
【請求項2】
前記第1のコードを含む第1のテンプレートと、前記第2のコードを含む第2のテンプレートとを前記字句に対応付けて記憶した前記記憶部を参照して、前記第1のテンプレートと前記第2のテンプレートのうちで取得した前記字句に対応するテンプレートを取得する処理を更に有し、
取得した前記第1のクラスの内部に前記第1のコードと前記第2のコードのいずれかを生成する処理は、取得した前記テンプレートに含まれる前記第1のコードと前記第2のコードのいずれかに取得した前記第2のクラスを当てはめたコードを生成することにより行われることを特徴とする請求項1に記載のクラス生成プログラム。
【請求項3】
前記第1の書式は、複数の前記ベクトルレジスタのうちの一を指定する書式であり、
前記第2の書式は、前記ベクトルレジスタに含まれる要素の個数と前記要素のサイズとを指定する書式であることを特徴とする請求項1に記載のクラス生成プログラム。
【請求項4】
前記第1の書式は、前記ベクトルレジスタに含まれる要素の個数と前記要素のサイズとを指定する書式であり、
前記第2の書式は、前記要素を指定する書式、又は前記ベクトルレジスタのリストを指定する書式であることを特徴とする請求項1に記載のクラス生成プログラム。
【請求項5】
前記字句は、ドット、角括弧、及びハイフンのいずれかであることを特徴とする請求項1に記載のクラス生成プログラム。
【請求項6】
ベクトルレジスタに関する第1の書式を表す第1のクラスと、前記ベクトルレジスタに関する第2の書式を表すと共に前記第1のクラス
の機能を継承した第2のクラスと、
前記第2のクラスのインスタンスを前記第1のクラスのメンバ変数として指定する際に利用される符号、前記ベクトルレジスタに含まれる要素を指定する際に利用される符号、又は前記ベクトルレジスタのリストを指定する際に利用される符号である字句とを対応付けて記憶した記憶部を参照して、相互に対応する前記第1のクラス、前記第2のクラス、及び前記字句を取得する処理と、
取得した前記字句に応じて、取得した前記第2のクラスのインスタンスを生成する第1のコードと、前記字句を多重定義する第2のコードのいずれかを、取得した前記第1のクラスの内部に生成する処理と、
をコンピュータが実行することを特徴とするクラス生成方法。
【発明の詳細な説明】
【技術分野】
【0001】
本発明は、クラス生成プログラム及びクラス生成方法に関する。
【背景技術】
【0002】
プログラムの実行速度を高速化する技術の一つとしてJIT(Just In Time)コンパイラ技術がある。JITコンパイラ技術は、プロセッサの命令セットに含まれる命令と同一の処理を実行する関数を開発者がソースコードに記述することにより、その命令の機械語をコンパイル後の実行可能プログラムに含める技術である。これにより、プログラム実行の際に入力されたパラメータを高速に処理するのに適した機械語を実行可能プログラムに含めることができ、プログラムの実行速度を高速化することが可能となる。
【0003】
そのようなJITコンパイラ技術では、上記のように命令と同一の処理を行う関数の引数を、開発者が慣れ親しんだアセンブリの文法に似た文法で記述できると開発者にとって便利である。しかし、ソースコードで使用する言語とアセンブリの各々の文法は異なるため、このようにアセンブリに類似した文法で関数の引数を記述するのは困難である。
【先行技術文献】
【特許文献】
【0004】
【発明の概要】
【発明が解決しようとする課題】
【0005】
一側面によれば、本発明は、アセンブリに類似した文法をソースコードで使用できるようにすることを目的とする。
【課題を解決するための手段】
【0006】
一側面によれば、ベクトルレジスタに関する第1の書式を表す第1のクラスと、前記ベクトルレジスタに関する第2の書式を表すと共に前記第1のクラスの機能を継承した第2のクラスと、前記第2のクラスのインスタンスを前記第1のクラスのメンバ変数として指定する際に利用される符号、前記ベクトルレジスタに含まれる要素を指定する際に利用される符号、又は前記ベクトルレジスタのリストを指定する際に利用される符号である字句とを対応付けて記憶した記憶部を参照して、相互に対応する前記第1のクラス、前記第2のクラス、及び前記字句を取得する処理と、取得した前記字句に応じて、取得した前記第2のクラスのインスタンスを生成する第1のコードと、前記字句を多重定義する第2のコードのいずれかを、取得した前記第1のクラスの内部に生成する処理とをコンピュータに実行させるためのクラス生成プログラムが提供される。
【発明の効果】
【0007】
一側面によれば、アセンブリに類似した文法をソースコードで使用できる。
【図面の簡単な説明】
【0008】
【
図1】
図1(a)は、AOTコンパイラ技術でコンパイルすることを前提としたC++の疑似ソースコードの一例を示す図であり、
図1(b)は、パラメータ「q」と配列「in」、「out」を宣言したC++の疑似ソースコードの一例を示す図であり、
図1(c)は、配列「Tbl」の初期値を宣言したC++の疑似ソースコードの一例を示す図である。
【
図2】
図2は、AOTコンパイラ技術でソースコードをコンパイルして得られたアセンブリの疑似コードの模式図である。
【
図3】
図3は、AOTコンパイラ技術で得られた実行可能プログラムの動作について模式的に示す図である。
【
図4】
図4は、JITコンパイラ技術でコンパイルすることを前提としたC++の疑似ソースコードの一例を示す図である。
【
図5】
図5は、入力パラメータqが「8」の場合にJITコンパイラ技術で
図4のソースコードをコンパイルして得られたアセンブリの疑似コードの模式図である。
【
図6】
図6は、JITコンパイラ技術でソースコードをコンパイルして得られた機械語からなる実行可能プログラムの動作について示す模式図である。
【
図7】
図7は、SIMD命令を実行することが可能なターゲットマシンのハードウェア構成図である。
【
図8】
図8(a)は、AArch64において128ビット長のベクトルレジスタvnを指定する書式を示す模式図であり、
図8(b)は、AArch64において64ビット長のベクトルレジスタvnを指定する書式を示す模式図である。
【
図9】
図9は、要素のサイズと個数とを書式ごとにまとめた図である。
【
図10】
図10は、
図8(a)、(b)の書式を利用したアセンブリの記述方法について示す模式図である。
【
図11】
図11は、mul命令に対応したニーモニック関数mulのC++の疑似ソースコードの一例を示す図である。
【
図12】
図12は、アセンブリに似た文法でニーモニック関数の引数を記述できるようにするために開発者が予め記述したC++のクラス定義の疑似ソースコードを示す図である。
【
図13】
図13は、ニーモニック関数mulの引数の記述例を示す図である。
【
図14】
図14は、問題について説明するためのC++の疑似ソースコードの模式図である。
【
図15】
図15は、本実施形態に係る情報処理装置の動作を示す模式図(その1)である。
【
図16】
図16は、本実施形態においてターゲット記述ファイルに記述されたC++の疑似ソースコードの模式図である。
【
図17】
図17は、本実施形態においてヘッダファイルに記述されたC++の疑似ソースコードの模式図である。
【
図18】
図18は、本実施形態に係る情報処理装置の動作を示す模式図(その2)である。
【
図19】
図19は、本実施形態に係るクラス生成部が生成したヘッダファイルのC++の疑似ソースコードの模式図(その1)である。
【
図20】
図20は、本実施形態に係るクラス生成部が生成したヘッダファイルのC++の疑似ソースコードの模式図(その2)である。
【
図21】
図21は、本実施形態に係る開発環境について示す模式図である。
【
図22】
図22は、本実施形態のソースファイルにおけるニーモニック関数mulの記述例を示す図である。
【
図23】
図23は、本実施形態で得られる利点について説明するためのC++の疑似ソースコードの模式図である。
【
図24】
図24は、本実施形態に係る情報処理装置の機能構成図である。
【
図25】
図25は、本実施形態に係るクラス生成方法について示すフローチャートである。
【
図26】
図26は、本実施形態に係る情報処理装置のハードウェア構成図である。
【発明を実施するための形態】
【0009】
本実施形態の説明に先立ち、本願発明者が検討した事項について説明する。
【0010】
前述のようにJITコンパイラ技術はプログラムの実行速度の高速化に有用である。このようなJITコンパイラ技術の利点について、AOT(Ahead Of Time)コンパイラ技術と比較しながら説明する。
【0011】
図1(a)は、AOTコンパイラ技術でコンパイルすることを前提としたC++の疑似ソースコード10の一例を示す図である。
【0012】
AOTコンパイラ技術では、開発者はC言語やC++の文法に即してソースコードを記述し、そのソースコードをGCC(GNU Compiler Collection)等のコンパイラが機械語にコンパイルする。
【0013】
図1(a)の例では、処理10aにおいて配列「Tbl」の各要素をパラメータ「q」で除する。そして、処理10bにおいて、配列「in」の要素を配列「Tbl」の要素で除し、それを配列「out」に格納する。
【0014】
図1(b)は、上記のパラメータ「q」と配列「in」、「out」を宣言したC++の疑似ソースコード11の一例を示す図である。
【0015】
パラメータ「q」は、前述の処理10aにおける除数であり、以下では入力パラメータとも呼ぶ。また、配列「in」と配列「out」は、それぞれ処理10bにおける入力データと出力データである。これらの配列「in」、「out」に格納するデータは特に限定されない。ここでは16個の画素データからなる画像を1000000枚格納する二次元配列として配列「in」と配列「out」を宣言する。
【0016】
図1(c)は、配列「Tbl」の初期値を宣言したC++の疑似ソースコード12の一例を示す図である。
【0017】
配列「Tbl」は、画素データを量子化する量子化テーブルの値を格納する配列である。ここでは、各配列「in」、「out」の各々に対応した16個の要素を持つ配列として配列「Tbl」を宣言する。そして、配列「Tbl」の各要素の初期値は2のべき乗とする。
【0018】
図1(a)~
図1(c)のソースコード10~12は全てC言語やC++の文法に即して開発者が記述し、コンパイラによってアセンブリに変換される。
【0019】
図2は、AOTコンパイラ技術で前述のソースコード10をコンパイルして得られたアセンブリ14の疑似コードの模式図である。
【0020】
そのアセンブリ14には、ターゲットマシンの命令セットに含まれる複数の命令が、ソースコード10における各処理10a、10bに対応して記述される。なお、以下では、命令セットがARM社のAArch64である場合を例にして説明する。
【0021】
例えば、処理10aはload命令からmov命令に至る6個の命令で実現され、処理10bはmov命令からjmplt命令に至る9個の命令で実現される。これらの命令は、オペランドとして記述されたレジスタや即値に対して種々の操作を行う命令である。なお、ここでは汎用のレジスタをRn(n=0,1,2,…)で表し、命令の位置を表すラベルをLm(m=0,1,2,…)で表す。そして、最初にレジスタR2に入力パラメータ「q」が保存されているものとする。
【0022】
また、命令セットに含まれる全ての命令は、ニーモニックと呼ばれる名前で一意に識別される。例えば、mov命令のニーモニックは「mov」であり、store命令のニーモニックは「store」である。
【0023】
アセンブリ14においては、命令のニーモニックの後ろにオペランドを記述するという文法が採用される。例えば、「mov R0, #0」は、即値である「0」をレジスタR0に格納する命令である。また、「load R1, [Tbl[R0]]」は、アドレスTbl[R0]にあるメモリの内容をレジスタR1にロードする命令である。
【0024】
一方、「store [Tbl[R0]], R1」は、レジスタR1の内容を、メモリのアドレスTbl[R0]に格納する命令である。また、「div R1, R1, R2」は、レジスタR1の内容をレジスタR2の内容で除した値をレジスタR1に格納する命令である。そして、「jmplt R0, #16, L0」は、レジスタR0の内容が即値の「16」未満の場合にラベルL0にジャンプする命令である。
【0025】
ここで、処理10bにおける命令「div R2, R2, R1」について考える。この命令は、ソースコード10の処理10bにおける「in[i]/Tbl[i]」に相当する命令である。除数のTbl[i]は、ソースコード10の処理10aにおいて入力パラメータ「q」で除されているが、上記の命令「div R2, R2, R1」は入力パラメータ「q」の値の如何を問わずに正しい除算の結果を与える命令である。したがって、アセンブリ14は、どのような入力パラメータ「q」に対しても正しい結果を与える汎用的なコードとなっている。
【0026】
しかしながら、div命令は、他の命令と比較して実行サイクル数が多い命令であるためスループットの低下を招いてしまう。命令セットにもよるが、div命令以外の命令の実行サイクル数は1~5であるのに対し、div命令の実行サイクル数は80程度もある。更に、深層学習や画像処理等ではforループのループの回数が膨大となるため、そのforループの内側にあるdiv命令によってスループットの低下が更に顕著となる。
【0027】
このようなアセンブリ14をアセンブラが機械語に翻訳することにより機械語からなる実行可能プログラムが生成されることになる。
【0028】
図3は、AOTコンパイラ技術で得られた実行可能プログラムの動作について模式的に示す図である。
【0029】
図3に示すように、実行可能プログラム15は、入力データである配列「in」の各要素と入力パラメータ「q」の入力を受け付ける。そして、前述のように入力パラメータ「q」や配列「in」の値の如何を問わずに、実行可能プログラムは同一の処理を行い、その処理の結果を配列「out」の各要素に格納する。
【0030】
次に、スループットの低下を抑制し得るJITコンパイラ技術を前提としたプログラムについて説明する。
【0031】
図4は、JITコンパイラ技術でコンパイルすることを前提としたC++の疑似ソースコード16の一例を示す図である。
【0032】
このソースコード16は、その実行結果が
図1(a)のソースコード10の実行結果と同一になるように開発者によって記述されたコードであって、処理16aと処理16bとを有する。このうち、処理16aは、ソースコード10の処理10aと同様に、配列「Tbl」の各要素をパラメータ「q」で除する処理である。また、処理16bは、ソースコード10の処理10bと同様に、配列「in」の要素を配列「Tbl」の要素で除してそれを配列「out」に格納する処理である。
【0033】
その処理16bには、関数名がニーモニックと同一の「mov(R0, i)」等の関数が開発者によって記述される。関数「mov(R0, i)」は、アセンブリ「mov R0, #i」に対応した関数であって、「mov R0, #i」が行う処理を表す機械語をメモリに書き込む関数である。このように関数名が命令のニーモニックと同一であり、かつその命令が行う処理を表す機械語をメモリに書き込む関数のことを以下ではニーモニック関数と呼ぶ。
【0034】
処理16bは、forループの内部でin[i]/Tbl[i]を繰り返して実行する処理であるが、この例では開発者がswitch文を記述したことにより、除数である配列Tbl[i]の値に応じて異なるニーモニック関数が実行される。
【0035】
例えば、Tbl[i]の値が「1」の場合には、in[i]に対する除数が「1」となるため、in[i]に対して何も行う必要がない。よって、この場合には、「case 1」においてin[i]の値が格納されているレジスタR1に対する操作は行わない。
【0036】
一方、Tbl[i]の値が「2」の場合には、「case 2」においてshiftR命令に対応した「shiftR(R1, R1, #1)」を実行する。このニーモニック関数は、レジスタR1の内容を1ビットだけ右にシフトし、その結果をレジスタR1に書き込む処理を表す機械語をメモリに書き込む関数である。よって、「shiftR(R1, R1, #1)」を実行することにより、レジスタR1に格納されているin[i]を2で除したのと等価な処理を行うことができる。
【0037】
また、Tbl[i]の値が「4」の場合には、「case 4」において「shiftR(R1, R1, #2)」を実行する。これにより、レジスタR1の内容が右に2ビットだけシフトし、レジスタR1に格納されているin[i]を4で除したのと等価な処理を行うことができる。
【0038】
そして、Tbl[i]の値が「1」、「2」、「4」のいずれでもない場合には、「default」において「div(R1, R1, R2)」を実行する。このニーモニック関数は、div命令に対応した関数であって、レジスタR1の内容をレジスタR2の内容で除した値をレジスタR1に書き込む関数である。
【0039】
このようなソースコード16によれば、Tbl[i]の値が「1」、「2」、「4」のいずれかである場合には、div命令よりも実行サイクル数が少ないshift命令に等価な機械語や何もしない機械語がメモリに書き込まれる。そして、Tbl[i]の値が「1」、「2」、「4」のいずれでもない場合にのみdiv命令に等価な機械語がメモリに書き込まれる。
【0040】
JITコンパイラ技術では、このようにTbl[i]等のパラメータの値に応じて実行サイクル数を低減するのに最適な機械語を書き込むことにより、AOTコンパイラ技術と比較してプログラムの実行速度を高速化することができる。
【0041】
図5は、入力パラメータ「q」が「8」の場合にJITコンパイラ技術で
図4のソースコード16をコンパイルして得られたアセンブリ17の疑似コードの模式図である。また、
図5においては、そのアセンブリをアセンブラでコンパイルして得られた機械語18のメモリ内での配置も模式的に示している。
【0042】
図5に示すように、q=8の場合には、配列「Tbl」の各要素が先頭から順に「1」、「2」、「4」となる。よって、ソースコード16の「case 1」、「case 2」、「case 4」の各場合に対応した命令列17a~17cがアセンブリ17に記述される。そして、これらの命令の処理を表す機械語18がメモリ内に配置されることになる。
【0043】
図6は、JITコンパイラ技術でソースコード16をコンパイルして得られた機械語からなる実行可能プログラム20の動作について示す模式図である。
【0044】
図6に示すように、実行可能プログラム20は、まず入力パラメータ「q」の入力を受け付ける(ステップP10)。次いで、実行可能プログラム20は、その入力パラメータ「q」の値に応じて、処理が高速になる機械語18を生成する(ステップP11)。前述の
図5の例では、「Tbl[i]」の値に適した機械語18が生成される。
【0045】
続いて、実行可能プログラム20は、入力データである配列「in」の各要素の入力を受け付けて(ステップP12)、処理の結果を配列「out」の各要素に格納する(ステップP13)。
【0046】
このように入力パラメータ「q」の値に応じて適切な機械語18を生成することにより、JITコンパイラ技術ではAOTコンパイラ技術よりもプログラムの実行速度を高速化できる。
【0047】
ところで、JITコンパイラ技術で得られた実行可能プログラムを実行するターゲットマシンにおいては、大規模な演算を並列的に行うためにSIMD(Single Instruction Multiple Data)命令が実行されることがある。
【0048】
図7は、SIMD命令を実行することが可能なターゲットマシンのハードウェア構成図である。
【0049】
このターゲットマシン31は、サーバやPC(Personal Computer)等の計算機であって、メモリ32とプロセッサ33とを有する。
【0050】
このうち、メモリ32は、実行可能プログラムが展開されるDRAM(Dynamic Random Access Memory)等の揮発性メモリである。
【0051】
一方、プロセッサ33は、メモリ32と協働して実行可能プログラムを実行するハードウェアであって、計算コア34とレジスタファイル35とを備える。計算コア34は、算術演算や論理演算を行うALU(Arithmetic and Logic Unit)等のハードウェアである。また、レジスタファイル35は、計算コア34が実行する算術演算や論理演算の対象となるデータが格納されるSRAM(Static Random Access Memory)等の記憶素子である。この例では、インデックスn(=0,1,2,…)で識別される複数の汎用のベクトルレジスタvnがレジスタファイル35に設けられる。これらのベクトルレジスタvnは、ベクトルデータを格納するためのレジスタであって、そのサイズは128ビット又は64ビットである。
【0052】
図8(a)は、プロセッサ33の命令セットであるAArch64において、128ビット長のベクトルレジスタvnを指定するアセンブリの書式を示す模式図である。
【0053】
図8(a)に示すように、128ビット長のベクトルレジスタvn(=0,1,2,…31)を指定するには、「vn.2D」、「vn.4S」、「vn.8H」、「vn.16B」というアセンブリの書式が採用される。
【0054】
この書式において、「vn」は、インデックスが「n」のベクトルレジスタvnを指定する書式である。そして、ドット「.」の後に続く「2D」、「4S」、「8H」、「16B」は、一つのベクトルレジスタvnに含まれる要素の個数と、一つの要素のサイズとを示す書式である。なお、各々の要素は、ベクトルデータの各々の成分を格納するための記憶単位である。例えば、「2D」における「2」は要素の個数が2個であることを示し、「D」はその要素のサイズがダブルワード(64ビット)であることを示す。
【0055】
同様に、「4」、「8」、「16」は、それぞれ要素の個数が4個、8個、16個であることを示す。そして、「S」、「H」、「B」は、要素のサイズがそれぞれシングルワード(32ビット)、ハーフワード(16ビット)、バイト(8ビット)であることを示す。
【0056】
このように、この書式では、「vn」と「2D」とをドット「.」で連結した「vn.2D」等の文字列により、ベクトルレジスタ、要素の個数、及び要素のサイズを指定する。
【0057】
また、一つのベクトルレジスタの複数の要素のうちの一つを指定するために、「vn.4S[i]」という書式が採用される。角括弧「[]」は、要素の位置を指定する字句である。また、その角括弧の内側の「i」は、要素の位置を一意に識別する数字である。ここでは、ベクトルレジスタvnの下位ビットから「i」を昇順に並べる。例えば、「vn.4S[0]」は四つの要素の最下位の要素を示し、vn.4S[1]は最下位から二番目の要素を示す。
【0058】
図8(b)は、AArch64において64ビット長のベクトルレジスタvn(=0,1,2,…31)を指定する書式を示す模式図である。
【0059】
この場合も、128ビット長のベクトルレジスタvnを指定する書式と同じ文法でベクトルレジスタ、要素の個数、及び要素のサイズを指定する。例えば、「vn.8B」は、要素の個数が8個で要素のサイズが1バイトのベクトルレジスタvnを指定する書式である。
図9は、要素のサイズと個数とを上記の書式ごとにまとめた図である。
【0060】
図9に示すように、この書式によれば、同一のベクトルレジスタvnに対して、要素のサイズと個数が異なる複数の指定が可能となる。
【0061】
図10は、
図8(a)、(b)の書式を利用したアセンブリの記述方法について示す模式図である。
【0062】
ここではmul命令の記述例について説明する。mul命令は、三つのオペランドをとる命令であって、各オペランドにベクトルレジスタが指定される。この例では、「v1.4h」における4個の要素の各々の内容が、「v2.4h[2]」の内容によって乗算され、その結果が「v0.4h」における4個の要素の各々に格納される。
【0063】
図11は、mul命令に対応したニーモニック関数mulのC++の疑似ソースコードの一例を示す図である。
【0064】
このソースコード41は、ニーモニック関数mulを定義するためのソースコードであって、開発者によって予め作成される。そのニーモニック関数mulの引数は、mul命令がとる「オペランド0」、「オペランド1」、及び「オペランド2」の三個である。
【0065】
ニーモニック関数mulの内部には、mul命令の処理を表す機械語をメモリ32に書き込むコードが記述される。ここでは、mul命令の命令長は32ビットであり、mul命令のオペコードは16ビットで0x0011であるとする。この場合、開発者は、変数mnemonicにオペコードの0x0011を代入する文「unsigned mnemonic = 0x0001;」をニーモニック関数mulの本体に記述する。同様に、開発者は、変数op0、op1、op2の各々に「オペランド0」、「オペランド1」、「オペランド2」を代入する文をニーモニック関数mulの本体に記述する。
【0066】
そして、これらの文の後に、開発者は、「write((mnemonic<<16)+(op0<<10)+(op1<<5) +op2 );」という文を記述する。この例では、mnemonicの値を左に16ビットだけシフトしたビット列と、変数op0の値を左に10ビットだけシフトした値と、変数op1の値を左に5ビットだけシフトした値と、変数op0のビット和をとる。そして、そのビット和が関数writeの引数となる。このビット列においては、先頭の16ビットがmov命令のオペコードとなり、その後ろに各変数op0、op1、op2のビット列が続く。
【0067】
このニーモニック関数mulの引数を
図10のアセンブリに類似の文法で記述できると、開発者にとって慣れ親しんだアセンブリの文法でソースコードを記述できるため、開発者にとって使いやすいニーモニック関数となる。
【0068】
但し、C++においては、ドット「.」はクラスのメンバを示す字句であり、角括弧「[]」は配列を示す字句であるため、これらの字句を直ちにニーモニック関数mulの引数に使用することはできない。
【0069】
そのため、この例では、以下のようにC++等のオブジェクト指向言語におけるクラスのメンバを指定する文法を利用して、アセンブリに似た文法でニーモニック関数の引数を記述できるようにする。
【0070】
図12は、アセンブリに似た文法でニーモニック関数の引数を記述できるようにするために開発者が予め記述したC++のクラス定義の疑似ソースコード43を示す図である。
【0071】
図12に示すように、ここでは前述の書式「vn.4h」(n=0,1,…31)に対応したクラスとしてVReg4Hクラスを定義する。そのVReg4Hクラスのメンバは、書式「vn.4h」で指定される四つの要素に対応した「element0」、「element1」、「element2」、「element3」とする。なお、これらのメンバの型は、予め定義しておいた適当な型「VRegHElem」とする。
【0072】
そして、文「static const VReg4H v0_4h, v1_4h, v2_4h,,;」により、VRreg4Hクラスの三つのインスタンス「v0_4h」、「v1_4h」、「v2_4h」を生成する。これらのインスタンスは、アセンブリの文法で記述した「v0.4h」、「v1.4h」、「v2.4h」にそれぞれ対応する。このようにドット「.」に代えてアンダーバ「_」を使用することで、この例ではアセンブリの文法を模した記述を行う。
【0073】
図13は、この場合のニーモニック関数mulの引数の記述例を示す図である。
【0074】
上記のようにソースコード43でインスタンス「v0_4h」、「v1_4h」、「v2_4h」を生成したことにより、ニーモニック関数mulの第1引数と第2引数としてインスタンス「v0_4h」、「v1_4h」を使用できる。また、第3引数としては、インスタンス「v2_4h」のメンバを示す「v2_4h.element2」を使用できる。
【0075】
しかしながら、このような引数の記述は、
図10に示したアセンブリの記述「mul v0.4h v1.4h v2.4h[2]」とは大きく異なった記述となる。よって、開発者が
図13のクラス定義を熟知していないと、コードの書き間違いや定義の調べ直しの手間が発生し、アプリケーションプログラム用のソースコードを開発する効率が低下してしまう。
また、この例では次のような問題も生ずる。
【0076】
図14は、その問題について説明するためのC++の疑似ソースコードの模式図である。
【0077】
このソースコード45は、開発者が記述したアプリケーションプログラム用のソースコードである。この例では、コードT1において、VReg4Hクラスのインスタンス「v0_4h」、「v1_4h」、「v2_4h」を生成する。同様に、コードT2において、VReg8Hクラスのインスタンス「v0_8h」、「v1_8h」、「v2_8h」を生成する。なお、VReg8Hクラスは、前述の書式「vn.8h」(n=0,1,…31)に対応したクラスである。
【0078】
また、コードT3は、VReg4H型の変数「tmp」を宣言するコードである。
【0079】
そして、コードT4は、パラメータAの値に応じて操作対象のベクトルレジスタを変えるためのコードである。例えば、パラメータAの値が「0」の場合には、「v0_4h」で表されるベクトルレジスタv0が操作対象となり、「v0_4h」が変数「tmp」に格納される。一方、パラメータAの値が「1」の場合には、「v1_4h」で表されるベクトルレジスタv1が操作対象となり、「v1_4h」が変数「tmp」に格納される。
【0080】
また、コードT5は、変数「tmp」に対して処理を行う関数func4Hを呼び出すコードである。関数func4Hの引数は一つであり、その型はVReg4H型であるとする。前述のコードT4では、パラメータAの値の如何を問わずにVReg4H型のインスタンスが変数「tmp」に格納されるため、変数「tmp」は型変換をせずに関数func4Hに渡すことができる。
【0081】
一方、コードT6は、コードT4におけるのと同一のレジスタに対し、コードT4とは異なる書式で処理をするためのコードである。
【0082】
例えば、変数「tmp」に「v0_4h」が格納されている場合には、これとは異なる書式「v0_8h」に対して処理を行う関数func8Hが呼び出される。関数func8Hの引数は一つであり、その型はVReg8H型であるとする。「v0_4h」と「v0_8h」はいずれも同一のベクトルレジスタv0に対応しているが、それらの型がVReg4H型とVReg8H型で相違しているため、例えば「func8H(v0_4h)」という記述はできず、この例のように「func8H(v0_8h)」と記述する必要がある。
【0083】
このように、処理対象の書式がVReg8H型の「v0_8h」の場合には、VReg8H型を引数とする関数「func8H」を呼び出す制御が必要となるため、その制御を実現するためのコードを記述する手間が生じ、コーディングが煩雑となる。
【0084】
同様に、変数「tmp」に「v1_4h」が格納されている場合にも、「func8H(v1_4h)」という記述はできず、この例のように「func8H(v1_8h)」と記述する必要があり、やはりコーディングが煩雑となる。
以下、各実施形態について説明する。
【0085】
(第1実施形態)
本実施形態では、以下のようにしてアセンブリに類似した文法でソースコードを記述できるようにする。
【0086】
[全体構成]
図15は、本実施形態に係る情報処理装置の動作を示す模式図である。
この情報処理装置50は、PCやサーバ等の計算機であって、C++のヘッダファイル73を生成するためのファイル生成部54と、そのヘッダファイル73にクラスを生成するツールであるクラス生成部55とを有する。
図15においては、ファイルの流れを矢印で表し、そのファイルを用いてファイル生成部54とクラス生成部55が行う処理を模式的に示している。
【0087】
ヘッダファイル73を生成するに際し、情報処理装置50は、ターゲット記述ファイル71を読み込む(ステップS11)。ターゲット記述ファイル71は、開発者によってクラスのテンプレートが記述されたtd形式のソースファイルである。ここではそのファイル名を「Registerinfo.td」とする。
【0088】
図16は、ターゲット記述ファイル71に記述されたC++の疑似ソースコードの模式図である。
【0089】
図16に示すように、ターゲット記述ファイル71には、各クラスのテンプレート71a、71bが記述される。
【0090】
このうち、テンプレート71aは、VRegクラス72aのテンプレートである。VRegクラス72aは、複数のベクトルレジスタvn(n=0,1,…31)のうちの一を指定する書式「VReg」を表すクラスである。そして、このVRegクラス72aのインスタンスのインデックス「n」は、ベクトルレジスタvnのインデックスに等しい。
【0091】
また、テンプレート71bは、
図9の各書式を表すクラス72b~72iのテンプレートである。この例では、VReg2Dクラス72bのクラス名「VReg2D」において、「VReg」を除いた文字列「2D」の数字「2」で要素の個数を表し、これに続く「D」で要素のサイズを表す。これにより、VReg2Dクラス72bは、
図9の書式「.2D」を表すクラスとなる。
【0092】
同様に、VReg4Sクラス72cは書式「.4S」を表すクラスであり、VReg8Hクラス72dは書式「.8H」を表すクラスである。そして、VReg8Hクラス72eは書式「.8H」を表すクラスである。
【0093】
更に、このターゲット記述ファイル71には、前述のVRegクラスのインスタンスを生成するための処理71cも記述される。この処理71cにおける文「Def vn: VReg< n >;」(n=0,1,2, …31)は、ベクトルレジスタvnに対応したVRegクラスのインスタンスを生成するための文である。
【0094】
再び
図15を参照する。
次に、情報処理装置50のファイル生成部54がターゲット記述ファイル71からヘッダファイル73を生成する(ステップS12)。ファイル生成部54は、tdファイルからhppファイルを生成するコードジェネレータである。
【0095】
そのようなコードジェネレータとしては、例えばllvm-tblgenがある。llvm-tblgenを使用する場合には、開発者が情報処理装置50のコマンドラインに「llvm-tblegen -o=RegisterInfo.hpp RegisterInfo.td」と入力することにより、ファイル名が「RegisterInfo.hpp」のヘッダファイル73が生成される。
【0096】
そのヘッダファイル73は、ターゲット記述ファイル71に記述された全てのクラスの定義が生成されたhpp形式のファイルである。
【0097】
図17は、ヘッダファイル73に記述されたC++の疑似ソースコードの模式図である。
【0098】
図17に示すように、ヘッダファイル73には、各クラスの定義73a、73bが記述される。このうち、定義73aはVRegクラス72aの定義であり、定義73bはクラス72b~72iの定義である。
【0099】
また、ヘッダファイル73には、VRegクラス72aのインスタンスを生成するための処理73cも記述される。処理73cは、ターゲット記述ファイル71の処理71cによって生成された処理であり、ここでは「v0(0)」、「v1(1)」、「v2(2)」、…「v31(31)」の各インスタンスが生成される。
【0100】
これ以降の情報処理装置50の動作について
図18を参照しながら説明する。
【0101】
図18は、本実施形態に係る情報処理装置50の動作を示す模式図である。
まず、情報処理装置50のクラス生成部55が書式ルール情報75を参照する(ステップS13)。書式ルール情報75は、第1のクラス、第2のクラス、及び字句の各々を対応付けたテーブルであり、開発者によって予め作成される。
【0102】
このうち、第1のクラスは、
図17のクラス72a~72iである。これらのクラス72a~72iは、いずれもベクトルレジスタvnに関する書式を表すクラスである。例えば、VRegクラス72aは、複数のベクトルレジスタvn(n=0, 1, 2, …31)のうちの一を指定する書式である。また、残りのクラス72b~72iは、ベクトルレジスタvnに含まれる要素の個数とサイズとを指定する書式である。
【0103】
一例として、VReg2Dクラス72bは、要素の個数として「2」を指定し、要素のサイズとしてダブルワード(64ビット)を指定するクラスである。また、VReg4Sクラスは、要素の個数として「4」を指定し、要素のサイズとしてシングルワード(32ビット)を指定するクラスである。
【0104】
書式ルール情報75の一行目に示すように、第1のクラスがVRegクラス72aの場合には、第2のクラスとして残りのクラス72b~72iの各々が書式ルール情報75に格納され、かつ、ドット「.」が字句に格納される。
【0105】
また、書式ルール情報75の二行目以降においては、第1のクラスとしてクラス72b~72iのいずれかが格納される。そして、第2のクラスとしては、VReg8BElemクラスやVReg8BListクラス等のように文字列「Elem」、「List」を含むクラスが格納される。
【0106】
文字列「Elem」を含むクラスは、ベクトルレジスタの要素を指定する書式を表すクラスである。例えば、VReg8BElemクラスは、書式「vn.8B」で表される8個の要素のいずれかを指定するための書式である。この場合は、要素を指定するための角括弧「[]」が書式ルール情報75の「字句」に格納される。
【0107】
また、文字列「List」を含むクラスは、ベクトルレジスタのリストを指定する書式を表すクラスである。例えば、VReg8BListクラスは、書式「vn.8B」で表されるベクトルレジスタvnのリストを指定する書式である。この場合は、リストを示すハイフン「-」が書式ルール情報75の「字句」に格納される。
【0108】
なお、書式ルール情報75のいずれの行においても、第2のクラスは第1のクラスを継承した子クラスである。例えば、一行目のVReg2Dクラス、VReg4Sクラス、VReg8Hクラス等はVRegクラスの子クラスである。同様に、二行目のVReg2DElemクラスはVReg2Dクラスの子クラスであり、三行目のVReg2DListクラスはVReg2Dクラスの子クラスである。四行目以降も同様である。
【0109】
第2のクラスのインスタンスを第1のクラスのメンバ変数とすると、その子クラスを指定するためのC++の文法としてドット「.」を使用できる。例えば、書式ルール情報75の一行目のVRegクラスのインスタンスを「vn」とし、VReg2Dクラスのインスタンスを「2d」とすれば、「vn.2d」というアセンブリの文法に似た表記が可能となる。
【0110】
クラス生成部55は、このような書式ルール情報75を参照することにより、相互に対応する第1のクラス、第2のクラス、及び字句を取得する。
【0111】
次に、クラス生成部55は、テンプレート情報76を参照する(ステップS14)。
【0112】
テンプレート情報76は、ヘッダファイル73に記述するソースコードのテンプレートである第1のテンプレート76aと第2のテンプレート76bとを字句に対応付けた情報であり、開発者によって予め作成される。
【0113】
このうち、第1のテンプレート76aは、字句ドット「.」に対応したテンプレートであり、第1のクラスの内部に第1のコード77を有する。第1のコード77は特に限定されないが、本実施形態では第2のクラスのインスタンスを生成するための「第2のクラス インスタンス;」という文を第1のコード77とする。
【0114】
また、第2のテンプレート76bは、角括弧「[]」とハイフン「-」の各字句に対応したテンプレートであり、これらの字句を多重定義するメンバ関数「operator」が記述された第2のコード78を有する。多重定義は、オーバーロードとも呼ばれ、同一の字句について複数の定義を行い、プログラムの実行時に文脈に合わせて一つの定義を選択する仕組みである。
【0115】
そして、「operator」は、この多重定義を行うためのC++における予約語である。ここでは、開発者が、メンバ関数「operator」が第1のクラスのメンバとなるように第2のテンプレート76bを作成する。
【0116】
そのメンバ関数「operator」の引数は整数「i」であり、その返り値は第2のクラスである。これにより、例えば字句が角括弧「[]」で整数「i」が「2」の場合には、メンバ関数「operator」によって「[2]」という角括弧付きの表現が可能となり、
図8(a)、(b)のアセンブリの文法と同様に要素の位置を角括弧「[]」で表現できる。
【0117】
そして、クラス生成部55は、第1のテンプレート76aと第2のテンプレート76bのうちで、ステップS13で取得した字句に対応するテンプレートを取得する。
【0118】
次いで、クラス生成部55は、取得したテンプレートに記述されている第1のコード77と第2のコード78のいずれかに第2のクラスを当てはめたコードをヘッダファイル73に生成する(ステップS15)。その当てはめ方について、書式ルール情報75の一行目の「VReg」、「VReg2D」、及び「ドット」の各々をステップS13で取得した場合を例にして説明する。この場合は、字句が「ドット」であるから、ステップS14においてクラス生成部55は「ドット」に対応した第1のテンプレート76aを取得する。
【0119】
そして、クラス生成部55は、ステップS15において、第2のクラスを表す文字列「VReg2D」を第1のコード77の「第2のクラス」に代入する。これと共に、クラス生成部55は、第1のコード77の「インスタンス」に文字列「d2」を代入する。その後、クラス生成部55は、このように文字列「VReg2D」、「d2」が当てはめられた第1のコード77をヘッダファイル73に生成する。生成する場所は、書式ルール情報75においてVReg2Dクラスに対応付けられたVRegクラスの内部である。
【0120】
一方、クラス生成部55が、ステップS13において書式ルール情報75の二行目の「VReg2D」、「VReg2DElem」、及び「角括弧」の各々を取得した場合を考える。この場合は、字句が「角括弧」であるから、ステップS14においてクラス生成部55は「角括弧」に対応した第2のテンプレート76bを取得する。
【0121】
そして、クラス生成部55は、ステップS15において、第2のクラスを表す文字列「VReg2DElem」を第2のコード78の「第2のクラス」に代入する。これと共に、クラス生成部55は、第2のコード78の「字句」に角括弧「[]」を代入する。その後、クラス生成部55は、このように文字列「VReg2DElem」と字句「[]」が当てはめられた第2のコード78をヘッダファイル73に生成する。生成する場所は、書式ルール情報75においてVReg2DElemクラスに対応付けられたVReg2Dクラスの内部である。
【0122】
なお、書式ルール情報75の三行目のように字句が「ハイフン」である場合には、クラス生成部55は、第2のコード78の「字句」に「-」を代入する。
【0123】
そして、クラス生成部55は、書式ルール情報75の全ての行を読み込むことにより、書式ルール情報75に格納されている全ての第1のクラスの内部に第1のコード77や第2のコード78を生成する。
【0124】
図19及び
図20は、このようにしてクラス生成部55が生成したヘッダファイル73のC++の疑似ソースコードの模式図である。
【0125】
図19及び
図20に示すように、ヘッダファイル73にはファイル生成部54によって予めクラス72a~72iが生成されており、これらのクラスの内部にクラス生成部55が第1のコード77や第2のコード78を生成する。
【0126】
例えば、VRegクラス72aは、書式ルール情報75(
図18参照)の一行目の第1のクラスであって、その内部には複数の第1のコード77が生成される。これらの第1のコード77の各々は、書式ルール情報75の一行目の複数の第2のクラス「VReg2D」、「VReg4S」、…「VReg8B」にそれぞれ対応しており、これらのクラスのインスタンス「d2」、「s4」、…「b8」を生成するコードである。
【0127】
また、クラス72b~72iは、書式ルール情報75の二行目以降の第1のクラスであって、各々の内部に第2のコード78が生成される。
以上により、情報処理装置50が行う基本処理を終える。
【0128】
次に、ヘッダファイル73を利用したアプリケーションプログラムの開発環境について説明する。
【0129】
図21は、本実施形態に係る開発環境について示す模式図である。
この例では、情報処理装置50の内部に開発環境を構築する場合を想定する。その場合、クラス生成部55が、前述のように書式ルール情報75とテンプレート情報76とに基づいてヘッダファイル73を生成する。
【0130】
一方、開発者は、例えばC++を用いてニーモニック関数のソースファイル80を作成する。ソースファイル80は、
図11に示したようなニーモニック関数を定義するためのソースコード41が記述されたファイルである。開発者は、プロセッサ33(
図7参照)の命令セットに含まれる全ての命令に対応した全てのニーモニック関数の定義を予めソースファイル80に記述しておく。
【0131】
更に、開発者は、アプリケーションプログラム用のソースファイル81を作成する。ソースファイル81は、JITコンパイラ技術によってコンパイルされることを前提としたC++等のファイルである。そのソースファイル81には、C++のライブラリ関数に加えて、ソースファイル80にあるニーモニック関数も記述される。
【0132】
図22は、このソースファイル81におけるニーモニック関数mulの記述例を示す図である。ここではVReg4Sクラスのインスタンスである「4s」をニーモニック関数mulの引数に使用する場合を例示するが、VReg4H等の他のクラスのインスタンスをニーモニック関数mulの引数に使用してもよい。
【0133】
図22に示すように、このニーモニック関数mulの第1引数は「v0.s4」となる。その表記における「v0」は、ヘッダファイル73の処理73c(
図20参照)においてVRegクラス72aのインスタンスとして定義されている。そして、「s4」は、
図19に示したように、ヘッダファイル73においてVRegクラス72aのメンバであるVReg4Sクラスのインスタンスとして定義されている。
【0134】
よって、ドット「.」を用いた「v0.s4」との表記は、「v0」のメンバである「s4」という意味となり、C++の文法で正しい表記となる。第2引数の「v2.s4」についても同様である。
【0135】
また、
図19に示したように、ヘッダファイル73のVReg4Sクラス72cにおいては、字句「[]」を多重定義するメンバ関数「operator」が定義されている。そのため、ニーモニック関数mulの第3引数の「v2.s4[2]」は、メンバ関数「operator」に「2」を渡した結果である「s4[2]」がVRegクラスのインスタンス「v2」のメンバであるという意味となり、C++の文法で正しい表記となる。
【0136】
このように、本実施形態ではアプリケーションプログラム用のソースファイル81にドット「.」や角括弧「[]」等を使用することができるようになり、「v0.s4」や「v2.s4[2]」等のようにアセンブリに類似した文法の記述を行うことができる。同様に、ハイフン「-」を多重定義するメンバ関数「operator」により、「v0.16b-v3.16b」等のようにアセンブリにおいてリストを表す記述をソースファイル81においても行うことが可能となる。
【0137】
再び
図21を参照する。
上記のようにしてヘッダファイル73と各ソースファイル80、81を用意した後は、開発者の指示の下で、コンパイラ、アセンブラ、及びリンカのプログラム群82がビルドを行う。ビルドにおいては、プログラム群82に含まれるコンパイラがソースファイル81をコンパイルする。
【0138】
このとき、コンパイラは、ヘッダファイル73と各ソースファイル80、81を読み込んでアセンブリの中間言語ファイルを出力する。そして、アセンブラがその中間言語ファイルを機械語に変換してオブジェクトファイルを生成する。
【0139】
その後、リンカは、オブジェクトファイルと種々のライブラリとをリンクすることにより、プロセッサ33で実行可能なバイナリ形式の実行可能プログラム83を生成する。
【0140】
以上により、アプリケーションプログラム用のソースファイル81から実行可能プログラム83を生成することができる。
【0141】
その実行可能プログラム83はJITコンパイラ技術により、実行時にパラメータに応じて、
図5に記載されているような機械語を生成するため、深層学習や画像処理等のようにループの回数が膨大で大規模な演算が必要なアプリケーションプログラムの高速化に特に有効である。同様に、動画圧縮等の画像処理、暗号化処理、復号処理、及びブロックチェーン技術等で使用するアプリケーションプログラムも高速化することができる。
【0142】
上記した本実施形態によれば、
図18に示したように、開発者が、ベクトルレジスタの各書式を表す第1のクラスと第2のクラスを字句に対応付けて書式ルール情報75に格納しておく。そして、クラス生成部55が、書式ルール情報75から取得した字句に応じて、第2のクラスのインスタンスを生成する第1のコード77と、メンバ関数「operator」で各字句を多重定義する第2のコード78のいずれかをヘッダファイル73に生成する。
【0143】
これにより、書式ルール情報75におけるドット「.」、角括弧「[]」、及びハイフン「-」等の各字句が定義済みとなるため、これらの字句を開発者がソースファイル81に記述することができる。その結果、開発者が慣れ親しんだアセンブリに類似の文法でニーモニック関数の引数を記述することが可能となるため、開発者が新たな文法を覚える必要がなく、開発者の負担を軽減できる。しかも、このように慣れ親しんだ文法で開発者がアプリケーションプログラム用のソースファイル81にソースコードを記述できるため、実行可能プログラム83にバグが生じ難くなる。これにより、バグのある実行可能プログラム83をターゲットマシン31で無駄に実行する時間が減り、ターゲットマシン31のハードウェア資源の無駄な消費を改善できる。
【0144】
特に、この例では、ベクトルレジスタvnを指定する書式をVRegクラスで表し、そのVRegクラスを継承したVReg2Dクラス等によってベクトルレジスタに含まれる要素の個数とサイズとを指定する書式を表す。VReg2DクラスのインスタンスをVRegクラスのメンバ変数にすることにより、「vn.2d」のように、ベクトルレジスタvnを指定する文字列「vn」と、要素の個数とサイズとを指定する文字列「2d」とをドット「.」で連結した表記をソースファイル81で使用できるようになる。
【0145】
更に、本実施形態では、VReg2Dクラスを継承したVReg2DElemやVReg2DListクラス等型をメンバ関数「operator」が返すようにする。そのため、「v0.2d[2]」や「v0.2d-V3.2d」等のように、メンバ関数「operator」が多重定義する角括弧「[]」やハイフン「-」をソースファイル81で使用することが可能となる。
【0146】
しかも、この例では、開発者が予めテンプレート情報76に各コード77、78のテンプレート76a、76bを用意し、クラス生成部55が各テンプレートに第2のクラスを当てはめることによりヘッダファイル73にコードを生成する。そのため、クラス生成部55が各コード77、78の全てを生成する必要がなく、コードの生成に要する時間を短縮化することが可能となる。
【0147】
更に、本実施形態によれば、同一のレジスタに対して異なる書式で処理をする場合であっても、
図14のような煩雑なコーディングを以下のように回避できるという利点が得られる。
【0148】
図23は、その利点について説明するためのC++の疑似ソースコードの模式図である。
【0149】
このソースコード85は、開発者がアプリケーションプログラム用のソースファイル81(
図21参照)に記述したC++のソースコードであって、
図14のソースコード45と同一の処理を実現するためのプログラムである。
【0150】
この例では、コードT11において、VRegクラスのインスタンス「tmp」を生成する。
【0151】
また、コードT12は、パラメータAの値に応じて操作対象のベクトルレジスタを変えるためのコードである。ここでは、パラメータAが「0」の場合には、0番目のベクトルレジスタv0を表すインスタンス「v0」を変数「tmp」に格納する。そして、パラメータAが「1」の場合には、1番目のベクトルレジスタv1を表すインスタンス「v1」を変数「tmp」に格納する。なお、
図20に示したように、各インスタンス「v0」、「v1」は、ヘッダファイル73の処理73cにおいてVRegクラスのインスタンスとして定義済みである。
【0152】
そして、コードT13は、変数「tmp.h4」に対して処理を行う関数func4Hを呼び出すコードである。なお、変数「tmp」にインスタンス「v0」が格納されている場合には、変数「tmp.h4」はベクトルレジスタv0を4個の要素に分ける書式「v0.4H」に対応したインスタンスを表すことになる。
【0153】
ここでは、
図14の例と同様に、関数func4Hの引数の型はVReg4H型であるとする。この場合、ヘッダファイル73(
図19参照)において「h4」はVReg4Hクラスのインスタンスとして定義されているため、変数「tmp.h4」の型もVReg4H型となり、関数func4Hの引数と変数「tmp.h4」の型が一致する。よって、変数「tmp.h4」は型変換をせずに関数func4Hに渡すことができる。
【0154】
一方、コードT14は、変数「tmp.h8」に対して処理を行う関数func8Hを呼び出すコードである。その変数「tmp.h8」は、変数「tmp」にインスタンス「v0」が格納されている場合には、ベクトルレジスタv0を8個の要素に分ける書式「v0.8H」に対応したインスタンスを表すことになる。
【0155】
また、関数func8Hの引数の型はVReg8H型であるとする。ヘッダファイル73(
図19参照)において「h8」はVReg8Hクラスのインスタンスとして定義されているため、変数「tmp.h8」の型もVReg8H型となり、関数func8Hの引数と変数「tmp.h8」の型は一致する。よって、変数「tmp.h8」は型変換をせずに関数func8Hに渡すことができる。
【0156】
以上のように、本実施形態によれば、ヘッダファイル73においてVRegクラスのメンバとしてVReg4H型とVReg8H型の各インスタンス「h4」、「h8」を生成する。そのため、「tmp.h4」や「tmp.h8」のようにVReg型の「tmp」のメンバの型を変えるだけで同一のベクトルレジスタv0に関する異なる書式に対応したVReg4HクラスとVReg8Hクラスを表すことができる。その結果、
図14の例のように書式に応じて使用する関数を変更する必要がなくなり、コーディングを単純にすることができる。
【0157】
[機能構成]
次に、本実施形態に係る情報処理装置50の機能構成について説明する。
図24は、本実施形態に係る情報処理装置50の機能構成図である。
図24に示すように、情報処理装置50は、制御部52と記憶部53とを有する。
【0158】
このうち、記憶部53は、HDD(Hard Disk Drive)等の記憶装置やDRAM等のメモリによって実現される処理部であって、書式ルール情報75、テンプレート情報76、ターゲット記述ファイル71、及びヘッダファイル73を記憶する。このうち、ターゲット記述ファイル71、書式ルール情報75、及びテンプレート情報76は、開発者によって予め記憶部53に格納される。
【0159】
そして、制御部52は、情報処理装置50の全体を制御する処理部であり、ファイル生成部54とクラス生成部55とを備える。
【0160】
ファイル生成部54は、前述のようにllvm-tblgen等のコードジェネレータであり、ターゲット記述ファイル71からヘッダファイル73を生成する。
【0161】
また、クラス生成部55は、ファイル生成部54が生成したヘッダファイル73にクラスを生成する処理部である。この例では、クラス生成部55は、第1の取得部56、第2の取得部57、生成部58、及び出力部59を備える。
【0162】
第1の取得部56は、
図18の書式ルール情報75を参照することにより、相互に対応する第1のクラス、第2のクラス、及び字句を取得する処理部である。また、第2の取得部57は、
図18のテンプレート情報76を参照することにより、各テンプレート76a、76bのうちで第1の取得部56が取得した字句に対応するテンプレートを取得する処理部である。
【0163】
一方、生成部58は、第2の取得部57が取得したテンプレートに含まれる第1のコード77と第2のコード78のいずれかを、第1の取得部56が取得した字句に応じてヘッダファイル73の各クラスの内部に生成する。一例として、生成部58は、取得したテンプレートにおける第1のコード77と第2のコード78のいずれかに第2のクラスを当てはめたコードを生成し、そのコードをヘッダファイル73の第1のクラスの内部に生成する。
【0164】
そして、出力部59は、生成部58が生成したヘッダファイル73を記憶部53に書き出す処理部である。
【0165】
[処理の流れ]
図25は、本実施形態に係るクラス生成方法について示すフローチャートである。
【0166】
まず、ファイル生成部54が記憶部53からターゲット記述ファイル71を読み込み(ステップS11)、そのターゲット記述ファイル71からヘッダファイル73を生成する(ステップS12)。
図17を参照して説明したように、そのヘッダファイル73には、ファイル生成部54によって各クラス72a~72iの定義73a、73bが生成される。また、ファイル生成部54は、VRegクラス72aのインスタンスを生成する処理73c(
図17参照)もヘッダファイル73に生成する。
【0167】
次いで、第1の取得部56が、書式ルール情報75(
図18参照)を参照することにより、相互に対応する第1のクラス、第2のクラス、及び字句を取得する(ステップS13)。
【0168】
続いて、第2の取得部57が、テンプレート情報76(
図18参照)を参照することにより、各テンプレート76a、76bのうちでステップS13において取得した字句に対応するテンプレートを取得する(ステップS14)。例えば、ステップS13で取得した字句がドット「.」である場合には、第2の取得部57は、ドット「.」に対応付けられた第1のテンプレート76aを取得する。また、ステップS13で取得した字句が角括弧「[]」とハイフン「-」のいずれかである場合には、第2の取得部57は、これらの字句に対応付けられた第2のテンプレート76bを取得する。
【0169】
次に、生成部58が、ステップS13で取得した第2のクラスを第1のコード77と第2のコード78のいずれかに当てはめたコードをヘッダファイル73の第1のクラスの内部に生成する(ステップS15)。
【0170】
例えば、ステップS13において第1の取得部56が書式ルール情報75(
図18参照)の一行目を取得した場合を考える。その場合は、
図19に示したように、生成部58は、VRegクラス72aの内部にVReg2Dクラス等の第2のクラスのインスタンスを生成するための複数の第1のコード77を生成する。
【0171】
一方、ステップS13において第1の取得部56が書式ルール情報75の二行目を取得した場合を考える。その場合は、
図19~
図20に示したように、生成部58は、角括弧「[]」やハイフン「-」を多重定義するメンバ関数「operator」を含む第2のコード78を各クラス72b~72iの内部に生成する。
【0172】
そして、書式ルール情報75に含まれる全ての行に対してステップS13~S15の処理を行うことにより、書式ルール情報75に含まれる全ての第1のクラスの内部に第1のコード77や第2のコード78を生成する。
【0173】
その後、出力部59がヘッダファイル73を記憶部53に書き出す(ステップS16)。
【0174】
[ハードウェア構成]
次に、本実施形態に係る情報処理装置50のハードウェア構成について説明する。
【0175】
図26は、本実施形態に係る情報処理装置50のハードウェア構成図である。
【0176】
図26に示すように、情報処理装置50は、記憶装置50a、メモリ50b、プロセッサ50c、通信インターフェース50d、表示装置50e、及び入力装置50fを有する。これらの各部はバス50gにより相互に接続される。
【0177】
このうち、記憶装置50aは、HDDやSSD(Solid State Drive)等の不揮発性のストレージデバイスであり、本実施形態に係るクラス生成プログラム90を記憶する。
【0178】
なお、クラス生成プログラム90をコンピュータが読み取り可能な記録媒体50hに記録させておき、プロセッサ50cに記録媒体50hのクラス生成プログラム90を読み取らせるようにしてもよい。
【0179】
そのような記録媒体50hとしては、例えばCD-ROM(Compact Disc - Read Only Memory)、DVD(Digital Versatile Disc)、及びUSB(Universal Serial Bus)メモリ等の物理的な可搬型記録媒体がある。また、フラッシュメモリ等の半導体メモリやハードディスクドライブを記録媒体50hとして使用してもよい。これらの記録媒体50hは、物理的な形態を持たない搬送波のような一時的な媒体ではない。
【0180】
更に、公衆回線、インターネット、及びLAN(Local Area Network)等に接続された装置にクラス生成プログラム90を記憶させておき、プロセッサ50cがそのクラス生成プログラム90を読み出して実行するようにしてもよい。
【0181】
一方、メモリ50bは、DRAM等のようにデータを一時的に記憶するハードウェアであって、その上に前述のクラス生成プログラム90が展開される。
【0182】
プロセッサ50cは、情報処理装置50の各部を制御したり、メモリ50bと協働してクラス生成プログラム90を実行したりするCPUやGPU等のハードウェアである。
【0183】
このようにメモリ50bとプロセッサ50cとが協働してクラス生成プログラム90を実行することにより、
図24のファイル生成部54、第1の取得部56、第2の取得部57、生成部58、及び出力部59を備えた制御部52が実現される。また、記憶部53は、記憶装置50aとメモリ50bによって実現される。
【0184】
更に、通信インターフェース50dは、情報処理装置50をLAN等のネットワークに接続するためのインターフェースである。
【0185】
そして、表示装置50eは、液晶表示装置等のハードウェアであって、開発者に種々の情報の入力を促すプロンプトを表示する。また、入力装置50fは、キーボードやマウス等のハードウェアである。例えば、開発者は、入力装置50fを操作することにより、情報処理装置50のファイル生成部54に対してターゲット記述ファイル71からヘッダファイル73を生成するように指示を出すことになる。
【符号の説明】
【0186】
31…ターゲットマシン、32…メモリ、33…プロセッサ、34…計算コア、35…レジスタファイル、50…情報処理装置、50a…記憶装置、50b…メモリ、50c…プロセッサ、50d…通信インターフェース、50e…表示装置、50f…入力装置、50g…バス、50h…記録媒体、52…制御部、53…記憶部、54…ファイル生成部、55…クラス生成部、56…第1の取得部、57…第2の取得部、58…生成部、59…出力部、73…ヘッダファイル、75…書式ルール情報、76…テンプレート情報、76a…第1のテンプレート、76b…第2のテンプレート、77…第1のコード、78…第2のコード。