HEXA BLOG
ヘキサブログ
プログラム
AVXを使ってみました!
こんにちは!
そろそろ職場の空気を掴みはじめてきた、新人のイワモーです
さて、前回のブログでは新しいPCを買った事をお話ししたと思いますが、
その中でAVXを勉強中という事を書きました。
今回は早速、そのAVXについて少しお話してみようかと思います
まず簡単に説明すると・・・
AVXとは、拡張SIMD命令セットの事で、従来のSSE命令では最大128bitまでの演算幅だったのが、
AVXでは256bitまで拡張されており、一回の命令で最大8つの数値を演算させる事が可能になったSIMD命令。
そして、SSEの拡張を重ねた結果、非常に煩雑になってしまったSIMD命令への解決へのアプローチ
という感じでしょうか。
厳密には更に説明が必要だったりしますが、詳細についてはAVXのリファレンス等を読んで頂ければと思います
インテルAVXリファレンス(大き目のPDFデータなので、注意してください)
http://download.intel.com/jp/software/AVE/319433-006JA.pdf
では、実際にはどんな感じなのか
AVXを用いた簡単なコードの流れを少し書いてみました
今回扱うデータはこの様な形にしました。
ゲーム等ではよく使いそうな、よくあるVector4データです。
struct VERTEX_DATA { float x; float y; float z; float w; }; VERTEX_DATA *pDataBuffer0; //データバッファ VERTEX_DATA *pDataBuffer1; //計算値のバッファ static const int MAX_VERTEX = 10000000; //データの大きさ
まずAVXを使うにあたり注意する所は、
アラインメントを32byteで定義してメモリを確保しなければならない所です
AVXでは、基本的に一つのデータにつき、32byteのアラインメントを必要としています。
pDataBuffer0 = (VERTEX_DATA*)_aligned_malloc( sizeof(VERTEX_DATA) * MAX_VERTEX, 32); pDataBuffer1 = (VERTEX_DATA*)_aligned_malloc( sizeof(VERTEX_DATA) * MAX_VERTEX, 32);
普段_aligned_mallocはあまり使わないアロケート方法ですが、
第2引き数でアラインメント幅を入力する事が出来ます。
これでメモリを32byteアラインメントで確保しました
もちろん、構造体の定義の方で__declspec(align(32))の様にアラインメントを定義してしまっても問題は無いと思います。
その場合は、普通のnew演算子でメモリをアロケートしても大丈夫です
次にデータの入力ですが、これは普通のプログラムと同じ様に代入できます。
pDataBuffer0[i].x = 100; pDataBuffer0[i].y = 100; pDataBuffer0[i].z = 100; pDataBuffer0[i].w = 100; pDataBuffer1[i].x = 100; pDataBuffer1[i].y = 100; pDataBuffer1[i].z = 100; pDataBuffer1[i].w = 100;
データ入力が終わったら後はAVXのイントリンシック命令を使って計算させるだけです
__m256というAVX用のデータ型に値をロードし、計算させ、結果を元に戻す、という手順です
//MAX_VERTEXは、2の倍数と今回は仮定 //また_mm256_load_psはfloat8個分のデータ転送を行えるので、VERTEX_DATA2個分に相当する。 //よって、ループカウンタを2でインクリメント __m256 srcIntrin; __m256 destIntrin; for(int i=0; i<MAX_VERTEX; i+=2) { //値を__m256の変数にロードする srcIntrin = _mm256_load_ps((float*)&pDataBuffer0[i]); destIntrin = _mm256_load_ps((float*)&pDataBuffer1[i]); //ロードが終わったら、計算命令にデータを入れ(この命令は掛け算)結果を受け取り srcIntrin = _mm256_mul_ps(srcIntrin,destIntrin); //計算結果を元の場所に戻す _mm256_store_ps((float*)&pDataBuffer0[i],srcIntrin); }
これで、無事にAVXを使って計算させる事に成功しました
上の例では、_mm256_mul_psを利用し、掛け算を行っています。
最後に忘れてはならないのが、確保したメモリの解放です
_aligned_mallocを使っている場合は_aligned_freeでメモリを解放してあげましょう。
_aligned_free(pDataBuffer0); _aligned_free(pDataBuffer1);
もしも構造体を__declspec(align(32))で定義し、newで確保している場合は、
そのままdelete命令で解放してしまいましょう
以上が基本的な流れです
また、今回はコンパイルすれば動作するコードを .CPPデータとして添付ました。
main.cpp
※ ・CPPデータのコンパイルは、VisualStudio2010が必要となります
・データの実行については、OSのバージョンがWindows7SP1である必要があります。
・AVXに対応しているCPUが必要となります。
自分の環境では実際にAVXを用いたパターンと、通常の計算方法をリリースビルドで比べてみると、
割り算等のコストが高めの演算では6倍近い速度で計算を行わせる事ができました。
しかし、足し算や引き算等のコストが低めの計算では3割程早くなる程度でした
使いこなせれば動作速度を向上させるツールに十分なると思いますが、
アラインメントに気を遣うのでメンテナンスしずらい点、新しい命令が故のバグ、
対応環境の少なさ、効果を発揮できる場面の見極め等々、壁はとても大きいです。
それに加えて、AVXは従来のSSE命令が混在しているプログラムだと最大限のパフォーマンスが得られないという欠点もあります。
ですが、実際に動作速度を向上出来た時の感動も大きいです
まだまだSIMD最適化に片足を突っ込んだばかりですが、有志で開いている勉強会等に積極的に参加していき、少しずつ理解を深めていきたいと思います
それではまた
CATEGORY
- about ヘキサ (166)
- 部活動 (6)
- CG (18)
- プロジェクトマネジメント (1)
- 研修 (5)
- 美学 (1)
- いいモノづくり道 (230)
- 採用 -お役立ち情報も- (149)
- プログラム (188)
- デザイン (99)
- ゲーム (274)
- 日記 (1,104)
- 書籍紹介 (113)
- その他 (875)
- 就活アドバイス (20)
- ラーメン (3)
- ライフハック (25)
- イベント紹介 (10)
- 料理 (23)
- TIPS (7)
- 怖い話 (3)
- サウンド (5)
- 子育て (1)
- 筋トレ (1)
- 商品紹介 (21)
- アプリ紹介 (31)
- ソフトウェア紹介 (33)
- ガジェット紹介 (12)
- サイト紹介 (10)
- 研究・開発 (34)
- 回路図 (4)
- アナログゲーム (40)
- 交流会 (21)
- 報告会 (3)
- インフラ (25)
- グリとブラン (6)
- カメラ (9)
- クラフト (27)
- 部活 (14)
- 画伯 (15)
- カレー (6)
- 音楽(洋楽) (6)
- 映画・舞台鑑賞 (43)
- 飼育 (5)
- いぬ (8)
- ねこ (19)
ARCHIVE
- 2024年
- 2023年
- 2022年
- 2021年
- 2020年
- 2019年
- 2018年
- 2017年
- 2016年
- 2015年
- 2014年
- 2013年
- 2012年
- 2011年
- 2010年
- 2009年
- 2008年
- 2007年