###### tags: `Intringic` `Unity` # x86専用命令(Avx,Avx2)でn未満の値を取り出して、その値のみを結果として返す際の速度検証 ## 最初に 専用命令やBurstCompileは条件分岐が入っているコードを得意としていないはずなので、普通のコードとBurstDirctCall,専用命令などの速度を検証する。 また、専用命令でどのようなコードを書くと早いコードが書けるのか検証していく。 *Mono+il2cppパターンで検証 ## 検証するコード 1. ふつうのコード ```csharp for (int i = 0; i < fa1.Length; i++) { float v = fa1[i]; if (v < 3) { fb[i] = v; } } ``` 2. ダイレクトコール ```csharp [BurstCompile(CompileSynchronously = true)]//8倍の計算のみ対応 private unsafe static void DirectCall(float* arr, float* result, int count, out int resultLen) { resultLen = 0; for (int i = 0; i < count; i++) { float v = arr[i]; if (v < 3) { result[resultLen] = v; resultLen++; } } } ``` 3. 専用命令 ```csharp resultLen = 0; if (Avx.IsAvxSupported) { v256 condition = mm256_set1_ps(3); for (int i = 0; i < count - mod; i += 8) { v256 load = mm256_loadu_ps(arr + i); v256 mask = mm256_cmp_ps(load, condition, 1); resultLen += //ここで正解の個数や値の保存を行う } } ``` 4. 専用命令+まとめて処理(bufferは計算前に事前に用意) ```csharp resultLen = 0; if (Avx.IsAvxSupported) { int mod = count % 8; resultLen = 0; v256 condition = mm256_set1_ps(3); for (int i = 0; i < count - mod; i += 8) { v256 load = mm256_loadu_ps(arr + i); buffer[i] = mm256_cmp_ps(load, condition, 1); buffer2[i] = load; } int counti = count / 8; for (int i = 0; i < count - mod; i += 8) { resultLen += //ここで正解の個数や値の保存をまとめて行う } } ``` ## 速度の検証結果 ![](https://i.imgur.com/DDlP28a.png) ## まとめ 条件分岐が入っている+storeの作業があったとしても今回のケースでは専用命令の方が速いことが分かった。 また、処理を分けてまとめて行った場合と256bitごとで処理した場合とでは、256bitごとやったほうが速いことが分かった。