我试图在i7上以最有效的方式计算浮点数和位向量之间的点积。实际上,我正在对128或256维向量执行此操作,但为了说明起见,让我编写64维的代码来说明问题:
// a has 64 elements. b is a bitvector of 64 dimensions.
float dot(float *restrict a, uint64_t b) {
float sum = 0;
for(int i=0; b && i<64; i++, b>>=1) {
if (b & 1) sum += a[i];
}
return sum;
}
这当然是有效的,但问题是,这是整个程序的时间关键点(消耗了50分钟运行的95%的CPU时间),所以我迫切需要让它更快。
我的猜测是上面的分支是游戏杀手(防止无序执行,导致错误的分支预测)。我不确定向量指令是否可以在这里使用和帮助。使用带有-std=c99 -march=native -mtune=native -Ofast -funroll-loops的gcc 4.8,我目前得到以下输出
movl $4660, %edx
movl $5, %ecx
xorps %xmm0, %xmm0
.p2align 4,,10
.p2align 3
.L4:
testb $1, %cl
je .L2
addss (%rdx), %xmm0
.L2:
leaq 4(%rdx), %rax
shrq %rcx
testb $1, %cl
je .L8
addss 4(%rdx), %xmm0
.L8:
shrq %rcx
testb $1, %cl
je .L9
addss 4(%rax), %xmm0
.L9:
shrq %rcx
testb $1, %cl
je .L10
addss 8(%rax), %xmm0
.L10:
shrq %rcx
testb $1, %cl
je .L11
addss 12(%rax), %xmm0
.L11:
shrq %rcx
testb $1, %cl
je .L12
addss 16(%rax), %xmm0
.L12:
shrq %rcx
testb $1, %cl
je .L13
addss 20(%rax), %xmm0
.L13:
shrq %rcx
testb $1, %cl
je .L14
addss 24(%rax), %xmm0
.L14:
leaq 28(%rax), %rdx
shrq %rcx
cmpq $4916, %rdx
jne .L4
ret
编辑可以对数据进行置换(只要所有参数的置换都是相同的),顺序并不重要。
我想知道有没有什么东西可以比Chris Dodd的SSE2代码快3倍以上。
新注释: AVX/AVX2代码也是受欢迎的!
编辑2给定一个位向量,我必须将它与128 (或256位,如果是256位)不同的浮点向量相乘(所以一次涉及多个浮点向量也是可以的)。这就是整个过程。任何可以加速整个过程的东西都是受欢迎的!
https://stackoverflow.com/questions/16051365
复制相似问题