我正在寫一個cuda程序,用於匹配分辨率〜180X180的每個輸入圖像,以及約10,000個分辨率爲〜128 * 128的模板圖像。目標是實現實時性能,即在1秒內對25〜30個輸入圖像進行模板匹配(每個圖像都有10,000個模板)。如何確定CUDA GPU的性能?
目前我使用以下方法
- 預裝的所有模板上的GPU全局內存保存運行時的I/O操作。
- 創建單個內核以將一個源圖像與所有模板圖像進行匹配,併爲所有正匹配返回一個數組。
- 在時域中執行所有操作(不使用FFT)。原因是,我嘗試過基-4實現,但它需要大量的中間全局讀取和寫入,最終花費更多時間。
到目前爲止1個輸入圖像到10,000個模板,它需要大約2秒。
我的問題是:
- 是否有辦法,以確定此任務是achieveable實時或不?我的意思是在最大FLOPS和I/O帶寬限制e.t.c的幫助下。
- 如何計算GPU是否最大程度地被充分利用?
- 提高性能的可能方法?
機規格:i7-4770,8GB,GTX-680]
闡釋目前的內核代碼:
- 所有模板圖像[尺寸爲RGB約128X128]每加載在GPU內存上。想法是在運行時操作中保存I/O。
- 每個輸入圖像都加載到紋理內存上,原因在於紋理對於2D尋址來說是很好的選擇。
- 每個「塊」有1024個線程。
- 每個線程計算每個輸出像素的值,輸出大小爲[31X31 = 961像素]。
- 啓動的塊數等於匹配的模板圖像的數量。
內核代碼:
__global__ void cudaMatchTemplate(TemplateArray *templates, uchar *Match)
{
int global = blockIdx.x*blockDim.x + threadIdx.x;
__shared__ int idx[TEMPLATE_MATCH_DIM];
__shared__ float out_shared[TEMPLATE_MATCH_DIM];
//halving the template size....
int rows = (templates[blockIdx.x].nHeight)/2;
int cols = (templates[blockIdx.x].nWidth)/2;
int fullCol = templates[blockIdx.x].nWidth;
int x = templates[blockIdx.x].nMatchLeft;
int y = templates[blockIdx.x].nMatchTop;
int offset_y = (threadIdx.x/TEMPLATE_MATCH_SIZE);
int offset_x = (threadIdx.x - offset_y*TEMPLATE_MATCH_SIZE);
// *************** Performing match in time domain *****************************//
int sum = 0;
float temp;
int idxXFactor = 3*(2*(offset_x) + x);
int idxYFactor = 2*(offset_y) + y ;
for (int i = 0; i < rows; i++)
{
int I=3*i*fullCol;
int sourceIdxY = idxYFactor + 2*i;
for (int j = 0; j < cols; j++)
{
int J=3*j;
int sourceIdxX = idxXFactor + 2*J;
int templateIdx = 2*I+2*J;
//**** R *****//
temp = float(tex2D(SourceImgColorTex,sourceIdxX,sourceIdxY)) - float(templates[blockIdx.x].pRAWPixels_gpu[templateIdx]);
sum = sum + temp*temp;
//**** G *****//
temp = float(tex2D(SourceImgColorTex,sourceIdxX+1,sourceIdxY)) - float(templates[blockIdx.x].pRAWPixels_gpu[templateIdx +1]);
sum = sum + temp*temp;
//**** B *****//
temp = float(tex2D(SourceImgColorTex,sourceIdxX+2,sourceIdxY)) - float(templates[blockIdx.x].pRAWPixels_gpu[templateIdx +2]);
sum = sum + temp*temp;
}
}
__syncthreads();
//placing all values in shared memory for comparison.
if(threadIdx.x < TEMPLATE_MATCH_DIM)
{
idx[threadIdx.x] = threadIdx.x;
out_shared[threadIdx.x] = sum;
}
__syncthreads();
// //computing the Min location.....//
#pragma unroll
for(int s=512; s>0; s>>=1)
{
if ((threadIdx.x < s) &&((threadIdx.x + s)<TEMPLATE_MATCH_DIM))
{
idx[threadIdx.x] = out_shared[threadIdx.x] < out_shared[threadIdx.x + s] ? idx[threadIdx.x] : idx[threadIdx.x + s];
out_shared[threadIdx.x] = out_shared[threadIdx.x] < out_shared[threadIdx.x + s] ? out_shared[threadIdx.x] : out_shared[threadIdx.x + s];
}
}
__syncthreads();
if(threadIdx.x <1)
{
int half_Margin = MARGIN_FOR_TEMPLATE_MATCH/2;
int matchY = idx[0]/TEMPLATE_MATCH_SIZE ;
int matchX = idx[0] - matchY * TEMPLATE_MATCH_SIZE;
int diff = absolute(half_Margin - matchX) + absolute(half_Margin - matchY);
if(diff < THRESHOLD)
{
Match[blockIdx.x] = 1;
}
else
Match[blockIdx.x] = 0;
}
}
你真的在問怎麼加速一些你沒有顯示的代碼,幾乎沒有被50-60次描述過嗎? – talonmies
我已根據您的要求更新了我的查詢,請讓我知道您是否需要進一步清理。我希望這將有助於回答問題。 – Genutek