当前位置: 首页 > wzjs >正文

网站月流量什么意思想要网站推广页

网站月流量什么意思,想要网站推广页,网页制作教程课程报告,58商机创业网高精度矢量内积计算方法 (单精度浮点, 超长矢量) 对于单精度浮点类型的超长矢量(超过1亿元素)内积计算,累加误差确实是一个重要问题。以下是几种减少误差的方法: 1. Kahan求和算法 这是最常用的补偿求和算法,可以有效减少累加误差&#xf…

高精度矢量内积计算方法 (单精度浮点, 超长矢量)

对于单精度浮点类型的超长矢量(超过1亿元素)内积计算,累加误差确实是一个重要问题。以下是几种减少误差的方法:

1. Kahan求和算法

这是最常用的补偿求和算法,可以有效减少累加误差:

float kahan_dot_product(const float* a, const float* b, size_t n) {float sum = 0.0f;float c = 0.0f; // 补偿变量for (size_t i = 0; i < n; i++) {float product = a[i] * b[i];float y = product - c;float t = sum + y;c = (t - sum) - y;sum = t;}return sum;
}

2. 成对求和 (Pairwise Summation)

将求和过程组织为二叉树形式,减少大数吃小数的机会:

float pairwise_dot(const float* a, const float* b, size_t start, size_t end) {if (end - start <= 128) { // 基础块大小可调整float sum = 0.0f;for (size_t i = start; i < end; i++) {sum += a[i] * b[i];}return sum;}size_t mid = start + (end - start) / 2;float left = pairwise_dot(a, b, start, mid);float right = pairwise_dot(a, b, mid, end);return left + right;
}

3. 多精度累加器

使用双精度或更高精度累加器:

float high_precision_dot(const float* a, const float* b, size_t n) {double sum = 0.0;for (size_t i = 0; i < n; i++) {sum += (double)a[i] * (double)b[i];}return (float)sum;
}

4. 分块并行计算

对于超长矢量,可以结合并行计算和误差控制:

float parallel_dot(const float* a, const float* b, size_t n, int num_threads) {std::vector<double> partial_sums(num_threads, 0.0);#pragma omp parallel for num_threads(num_threads)for (int t = 0; t < num_threads; t++) {size_t start = t * n / num_threads;size_t end = (t + 1) * n / num_threads;double local_sum = 0.0;for (size_t i = start; i < end; i++) {local_sum += (double)a[i] * (double)b[i];}partial_sums[t] = local_sum;}double total = 0.0;for (double s : partial_sums) {total += s;}return (float)total;
}

实际应用建议

  1. 对于GPU计算:使用Kahan求和或成对求和,因为双精度运算在GPU上可能性能较差
  2. 对于CPU计算:优先考虑双精度累加器方法,简单且有效
  3. 混合精度:可以考虑使用融合乘加(FMA)指令结合补偿算法
  4. 内存访问优化:确保数据连续访问,减少缓存未命中

误差分析

对于1亿个单精度数的内积:

  • 普通累加:相对误差可能达到1e-4量级
  • Kahan求和:误差可降低到1e-8量级
  • 双精度累加:误差可降低到1e-16量级

选择哪种方法取决于您的精度要求和计算环境限制。


测试代码

#include <cmath>
#include <iostream>
#include <iomanip>
#include <omp.h>
#include <cstdlib>
#include <immintrin.h>using namespace std;//编译: g++ -DAVX2 -DAVX512F -std=c++17 -Ofast -march=native -fopenmp test_dot.cpp/********************************************************<x,y>内积计算用double双精度做累加类型,保证数值稳定
**********************************************************/template<typename F,int P=0>
F dot(int n, const F *x, const F *y)
{if constexpr (P==0){double s_time=omp_get_wtime();//累加用单精度F s=0;for(int i=0; i<n; i++){s+=x[i]*y[i];}double e_time=omp_get_wtime();cout<<"P="<<P<<": time used "<<e_time-s_time<<endl;return s;}else if constexpr (P==1){double s_time=omp_get_wtime();//累加用双精度,乘法用单精度double s=0;for(int i=0; i<n; i++){s+=x[i]*y[i];}double e_time=omp_get_wtime();cout<<"P="<<P<<": time used "<<e_time-s_time<<endl;return s;}else if constexpr (P==2){double s_time=omp_get_wtime();//累加用双精度,乘法用双精度double s=0;for(int i=0; i<n; i++){double a=x[i];double b=y[i];s+=a*b;}double e_time=omp_get_wtime();cout<<"P="<<P<<": time used "<<e_time-s_time<<endl;return s;}
#ifdef AVX2 else if constexpr(P==3){static_assert(is_same_v<F,float>);/********************************************************************OpenMP多线程,AVX2计算<x,x>,<x,y>累加和乘法都用双精度	*********************************************************************/double s_time=omp_get_wtime();__m256d xx_sum,xy_sum;xx_sum=xy_sum=_mm256_setzero_pd();#pragma omp parallel{__m256d sum_xx=_mm256_setzero_pd();__m256d sum_xy=_mm256_setzero_pd();#pragma omp forfor(int i=0; i<n; i+=8){__m256 x8=_mm256_loadu_ps(x+i);__m256 y8=_mm256_loadu_ps(y+i);__m128 lo,hi;__m256d t1,t2,t3,t4;lo=_mm256_extractf128_ps(x8,0);hi=_mm256_extractf128_ps(x8,1);t1=_mm256_cvtps_pd(lo);t2=_mm256_cvtps_pd(hi);lo=_mm256_extractf128_ps(y8,0);hi=_mm256_extractf128_ps(y8,1);t3=_mm256_cvtps_pd(lo);t4=_mm256_cvtps_pd(hi);
#if 0				sum_xx=_mm256_add_pd(sum_xx,_mm256_mul_pd(t1,t1));sum_xx=_mm256_add_pd(sum_xx,_mm256_mul_pd(t2,t2));sum_xy=_mm256_add_pd(sum_xy,_mm256_mul_pd(t1,t3));sum_xy=_mm256_add_pd(sum_xy,_mm256_mul_pd(t2,t4));
#else/**********************************FMA***********************************/sum_xx=_mm256_fmadd_pd(t1,t1,sum_xx);sum_xx=_mm256_fmadd_pd(t2,t2,sum_xx);sum_xy=_mm256_fmadd_pd(t1,t3,sum_xy);sum_xy=_mm256_fmadd_pd(t2,t4,sum_xy);
#endif}#pragma omp critical{xx_sum=_mm256_add_pd(xx_sum,sum_xx);xy_sum=_mm256_add_pd(xy_sum,sum_xy);}}double tmp[4];_mm256_storeu_pd(tmp,xy_sum);double xy=tmp[0]+tmp[1]+tmp[2]+tmp[3];_mm256_storeu_pd(tmp,xx_sum);double xx=tmp[0]+tmp[1]+tmp[2]+tmp[3];for(int i=n&~7; i<n; i++){double a=x[i];double b=y[i];xx+=a*a;xy+=a*b;}double e_time=omp_get_wtime();cout<<"P="<<P<<": time used "<<e_time-s_time<<endl;cout<<"xx="<<xx<<endl;return xy;}//P==3
#endif 	
#ifdef AVX512F 	else if constexpr(P==4){static_assert(is_same_v<F,float>);/********************************************************************OpenMP多线程,AVX512F计算<x,x>,<x,y>累加和乘法都用双精度	*********************************************************************/double s_time=omp_get_wtime();__m512d xx_sum=_mm512_setzero_pd();__m512d xy_sum=_mm512_setzero_pd();#pragma omp parallel{__m512d sum_xx=_mm512_setzero_pd();__m512d sum_xy=_mm512_setzero_pd();#pragma omp forfor(int i=0; i<n; i+=16){__m512 x16=_mm512_loadu_ps(x+i);__m512 y16=_mm512_loadu_ps(y+i);__m256 lo,hi;__m512d t1,t2,t3,t4;lo=_mm512_extractf32x8_ps(x16,0);hi=_mm512_extractf32x8_ps(x16,1);t1=_mm512_cvtps_pd(lo);t2=_mm512_cvtps_pd(hi);lo=_mm512_extractf32x8_ps(y16,0);hi=_mm512_extractf32x8_ps(y16,1);t3=_mm512_cvtps_pd(lo);t4=_mm512_cvtps_pd(hi);
#if 0				sum_xx=_mm512_add_pd(sum_xx,_mm512_mul_pd(t1,t1));sum_xx=_mm512_add_pd(sum_xx,_mm512_mul_pd(t2,t2));sum_xy=_mm512_add_pd(sum_xy,_mm512_mul_pd(t1,t3));sum_xy=_mm512_add_pd(sum_xy,_mm512_mul_pd(t2,t4));
#else/***********************************FMA************************************/sum_xx=_mm512_fmadd_pd(t1,t1,sum_xx);sum_xx=_mm512_fmadd_pd(t2,t2,sum_xx);sum_xy=_mm512_fmadd_pd(t1,t3,sum_xy);sum_xy=_mm512_fmadd_pd(t2,t4,sum_xy);
#endif}#pragma omp critical{xx_sum=_mm512_add_pd(xx_sum,sum_xx);xy_sum=_mm512_add_pd(xy_sum,sum_xy);}}double tmp[8];_mm512_storeu_pd(tmp,xy_sum);double xy=tmp[0]+tmp[1]+tmp[2]+tmp[3]+tmp[4]+tmp[5]+tmp[6]+tmp[7];_mm512_storeu_pd(tmp,xx_sum);double xx=tmp[0]+tmp[1]+tmp[2]+tmp[3]+tmp[4]+tmp[5]+tmp[6]+tmp[7];for(int i=n&~15; i<n; i++){double a=x[i];double b=y[i];xx+=a*a;xy+=a*b;}double e_time=omp_get_wtime();cout<<"P="<<P<<": time used "<<e_time-s_time<<endl;cout<<"xx="<<xx<<endl;return xy;}
#endif return(0);}const int N=50000000;void test()
{using FLOAT=float;FLOAT *x=new FLOAT[N];FLOAT *y=new FLOAT[N];for(int i=0; i<N; i++){FLOAT t=0.001*sqrtf(FLOAT(i));FLOAT s=sqrt(sqrt(FLOAT(i)));x[i]=(rand()<RAND_MAX/2)?t:-t;y[i]=(rand()<RAND_MAX/2)?s:-s;}cout<<setprecision(15)<<endl;cout<<(double)dot<FLOAT,0>(N,x,y)<<endl;cout<<(double)dot<FLOAT,1>(N,x,y)<<endl;cout<<(double)dot<FLOAT,2>(N,x,y)<<endl;#ifdef AVX2	cout<<(double)dot<FLOAT,3>(N,x,y)<<endl;
#endif #ifdef AVX512F	cout<<(double)dot<FLOAT,4>(N,x,y)<<endl;
#endif }int main(int argc, char **argv)
{test();return(0);
}
http://www.dtcms.com/wzjs/271324.html

相关文章:

  • 做响应式网站的常用尺寸短视频seo系统
  • java开发网站跟php开发网站区别优化师
  • 湘潭网站建设 要选磐石网络石家庄seo扣费
  • 网站建设的ppt模板临沂森佳木业有限公司
  • 网站建设授权委托书品牌策划方案案例
  • 中文网站开发软件百度指数预测
  • 做网站的工资高成都seo优化公司排名
  • 昆明做网站建设公司百度推广入口
  • 做微商的网站百度联盟怎么赚钱
  • 用HBuilder做网站的模板做一个网站需要多少钱
  • 昌平网站制作公司新闻稿件代发平台
  • 专注苏州网站优化室内设计培训班学费一般多少
  • 北京好的做网站的公司有哪些网络宣传的方法有哪些
  • 建立网站的服务器刷推广链接
  • 哪个网站专门做商铺啊推广类软文案例
  • 网站上传 空间 数据库怎么根据视频链接找到网址
  • 绵阳市网站建设公司百度网站认证
  • 把网站做成app多少钱在线搜索资源
  • 咸秧草做哪些网站关键词排名推广
  • wordpress改织梦保定seo外包服务商
  • 怎么做wap网站免费seo排名软件
  • cdn网站加速 免备案seo关键词挖掘工具
  • 网站建设速度如何解决app推广平台网站
  • 查网站是不是用shopify做的2022年关键词排名
  • 做分销网站推广产品吸引人的句子
  • 彩票网站的客服有做吗百度搜索风云榜小说排行榜
  • 网站诚信认证电话销售营销培训心得体会
  • 微擎怎么做网站互联网推广的方式
  • soho的网站怎么做天津seo优化排名
  • abc网站建设是什么意思优化网站页面