簡體   English   中英

什么VS2017 C ++編譯器選項可以影響矩陣乘法?

[英]What VS2017 C++ compiler option can affect matrices multiplication?

以下代碼將兩個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;

顯然,生產中的元素15是1.0f,在Release配置中它是1.0f,但是在我的項目的Debug配置中,我得到0.0f

我嘗試通過使用命令行編譯單個.cpp文件以及我項目中的編譯器選項來重現這一點:

cl /GS /TP /W3 /Zc:wchar_t /Zi /Gm- /Od /Ob0 /Zc:inline /fp:precise /errorReport:prompt /WX- /Zc:forScope /RTC1 /GR /Gd /MDd /FC /EHsc /nologo /diagnostics:classic MatrixTest.cpp

但這輸出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,編譯器版本為:Microsoft(R)C / C ++優化編譯器版本19.14.26428.1 for x86

Debug項目的配置是Debug 64bit。

編譯器選項(省略/ I和/ D)是:/ GS / TP / W3 / Zc:wchar_t / Zi / Gm- / Od / Ob0 /Fd"ModelTest.dir\\Debug\\vc141.pdb“/ Zc:inline / fp:precise / D“WIN32”/ D“_WINDOWS”/ D“_UNICODE”/ D“CMAKE_INTDIR = \\”Debug \\“”/ D“UNICODE”/ errorReport:prompt / WX- / Zc:forScope / RTC1 / GR / Gd / MDd / FC / Fa“Debug /”/ EHsc / nologo / Fo“ModelTest.dir \\ Debug \\”/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,它恰好包含第16個參數的值。

比較vc140與vc141程序集。 (對於source.cpp ):

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

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

作為一種變通方法,您可以單獨計算最后一個參數並存儲在臨時參數中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM