2

その命令セット (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;
};

この情報により、さらに分析が可能になることを願っています...

4

0 に答える 0