参考:http://blog.163.com/chenqneu@126/blog/static/45738484200781493846369/

C++ SSE浮点运算实例(__m128)

实验环境VC++ 8.0
(1)
#include "stdafx.h"
#include "omp.h"
#include <xmmintrin.h>
#include <iostream>
using namespace std;
const int N=120;

int _tmain(int argc, _TCHAR* argv[])
{
    __m128 *p1,*p2,*p3;
    float f1[N],f2[N],f3[N];
    for(int i=0;i<N;i++){
        f1[i]=i+0.12;
        f2[i]=i+0.16;
    };
    p1=(__m128*)f1;
    p2=(__m128*)f2;
    p3=(__m128*)f3;
     for(int i=0;i<N;i+=4){
        *p3=_mm_add_ps(*p1,*p2);
        p3++;
        p2++;
        p1++;
    }
    for(int i=0;i<N;i++)
        cout<<f3[i]<<endl;
    return 0;
}
程序执行时错误,数据读取时异常,发生访问冲突。
(2)
#include "stdafx.h"
#include "omp.h"
#include <xmmintrin.h>
#include <iostream>
using namespace std;
const int N=120;

int _tmain(int argc, _TCHAR* argv[])
{
    __m128 *p1,*p2,*p3;
    __declspec(align(16)) float f1[N],f2[N],f3[N];
    for(int i=0;i<N;i++){
        f1[i]=i+0.12;
        f2[i]=i+0.16;
    };
    p1=(__m128*)f1;
    p2=(__m128*)f2;
    p3=(__m128*)f3;
    for(int i=0;i<N;i+=4){
        *p3=_mm_add_ps(*p1,*p2);
        p3++;
        p2++;
        p1++;
    }
    for(int i=0;i<N;i++)
        cout<<f3[i]<<endl;
    return 0;
}
程序正常运行,并且结果正确,原因是SSE浮点运算要求按16字(128位)对齐,所以 __declspec(align(16)) float f1[N],f2[N],f3[N];便可以了。
(3)
#include "stdafx.h"
#include "omp.h"
#include <xmmintrin.h>
#include <iostream>
using namespace std;
const int N=120;

int _tmain(int argc, _TCHAR* argv[])
{
    __m128 *p1,*p2,*p3;
    __declspec(align(16)) float *pf1,*pf2,*pf3;
    pf1=(__declspec(align(16))float*)_mm_malloc(sizeof(float)*N,16);
    pf2=(__declspec(align(16))float*)_mm_malloc(sizeof(float)*N,16);
    pf3=(__declspec(align(16))float*)_mm_malloc(sizeof(float)*N,16);
    for(int i=0;i<N;i++){
        pf1[i]=i+0.12;
        pf2[i]=i+0.16;
    };
    p1=(__m128*)pf1;
    p2=(__m128*)pf2;
    p3=(__m128*)pf3;
    for(int i=0;i<N;i+=4){
        *p3=_mm_add_ps(*p1,*p2);
        p3++;
        p2++;
        p1++;
    }
    for(int i=0;i<N;i++)
        cout<<pf3[i]<<endl;
    _mm_free(pf1);
    _mm_free(pf2);
    _mm_free(pf3);
    return 0;
}
这个程序也是正确的,通过动态分配内存来实现,_mm_malloc(sizeof,16)和_mm_free()。
注意:下面的动态内存申请方法是有问题的:
pf1=(__declspec(align(16))(float*))_mm_malloc(sizeof(float)*N,16);
提示:error C2440: “=”: 无法从“int (__cdecl *)(float *)”转换为“float *”
pf1=(__declspec(align(16)))(float*)_mm_malloc(sizeof(float)*N,16);
提示:error C2440: “=”: 无法从“int”转换为“float *”
(4)
#include "stdafx.h"
#include "omp.h"
#include <xmmintrin.h>
#include <iostream>
using namespace std;
const int N=120;

int _tmain(int argc, _TCHAR* argv[])
{
    __m128 m1,m2,m3;
    __declspec(align(16)) float *pf1,*pf2,*pf3;
    pf1=(__declspec(align(16))float*)_mm_malloc(sizeof(float)*N,16);
    pf2=(__declspec(align(16))float*)_mm_malloc(sizeof(float)*N,16);
    pf3=(__declspec(align(16))float*)_mm_malloc(sizeof(float)*N,16);
    for(int i=0;i<N;i++){
        pf1[i]=i+0.12;
        pf2[i]=i+0.16;
    };
    for(int i=0;i<N;i+=4){
        m1=_mm_load_ps(pf1+i);
        m2=_mm_load_ps(pf2+i);
        m3=_mm_add_ps(m1,m2);
        _mm_store_ps(pf3+i,m3);
    }
    for(int i=0;i<N;i++)
        cout<<pf3[i]<<endl;
    _mm_free(pf1);
    _mm_free(pf2);
    _mm_free(pf3);
    return 0;
}
使用_mm_load_ps(float *)和_mm_store_ps(float *,__m128)也可以用来直接加载和保存4组浮点数,替换__m128*来进行数据引用。当然,这里仍旧要求浮点数组是按16字对齐的。
(5)
#include "stdafx.h"
#include "omp.h"
#include <xmmintrin.h>
#include <iostream>
using namespace std;
const int N=120;

