2

我试图通过打开 /arch:AVX2 为特定软件获取更快的二进制文件,因为我在应该支持该指令集(i7 4770 和 i7 4800MQ)的 CPU 上运行它。
但是,这样做会产生一个可执行文件,该可执行文件会崩溃并显示“xxx.exe 已停止工作”消息,就好像我在非 AVX2 硬件上运行它一样。
我知道通过运行 y-cruncher 在我的系统上正确支持 AVX2,它检测 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