その命令セット (i7 4770 および i7 4800MQ) をサポートする必要がある CPU で実行しているため、/arch:AVX2 をオンにして、特定のソフトウェアのより高速なバイナリを取得しようとしています。
ただし、そうすると実行可能ファイルが生成され、AVX2 以外のハードウェアで実行しているかのように、「xxx.exe が動作を停止しました」というメッセージが表示されてクラッシュします。
AVX2 ハードウェアを検出し、対応する実行可能ファイルを実行する y-cruncher を実行することで、私のシステムで AVX2 が正しくサポートされていることがわかりました。
/arch:AVX を指定すると、同じ問題が発生します。
/arch オプションなしでビルドすると、コードは正常に実行されます。その他に使用されるビルド オプションは次のとおりです。
/Ox /Ob2 /Oi /Oy /GT /GL /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /openmp /Gd /TP /GL /GF /Ot /Qfast_transcendentals
ソフトウェア自体は、より幅広いプラットフォームで実行するように設計されているため、特定の AVX2 組み込み関数を使用しません。コードを変更せず に、自分のプラットフォームでより良いパフォーマンスを得ようとしているだけです (これは複雑なソフトウェアであり、私は専門のプログラマーではありません)。
私の質問は、なぜそのオプションが AVX2 対応のマシンでプログラムをクラッシュさせるのでしょうか? 他のフラグとの非互換性など、/arch:AVX2 の正常な動作を妨げるものがないのでしょうか? (MS ドキュメントを確認したところ、AVX2 に関連する「相互依存関係」は見つかりませんでした)。
編集: Regis Portalez が提案したように、コードに関する情報をここに追加します。問題の原因となっているコード スニペットを次に示します。アクセス違反を示す最後の行の前に VS デバッガーが停止します。
void Film::ComputeGroupScale(u_int i)
{
const Color white(space.ToXYZ(RGB(1.f)));
if (groups[i].temperature > 0.f) {
Color colorTemp(SPD(groups[i].temperature));
colorTemp /= colorTemp.Y();
groups[i].convert = Adapter(white,
space.ToXYZ(groups[i].rgbScale)) *
Adapter(white, colorTemp);
} else {
groups[i].convert = Adapter(white,
space.ToXYZ(groups[i].rgbScale));
}
groups[i].convert *= groups[i].globalScale;
}
以下は、最後の行のアセンブリ コードです。
}
groups[i].convert *= groups[i].globalScale;
00007FFB28E43B2A vbroadcastss ymm2,dword ptr [rax+rbx+40h]
00007FFB28E43B31 mov rax,qword ptr [rdi+1B8h]
00007FFB28E43B38 vmulps ymm0,ymm2,ymmword ptr [rax+rbx+54h]
00007FFB28E43B3E vmovups ymmword ptr [rax+rbx+54h],ymm0
00007FFB28E43B44 vmulss xmm0,xmm2,dword ptr [rax+rbx+74h]
00007FFB28E43B4A vmovss dword ptr [rax+rbx+74h],xmm0
00007FFB28E43B50 vzeroupper
}
デバッガーは、アクセス違反がvbroadcastssで発生していることを示しています。レジスタの内容は次のとおりで、位置 0 を読み取ろうとしていることが示されています。
RAX = 000000003F800000 RBX = 0000000000000000 RCX = 000007FEDC1143A8 RDX = 000000000021B6E8
RSI = 0000000007709710 RDI = 0000000002D165E0 R8 = 000000000021B6B0 R9 = 0000000004D25190
R10 = 00000000003B0274 R11 = 000000000021B428 R12 = 0000000000000001 R13 = 0000000000000000
R14 = 0000000000000000 R15 = 0000000002288480 RIP = 000007FEDBDC2C0A RSP = 000000000021B690
RBP = 000000000021B790 EFL = 00010340
0x000000003f800040 = 00000000
比較として、 /arch:AVX2 を使用しない場合のアセンブリは次のとおりです。
groups[i].convert *= groups[i].globalScale;
000007FEDCA019E8 movups xmm0,xmmword ptr [rax+rbx+54h]
000007FEDCA019ED shufps xmm2,xmm2,0
000007FEDCA019F1 mulps xmm0,xmm2
000007FEDCA019F4 movups xmmword ptr [rax+rbx+54h],xmm0
000007FEDCA019F9 movups xmm0,xmmword ptr [rax+rbx+64h]
000007FEDCA019FE mulps xmm0,xmm2
000007FEDCA01A01 movups xmmword ptr [rax+rbx+64h],xmm0
000007FEDCA01A06 mulss xmm2,dword ptr [rax+rbx+74h]
000007FEDCA01A0C movss dword ptr [rax+rbx+74h],xmm2
}
アクセス違反に関係するグループオブジェクトは次のように定義されます。
std::vector<Group> groups;
class Group {
public:
Group(const string &n) : samples(0.f), name(n),
globalScale(1.f), temperature(0.f),
rgbScale(1.f), convert(Color(1.f), Color(1.f)),
enable(true) { }
~Group() {
for(vector<Buffer *>::iterator buffer = buffers.begin(); buffer != buffers.end(); ++buffer)
delete *buffer;
}
void CreateBuffers(const vector<BufferConfig> &configs, u_int x, u_int y);
Buffer *getBuffer(u_int index) const {
return buffers[index];
}
double samples;
vector<Buffer *> buffers;
string name;
float globalScale, temperature;
RGB rgbScale;
Adapter convert;
bool enable;
};
この情報により、さらに分析が可能になることを願っています...