C++ 如何优化简单循环?
循环很简单C++ 如何优化简单循环?,c++,optimization,vectorization,multicore,simd,C++,Optimization,Vectorization,Multicore,Simd,循环很简单 void loop(int n, double* a, double const* b) { #pragma ivdep for (int i = 0; i < n; ++i, ++a, ++b) *a *= *b; } void循环(int n,double*a,double const*b) { #布拉格马伊夫代普 对于(int i=0;i
void loop(int n, double* a, double const* b)
{
#pragma ivdep
for (int i = 0; i < n; ++i, ++a, ++b)
*a *= *b;
}
void循环(int n,double*a,double const*b)
{
#布拉格马伊夫代普
对于(int i=0;i
我使用英特尔C++编译器,使用
a
指向的数据不能与b
指向的数据重叠,那么给编译器提供最重要的信息,让它优化代码就是这个事实
在较旧的ICC版本中,“restrict”是向编译器提供密钥信息的唯一干净方法。在较新的版本中,有一些更干净的方法可以提供比ivdep
更有力的保证(事实上ivdep
对优化器的承诺比它看起来更弱,通常没有预期的效果)
但是如果
n
很大,那么整个过程都会被缓存未命中所控制,因此没有任何局部优化可以提供帮助。我假设n
很大。您可以通过启动k
线程在k
CPU上分配工作负载,并为每个线程提供n/k
元素。为每个线程使用大块的连续数据,不要进行细粒度的交错。尝试将块与缓存线对齐
如果计划扩展到一个以上的NUMA节点,请考虑将工作负载块显式复制到节点,线程继续运行,并复制结果。在这种情况下,它可能没有真正的帮助,因为每个步骤的工作负载都非常简单。您必须为此运行测试。手动展开循环是优化代码的简单方法,下面是我的代码。原始
loop
成本为618.48毫秒,而loop2
成本为381.10毫秒。在我的电脑中,编译器为GCC,带有选项'-O2'。我没有Intel ICC来验证代码,但我认为优化原则是相同的
类似地,我做了一些实验,将两个程序的执行时间与两个内存块的异或进行比较,其中一个程序在SIMD指令的帮助下进行矢量化,而另一个程序则手动循环展开。如果您感兴趣,请参阅
当然,p.S.loop2
仅在n为偶数时有效
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#define LEN 512*1024
#define times 1000
void loop(int n, double* a, double const* b){
int i;
for(i = 0; i < n; ++i, ++a, ++b)
*a *= *b;
}
void loop2(int n, double* a, double const* b){
int i;
for(i = 0; i < n; i=i+2, a=a+2, b=b+2)
*a *= *b;
*(a+1) *= *(b+1);
}
int main(void){
double *la, *lb;
struct timeval begin, end;
int i;
la = (double *)malloc(LEN*sizeof(double));
lb = (double *)malloc(LEN*sizeof(double));
gettimeofday(&begin, NULL);
for(i = 0; i < times; ++i){
loop(LEN, la, lb);
}
gettimeofday(&end, NULL);
printf("Time cost : %.2f ms\n",(end.tv_sec-begin.tv_sec)*1000.0\
+(end.tv_usec-begin.tv_usec)/1000.0);
gettimeofday(&begin, NULL);
for(i = 0; i < times; ++i){
loop2(LEN, la, lb);
}
gettimeofday(&end, NULL);
printf("Time cost : %.2f ms\n",(end.tv_sec-begin.tv_sec)*1000.0\
+(end.tv_usec-begin.tv_usec)/1000.0);
free(la);
free(lb);
return 0;
}
#包括
#包括
#包括
#定义LEN 512*1024
#定义乘以1000
无效循环(整数n,双*a,双常量*b){
int i;
对于(i=0;i