int _tmain(int argc, _TCHAR* argv[])
{
    __m128 m1,m2,m3;
    __declspec(align(16)) float *pf1,*pf2,*pf3;
    pf1=(float*)malloc(sizeof(float)*N);
    pf2=(float*)malloc(sizeof(float)*N);
    pf3=(float*)malloc(sizeof(float)*N);
    for(int i=0;i<N;i++){
        pf1[i]=i+0.12;
        pf2[i]=i+0.16;
    };
    for(int i=0;i<N;i+=4){
        m1=_mm_load_ps(pf1+i);
        m2=_mm_load_ps(pf2+i);
        m3=_mm_add_ps(m1,m2);
        _mm_store_ps(pf3+i,m3);
    }
    for(int i=0;i<N;i++)
        cout<<pf3[i]<<endl;
    free(pf1);
    free(pf2);
    free(pf3);
    return 0;
}
这里的程序就会出现运行时内存访问错误,原因就是浮点数组没有16字对齐时,不能用_mm_load_ps()和_mm_store_ps(),而是需要用 _mm_loadu_ps,_mm_storeu_ps()来处理,不过因为没对齐,所以处理速度会慢一些。
(6)
#include "stdafx.h"
#include "omp.h"
#include <xmmintrin.h>
#include <iostream>
using namespace std;
const int N=120;

int _tmain(int argc, _TCHAR* argv[])
{
    __m128 m1,m2,m3;
    __declspec(align(16)) float *pf1,*pf2,*pf3;
    pf1=(float*)malloc(sizeof(float)*N);
    pf2=(float*)malloc(sizeof(float)*N);
    pf3=(float*)malloc(sizeof(float)*N);
    for(int i=0;i<N;i++){
        pf1[i]=i+0.12;
        pf2[i]=i+0.16;
    };
    for(int i=0;i<N;i+=4){
        m1=_mm_loadu_ps(pf1+i);
        m2=_mm_loadu_ps(pf2+i);
        m3=_mm_add_ps(m1,m2);
        _mm_storeu_ps(pf3+i,m3);
    }
    for(int i=0;i<N;i++)
        cout<<dec<<pf3[i]<<endl;
    free(pf1);
    free(pf2);
    free(pf3);
    return 0;

}


