開發手札:圖形中int和float運算性能問題

       這一篇主要圍繞一些代碼潔癖問題進行觀察測試,在gameplay和shader開發中,int/float等數值類型的乘除運算屬於很常見的,關於其性能和耗時也有區別(這點我看了百度google也沒個明確的說法),當然我們如果只是寫普通代碼,其實不用過於在意此這些問題。

       如果是進行着色器開發,我們還是要明瞭一下比較好。在着色器開發中,片段函數中代碼的計算運算次數是很龐大的,以千萬/億爲單位,所以我們需要明確int/float/half/fixed的乘除運算性能問題,下面我們來測試一下,因爲shader使用c編寫,那麼我們就使用c來測試。

       如下,我單純的使用主線程進行int和float的運算,查看運算時間的差異(注意:1.我不使用線程是因爲線程有資源優先級的問題,我看百度上很多人用多線程測試,這種是錯誤的 2.同時我不使用數值類型強轉,避免其他性能消耗影響 3.最後我使用10和3這種除不盡的數值爲了普適化),那麼貼代碼跑起來吧,目標100000000000次運算。

#include "stdafx.h"
#include<thread>
#include<Windows.h>
#include<string.h>

using namespace std;

const int COUNT = 100000000000;

DWORD crtTime;

void PrintCrtTime()
{
	crtTime = GetTickCount();
	printf("\n");
	printf("當前時間:%d\n", crtTime);
}

void PrintElapseTime(string method)
{
	DWORD crt = GetTickCount();
	printf("執行方法:%s 當前時間:%d\n", method.c_str(), crt);
	printf("執行方法:%s 使用時間:%d\n", method.c_str(), crt - crtTime);
	printf("\n");
}

void IntMultiplyInt()
{
	PrintCrtTime();
	int count = COUNT;
	int a = 10;
	int b = 3;
	int c;
	while (count > 0)
	{
		a * b;
		//c = (int)(a * b);
		count--;
	}
	PrintElapseTime("int乘int");
}

void IntMultiplyFloat()
{
	PrintCrtTime();
	int count = COUNT;
	int a = 10;
	float b = 3.0;
	int c;
	while (count > 0)
	{
		a * b;
		//c = (int)(a * b);
		count--;
	}
	PrintElapseTime("int乘float");
}

void FloatMultiplyFloat()
{
	PrintCrtTime();
	int count = COUNT;
	float a = 10.0;
	float b = 3.0;
	int c;
	while (count > 0)
	{
		a * b;
		//c = (int)(a * b);
		count--;
	}
	PrintElapseTime("float乘float");
}

void IntDivisionInt()
{
	PrintCrtTime();
	int count = COUNT;
	int a = 10;
	int b = 3;
	int c;
	while (count > 0)
	{
		a / b;
		//c = (int)(a / b);
		count--;
	}
	PrintElapseTime("int除int");
}

void IntDivisionFloat()
{
	PrintCrtTime();
	int count = COUNT;
	int a = 10;
	float b = 3.0;
	int c;
	while (count > 0)
	{
		a / b;
		//c = (int)(a / b);
		count--;
	}
	PrintElapseTime("int除float");
}

void FloatDivisionFloat()
{
	PrintCrtTime();
	int count = COUNT;
	float a = 10.0;
	float b = 3.0;
	int c;
	while (count > 0)
	{
		a / b;
		//c = (int)(a / b);
		count--;
	}
	PrintElapseTime("float除float");
}

int main()
{
	IntMultiplyInt();
	IntMultiplyFloat();
	FloatMultiplyFloat();

	IntDivisionInt();
	IntDivisionFloat();
	FloatDivisionFloat();

	return 0;
}

        運算結果如下:

 

       可以看得出來,int除int消耗時間最多,但是從整體看來,我認爲幾乎沒有區別,所以在100000000000次運算下,我們可以說單純的int/float乘除,性能一樣。

       但是,我們使用代碼進行數值運算了,肯定要得到結果的,那麼就存在中間值之間的轉換問題,接下來我們使用int c儲存結果值,看下100000000000次運算的性能差別,如下:

      

       結果:

      

       可以看得出來以下三點:

       1.int除float消耗性能最高

       2.乘法除法運算中,不同類型相乘除最耗時

       3.都使用float運算,耗時最少,性能最高

       當然如果我們把c改成float呢?如下:

      

       結果:

      

       看得出來不同類型運算依舊是最耗時的,同時float類型不論做乘除運算都沒什麼性能差距。

       那麼,我們以後怎麼寫代碼合適呢?或者說我們可以拋棄掉哪些無所謂的寫法操作呢?我認爲有以下三點:

       1.儘量使用同類型進行運算。打個比方,我們需要對紋理或者分辨率進行運算,因爲紋理和分辨率都是int型,那麼我們可以使用float進行儲存後,再進行縮放/比例計算等運算。

       2.不用在意float的乘除問題,也就是說說不用將10.0f/3.0f改成10.0f*0.333333f等,這樣不僅沒有增加性能,還會造成多次複合運算後的精度不準確,我看很多主程寫代碼甚至都犧牲精確性都要將float的除法改成乘法,脾氣暴躁的看到剛畢業的實習生這麼寫,還要上去罵兩句,你自己要做測試,不要人云亦云。

      3.float就是比int進行計算快,我看很多人都潛意識覺得float的使用更消耗性能,好多時候都會強轉成int,沒必要,不僅運算更慢,還不精確。就用float儲存計算完事了。

      

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章