多線程寫影像檔的一點小測試

來源:互聯網
上載者:User

       在處理遙感映像中,發現往往比較耗時的是在資料的IO中,尤其是在O(寫入)的時候更加耗時。GDAL可以支援映像的多線程寫入,下面結合執行個體進行簡單的測試,看看實際效果會不會提高。

       在這裡我使用的是boost庫的thread庫來進行多線程建立。下面先使用計算PI來對boost的thread有個簡單的說明。這裡的計時使用的是boost的progress_timer。下面是使用多線程計算PI的一段小代碼,對於多線程計算的10部分沒有加起來。

#include <stdio.h>#include <boost/progress.hpp>//boost計時函數#include <boost/thread.hpp>//boost多線程#include <boost/bind.hpp>//boost bind庫using namespace boost;//計算PI的個數int iSize = 1000000000;int iSize1 = 100000000;//使用普通方式計算double CalcPi_S(){double dPi = 0.0;int iFlag = 1;for (int k=0; k<=iSize; k++){dPi = dPi + iFlag/(2*k+1.0);iFlag = -iFlag;}return dPi*4;}//多線程計算核心函數void ThreadPi(int iStart, int iEnd){double dPi = 0.0;int iFlag = 1;for (int k=iStart; k<=iEnd; k++){dPi = dPi + iFlag/(2*k+1.0);iFlag = -iFlag;}printf("%18.16lf\n", dPi*4);}//多線程計算函數void CalcPi_M(){for (int i=0; i<10; i++){boost::thread thrd(boost::bind(&ThreadPi, i*iSize1, (i+1)*iSize1));thrd.join();}}int main(){//不使用多執行緒progress_timer *pTime = new progress_timer();  // 開始計時printf("單線程計算PI\n");double dsPi = CalcPi_S();printf("計算結束,耗時:%f PI=%18.16lf\n", pTime->elapsed(), dsPi);//使用多執行緒pTime->restart(); // 開始計時printf("多線程計算PI\n");CalcPi_M();printf("計算結束,耗時:%f\n", pTime->elapsed());delete pTime;system("pause");return 0;}

      通過對上面的代碼進行測試,使用的是Release編譯的結果,結果大概如下,第一次:

單線程計算PI計算結束,耗時:9.643000 PI=3.14159265458805069.64 s多線程計算PI3.14159266358932590.00000001500000000.00000000833333330.00000000583333330.00000000450000000.00000000366666670.00000000309523810.00000000267857140.00000000236111110.0000000021111111計算結束,耗時:8.4980008.50 s請按任意鍵繼續. . .

      第二次:

單線程計算PI計算結束,耗時:12.039000 PI=3.1415926545880506多線程計算PI3.14159266358932590.00000001500000000.00000000833333330.00000000583333330.00000000450000000.00000000366666670.00000000309523810.00000000267857140.00000000236111110.0000000021111111計算結束,耗時:8.5500008.55 s請按任意鍵繼續. . .

       第三次:

單線程計算PI計算結束,耗時:14.473000 PI=3.1415926545880506多線程計算PI3.14159266358932590.00000001500000000.00000000833333330.00000000583333330.00000000450000000.00000000366666670.00000000309523810.00000000267857140.00000000236111110.0000000021111111計算結束,耗時:8.5000008.50 s請按任意鍵繼續. . .

       第四次:

單線程計算PI計算結束,耗時:10.898000 PI=3.1415926545880506多線程計算PI3.14159266358932590.00000001500000000.00000000833333330.00000000583333330.00000000450000000.00000000366666670.00000000309523810.00000000267857140.00000000236111110.0000000021111111計算結束,耗時:8.5100008.51 s請按任意鍵繼續. . .

       通過四次測試,發現多線程還是能夠稍微提高點速度,但是不知道為什麼,單線程計算的時候,時間跳躍比較大,起伏較大,不知道是什麼原因,有知道的童鞋望不吝告知。

       下面是建立了一個10000×10000的單波段映像,格式是Erdas的img格式,映像的內容是按照行號對255取餘的結果,結果映像就是一條一條的黑白相間的波紋。多線程還是使用10個線程來寫映像的不同部分。代碼如下:

