精彩圖文說明教程:迅速初始化內(nèi)存(1)
發(fā)表時間:2024-01-21 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]許多計算密集型的應(yīng)用都需要處理大量內(nèi)存,這種應(yīng)用中的內(nèi)存初始化是一個常規(guī)操作,而內(nèi)存和CPU內(nèi)部的數(shù)據(jù)交換之間的速度瓶頸決定了內(nèi)存初始化將會占用可觀的時間。但因為應(yīng)用程序初始化內(nèi)存往往調(diào)用CRT的memset或者Windows API的ZeroMemory,很少有人在初始化方面進(jìn)行優(yōu)化。另一方面,...
許多計算密集型的應(yīng)用都需要處理大量內(nèi)存,這種應(yīng)用中的內(nèi)存初始化是一個常規(guī)操作,而內(nèi)存和CPU內(nèi)部的數(shù)據(jù)交換之間的速度瓶頸決定了內(nèi)存初始化將會占用可觀的時間。但因為應(yīng)用程序初始化內(nèi)存往往調(diào)用CRT的memset或者Windows API的ZeroMemory,很少有人在初始化方面進(jìn)行優(yōu)化。
另一方面,現(xiàn)在的應(yīng)用硬件一般配置都比較好,大部分應(yīng)用都運行在PII之上,但我們在使用諸如VC之類的編譯環(huán)境時往往選擇速度優(yōu)化,并選擇合適的處理器,然后寄希望于編譯器給我們生成優(yōu)化的結(jié)果,結(jié)果往往發(fā)現(xiàn)并不如意。
在我們的一個圖像處理項目中,需要大量內(nèi)存操作,而且多個線程同時運行,內(nèi)存存取成為了各個模塊的競爭資源,所以對內(nèi)存存取優(yōu)化成為項目的關(guān)鍵。在努力減少內(nèi)存操作遍數(shù)的基礎(chǔ)上,加快內(nèi)存初始化成為我們的改進(jìn)重點。
在用VC各種手段都沒有太多改進(jìn)后,我們把目光轉(zhuǎn)向處理器特征。從Pentium系列開始,一方面Intel在不斷提高CPU主頻,同時也在針對多媒體等應(yīng)用相繼推出MMX/SSE/SSE2,增加了許多多位快速處理指令。在高層語言方面,Intel的C++ Compiler提供了針對不同處理器的最優(yōu)化結(jié)果。但在一個成熟項目中貿(mào)然使用另外一種編譯環(huán)境的風(fēng)險較大,所以我們從Intel環(huán)境中抽取了memset的實現(xiàn),重新組織了一個Lib,并在我們的項目中針對內(nèi)存初始化進(jìn)行了改動,并鏈接到抽取的lib庫中。在內(nèi)存初始化方面有了一個較大的提高。
下面我們用測試?yán)诱f明該過程。
一個例子
在測試程序中,分別調(diào)用微軟C庫的memset和intel版本的memset分別對100M內(nèi)存進(jìn)行60遍初始化,,為了模擬多線程環(huán)境,啟動了兩個線程同時進(jìn)行內(nèi)存初始化。測試時使用了Release版,為了方面查看包含了調(diào)試信息(調(diào)試信息無影響)。測試結(jié)果:
MSC 版本:12.453~12.547秒
Intel C版本:4.375~4.531秒
可見在大量內(nèi)存操作時差別比較大。對內(nèi)存存取密集型項目,因為內(nèi)存存取往往是瓶頸,應(yīng)該還可以提高整體處理性能。
下面是例子的代碼:
// 本程序示例了使用微軟CRT的memset和Intel優(yōu)化的memset初始化內(nèi)存的速度差異
// Lihw.
#include
#include
#include
extern "C"
void * __cdecl __intel_new_memset(void *, int, size_t);
#pragma comment(lib,"intelmem.lib")
#define SIZE 1024*1024*100
void threadfunc(void *dummy)
{
LPBYTE lpByte = (LPBYTE)dummy;//new BYTE[SIZE];
int j;
#define LoopTimes 60
DWORD dwStart, dwTime1,dwTime2;
//
//intel version
dwStart = GetTickCount();for (j=0; j< LoopTimes; j++)
{
__intel_new_memset(lpByte,1,SIZE);
}
dwTime1 = GetTickCount() - dwStart;
//MS crt version
dwStart = GetTickCount();
for (j=0; j< LoopTimes; j++)
{
memset(lpByte,1,SIZE);
//ZeroMemory(lpByte,SIZE);
}
dwTime2 = GetTickCount() - dwStart;
//delete []lpByte;
printf("Intel=%dms MSC=%dms\n",dwTime1,dwTime2);
}
int main(int argc, char* argv[])
{
#define THREADS 2
HANDLE hThread[THREADS]; //array to hold thread handle
LPBYTE lpByte[THREADS]; //Array to hold thread-specific memory
int i;
//Count mem alloc time. Debug version is very long
DWORD dwStart = GetTickCount();
for (i=0; i