gpt4 book ai didi

c++ - fnaf奇怪的表现

转载 作者:太空狗 更新时间:2023-10-29 11:46:12 25 4
gpt4 key购买 nike

与使用 *+ 相比,使用 fmaf 函数时我遇到了巨大的性能下降。我在两台 Linux 机器上使用 g++ 4.4.3 和 g++ 4.6.3

在两台不同的机器上,如果不使用 fmaf 填充 myOut vector ,则以下代码运行得更快。

带有 g++ 4.6.3 和 Intel(R) Xeon(R) CPU E5-2650 @ 2.00GHz 的服务器

$ ./a.out fmaf
Time: 1.55008 seconds.
$ ./a.out muladd
Time: 0.403018 seconds.

带有 g++ 4.4.3 和 Intel(R) Xeon(R) CPU X5650 @ 2.67GHz 的服务器

$ ./a.out fmaf
Time: 0.547544 seconds.
$ ./a.out muladd
Time: 0.34955 seconds.

fmaf 版本(除了避免额外的汇总然后更精确)不应该更快吗?

#include <stddef.h>
#include <iostream>
#include <math.h>
#include <string.h>
#include <stdlib.h>

#include <sys/time.h>

int main(int argc, char** argv) {
if (argc != 2) {
std::cout << "missing parameter: 'muladd' or 'fmaf'"
<< std::endl;
exit(-1);
}
struct timeval start,stop,result;
const size_t mySize = 1e6*100;

float* myA = new float[mySize];
float* myB = new float[mySize];
float* myC = new float[mySize];
float* myOut = new float[mySize];

gettimeofday(&start,NULL);
if (!strcmp(argv[1], "muladd")) {
for (size_t i = 0; i < mySize; ++i) {
myOut[i] = myA[i]*myB[i]+myC[i];
}
} else if (!strcmp(argv[1], "fmaf")) {
for (size_t i = 0; i < mySize; ++i) {
myOut[i] = fmaf(myA[i], myB[i], myC[i]);
}
} else {
std::cout << "specify 'muladd' or 'fmaf'" << std::endl;
exit(-1);
}

gettimeofday(&stop,NULL);
timersub(&stop,&start,&result);
std::cout << "Time: " << result.tv_sec + result.tv_usec/1000.0/1000.0
<< " seconds." << std::endl;

delete []myA;
delete []myB;
delete []myC;
delete []myOut;
}

最佳答案

您问题的答案称为向量化。当使用 g++ -O3 -S 编译时,比较 g++ 4.4.6 为您的代码的两个部分生成的汇编代码:

muladd 部分:

.L10:
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
movlps (%rbx,%rax), %xmm0
movlps (%r12,%rax), %xmm1
movhps 8(%rbx,%rax), %xmm0
movhps 8(%r12,%rax), %xmm1
mulps %xmm1, %xmm0
movaps %xmm2, %xmm1
movlps 0(%rbp,%rax), %xmm1
movhps 8(%rbp,%rax), %xmm1
addps %xmm1, %xmm0
movaps %xmm0, 0(%r13,%rax)
addq $16, %rax
cmpq $400000000, %rax
jne .L10

所有这些 *ps 都对压缩单精度 数字执行操作。这些是 SSE 指令,因此每个包由每个数组的 4 个连续元素组成。

实现 fmaf 版本的循环是:

.L14:
movss (%rbx,%r14,4), %xmm0
movss 0(%rbp,%r14,4), %xmm2
movss (%r12,%r14,4), %xmm1
call fmaf
movss %xmm0, 0(%r13,%r14,4)
addq $1, %r14
cmpq $100000000, %r14
jne .L14

此处标量 SSE 指令用于一次将数据移动一个数组元素并且在每次迭代时调用 fmaf 函数。

循环的 vector 部分更长,但执行的迭代次数减少了 4 倍。

关于c++ - fnaf奇怪的表现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12977128/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com