MacでAVXプログラミングの環境を整えようとしたら意外に面倒だった

研究でAVXプログラミングすることになった.
その時の環境構築メモ.

AVXプログラミングをする上での注意点

  • AVX命令を使うには, Sandy Bridge世代以降のCPUが必要. Macの場合, 2011年以降に発売されたマシンが必要.
  • gccのバージョン4.6以降からAVXがサポートされている. (それ以前からbrancheにはあったっぽい) Xcodeに付属しているgccはv4.2.1なので, MacPortsなり, Gentoo Prefixなりで4.6以降のgccをインストールする.

マシン環境

コンパイル対象

immintrin.h というのは, SSEとAVXの命令に対応するCの組み込み関数が定義されているヘッダファイル.

#include <immintrin.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int a[] __attribute__((aligned(32))) = {3, 4, 5, 6}; 
    int b[] __attribute__((aligned(32))) = {1, 2, 3, 4}; 
    __m128i a_; 
    __m128i b_; 
    __m128i z_; 
    int z[4];
    int i;

    a_ = _mm_set_epi32(a[0], a[1], a[2], a[3]);
    b_ = _mm_set_epi32(b[0], b[1], b[2], b[3]);
    z_ = _mm_add_epi32(a_, b_);

    z[3] = _mm_extract_epi32(z_, 0); 
    z[2] = _mm_extract_epi32(z_, 1); 
    z[1] = _mm_extract_epi32(z_, 2); 
    z[0] = _mm_extract_epi32(z_, 3); 

    for (i = 0; i < 4; i++) {
        printf("z[%i]: %i\n", i, z[3-i]);
    };  
    return 0;
}

gccでコンパイルしてみる

gcc4.6には, -mavx オプションが追加されている.

gcc -mavx -o add  add.c 

とすると

no such instruction: `vmovd %edx, %xmm1'

とかいって怒られる.

そこで,
Xcode 4とSnow LeopardとそれからAVX (きっちん)
を参考に環境構築をしてみた.

この記事によると, Mac上では, gcc4.2だろうがgcc4.6だろうが, Xcode付属のアセンブラを使ってるのでそこでこけてるみたい.
そこで, clangがAVX対応しているようなのでそっちを使ってみる.

$ clang -mavx -I/usr/lib/clang/2.1/include/ add.c -o add

とすると,

add.c:18:12: warning: implicit declaration of function '_mm_extract_epi32' is invalid in C99 [-Wimplicit-function-declaration]
    z[3] = _mm_extract_epi32(z_, 0);

とまた怒られる. _mm_extract_epi32なんて関数ないよと言われてるようだ.
ただ, _mm_set_epi32の方は通ってるみたい.
_mm_set_epi32はSSE2, _mm_extract_epi32の方は, SSE4.2の命令なので, もしかしてSSE4.2が使えてないのか.

最終的に

そこで結局, 参考記事の通りに, gccアセンブラコードを吐いて, clangにそのアセンブラコードを喰わせるとうまくいった.

$ gcc -mavx -S add.c
$ clang -mavx add.s
$ ./a.out

感想

yasmとかnasmとかgasとかllvmとか, コンパイラ&アセンブラ周りの知識がないせいかよくわからないことが多い.