浮點數的運算為什么更慢


1. 浮點數的表示

 

m 是尾數, 為±d.dddddd   其中 第一位必須非0

b 是基數, 

下面,讓我們回到一開始的問題:為什么0x00000009還原成浮點數,就成了0.000000?

首先,將0x00000009拆分,得到第一位符號位s=0,后面8位的指數E=00000000,最后23位的有效數字M=000 0000 0000 0000 0000 1001。

由於指數E全為0,所以符合上一節的第二種情況。因此,浮點數V就寫成:

V=(-1)^0×0.00000000000000000001001×2^(-126)=1.001×2^(-146)

 

 

結論

通用規則:

  • 整數和(和ANDORXOR)與乘積花費的時間相同,除法(和取模)的速度慢三倍。
  • 浮點數的乘積比求和的乘積慢兩倍,除法的乘積甚至更慢。
  • 在相同數據大小下,浮點運算始終比整數運算慢。
  • 越小越快。
  • 64位整數精度確實很慢。
  • 浮點數32位總和比64位快,但在乘積和除法上卻不是。
  • 80和128位精度僅在絕對必要時才應使用,它們非常慢。

特別案例:

  • 在x86-64 AVX上,浮點乘積在64位數據上比在32位上更快
  • 在POWER8 AltiVec上,浮點乘積以各種精度達到求和的速度對8位,16位,32位或64位整數以相同的速度執行整數運算。
  • 在ARM1176上,按位整數運算符比加法運算要快。

 

 

示例代碼:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <cv/cv_tools.h>
#include <picture/cv_picture.h>
#include "libyuv.h"
using namespace cv;
using namespace std;
using namespace oop;


int main()
{
    const int  N= 10000;
    int sum = 0;
    float sumf = 0;

    float nf = 734.0f;
    int n = 734;
    timeInit;
    timeMark("int");
    for(int j=0;j!=100000;++j)
    {
        sum = 0;
        for (int i = 0; i != N; ++i) {
            sum += n;
        }
    }
    timeMark("float");
    for (int j = 0; j != 100000; ++j)
    {
        sumf = 0;
        for (int i = 0; i != N; ++i) {
            sumf += nf;
        }
    }
    timeMark(")");
    timePrint;

    printf("sum=%d\nsumf=%.2f\n",sum,sumf);
    getchar();
}

 

輸出:

( int,float ) : 2107 ms
( float,) ) : 3951 ms

sum=7340000
sumf=7340000.00

 

Release:

( int,float ) : 0 ms
( float,) ) : 1814 ms

sum=7340000
sumf=7340000.00

 

實際上: Debug模式下, 兩者時間差不了多少,兩倍的關系

但是Release模式下, int 幾乎很快就完成了!!  說明int型被優化得很好了,float型運算不容易被編譯器優化!!!

 

 

我們在Release模式下, 優化設置為O2, 連接器設置為-優化以便於調試

查看int 乘法匯編指令:xmm0 表示128位的SSE寄存器,可見我們的代碼都被優化為SSE指令了!!

 

 

 查看float 匯編代碼:

感覺里面也有xmm 等SSE指令集, 至於為啥int型乘法比float乘法快很多,  還是有點搞不明白, 需要詳細分析里面的匯編指令才能搞明白

網上關於這方面的資料太少了, 哎~~

 

 

我們再看看float 和 int乘法對圖像進行處理的例子:

我們把BGR 3個通道分別乘以2 3 4 、 2.0f, 3.0f, 4.0f 然后輸出, 這里我們不考慮溢出的問題, 僅僅對乘法的效率進行測試

設置為Release模式,O2

int main()
{
    cv::Mat src = imread("D:/pic/nlm.jpg");
    //cvtColor(src,src,CV_BGR2GRAY);
    resize(src,src,Size(3840*2,2160*2));
    cv::Mat dst0(src.size(), src.type());
    cv::Mat dst1(src.size(), src.type());

    int w = src.cols;
    int h = src.rows;
    int of3=0;
    timeInit;
    timeMark("int");
    for (int j = 0; j != h; ++j) {
        for (int i = 0; i != w; ++i) {
            //int of3 = (j*w + i) * 3;
            dst0.data[of3    ] = src.data[of3] * 2;
            dst0.data[of3 + 1] = src.data[of3 + 1] * 3;
            dst0.data[of3 + 2] = src.data[of3 + 2] * 4;
            of3+=3;
        }
    }
    timeMark("float");
    of3=0;
    for (int j = 0; j != h; ++j) {
        for (int i = 0; i != w; ++i) {
            //int of3 = (j*w + i)*3;
            dst1.data[of3] = src.data[of3] * 2.0f;
            dst1.data[of3+1] = src.data[of3+1] * 3.0f;
            dst1.data[of3+2] = src.data[of3+2] * 4.0f;
            of3 += 3;
        }
    }
    timeMark("end");
    timePrint;
    myShow(dst0);
    myShow(dst1);

    waitKey(0);
}

輸出:

( int,float ) : 149 ms
( float,end ) : 173 ms

輸出圖像(分別為原圖,dst0,dst1)(截取了一部分)

 可見,時間並差不了多少,但int還是要快一點!!

 

 這是我看到的另外一個帖子,里面講的float乘法確實比較復雜 , 這可能是它比較慢的原因之一吧

https://blog.csdn.net/u014298090/article/details/21867187

 

總結一下: float運算更慢的原因:

1. float運算不容易被編譯器優化

2. float運算本身就慢(但並不比int型運算慢多少,大約1.3-2倍的樣子)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM