2013-03-14 8 views
8

私は2台のコンピュータで作業しています。 1つはAVXサポートなし、もう1つはAVXサポートなし。実行時に自分のCPUでサポートされている命令セットを見つけ、適切なコードパスを選択すると便利です。 私は、Agner Fogの提案に従ってCPUディスパッチャー(http://www.agner.org/optimize/#vectorclass)を作成しました。しかし、AVXをコンパイルしてVisual Studioとリンクすると、AVXを有効にしたコードでは、実行するとコードがクラッシュする原因になります。AVXとSSE用のビジュアルスタジオ用のcpuディスパッチャ

たとえば、私はいくつかのSSE2命令で定義されたSSE2命令セットを持つものと、AVX命令セットが定義されたものといくつかのAVX命令を持つものの2つのソースファイルを持っています。私の主な機能では、SSE2関数だけを参照すると、AVXを有効にしたAVX命令付きのソースコードを持っているため、コードはまだクラッシュします。どのように私はこれを修正することができますか?

編集: さて、私は問題を切り離したと思います。私はAgner霧のベクトルクラスを使用していると私はとして3つのソースファイルを定義しています。このクラッシュ

//file sse2.cpp - compiled with /arch:SSE2 
#include "vectorclass.h" 
float func_sse2(const float* a) { 
    Vec8f v1 = Vec8f().load(a); 
    float sum = horizontal_add(v1); 
    return sum; 
} 
//file avx.cpp - compiled with /arch:AVX 
#include "vectorclass.h" 
float func_avx(const float* a) { 
    Vec8f v1 = Vec8f().load(a); 
    float sum = horizontal_add(v1); 
    return sum; 
} 
//file foo.cpp - compiled with /arch:SSE2 
#include <stdio.h> 
extern float func_sse2(const float* a); 
extern float func_avx(const float* a); 
int main() { 
    float (*fp)(const float*a); 
    float a[] = {1,2,3,4,5,6,7,8}; 
    int iset = 6; 
    if(iset>=7) { 
     fp = func_avx; 
    } 
    else { 
     fp = func_sse2; 
    } 
    float sum = (*fp)(a); 
    printf("sum %f\n", sum); 
} 

。代わりにfec_SSE2でVec4fを使用するとクラッシュしません。私はこれを理解していない。私は、AVXを持つ別のソースファイルを持っていない限り、SSE2と共にVec8fを使用することができます。 Agner霧のマニュアルでは、AVX命令セットが指定されていない限り

が「256ビットの浮動小数点ベクトルクラス(Vec8f、 Vec4d)を使用してもメリットはありませんが、あればとにかく これらのクラスを使用することが便利であろうと言いますAVXなしで をコンパイルすると、各256ビットのベクトルは単に2つの128ビットベクトルに分割されます。

しかし、SSE2でコンパイルしたVec8fとAVXでコンパイルしたVec8fの2つのソースファイルがあるとクラッシュします。

EDIT2: 私はそれは、コマンドラインから

>cl -c sse2.cpp 
>cl -c /arch:AVX avx.cpp 
>cl foo.cpp sse2.obj avx.obj 
>foo.exe 

を仕事を得ることができEDIT3: これは、しかし、

>cl -c sse2.cpp 
>cl -c /arch:AVX avx.cpp 
>cl foo.cpp avx.obj sse2.obj 
>foo.exe 

もう一つの手掛かりをクラッシュします。リンクの順序は明らかです。 avx.objがsse2.objの前にある場合はクラッシュしますが、sse2.objがavx.objより前の場合はクラッシュしません。私は正しいコードパスを選択するかどうかはわかりませんが(私は今AVXシステムにアクセスできない)、少なくともクラッシュはしません。

+0

クラッシュの詳細はなんですか?デバッガで失敗した命令を特定しましたか? –

+0

デバッガは、func_SSEがAVX命令を使用しようとしていることを示しています。どうしてか分かりません。しかし、私はコマンドラインを使用してクラッシュせずにコードを動作させることができました。上記のコマンドを追加しました。私はまだIDEでそれを行う方法を知らない。プラス面では、私はWindowsでコマンドラインから初めてコンパイルしました! Linuxでコンパイルする唯一の方法です。 –

+0

IDEからリンク時コード生成を使用しましたか? –

答えて

1

異なるCPPファイルにSSE関数とAVX関数を入れ、/arch:AVXまでSSEバージョンをコンパイルしてください。

+0

それはまさに私がやったことです。 –

+0

これはデバッガで実行しただけです。 CPUが "無効命令"例外を生成すると、この命令の起点が表示されます。あなたの非AVX CPUはあなたが使用するいくつかのSSE命令をサポートしていない可能性があります。 SSE、SSE2、SSE3、SSSE3、SSE4.1、SSE4.2、およびSSE4A(SSE3は含まれますが、SSSE3、SSE4.1またはSSE4.2は含まれません)の多くの世代のSSE命令があります。 –

+0

私のCPUは最大SSE4.2をサポートしています。私はCPU-Zでそれをチェックしました。しかし、私は今、ベクトルクラスを使わずにコードを削除してみました。私はあなたに戻る必要があります... –

2

リンクの順序が重要であるという事実から、objファイルには何らかの初期化コードが存在する可能性があります。初期化コードが共通である場合、最初のコードのみが使用されます。私は、これは古い問題であり、それを尋ねた人がに表示されていることをことを実現(/ C /Ftestavx.asmでコンパイル)

+0

ディスパッチャは私のシステムでAVXでクラッシュしませんが、私のシステムではクラッシュしません。 AVXのないシステムでテストできますか? AVXのシステムでSSE命令が選択されていない可能性もありますが、それでもAVXを使用しているため、まだ動作していますか?アセンブリリストはちょうど私のために進んだビットですので、おそらく私はこれに戻ってくる必要があります。 –

7

を私はそれを再現することはできませんが、アセンブリリストでそれを見ることができるはずですもはや周りにはいないが、私は昨日同じ問題にぶつかった。ここに私が取り組んだことがあります。

sse2.cppファイルとavx.cppファイルの両方をコンパイルすると、関数を含むだけでなく、必要なテンプレート関数も含むオブジェクトファイルが生成されます。 (例えば、。Vec8f::load)これらのテンプレート関数も、要求された命令セットを使用してコンパイルされます。

これは、sse2.objおよびavx.objオブジェクトファイルにそれぞれ、それぞれの命令セットを使用してコンパイルされたVec8f::loadという定義が含まれることを意味します。

しかし、コンパイラはVec8f::loadを外部から見えるように扱うので、 'selectany'(別名 'pick any')というラベルを付けてオブジェクトファイルの 'COMDAT'セクションに置きます。これはリンカに、このシンボルの複数の定義、例えば2つの異なるオブジェクトファイルの定義を見ると、それが好きなものを選ぶことができることを伝えます。 (これは、最終的な実行可能ファイルの重複コードを減らすために、テンプレートとインライン関数の複数の定義によってサイズが大きくなります)。

問題は、オブジェクトの順序リンカーに渡されたファイルは、リンカーの選択に影響します。具体的にここでは、最初に表示される定義を選択しているようです。

avx.objの場合は、AVXコンパイル済みのバージョンVec8F::loadが常に使用されます。これは、その命令セットをサポートしていないマシンでクラッシュします。 一方、sse2.objが最初の場合は、SSE2コンパイル済みのバージョンが常に使用されます。これはクラッシュしませんが、AVXがサポートされていてもSSE2命令しか使用しません。

// 
// link with sse2.obj before avx.obj 
// 
0001:00000080 _main        foo.obj 
0001:00000330 [email protected]@[email protected]    sse2.obj 
0001:00000420 [email protected]@[email protected]    sse2.obj 
0001:00000440 [email protected]@[email protected][email protected]@@Z  sse2.obj 
0001:00000470 [email protected]@[email protected]     sse2.obj <-- sse2 version used 
0001:00000490 [email protected]@[email protected]@XZ  sse2.obj 
0001:000004c0 [email protected]@@[email protected]@XZ sse2.obj 
0001:000004f0 [email protected]@@[email protected]@XZ sse2.obj 
0001:00000520 [email protected]@@[email protected]@Z  sse2.obj <-- sse2 version used 
0001:00000680 [email protected]@[email protected]    avx.obj 
0001:00000740 [email protected]@[email protected]@XZ  avx.obj 

// 
// link with avx.obj before sse2.obj 
// 
0001:00000080 _main        foo.obj 
0001:00000270 [email protected]@[email protected]    avx.obj 
0001:00000330 [email protected]@[email protected]     avx.obj <-- avx version used 
0001:00000350 [email protected]@[email protected]@XZ  avx.obj 
0001:00000380 [email protected]@@[email protected]@Z  avx.obj <-- avx version used 
0001:00000580 [email protected]@[email protected]    sse2.obj 
0001:00000670 [email protected]@[email protected]    sse2.obj 
0001:00000690 [email protected]@[email protected][email protected]@@Z  sse2.obj 
0001:000006c0 [email protected]@[email protected]@XZ  sse2.obj 
0001:000006f0 [email protected]@@[email protected]@XZ sse2.obj 
0001:00000720 [email protected]@@[email protected]@XZ sse2.obj 

- あなたはリンカ「マップ」ファイルの出力を見れば、このような場合はは(。/ mapオプションを使用して製造)見ることができることをここで

は、関連(編集済み)抜粋ですそれを修正する、それは別の問題です。この場合、以下の鈍的なハックは、avxバージョンにテンプレート関数の異なる名前のバージョンを強制させることで機能するはずです。これにより、sse2とavxのバージョンが同一であっても、同じ関数の複数のバージョンが含まれるため、実行可能なサイズが増えます。 (含まれているファイルはグローバルな状態のいずれかの形式を管理している場合、あなたは2「セミグローバル」のバージョンを持つことになりますよう は、(a)は、それはもはや真のグローバルできなくなります、と -

// avx.cpp 
namespace AVXWrapper { 
\#include "vectorclass.h" 
} 
using namespace AVXWrapper; 

float func_avx(const float* a) 
{ 
    ... 
} 

あり、いくつかの重要な制限は、しかしですb)avx.cppで定義されている他のコードと関数の間でパラメータとしてvectorclass変数を渡すことはできません。

+0

私はこの質問をしました。私はそれを働かせることができた。私は問題が何だったのか分からない。しかし、それは今私にとってうまくいく。 cmakeで試してみてください。https://stackoverflow.com/questions/23808094/create-separate-object-files-from-the-same-source-code-and-link-to-an-executable –

関連する問題