LoginSignup
0
0

More than 3 years have passed since last update.

Arm SVE intrinsic load/store編

Posted at

この記事は前の記事の続きのつもりです。
「ロード」とか「ストア」とかの言葉は知っている人向け。

はじめに

SVEを用いて配列の計算を処理しようとすると(別にSVEに限らずAVXとかでもそうですが…)、

  • 通常の配列(doubleなど)をSVE型にload
  • SVE型どうしの演算
  • SVE型を通常の配列にstore

という処理をする事になります。
ので、loadとstore命令を書かなくてはならないわけです。
ここにはSVEでのload/store命令のうち、代表的な物を書いておきます。

以下のサンプルコードでは、基本的に倍精度浮動小数点srcを一回SVEレジスタにloadして、dstにstoreする、すなわちコピーを行う事を想定しておきます。
倍精度ではない値をやり取りしたいとかそういう場合は64を32に頭の中で入れ替えたりしてください。

前置きとして、プレディケータとして、

const svbool_t pg = svwhilelt_b64(i, N);

という物が定義されているものとします。
また、SIMD幅の中に存在する倍精度浮動小数点の数をNとしておきます。

スカラー値 load/store

srcポインタからSIMD幅分のデータを読み、SVE型に格納する。

const svfloat64_t data = svld1(pg, &src[i]);
svst1(pg, &dst[i], data);

svld1src[i]からsrc[i + N - 1]までの要素をdataに格納し、
svld1でその値をdst[i]からdst[i + N - 1]に書き戻している。

スカラー値 load/store、間隔vnum

srcポインタからSIMD幅分のデータを間隔vnum個開けて読み、SVE型に格納する。

const uint64_t vnum = 0;
const svfloat64_t data = svld1_vnum(pg, &src[i], vnum);
svst1_vnum(pg, &dst[i], data, vnum);

svld1_vnumsrc[i + N*vnum]からsrc[i + N*vnum + N - 1]までの要素をdataに格納し、
svst1_vnumでその値をdst[i + N*vnum]からdst[i + N*vnum + N - 1]に書き戻している。

ベクトル値 load/store

srcポインタのベクトルに指定された位置からデータを読み、SVE型に格納する。

const svuint64_t src_base_ptrs = svindex_u64((uint64_t)(&src[i]), sizeof(float64_t));
svuint64_t dst_base_ptrs = svindex_u64((uint64_t)(&dst[i]), sizeof(float64_t));
const svfloat64_t data = svld1_gather_f64(pg, src_base_ptrs);
svst1_scatter(pg, dst_base_ptrs, data);

まず、svindex_u64src[i]へのポインタをuint64_tにキャストした値を頭にし、sizeof(float64_t)のstepsizeを持つuint64_t型のベクトル型を作っている。
つまり、

{(uint64_t)(&src[i]), (uint64_t)(&src[i]) + sizeof(float64_t), (uint64_t)(&src[i]) + 2 * sizeof(float64_t), ...}

というベクトル型を作っている。
svld1_gathersrc_base_ptrs[i]からsrc_base_ptrs[i + N - 1]までの要素をdataに格納し、
svst1_scatterでその値をdst[i]からdst[i + N - 1]に書き戻している。

続きそのうち書く

スカラー値 load/store、ベクトル値オフセット

srcポインタに指定された位置からoffsetベクトルに指定されたバイト数だけ間隔を開けてデータを読み、SVE型に格納する。

const svuint64_t byte_offsets = svindex_u64(0, sizeof(float64_t));
const svfloat64_t data = svld1_gather_offset(pg, &src[i], byte_offsets);
svst1_scatter_offset(pg, &dst[i], byte_offsets, data);

svld1_gather_offsetで、(float64_t*)((uint64_t)(&src[i]) + offset[i])の値をdata[i]に格納し、
svst1_scatter_offsetでその値を(float64_t*)((uint64_t)(&dst[i]) + offset[i])に書き戻している。

おまけCPP

for(uint64_t i = 0 ; i < N ; i += stride){
    const svbool_t pg = svwhilelt_b64(i, N);
    const float64_t* const src_base_ptr = &src[i];
    float64_t* const dst_base_ptr = &dst[i];
    //const svfloat64_t data = svld1(pg, src_base_ptr);
    //svst1(pg, dst_base_ptr, data);

    //const uint64_t vnum = 0;
    //const svfloat64_t data = svld1_vnum(pg, src_base_ptr, vnum);
    //svst1_vnum(pg, dst_base_ptr, vnum, data);

    //const svuint64_t src_base_ptrs = svindex_u64((uint64_t)(src_base_ptr), sizeof(float64_t));
    //svuint64_t dst_base_ptrs = svindex_u64((uint64_t)(dst_base_ptr), sizeof(float64_t));
    //const svfloat64_t data = svld1_gather_f64(pg, src_base_ptrs);
    //svst1_scatter(pg, dst_base_ptrs, data);

    //const svuint64_t byte_offsets = svindex_u64(0, sizeof(float64_t));
    //const svfloat64_t data = svld1_gather_offset(pg, src_base_ptr, byte_offsets);
    //svst1_scatter_offset(pg, dst_base_ptr, byte_offsets, data);

    //const uint64_t byte_offset = 0;
    //const svuint64_t src_base_ptrs = svindex_u64((uint64_t)(src_base_ptr), sizeof(float64_t));
    //svuint64_t dst_base_ptrs = svindex_u64((uint64_t)(dst_base_ptr), sizeof(float64_t));
    //const svfloat64_t data = svld1_gather_offset_f64(pg, src_base_ptrs, byte_offset);
    //svst1_scatter_offset(pg, dst_base_ptrs, byte_offset, data);

    const uint64_t base_index = 0;
    const uint64_t step = 1;
    const svuint64_t indices = svindex_u64(base_index, step);
    const svfloat64_t data = svld1_gather_index(pg, src_base_ptr, indices);
    svst1_scatter_index(pg, dst_base_ptr, indices, data);
}
0
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
0
0