学习MIPP

链接:https://github.com/aff3ct/MIPP

1、 在VS中启用指令集如图所示;

指令集为SSE、SSE2时mipp::N<float>()等于1;指令集为AVX、AVX2时mipp::N<float>()等于8;这里我用的VS2019启用AVX512时会编译失败。

2、这里采用的指令集是AVX2,一个寄存器有256位,每个寄存器的元素数量根据保存的数据类型决定,比如mipp::N<float>等于8,float为32位,则寄存器mipp::Reg<float>可以存8个float数据;mipp::N<double>等于4,double为64位,寄存器mipp::Reg<double>只能存4个double数据。

因为调试时只能看到m256_f32类型为32位的float,采用double类型输出结果时实则两个元素float合为一个真正的double元素。

    int f = mipp::N<float>() * 2;
    std::vector<float> myVectorF(f);
    myVectorF[0] = 555.44;
    myVectorF[7] = 555.55;
    myVectorF[8] = 555.66;
    myVectorF[12] = 555.77;
    mipp::Reg<float> r1 = &myVectorF[0 * mipp::N<float>()];
    mipp::Reg<float> r2 = &myVectorF[1 * mipp::N<float>()];
    mipp::Reg<float> rout0;
    rout0 = r1 + r2;//8个float类型的数据正常需要8个时钟周期,这里向量相加只需要1个时钟周期,
    rout0.store(&myVectorF[(1) * mipp::N<float>()]);//将值保存到myVectorF的8-16位置上

    int db = mipp::N<double>() * 2;
    std::vector<double> myVectorD(db);
    myVectorD[0] = 0.33;
    myVectorD[3] = 1.44;
    myVectorD[4] = 2.55;
    mipp::Reg<double> r3 = &myVectorD[0 * mipp::N<double>()];
    mipp::Reg<double> r4 = &myVectorD[1 * mipp::N<double>()];
    mipp::Reg<double> rout1;
    rout1 = r3 + r4;
    rout1.store(&myVectorD[(0) * mipp::N<double>()]);

3、for循环计算时采用向量化计算的经典用法。

    vector<float> in1{0,1,2,3,4,5,6,7,8,9};
    vector<float> in2{1,2,3,4,5,6,7,8,9,0};
    vector<float> out(10,0);
    int n = in1.size();
    auto vecLoopSize = (n / mipp::N<float>()) * mipp::N<float>();
    mipp::Reg<float> rout, rin1, rin2;
    for (int i = 0; i < vecLoopSize; i += mipp::N<float>()) {
        rin1.load(&in1[i]); // Unaligned load by default (use the -DMIPP_ALIGNED_LOADS
        rin2.load(&in2[i]); // macro definition to force aligned loads and stores).
        rout = rin1 * 0.75f * mipp::exp(rin2);
        rout.store(&out[i]);
    }
    for (int i = vecLoopSize; i < n; i++) {
        out[i] = 0.75f * in1[i] * std::exp(in2[i]);
    }

 

Guess you like

Origin blog.csdn.net/Stone_Wang_MZ/article/details/108521223