下面是几个简单的例子: 
float sumfloat_sse(const float* pbuf, size_t cntbuf)
{    float s = 0;    // 求和变量.
    size_t i;
    size_t nBlockWidth = 4; // 块宽. SSE寄存器能一次处理4个float.
    size_t cntBlock = cntbuf / nBlockWidth; // 块数.
    size_t cntRem = cntbuf % nBlockWidth;   // 剩余数量.
    __m128 xfsSum = _mm_setzero_ps();   // 求和变量。[SSE] 赋初值0
    __m128 xfsLoad; // 加载.
    const float* p = pbuf;  // SSE批量处理时所用的指针.
    const float* q; // 将SSE变量上的多个数值合并时所用指针.
    // SSE批量处理.
    for(i=0; i<cntBlock; ++i)
    {        xfsLoad = _mm_load_ps(p);   // [SSE] 加载
        xfsSum = _mm_add_ps(xfsSum, xfsLoad);   // [SSE] 单精浮点紧缩加法
        p += nBlockWidth;
    }
    // 合并.
    q = (const float*)&xfsSum;
    s = q[0] + q[1] + q[2] + q[3];
    // 处理剩下的.
    for(i=0; i<cntRem; ++i)
    {        s += p[i];
    }
    return s;
}
int main(){float norm=0.5f,S=0.25,M=0.8f;
float *a;
  *a=2.0f;
float* res=new float[4];
__m128 _res;
const __m128 _s=sse::SET(S);
const __m128 _m=sse::SET(M);
//乘法
_res= sse::MUL(*a,_m);
//    float *res2=(float *)_In;
 memcpy(res,&_res,16);
 printf("res:%.9f,%.9f,%.9f\n",res[0],res[1],res[2]);
 //开平方的导数
_res=sse::RCPSQRT(_s);
memcpy(res,&_res,16);
printf("RCPSQRT:%.9f,%.9f,%.9f\n",res[0],res[1],res[2]);
//除法
_res=sse::RCP(_s);//开平方的导数
memcpy(res,&_res,16);
printf("RCP:%.9f,%.9f,%.9f\n",res[0],res[1],res[2]);
        float *f;
        int  n=10; // 数组的位数
        f = new float[n];
        for(int i=0;i<n;i++)
        f[i] = i;

        //    for(int i=0;i<n;i++)  cout << f[i] << "  ";

        float  aaa=  sumfloat_sse(f,n);
        printf("result:%f",aaa);
        delete [] f;

C++ SSE运算例子相关推荐

  1. matlab运算例子,MATLAB基本数学运算例子:

    基本数学运算例子: 55+4 ans= 59 100/2 ans= 50 100\2 ans= 0.02 sin(90) ans= 0.8940 sin(pi/2) ans= 1.000 abs(-1 ...

  2. SSE 加速运算例子详解:乘法、加法、平方、最小值、最大值、与操作

    SSE(Streaming SIMD Extensions)是英特尔在AMD的3D Now!发布一年之后,在其计算机芯片Pentium III中引入的指令集,是MMX的超集.AMD后来在Athlon ...

  3. c语音异或运算符_c语言异或(c语言异或运算例子)

    用异或算法逐字节对文件C进行加密,输出到另外一个新文件D中. #include #include int main(){ FILE *p1,*p2; char ch,n; p1=fopen("D:\\ ...

  4. tensorflow中转置卷积运算例子

    import tensorflow as tf import numpy as np import tensorflow as keras from tensorflow.keras import l ...

  5. c++单精度和双精度的运算例子(计算机占位存储)

    计算机中float, double类型数据分别占据4,8个字节,其中float类型和double可以表示的小数位数不同,导致了精度不同.double的精度更高. 计算机中数据的表示由:符号位, 指数位 ...

  6. java Flink滚动时间窗口聚合TumblingProcessingTimeWindows运算例子

    整个的思路是: 构造数据源 窗口聚合代码 1. 构造数据源 首先构造数据,新建一个MyData2.java的文件,写入这个MyData2的类 package create_data;import ja ...

  7. SSE2 Intrinsics各函数介绍 及简单例子

    转载地址 http://blog.csdn.net/fengbingchun/article/details/18460199 关于ARM上的SIMD可以参见网址,ARM上的SIMD技术叫NEON: ...

  8. c/c++ 代码中使用sse指令集加速

    使用SSE指令,首先要了解这一类用于进行初始化加载数据以及将暂存器的数据保存到内存相关的指令, 我们知道,大多数SSE指令是使用的xmm0到xmm8的暂存器,那么使用之前,就需要将数据从内存加载到这些 ...

  9. java加减乘除运算代码_从“位运算”炫技到“操作符”,再到逐步理解“群论”...

    由位运算到操作符,再到逐步理解群论 Step by Step for Understanding from Bitwise to Operators, then Group Theory 是否曾经会有 ...

最新文章

  1. TensorFlow实战笔记(17)---TFlearn
  2. 石墨烯新新新应用,MIT大规模生产细胞大小机器人,有感知能存储
  3. spark-streaming问题集锦
  4. Qt Creator连接MCU
  5. C语言中return的各种用法
  6. SP703 SERVICE - Mobile Service[DP]
  7. 转: Linux下单网卡多vlan多虚拟机
  8. java类对象的内部结构图解(java对象模型精讲)
  9. Ubuntu下解决文件名mp3标签和文本文件内容的乱码问题
  10. eclipse启动时return code 13
  11. Android ssl 异常,SSL握手异常,同时通过https连接使用Android中的自签名证书Nougat
  12. 经典网页三剑客html、css 和 JavaScript实现的导航网页
  13. Linux系统管理(一)基础管理
  14. 数学--计算几何--三角定位原理和升级
  15. 微信小程序入门案例-会议邀请函
  16. 如何关闭Internet Explorer 增强的安全配置
  17. 计算机专业eng4u,加拿大高中文凭ossd项目之ENG4U英语4U课程内容介绍!
  18. AUPRC Vs 平均查准率
  19. char[4]转int或int转char
  20. 【计算机视觉】OPENCV对于有alpha通道的透明背景图片的读取和图片叠加

热门文章

  1. Miscellaneous Character Drivers
  2. java语言中声明布尔型_【Java初探02】——Java语言基础
  3. java nio doug_Java NIO简介
  4. lambdas_借助Java 8和lambdas,可以一起使用AssertJ和Awaitility
  5. php 教程 字符联接,PHP字符串的连接_PHP教程
  6. 文章 图片 PHP保存,关于文章图片储存
  7. 简述mysql的概念及作用_数据库 简答题
  8. bool变量取反_Task 01:Python基础入门:从变量到异常处理(第1天)
  9. 没被同事卷死,被司机卷死了...
  10. JAVA写出来的塔防能有多好玩?......真香!