2015-08-14 42 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上运行,那么整数操作可以为你提供优势。如果性能对您的应用来说非常重要,那么您可以发布两个版本,并决定在运行时使用哪一个(基于时间点)。 –