[英]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.