在 64 位处理器上不使用 double(而是使用 float 代替)有什么好处吗?

Is there any benefit of not using double on a 64bit (and using, say, float instead) processor?

我总是使用 double 来进行计算,但 double 提供的精度远远超出我的需要(或者说是有道理的,考虑到我所做的大部分计算都是从近似值开始的)。

但是由于处理器已经是 64 位的,我不认为使用位数较少的类型会有任何好处。

我是 right/wrong,我将如何优化速度(我知道较小的类型会更有效地使用内存)

这里是测试

#include <cmath>
#include <ctime>
#include <cstdio>

template<typename T>
void creatematrix(int m,int n, T **&M){
    M = new T*[m];
    T *M_data = new T[m*n];

    for(int i=0; i< m; ++i) 
    {
        M[i] = M_data + i * n;
    }
}

void main(){
    clock_t start,end;
    double diffs;
    const int N = 4096;
    const int rep =8;

    float **m1,**m2;
    creatematrix(N,N,m1);creatematrix(N,N,m2);

    start=clock();
    for(int k = 0;k<rep;k++){
        for(int i = 0;i<N;i++){
            for(int j =0;j<N;j++)
                m1[i][j]=sqrt(m1[i][j]*m2[i][j]+0.1586);
        }
    }
    end = clock();
    diffs = (end - start)/(double)CLOCKS_PER_SEC;
    printf("time = %lf\n",diffs);


    delete[] m1[0];
    delete[] m1;

    delete[] m2[0];
    delete[] m2;

    getchar();
}

double 和 float 之间没有时间差异,但是当不使用平方根时,float 快两倍。

有几种方法可以提高它们的速度:

  • 更快 I/O:您只有一半的位可以在 disk/memory/cache/registers
  • 之间移动
  • 通常唯一较慢的运算是平方根和除法。例如,在 Haswell 上,DIVSS(浮点除法)需要 7 个时钟周期,而 DIVSD(双除法)需要 8-14(来源:Agner Fog's tables)。
  • 如果您可以利用 SIMD 指令,那么每条指令可以处理两倍的数量(即在 128 位 SSE 寄存器中,您可以对 4 个浮点数进行操作,但只能对 2 个双精度数进行操作)。
  • 特殊函数(logsin)可以使用低阶多项式:例如log uses a degree 7 polynomial, whereas logf 的 openlibm 实现只需要 4 级。
  • 如果你需要更高的中间精度,你可以简单地将 float 提升到 double,而对于 double 你需要 software double-double,或者更慢的 [=19] =].

请注意,这些要点也适用于 32 位体系结构:与整数不同,格式的大小与您的体系结构相匹配并没有什么特别之处,即在大多数机器上,双精度数与 "native"作为浮动。