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)
結論
通用規則:
- 整數和(和
AND/OR/XOR)與乘積花費的時間相同,除法(和取模)的速度慢三倍。 - 浮點數的乘積比求和的乘積慢兩倍,除法的乘積甚至更慢。
- 在相同數據大小下,浮點運算始終比整數運算慢。
- 越小越快。
- 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倍的樣子)