#include <stdio.h>#include "gdal_priv.h"#include <boost/progress.hpp>//boost計時函數#include <boost/thread.hpp>#include <boost/bind.hpp>using namespace boost;#pragma comment(lib, "gdal_i.lib")typedef unsigned char DT_8U;/*** @brief 建立輸出映像*/bool CreateImage(const char* pszFile){GDALAllRegister();GDALDriverH hDriver = GDALGetDriverByName( "HFA" );if( hDriver == NULL )return false;GDALDatasetH hDstDS = GDALCreate( hDriver, pszFile, 10000, 10000, 1, GDT_Byte, NULL );//建立輸出檔案if( hDstDS == NULL )return false;GDALClose(hDstDS);return true;}bool SingleProcess(const char* pszFile){GDALAllRegister();GDALDataset *poSrcDS = (GDALDataset *) GDALOpen( pszFile, GA_Update );if( poSrcDS == NULL )return false;int iWidth = poSrcDS->GetRasterXSize();int iHeight = poSrcDS->GetRasterYSize();GDALRasterBand *pBand = poSrcDS->GetRasterBand(1);DT_8U *pBuf = new DT_8U[iWidth];memset(pBuf, 0, sizeof(DT_8U)*iWidth);//超出AOI外for (int i=0; i<iHeight; i++){int iValue = i % 255;memset(pBuf, iValue, sizeof(DT_8U)*iWidth);//超出AOI外pBand->RasterIO(GF_Write , 0, i, iWidth, 1, pBuf, iWidth, 1, GDT_Byte, 0, 0);}GDALClose((GDALDatasetH) poSrcDS);return true;}void ThreadFun(const char* pszFile, int iStart, int iEnd/*, int index*/){GDALAllRegister();GDALDataset *poSrcDS = (GDALDataset *) GDALOpen( pszFile, GA_Update );if( poSrcDS == NULL )return;int iWidth = poSrcDS->GetRasterXSize();int iHeight = poSrcDS->GetRasterYSize();GDALRasterBand *pBand = poSrcDS->GetRasterBand(1);DT_8U *pBuf = new DT_8U[iWidth];memset(pBuf, 0, sizeof(DT_8U)*iWidth);//超出AOI外for (int i=iStart; i<iEnd; i++){int iValue = i % 255;memset(pBuf, iValue, sizeof(DT_8U)*iWidth);//超出AOI外pBand->RasterIO(GF_Write , 0, i, iWidth, 1, pBuf, iWidth, 1, GDT_Byte, 0, 0);}GDALClose((GDALDatasetH) poSrcDS);//printf("線程%n結束\n", index);}bool MultiProcess(const char* pszFile){for (int i=0; i<10; i++){boost::thread thrd(boost::bind(&ThreadFun, pszFile, i*1000, (i+1)*1000/*, i*/));thrd.join();}return true;}int main(){//不使用多執行緒progress_timer *pTime = new progress_timer();  // 開始計時const char* pszFileSingle = "F:\\Data\\Test\\Single.img";printf("建立映像開始\n");CreateImage(pszFileSingle);printf("建立映像結束,耗時:%f\n", pTime->elapsed());pTime->restart(); // 開始計時SingleProcess(pszFileSingle);printf("單線程處理映像結束,耗時:%f\n", pTime->elapsed());//使用多執行緒pTime->restart(); // 開始計時const char* pszFileMulti = "F:\\Data\\Test\\Multi.img";printf("建立映像開始\n");CreateImage(pszFileMulti);printf("建立映像結束,耗時:%f\n", pTime->elapsed());pTime->restart(); // 開始計時MultiProcess(pszFileMulti);printf("多執行緒映像結束,耗時:%f\n", pTime->elapsed());delete pTime;system("pause");return 0;}

       依舊使用Release編譯的結果,啟動並執行結果如下,第一次:

建立映像開始建立映像結束,耗時:2.852000單線程處理映像結束,耗時:20.579000建立映像開始建立映像結束,耗時:3.261000多執行緒映像結束,耗時:29.34300029.34 s請按任意鍵繼續. . .

      第二次:

建立映像開始建立映像結束,耗時:2.034000單線程處理映像結束,耗時:22.311000建立映像開始建立映像結束,耗時:2.217000多執行緒映像結束,耗時:30.57000030.57 s請按任意鍵繼續. . .

      第三次:

建立映像開始建立映像結束,耗時:2.007000單線程處理映像結束,耗時:20.285000建立映像開始建立映像結束,耗時:2.267000多執行緒映像結束,耗時:28.72300028.73 s請按任意鍵繼續. . .

       就貼三次吧,在我電腦上測試了不下十次,發現都是多線程寫入的速度慢,但是結果映像是對的。對於出現這種情況,也是出乎意料的,按理說多線程應該更快才對,但是這裡卻出現了相反的情況,不知道是不是boost庫多線程的問題還是多線程寫入映像的問題,不管是什麼情況,對於想使用多線程來建立映像的人來說,這條路可能比想象中的要更加艱難。

       如果你有更好的方式,望告知,謝謝。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.