IntelからOpenPOWERにポートする作業について記述してきたが、一つ必要なものがある。C言語において、2つの関数が同じ入力なら同じ結果を返すことを保障するテストフレームワークである。
例えば、以下のソースコードを見て欲しい。
extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__,__artificial__))
_mm_add_pd (__m128d __A, __m128d __B)
{
return (__m128d) ((__v2df)__A + (__v2df)__B);
}
このソースコードは、_mm_add_pdというIntelのIntrinsic関数をOpenPOWERにポートしたものだが、このポートには一つ問題がある。
このソースコードは本当に正確な結果を返すのだろうか。
1つ2つ動作確認しても本当に正しいかどうかわからない。
ここで必要なものは、ランダムに生成した値をIntelとOpenPOWERの__Aと__Bに入力し、帰ってきた値がIntelとOpenPOWERで同じであるかどうかのチェックを自動的に行うテストフレームワークである。
今のところそういうテストフレームワークは存在しない。
今回は__Aにはいる型はベクトル型である。Intel固有の型であるため、OpenPOWERやRISC-Vでは構造体として定義してやる必要がある。
以下はちょっと違う型であるが、OpenPOWERでは以下のように定義する。
/* Internal data types for implementing the AVX in PowerISA intrinsics. */
typedef struct __v4df
{
__vector double vd0;
__vector double vd1;
} __vx4df;
/* The Intel API is flexible enough that we must allow aliasing with other
vector types, and their scalar components. */
typedef struct __m256d
{
__vector double vd0;
__vector double vd1;
}__attribute__ ((__may_alias__)) __m256d;
Intel側で、__m128dをテキストに変換してファイルとして格納し、OpenPOWERやRISC-V側でC言語の型に戻す処理が必要となる。ネットワークでリアルタイムにつなぐ必要はなく、ファイル転送で十分対応できる。
定義そのものが違うのと、アラインメントも考えないといけないので、一筋縄では行かない。
ということで、これからもやっていこうかと思う。