C++ 什么是VS2017 C++;编译器选项会影响矩阵乘法吗?

C++ 什么是VS2017 C++;编译器选项会影响矩阵乘法吗?,c++,visual-studio,C++,Visual Studio,以下代码将两个4维标识矩阵相乘: const Matrix4 id = Matrix4( 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); auto & a = id; auto & b = id; auto m1 = Matrix4( a.data[0] * b.data[0] + a.

以下代码将两个4维标识矩阵相乘:

const Matrix4 id = Matrix4(
    1.0f, 0.0f, 0.0f, 0.0f, 
    0.0f, 1.0f, 0.0f, 0.0f, 
    0.0f, 0.0f, 1.0f, 0.0f, 
    0.0f, 0.0f, 0.0f, 1.0f);

auto & a = id;
auto & b = id;

auto m1 = Matrix4(
    a.data[0] * b.data[0] + a.data[4] * b.data[1] + a.data[8] * b.data[2] +
    a.data[12] * b.data[3],

    a.data[0] * b.data[4] + a.data[4] * b.data[5] + a.data[8] * b.data[6] +
    a.data[12] * b.data[7],

    a.data[0] * b.data[8] + a.data[4] * b.data[9] + a.data[8] * b.data[10] +
    a.data[12] * b.data[11],
    a.data[0] * b.data[12] + a.data[4] * b.data[13] + a.data[8] * b.data[14] +
    a.data[12] * b.data[15],
    a.data[1] * b.data[0] + a.data[5] * b.data[1] + a.data[9] * b.data[2] +
    a.data[13] * b.data[3],
    a.data[1] * b.data[4] + a.data[5] * b.data[5] + a.data[9] * b.data[6] +
    a.data[13] * b.data[7],
    a.data[1] * b.data[8] + a.data[5] * b.data[9] + a.data[9] * b.data[10] +
    a.data[13] * b.data[11],
    a.data[1] * b.data[12] + a.data[5] * b.data[13] + a.data[9] * b.data[14] +
    a.data[13] * b.data[15],
    a.data[2] * b.data[0] + a.data[6] * b.data[1] + a.data[10] * b.data[2] +
    a.data[14] * b.data[3],
    a.data[2] * b.data[4] + a.data[6] * b.data[5] + a.data[10] * b.data[6] +
    a.data[14] * b.data[7],
    a.data[2] * b.data[8] + a.data[6] * b.data[9] + a.data[10] * b.data[10] +
    a.data[14] * b.data[11],
    a.data[2] * b.data[12] + a.data[6] * b.data[13] + a.data[10] * b.data[14] +
    a.data[14] * b.data[15],
    a.data[3] * b.data[0] + a.data[7] * b.data[1] + a.data[11] * b.data[2] +
    a.data[15] * b.data[3],
    a.data[3] * b.data[4] + a.data[7] * b.data[5] + a.data[11] * b.data[6] +
    a.data[15] * b.data[7],
    a.data[3] * b.data[8] + a.data[7] * b.data[9] + a.data[11] * b.data[10] +
    a.data[15] * b.data[11],
    a.data[3] * b.data[12] + a.data[7] * b.data[13] + a.data[11] * b.data[14] +
    a.data[15] * b.data[15]);

const int diff_index = 15;

std::cout << "Actual value of element " << diff_index << " is " << m1.data[diff_index] << " expected " << id.data[diff_index] << std::endl;
但这会输出1.0f。只有将MatrixTest.cpp编译为项目的一部分,我才能获得0.0f

下面,我提供了Matrix类的定义,该定义非常简单:

struct Matrix4
{
    float data[16];

    Matrix4(float m00,
        float m01,
        float m02,
        float m03,
        float m10,
        float m11,
        float m12,
        float m13,
        float m20,
        float m21,
        float m22,
        float m23,
        float m30,
        float m31,
        float m32,
        float m33)
    {
        data[0] = m00;
        data[4] = m01;
        data[8] = m02;
        data[12] = m03;
        data[1] = m10;
        data[5] = m11;
        data[9] = m12;
        data[13] = m13;
        data[2] = m20;
        data[6] = m21;
        data[10] = m22;
        data[14] = m23;
        data[3] = m30;
        data[7] = m31;
        data[11] = m32;
        data[15] = m33;
    }
};
我相信,这不是内存损坏的结果,因为我的项目非常琐碎,而且这些代码在一些实际应用程序中已经运行了很长时间,所以我认为一定发生了一些奇怪的事情

更新1

VS2017 15.7.1,编译器版本为:针对x86的Microsoft(R)C/C++优化编译器版本19.14.26428.1

项目的配置为调试64位

编译器选项(省略/I和/D)是:/GS/TP/W3/Zc:wchar\u t/Zi/Gm-/Od/Ob0/Fd“ModelTest.dir\Debug\vc141.pdb”/Zc:inline/fp:precise/D“WIN32”/D“\u WINDOWS”/D“\u UNICODE”/D“CMAKE\u INTDIR=”Debug\”/D“UNICODE”/errorReport:prompt/WX-/Zc:forScope/RTC1/GR/Gd/MDd/FC/Fa”Debug//EHsc/nologo/Fo“test.dir\model调试”/Fp“ModelTest.dir\Debug\ModelTest.pch”/diagnostics:classic


项目(.sln和.vcxproj)由cmake-3.11.2-win64-x64生成。

似乎是VS 15.7.2(19.14)x64中的编译器错误

没有足够的浮点寄存器来执行所有计算。 旧版本(v140)将xmm14卸载到堆栈上。但是vc141溢出到xmm0,xmm0恰好包含第16个参数的值

比较程序集。(适用于):

vc140:

  movss       xmm1,dword ptr [rdx+rax]  
  mulss       xmm1,dword ptr [r8+rcx]  
  addss       xmm0,xmm1  
. . .
  movss       dword ptr [rsp+1A8h],xmm14  < save xmm14
. . .
  movss       xmm15,dword ptr [rdx+rax]  
  mulss       xmm15,dword ptr [r8+rcx]  
  addss       xmm14,xmm15
  movss       dword ptr [rsp+80h],xmm0  < push xmm0
movss xmm1,dword ptr[rdx+rax]
mulss xmm1,dword ptr[r8+rcx]
地址xmm0,xmm1
. . .
movss dword ptr[rsp+1A8h],xmm14<保存xmm14
. . .
movss xmm15,dword ptr[rdx+rax]
mulss xmm15,dword ptr[r8+rcx]
地址:xmm14,xmm15
movss dword ptr[rsp+80h],xmm0
vc141:

  movss       xmm1,dword ptr [rdx+rax]  
  mulss       xmm1,dword ptr [r8+rcx]  
  addss       xmm0,xmm1  
. . .
. . .
  movss       xmm0,dword ptr [rdx+rax]  < overwrites xmm0  
  mulss       xmm0,dword ptr [r8+rcx]  
  addss       xmm15,xmm0  
  movss       dword ptr [rsp+80h],xmm0  < push xmm0
movss xmm1,dword ptr[rdx+rax]
mulss xmm1,dword ptr[r8+rcx]
地址xmm0,xmm1
. . .
. . .
movss xmm0,dword ptr[rdx+rax]<覆盖xmm0
mulss xmm0,dword ptr[r8+rcx]
地址:xmm15,xmm0
movss dword ptr[rsp+80h],xmm0

作为一种解决方法,您可以单独计算最后一个参数并将其存储在临时文件中。

如果您提供的代码不能产生问题,那么问题一定是您没有提供的代码。似乎您在其他地方有未定义的行为,所有这些代码都与确定实际问题无关。我的VS2017编译器版本是Microsoft(R)C/C++优化编译器版本19.14.26428.1 for x86Still。。。这只是基础数学。没什么特别的,连限定矩阵乘法都太强了。优化器可以做一些技巧,但如果您正在调试,那就不太可能了。可能是您的cpp文件中有其他内容导致了这种行为。顺便说一句,在发布版本中没有它,您如何编译?在我的项目中,我只是从main()调用testMatrix()并返回.Hmm。。。如果这是正确的,我的这只是基本的数学不是真的合适…如果这是真的,这可能是另一个副作用的32寄存器支持AVX512错误。他们补充说,在15.7版本中,出现了大量问题,从错误编译到ICEs。
  movss       xmm1,dword ptr [rdx+rax]  
  mulss       xmm1,dword ptr [r8+rcx]  
  addss       xmm0,xmm1  
. . .
. . .
  movss       xmm0,dword ptr [rdx+rax]  < overwrites xmm0  
  mulss       xmm0,dword ptr [r8+rcx]  
  addss       xmm15,xmm0  
  movss       dword ptr [rsp+80h],xmm0  < push xmm0