c++高性能编程(SIMD矢量化)

HW04

作业地址
个人作业主页

作业描述

加速程序

思路

对step()加速。首先改写成SOA结构,并用std::array替换std::vector

constexpr size_t N = 48
using ArrF = std::array<float, N>;

struct Star {
    ArrF px, py, pz; 
    ArrF vx, vy, vz;
    ArrF mass;
};

Star stars;

提取运算中不变量,提前计算出结果。除法用乘法代替。然后为了方便编译器优化,把复杂的循环体拆成多个执行简单计算的循环体。
为了减小访问内存的开销,用临时变量记录累加值。
数组访问全部改为size_t类型。

void step() {
	ArrF dx, dy, dz, d2;
    for (size_t i = 0; i < N; ++i) {
        for (size_t j = 0; j < N; ++j) {
            dx[j] = stars.px[j] - stars.px[i];
            dx[j] *= dx[j];
        }
        for (size_t j = 0; j < N; ++j) {
            dy[j] = stars.py[j] - stars.py[i];            
            dy[j] *= dy[j];
        }
        for (size_t j = 0; j < N; ++j) {
            dz[j] = stars.pz[j] - stars.pz[i];            
            dz[j] *= dz[j];
        }
        for (size_t j = 0; j < N; ++j) {
            d2[j] = dx[j] + dy[j] + dz[j] + eps * eps;
            d2[j] *= std::sqrt(d2[j]);
            d2[j] = 1 / d2[j];
        }
        
        float vx = 0, vy = 0, vz = 0; 
        float fac = stars.mass[i] * G_dt;
        for (size_t j = 0; j < N; ++j) {
            vx += dx[j] * d2[j] * fac; 
            vy += dy[j] * d2[j] * fac;
            vz += dz[j] * d2[j] * fac;        
        }

        stars.vx[i] += vx;
        stars.vy[i] += vy;
        stars.vz[i] += vz;
    } 
    
    for (size_t i = 0; i < N; ++i) {
        stars.px[i] += stars.vx[i] * dt;
    }
    
    for (size_t i = 0; i < N; ++i) {
        stars.py[i] += stars.vy[i] * dt;
    }
    
    for (size_t i = 0; i < N; ++i) {
        stars.pz[i] += stars.vz[i] * dt;
    }
}

经过测试利用#pragma GCC unroll进行循环展开并不会带来性能上的提升。
有可能是指令本身已经比较 多导致的。
CMakeLists.txt中开启O3优化set(CMAKE_BUILD_TYPE Release)同时设置-ffast-mathtarget_compile_options(main PUBLIC -ffast-math -march=native)优化中最重要的两项:SOA和-ffast-math,可以分开测试单独改变其中某一项多带来的加速比。
对于是否需要把复杂的循环语句进行拆解,其实是不一定的,我看到了别人的作业中,只是单纯的利用临时变量来代替循环中的内存访问,也带来了很好的加速,至于原理我也不是很清楚。
下面是结果对比:
源程序:
在这里插入图片描述
加速后:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值