2015-08-14 45 views
0

爲了編寫高效的代碼,您應該使用最簡單的數據類型。對於Renderscript來說更是如此,在內核中同樣的計算重複了很多次。現在,我想寫一個非常簡單的內核,其採用(顏色)的位圖作爲輸入並且產生一個int []數組作爲輸出:優化數據類型以提高速度

#pragma version(1) 
#pragma rs java_package_name(com.example.xxx) 
#pragma rs_fp_relaxed 

uint __attribute__((kernel)) grauInt(uchar4 in) { 
uint gr= (uint) (0.21*in.r + 0.72*in.g + 0.07*in.b);  
return gr; 
} 

Java端:

int[] data1 = new int[width*height]; 
ScriptC_gray graysc; 
graysc=new ScriptC_gray(rs); 
Type.Builder TypeOut = new Type.Builder(rs, Element.U32(rs)); 
TypeOut.setX(width).setY(height); 
Allocation outAlloc = Allocation.createTyped(rs, TypeOut.create()); 

Allocation inAlloc = Allocation.createFromBitmap(rs, bmpfoto1,  Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 
graysc.forEach_grauInt(inAlloc,outAlloc); 
outAlloc.copyTo(data1); 

這需要40我的三星S5(5.0)和我的三星Tab2(4.2)180毫秒爲600k像素位圖。現在我試圖優化。由於輸出實際上是一個8位無符號整數(0-255),我試過如下:

uchar __attribute__((kernel)) grauInt(uchar4 in) { 
uchar gr= 0.2125*in.r + 0.7154*in.g + 0.0721*in.b; 
return gr; 
} 

,並在Java中改變4號線到:

Type.Builder TypeOut = new Type.Builder(rs, Element.U8(rs)); 

然而,這造成了錯誤「 32位整數源不匹配分配類型UNSIGNED_8「。我的解釋是,forEach_grauInt(inAlloc,outAlloc)語句在輸入和輸出端需要相同的Element-type。因此,我試圖«disconnecd»入點和出分配和考慮投入分配(位圖)作爲一個全局變量bmpAllocIn如下:

#pragma version(1) 
#pragma rs java_package_name(com.example.dani.oldgauss) 
#pragma rs_fp_relaxed 

rs_allocation bmpAllocIn; 
int32_t width; 
int32_t height; 

uchar __attribute__((kernel)) grauInt(uint32_t x, uint32_t y) { 
uchar4 c=rsGetElementAt_uchar4(bmpAllocIn, x, y); 
uchar gr= (uchar) 0.2125*c.r + 0.7154*c.g + 0.0721*c.b; 
return gr; 
} 

隨着Java方面:

int[] data1 = new int[width*height]; 
ScriptC_gray graysc; 
graysc=new ScriptC_gray(rs); 

graysc.set_bmpAllocIn(Allocation.createFromBitmap(rs,bmpfoto1)); 
Type.Builder TypeOut = new Type.Builder(rs, Element.U8(rs)); 
TypeOut.setX(width).setY(height); 
Allocation outAlloc = Allocation.createTyped(rs, TypeOut.create()); 

graysc.forEach_grauInt(outAlloc); 
outAlloc.copyTo(data1); 

現在令人驚訝的是,我再次得到相同的錯誤消息:「32位整數源不匹配分配類型UNSIGNED_8」。這我不明白。我在這裏做錯了什麼?

回答

1

原因是

int[] data1 = new int[width * height]; 

線。您正嘗試使用它創建的數組作爲copyTo()的目標,並引發異常。更改爲

byte[] data1 = new byte[width * height]; 

並且一切都會好的。順便說一句,輸入和輸出分配可以是不同的類型。作爲一個方面說明,你也可以完全消除你的RS濾波器的浮點運算,它可以提高某些體系結構的性能。

+0

哇,謝謝。出於某種奇怪的原因,我總是與Int []數組一起工作,因爲我認爲Byte []是有符號的(-127-128),但我看到Byte []是靈活的...聰明!所以,這簡直令人難以置信:速度通過改變到正確的類型而增加了一倍。本課有一個諷刺意味的是,在提出這個問題時,我沒有記住REAL類型不匹配不在內核內,而是在copyTo語句內。非常感謝,非常感謝! – Settembrini

+0

關於附註:「它會提高某些架構的性能。」 - >你的意思是,該整數應該是浮動的首選,這不是因爲大小(兩者都是32位),而是因爲浮點計算本質上比整數計算效率低,對嗎? – Settembrini

+0

它確實取決於體系結構。在許多GPU上,FP操作與整數一樣快(或快),在這種特殊情況下,整數版本還需要一個操作(分割或位移),所以它可能會變慢。但是,如果你的目標是舊的,功能較差的設備,RS可能被編譯爲在CPU上運行,那麼整數操作可以爲你提供優勢。如果性能對您的應用來說非常重要,那麼您可以發佈兩個版本,並決定在運行時使用哪一個(基於時間點)。 –