SIMD 演算におけるキャッシュ制御方法とか

キャッシュ制御は重要 (?)

プロセッサに近いメモリの順番は,
 メインメモリ ⇔ L3 キャッシュ ⇔ L2 キャッシュ ⇔ L1 キャッシュ ⇔ レジスタ ⇔ 演算器
という感じだと思います.

SSE や AVX にはキャッシュ操作をサポートする命令が存在します.SSE 命令・AVX 命令では並列化による高速化だけでなくキャッシュ制御による高速化が期待できます.特に,SSE が 128bit 単位の演算に対し AVX は 256bit 単位になるためメモリアクセスを効率的に行うことができるようになれば SSE よりも高い演算性能が得られる可能性があります.


計算結果をキャッシュを介さずに保存する

SIMD で計算した結果を他の計算に再利用しない場合,キャッシュに残さずにメモリに格納する場合に用いる方法です.

void _mm256_stream_ps(float* p, __m256 a)//単精度
void _mm256_stream_pd(double* p, __m256d a)//倍精度

ただし,単精度も倍精度も p のアドレスは必ず 32byte にアライメントを揃えておく必要があります.また,キャッシュに残しておきたい場合は _mm256_store_pd 等を使用します.


プリフェッチ(先読み)

事前にプロセッサに近いキャッシュ階層にデータをロードしておきたい場合に使用する方法です.

void _mm_prefetch(char const* p, int i)

p はロードしたいメモリのアドレスを指定しておきます.i にはプリフェッチ命令のタイプを指定するようです.プリフェッチのタイプは以下の通りです.

  • _MM_HINT_T0: 一次命令.すべてのキャッシュにデータを読み込む
  • _MM_HINT_T1: 一次命令.L0 以外のキャッシュにデータを読み込む
  • _MM_HINT_T2: 一次命令.L0 と L1 以外のキャッシュへデータを読み込む
  • _MM_HINT_NTA: 非一次命令.L0 へデータを読み込む

プリフェッチの参考資料はコチラ http://jp.xlsoft.com/documents/intel/seminar/2_Sofrware%20Optimize.pdf

プリフェッチはよくわからないので今後要勉強です...


その他

キャッシュからデータを追い出す

void _mm_clflush(void const* p)

同期の類い

  • load の保証
void _mm_lfence()
  • store の保証
void _mm_sfence()
  • メモリアクセス全般を保証
void _mm_mfence()