Gcc 基准测试SSE指令
我正在对一些代码(4个浮点乘以4个浮点)进行基准测试,而传统的C代码也在做同样的事情。我认为我的基准代码在某种程度上肯定是不正确的,因为它似乎说非苏格兰和南方能源公司代码比苏格兰和南方能源公司代码快2-3倍 有人能告诉我下面的基准代码有什么问题吗?或许可以提出另一种方法,准确显示SSE和非SSE代码的速度Gcc 基准测试SSE指令,gcc,assembly,benchmarking,sse,Gcc,Assembly,Benchmarking,Sse,我正在对一些代码(4个浮点乘以4个浮点)进行基准测试,而传统的C代码也在做同样的事情。我认为我的基准代码在某种程度上肯定是不正确的,因为它似乎说非苏格兰和南方能源公司代码比苏格兰和南方能源公司代码快2-3倍 有人能告诉我下面的基准代码有什么问题吗?或许可以提出另一种方法,准确显示SSE和非SSE代码的速度 #include <time.h> #include <string.h> #include <stdio.h> #define ITERATIONS 1
#include <time.h>
#include <string.h>
#include <stdio.h>
#define ITERATIONS 100000
#define MULT_FLOAT4(X, Y) ({ \
asm volatile ( \
"movaps (%0), %%xmm0\n\t" \
"mulps (%1), %%xmm0\n\t" \
"movaps %%xmm0, (%1)" \
:: "r" (X), "r" (Y)); })
int main(void)
{
int i, j;
float a[4] __attribute__((aligned(16))) = { 10, 20, 30, 40 };
time_t timer, sse_time, std_time;
timer = time(NULL);
for(j = 0; j < 5000; ++j)
for(i = 0; i < ITERATIONS; ++i) {
float b[4] __attribute__((aligned(16))) = { 0.1, 0.1, 0.1, 0.1 };
MULT_FLOAT4(a, b);
}
sse_time = time(NULL) - timer;
timer = time(NULL);
for(j = 0; j < 5000; ++j)
for(i = 0; i < ITERATIONS; ++i) {
float b[4] __attribute__((aligned(16))) = { 0.1, 0.1, 0.1, 0.1 };
b[0] *= a[0];
b[1] *= a[1];
b[2] *= a[2];
b[3] *= a[3];
}
std_time = time(NULL) - timer;
printf("sse_time %d\nstd_time %d\n", sse_time, std_time);
return 0;
}
#包括
#包括
#包括
#定义迭代次数100000次
#定义MULT_FLOAT4(X,Y)({\
挥发性物质(\
movaps(%0),%%xmm0\n\t\
mulps(%1),%%xmm0\n\t\
movaps%%xmm0,(%1)\
:“r”(X),“r”(Y));})
内部主(空)
{
int i,j;
浮动[4]uuu属性uuu((对齐(16))={10,20,30,40};
时间计时器、sse时间、标准时间;
计时器=时间(空);
对于(j=0;j<5000;++j)
对于(i=0;i
当您启用优化时,非SSE代码将被完全消除,而SSE代码仍保留在那里,因此这种情况很简单。更有趣的是当优化关闭时:在这种情况下,SSE代码仍然较慢,而循环的代码是相同的
最内层循环体的非SSE代码:
movl $0x3dcccccd, %eax
movl %eax, -80(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -76(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -72(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -68(%rbp)
movss -80(%rbp), %xmm1
movss -48(%rbp), %xmm0
mulss %xmm1, %xmm0
movss %xmm0, -80(%rbp)
movss -76(%rbp), %xmm1
movss -44(%rbp), %xmm0
mulss %xmm1, %xmm0
movss %xmm0, -76(%rbp)
movss -72(%rbp), %xmm1
movss -40(%rbp), %xmm0
mulss %xmm1, %xmm0
movss %xmm0, -72(%rbp)
movss -68(%rbp), %xmm1
movss -36(%rbp), %xmm0
mulss %xmm1, %xmm0
movss %xmm0, -68(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -64(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -60(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -56(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -52(%rbp)
leaq -48(%rbp), %rax
leaq -64(%rbp), %rdx
movaps (%rax), %xmm0
mulps (%rdx), %xmm0
movaps %xmm0, (%rdx)
最内层循环体的SSE代码:
movl $0x3dcccccd, %eax
movl %eax, -80(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -76(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -72(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -68(%rbp)
movss -80(%rbp), %xmm1
movss -48(%rbp), %xmm0
mulss %xmm1, %xmm0
movss %xmm0, -80(%rbp)
movss -76(%rbp), %xmm1
movss -44(%rbp), %xmm0
mulss %xmm1, %xmm0
movss %xmm0, -76(%rbp)
movss -72(%rbp), %xmm1
movss -40(%rbp), %xmm0
mulss %xmm1, %xmm0
movss %xmm0, -72(%rbp)
movss -68(%rbp), %xmm1
movss -36(%rbp), %xmm0
mulss %xmm1, %xmm0
movss %xmm0, -68(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -64(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -60(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -56(%rbp)
movl $0x3dcccccd, %eax
movl %eax, -52(%rbp)
leaq -48(%rbp), %rax
leaq -64(%rbp), %rdx
movaps (%rax), %xmm0
mulps (%rdx), %xmm0
movaps %xmm0, (%rdx)
我对此不确定,但我猜:
如您所见,编译器仅通过4个32位存储来存储4个浮点值。然后通过16字节的加载将其读回。这会导致商店转发暂停,发生这种情况时成本高昂。您可以在英特尔手册中查找。标量版本中不会出现这种情况,这会导致性能差异
为了加快速度,您需要确保不会发生此暂停。如果使用4个浮点的常量数组,则将其设为常量,并将结果存储在另一个对齐的数组中。这样,编译器希望不会在加载之前生成那些不必要的4字节MOV。或者,如果需要填充生成的数组,请使用16字节的store命令。如果您无法避免这些4字节MOV,则需要在存储之后但在加载之前执行其他操作(例如计算其他操作)。谢谢您的回答。:)然而,我真的需要一个非常快的4浮点乘法器使用SSE进行图像处理。如果我使用的方法存在某种缺陷,你能否建议另一种方法,利用苏格兰和南方能源公司的力量,但不会导致这种减速。我读到SSE实际上是为我心目中的那种图像处理而设计的,所以肯定有一种方法可以做到我想要的?(我需要fast 4float乘法器来进行alpha混合等操作)谢谢,我会查找“商店转发摊”,并尝试了解这里发生的事情给你: