MSVC 2013:如何正确启用AVX2?

时间:2016-10-08 10:38:39

标签: avx avx2 visual-c++-2013

我试图通过打开/ arch:AVX2来获取特定软件的更快二进制文件,因为我在应该支持该指令集的CPU上运行它(i7 4770和i7 4800MQ)。 但是,这样做会产生一个可执行文件,它会随着消息“#34; 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的计算机上崩溃?我错过了阻止/拱起的东西: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  
}

访问冲突中涉及的 groups 对象定义为:

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;
};

我希望此信息可以进行更多分析...

0 个答案:

没有答案