LoginSignup
2
1

More than 1 year has passed since last update.

AVX/AVX2によるnot演算の作成とsetzero

Posted at

はじめに

ここでは,AVXにはないnot演算の作成方法と,全てのレジスタを0にするsetzeroは論理演算でできていることについて説明します.

両者は,全てのビットを1にする(すべてをFにする),全てのビットを0にする命令です.

not演算の作成

notは,全てのビットが1のマスクとのxorで実現できます.
全てが1のマスクは,-1をセットする(0xFF...をセットする)ことで作成できますがセット命令はメモリからのロードが必要となります.
一方で,比較命令の結果を使うことで,メモリを介することなく直接レジスタに全て1のマスクを生成できます.
比較結果がtrueの時,全てのビットが1となるため,適当な値(この場合は引数で入れた値)を自分と自分の比較にすることですべてがFになるマスクが作成可能です.

inline __m256i _mm256_not_si256(__m256i src)
{
    return _mm256_xor_si256(src, _mm256_cmpeq_epi8(src, src));
}

もちろんこのマスクは使いまわすことができるため,大きなループで,何度もnot命令を出す場合は,マスク生成の時間を除くことができます
つまり,xor演算1回でnotを行うことができます.
この場合は,ループ外の演算のコストは無視できるほど小さいため,cmpでマスクを作ろうと,set(-1)でマスクを作ろうと計算時間に影響はありません.

const __m256i zero = _mm256_setzero_si256();
const __m256i ffmask = _mm256_cmpeq_epi8(zero, zero);
//const __m256i ffmask = _mm256_set1_epi8(-1);
__m256i s[size];
__m256i d[size];
for(int i=0;i<size;i++)
{
    d[i]=_mm256_xor_si256(s[i],ffmask);
}

float/doubleのビット反転も同様に作成可能ですが,not演算のように全てのビットの反転処理が浮動小数点型で必要になることはあまり考えられません.
最上位の符号部や指数部,仮数部を各々でビット演算を扱うことが想定されます.
その場合は,andnot演算やxor演算で必要な処理を表現できます.

_mm256_setzero_ps|pd_si256

__m256i _mm256_setzero_si256 (void)
__m256 _mm256_setzero_ps (void)
__m256d _mm256_setzero_pd (void)
asm: vpxor ymm, ymm, ymm //si256
asm: vxorps ymm, ymm, ymm //ps
asm: vxorpd ymm, ymm, ymm //pd
Architecture Latency Throughput Uops
Alderlake 0.2 0.02 -
Icelake 0.2 0.23 1
Skylake 0.2 0.25 1
Broadwell 0.3 0.25 1
Haswell 0.3 0.25 1
Ivy Bridge 0.3 0.25 1
Sandy Bridge 0.3 0.25 1
Zen3 0.2 0.02 1
Zen2 0.2 0.25 1
Zen 0.5 0.5 2
  • AlderlakeやZen3はスループットが非常に速くなっています.

説明

レジスタを0で初期化します.
どれかのレジスタの引数を同じにしてxor演算をすれば0の値が作れます.
即値の0をセットするわけではないため,メモリからのロードコストはかかりません.
0にする方法は他にもvsub same same等でも実現できますがほとんどのアーキテクチャでxorによる初期化が最速です.

また,xor same sameは論理演算よりも速く動作します.
参考までに論理演算の性能を示します.
論理演算(浮動小数点)

Architecture Latency Throughput Uops
Alderlake 1 0.33 -
Icelake 1 0.33 1
Skylake 1 0.33 1
Broadwell 1 1 1
Haswell 1 1 1
Ivy Bridge 1 1 1
Sandy Bridge 1 1 1
Zen3 1 0.25 1
Zen2 1 0.25 1
Zen 1 0.5 2

論理演算(整数)

Architecture Latency Throughput Uops
Alderlake 1 0.33 -
Icelake 1 0.33 1
Skylake 1 0.33 1
Broadwell 1 0.33 1
Haswell 1 0.33 1
Zen3 1 0.25 1
Zen2 1 0.25 1
Zen 1 0.5 2
2
1
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
2
1