- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我最近开始使用 ICC (18.0.1.126) 来编译一段代码,该代码可以在任意优化设置上与 GCC 和 Clang 一起正常工作。该代码包含一个汇编例程,该例程使用 AVX2 和 FMA 指令将 4x4 double 矩阵相乘。经过多次调整后发现,汇编器例程在使用 -O1 - xcore-avx2 编译时工作正常,但在使用 -O2 - xcore-avx2 编译时给出错误的数值结果。然而,代码编译时所有优化设置都没有任何错误消息。它在配备 Broadwell Core i5 的 2015 年初 MacBook Air 上运行。
我还有几个版本的 4x4 矩阵乘法例程,最初是为速度测试而编写的,有/没有 FMA,并使用汇编程序/内在函数。这对他们所有人来说都是同样的问题。
我向例程传递一个指向 4x4 double 组第一个元素的指针,该数组创建为 双 MatrixDummy[4][4];并作为 (&MatrixDummy)[0][0]
汇编例程在这里:
//Routine multiplies the 4x4 matrices A * B and store the result in C
inline void RunAssembler_FMA_UnalignedCopy_MultiplyMatrixByMatrix(double *A, double *B, double *C)
{
__asm__ __volatile__ ("vmovupd %0, %%ymm0 \n\t"
"vmovupd %1, %%ymm1 \n\t"
"vmovupd %2, %%ymm2 \n\t"
"vmovupd %3, %%ymm3"
:
:
"m" (B[0]),
"m" (B[4]),
"m" (B[8]),
"m" (B[12])
:
"ymm0", "ymm1", "ymm2", "ymm3");
__asm__ __volatile__ ("vbroadcastsd %1, %%ymm4 \n\t"
"vbroadcastsd %2, %%ymm5 \n\t"
"vbroadcastsd %3, %%ymm6 \n\t"
"vbroadcastsd %4, %%ymm7 \n\t"
"vmulpd %%ymm4, %%ymm0, %%ymm8 \n\t"
"vfmadd231PD %%ymm5, %%ymm1, %%ymm8 \n\t"
"vfmadd231PD %%ymm6, %%ymm2, %%ymm8 \n\t"
"vfmadd231PD %%ymm7, %%ymm3, %%ymm8 \n\t"
"vmovupd %%ymm8, %0"
:
"=m" (C[0])
:
"m" (A[0]),
"m" (A[1]),
"m" (A[2]),
"m" (A[3])
:
"ymm4", "ymm5", "ymm6", "ymm7", "ymm8");
__asm__ __volatile__ ("vbroadcastsd %1, %%ymm4 \n\t"
"vbroadcastsd %2, %%ymm5 \n\t"
"vbroadcastsd %3, %%ymm6 \n\t"
"vbroadcastsd %4, %%ymm7 \n\t"
"vmulpd %%ymm4, %%ymm0, %%ymm8 \n\t"
"vfmadd231PD %%ymm5, %%ymm1, %%ymm8 \n\t"
"vfmadd231PD %%ymm6, %%ymm2, %%ymm8 \n\t"
"vfmadd231PD %%ymm7, %%ymm3, %%ymm8 \n\t"
"vmovupd %%ymm8, %0"
:
"=m" (C[4])
:
"m" (A[4]),
"m" (A[5]),
"m" (A[6]),
"m" (A[7])
:
"ymm4", "ymm5", "ymm6", "ymm7", "ymm8");
__asm__ __volatile__ ("vbroadcastsd %1, %%ymm4 \n\t"
"vbroadcastsd %2, %%ymm5 \n\t"
"vbroadcastsd %3, %%ymm6 \n\t"
"vbroadcastsd %4, %%ymm7 \n\t"
"vmulpd %%ymm4, %%ymm0, %%ymm8 \n\t"
"vfmadd231PD %%ymm5, %%ymm1, %%ymm8 \n\t"
"vfmadd231PD %%ymm6, %%ymm2, %%ymm8 \n\t"
"vfmadd231PD %%ymm7, %%ymm3, %%ymm8 \n\t"
"vmovupd %%ymm8, %0"
:
"=m" (C[8])
:
"m" (A[8]),
"m" (A[9]),
"m" (A[10]),
"m" (A[11])
:
"ymm4", "ymm5", "ymm6", "ymm7", "ymm8");
__asm__ __volatile__ ("vbroadcastsd %1, %%ymm4 \n\t"
"vbroadcastsd %2, %%ymm5 \n\t"
"vbroadcastsd %3, %%ymm6 \n\t"
"vbroadcastsd %4, %%ymm7 \n\t"
"vmulpd %%ymm4, %%ymm0, %%ymm8 \n\t"
"vfmadd231PD %%ymm5, %%ymm1, %%ymm8 \n\t"
"vfmadd231PD %%ymm6, %%ymm2, %%ymm8 \n\t"
"vfmadd231PD %%ymm7, %%ymm3, %%ymm8 \n\t"
"vmovupd %%ymm8, %0"
:
"=m" (C[12])
:
"m" (A[12]),
"m" (A[13]),
"m" (A[14]),
"m" (A[15])
:
"ymm4", "ymm5", "ymm6", "ymm7", "ymm8");
}
作为比较,以下代码应该做完全相同的事情,并且使用所有编译器/优化设置。由于如果我使用此例程而不是汇编例程,一切正常,我希望错误必须出在 ICC 如何使用 -O2 优化处理汇编例程。
inline void Run3ForLoops_MultiplyMatrixByMatrix_OutputTo3(double *A, double *B, double *C){
int i, j, k;
double dummy[4][4];
for(j=0; j<4; j++) {
for(k=0; k<4; k++) {
dummy[j][k] = 0.0;
for(i=0; I<4; i++) {
dummy[j][k] += *(A+j*4+i)*(*(B+i*4+k));
}
}
}
for(j=0; j<4; j++) {
for(k=0; k<4; k++) {
*(C+j*4+k) = dummy[j][k];
}
}
}
有什么想法吗?我真的很困惑。
最佳答案
您的代码的核心问题是假设如果您将一个值写入寄存器,该值仍将存在于下一条语句中。这个假设是错误的。在 asm
语句之间,编译器可以根据需要使用任何寄存器。例如,它可能决定使用 ymm0
在您的语句之间将变量从一个位置复制到另一个位置,从而破坏其先前的内容。
进行内联汇编的正确方法是,如果没有充分的理由,永远不要直接引用寄存器。您希望在汇编语句之间保留的每个值都需要使用适当的操作数放置在变量中。 manual对此很清楚。
例如,让我重写您的代码以使用正确的内联汇编:
#include <immintrin.h>
inline void RunAssembler_FMA_UnalignedCopy_MultiplyMatrixByMatrix(double *A, double *B, double *C)
{
size_t i;
/* the registers you use */
__m256 a0, a1, a2, a3, b0, b1, b2, b3, sum;
__m256 *B256 = (__m256 *)B, *C256 = (__m256 *)C;
/* load values from B */
asm ("vmovupd %1, %0" : "=x"(b0) : "m"(B256[0]));
asm ("vmovupd %1, %0" : "=x"(b1) : "m"(B256[1]));
asm ("vmovupd %1, %0" : "=x"(b2) : "m"(B256[2]));
asm ("vmovupd %1, %0" : "=x"(b3) : "m"(B256[3]));
for (i = 0; i < 4; i++) {
/* load values from A */
asm ("vbroadcastsd %1, %0" : "=x"(a0) : "m"(A[4 * i + 0]));
asm ("vbroadcastsd %1, %0" : "=x"(a1) : "m"(A[4 * i + 1]));
asm ("vbroadcastsd %1, %0" : "=x"(a2) : "m"(A[4 * i + 2]));
asm ("vbroadcastsd %1, %0" : "=x"(a3) : "m"(A[4 * i + 3]));
asm ("vmulpd %2, %1, %0" : "=x"(sum) : "x"(a0), "x"(b0));
asm ("vfmadd231pd %2, %1, %0" : "+x"(sum) : "x"(a1), "x"(b1));
asm ("vfmadd231pd %2, %1, %0" : "+x"(sum) : "x"(a2), "x"(b2));
asm ("vfmadd231pd %2, %1, %0" : "+x"(sum) : "x"(a3), "x"(b3));
asm ("vmovupd %1, %0" : "=m"(C256[i]) : "x"(sum));
}
}
有很多事情你应该立即注意到:
volatile
限定符,编译器可以更好地优化代码不过,您确实应该考虑改用内部函数,因为编译器可以使用内部函数进行比内联汇编更多的优化。这是因为编译器在某种程度上了解内在函数的作用,并可以利用这些知识生成更好的代码。
关于c++ - ICC 中的 -O2 搞乱了汇编程序,ICC 中的 -O1 和 GCC/Clang 中的所有优化都很好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49791664/
我没有 icc已安装,但我需要所有编译器优化标志的列表。我试过谷歌并搜索他们的网站文档,但我找不到任何东西。 我找到了一个列表 all编译器选项,但我只需要优化选项。 最佳答案 此页面列出了 IC 优
我使用的是 ubuntu 14.04。我刚刚下载并安装了英特尔并行工作室 2016。 如果我不是从 icc 文件夹中输入 icc,则会收到错误命令未找到。有没有办法像 gcc 一样设置 icc(在我运
我最近开始使用 ICC (18.0.1.126) 来编译一段代码,该代码可以在任意优化设置上与 GCC 和 Clang 一起正常工作。该代码包含一个汇编例程,该例程使用 AVX2 和 FMA 指令将
我的问题是我想从命令行调用 icc 编译器,但我的电脑找不到它。我已经安装了最新的 oneAPI 并获取了 setvars.sh。 即使我在安装例程下搜索'icc'文件我也找不到icc编译器文件。 '
使用 ICC 编译时,每条指令后面都是 2 个点分隔的数字,并以哈希符号为前缀。这是什么意思? For example: L__routine_start__Z12testFunctionPii_0:
有人可以解释为什么 icc 在下面的代码 1 中没有执行循环不变代码运动(移动 a 的指针赋值)的原因。当 a 指针赋值从代码 2 中完成的 t6 循环中移出时,我看到性能提高了 40%。我尝试将指针
考虑以下代码: template struct Foo { }; template struct Foo> { static void print() { std::cerr s
我在 Visual Studio 2012 中使用 Intel C++ 13.0.1.119 Build 20121008 for IA-32 在 Windows 上运行。我一直遇到链接器错误问题,并
我一直在尝试使用英特尔的四精度 float 。我有以下代码,它返回了意外的结果。 #include #include int print(const char *label, _Quad r) {
我写了一个应用程序,它通过 ImageMagick 修剪和调整一堆图像的大小。图像也被转换为灰度。但是当我尝试在 Photoshop CC 中打开转换后的图像时,会出现以下警告: The embedd
我正在用 icc 编译一个 cpp 代码(在 ubuntu 下): icc -I/usr/share/R/include -I/~/Desktop/work/p1/geqw4/vi3/out/sp/c
首先让我说我是 R 的新手,并试图弄清楚如何在我的特定数据集上运行 icc,这可能与正常情况下有点不同。 数据集如下所示 +------------+------------------+------
我遇到了 icc 问题,到目前为止我还没有找到任何解决方案。我的程序用gcc编译时运行正常,但用icc编译时显然没有执行任何操作。不会发生运行时错误。该程序结束得非常快(几毫秒),但预计需要几秒钟(对
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
在尝试使用 Jasper Reports 生成符合 PDF/A 标准的 PDF 时,我得到了 net.sf.jasperreports.engine.util.JRPdfaIccProfileNotF
因此,当使用基本的icc bob.cpp -o bob 编译并运行时,出现以下代码段错误: #include int foo () { return 6; } int main() { st
现在我正在使用 icc 来编译和运行我的 ANSI C 代码。 当我打开-O2 优化时,一切正常。但是,当我更改为 -fast 时,结果会有所不同(有很多 nan)。 我搜索并尝试,发现错误存在于-x
我想报告一个有趣的错误。下面的这段代码应该打印出 20 次“1.0”。相反,在我的 mac(雪豹 10.6.8)上使用 icc(11.1)编译时,我得到不稳定的值(16 次“0.0”然后 4 次“1.
有没有办法在使用英特尔编译器时改变缓存写入策略。我发现 Intel Core i7 处理器的一级缓存是回写缓存。 我的问题是:是否有任何可能的方法来调整编译器,将缓存策略从回写更改为直写? 最佳答案
我目前在 centos7 上校准显示器时遇到问题。使用 gnome 或 kde,我无法正确使用颜色设置来应用新创建的 ICC 配置文件。设备选项卡未显示列出(仅安装了打印机)。 经过一些阅读,我发现
我是一名优秀的程序员,十分优秀!