1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SX-Aurora TSUBASAでvector intrinsicを使ってみる

Last updated at Posted at 2022-12-23

はじめに

NEC SX-Aurora TSUBASAのnc++にてベクトル命令のIntrinsicが解禁されたということで、早速使ってみるテスト。

とはいえ、マニュアル等もほとんどないので、教えてもらった情報や、webサーフィンしながら集めた情報を組み合わせて、なんとか動くところまで持っていきます。

※NECさんより正確な情報を頂くことができたので、一部を修正しました。ただし、当時の試行錯誤も自身にとっての記録として重要なので、最低限の修正に留めました。

必要な環境

コンパイラ ver 4.0.0以降が必要です。

コードはどう書くのか

webで現状でみつかる_vel_~~で始まる命令は使えません。コンパイラ4.0.0以降では、__builtin_ve_~~で始まる命令になっています。

参考1:https://sx-aurora-dev.github.io/ve-intrinsics-tutorial/

参考2: https://speakerdeck.com/fixstars/c-plus-plus-kodofalse-sx-aurora-tsubasagao-su-hua-ji-fa-ji-jie-xue-xi-falseqian-chu-li-woti-cai-tosite?slide=40

追記: 読める環境にいる方は、NEC C++マニュアルのver.4.0.0以降からはi
ntrinsicに関する情報が少し載っています。

また、Intrinsic用に何かヘッダーをインクルードする必要もありません(少なくとも今試している限りでは)。何もインクルードすることなく__builtin_ve_~~命令を書いてしまってコンパイルは通ります。

どんな命令があるのかは、コンパイラのインストールされたディレクトリのinclude/_vector.hの中に書いてあります。(注意点として、このヘッダーをインクルードしてはいけません。コンパイルが通りません。)

サンプルプログラム

先にサンプルコードを載せた方がイメージしやすいと思うので、簡単な例を載せます。

#include <cstdio>

//the definition of vector type. 2048 means 8 byte x 256 //
typedef double __vr __attribute__((__vector_size__(2048)));  


int main(){
    constexpr int n = 256;

    double b[n]={0.0};

    for (int i = 0; i < n; ++i) {
        b[i] = (double)i;
    }

    //definition of vector type variable a//
    __vr a;

    //load to vector type a from double array b//
    __builtin_ve_vld(a, b, 8);

    // clear b
    for (int i = 0; i < n; ++i) {
        b[i] = 0.0;
    }

    //set from vector type a to double array b//
    __builtin_ve_vst(a, b, 8);

    //if the vector opeartion is correctly used, the numbers from 0.0 to 255.0 are printed.//
    for (int i = 0; i < n; ++i) {
        printf("b[%d] = %f\n", i, b[i]);
    }


    return 0;
}

これは、ベクトル型の変数aに、配列bから値をセットして、またaからbへ書き戻すだけのプログラムです。無事に書き戻せたことが分かるように、書き戻す前にbを0クリアしています。成功すれば0.0から255.0の値が表示されます。

ベクトル変数の定義

ベクトル演算ではベクトル型の変数を用います。まずはベクトル型自体を次のように定義します

//the definition of vector type. 2048 means 8 byte x 256 //
typedef double __vr __attribute__((__vector_size__(2048)));  

サイズはバイト単位で指定するようで、8tyte×256=2048byteとなります。これ以外の大きさの方が使えるかは不明です。

追記: __attribute__((__vector_size__(数字)))での指定では2のべき乗数の指定が可能です。また、__attribute__((ext_vector_type(数字)))で指定することもでき、こちらは任意の数を指定できるようです(とはいえ256以下と思われる)。

実際にベクトル型の変数を確保するには、次のように定義します。

//definition of vector type variable a//
    __vr a;

ベクトル変数への値の代入

事前に配列bに値を入れておいて、そこからベクトル型の変数へ代入(load)します。次の部分です。

//load to vector type a from double array b//
    __builtin_ve_vld(a, b, 8);

第三引数の8はストライドですが、いろいろ試してこの値が上手くいきました。経験則です。

ベクトル変数からの値の読み取り

今度はベクトル変数aから配列bに値を書き戻します(set)。次の部分です。

//set from vector type a to double array b//
    __builtin_ve_vst(a, b, 8);

ここでも第三引数のストライドを8にしました。

コンパイル

まずはコンパイラの4.0.0を有効化します。私の環境では次のようにします。

module load NECSDK-sx/4.0.0

あとは特に何も考えず、コンパイルします。ソースファイルをtest.cppとしたとき、次のようにします。

nc++ test.cpp

おわりに

webで出回っている命令と違っていたので、最初は何かインクルードしなきゃとか、velintrin.hが見つからないとかかなり混乱しましたが、なんとか動くところまで来ました。webの情報とは違ってclangも使わないようです。

**追記:**clangは使わないとオフィシャルな回答を頂きました。

徐々に慣れていけそうです。

これでコンパイラとエスパー対決しなくてよくなると思うと、かなり気が楽になります。

メリークリスマス!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?