RenderScript是否保证内存布局或跨越从Java层绑定的全局指针?
我读somewhere说最好使用rsGetElementAt / rsSetElementAt函数,因为不能保证布局。
但elsewhere据说在针对GPU优化时会避免使用这些优化,而绑定指针则可以。
在我的特定情况下,我需要内核来访问许多周围像素的值。到目前为止,我已经完成了从Java层绑定的浮点指针。
爪哇:
script.set_width(inputWidth);
script.bind_input(inputAllocation);
RS:
int width;
float *input;
void root(const float *v_in, float *v_out, uint32_t x, uint32_t y) {
int current = x + width * y;
int above = current - width;
int below = current + width;
*v_out = input[above - 1] + input[above ] + input[above + 1] +
input[current - 1] + input[current] + input[current + 1] +
input[below - 1] + input[below ] + input[below + 1] ;
}
这是对我实际行动的简单简化,只是为了通过一个例子轻松说明。实际上,我在这些组合中做了更多,并同时使用多个输入图像,以至于如此预先计算"以上的位置&# 34;和"以下"行有助于处理时间。
只要记忆保证是连续的,并且按照你通常所期望的顺序,一切都很好,到目前为止,我的测试设备上没有任何问题。
但是如果所有设备/处理器都无法保证这种内存布局,并且步幅实际上会有所不同,那么我的代码显然会中断,我将被迫使用rsGetElementAt,例如:
爪哇:
script.set_input(inputAllocation);
RS:
rs_allocation input;
void root(const float *v_in, float *v_out, uint32_t x, uint32_t y) {
*v_out = rsGetElementAt_float(input, x - 1, y - 1) + rsGetElementAt_float(input, x, y - 1) + rsGetElementAt_float(input, x + 1, y - 1) +
rsGetElementAt_float(input, x - 1, y ) + rsGetElementAt_float(input, x, y ) + rsGetElementAt_float(input, x + 1, y ) +
rsGetElementAt_float(input, x - 1, y + 1) + rsGetElementAt_float(input, x, y + 1) + rsGetElementAt_float(input, x + 1, y + 1) ;
}
使用rsGetElementAt()(710 ms)的脚本的平均执行时间几乎是使用input [](390 ms)的内核的两倍,我猜测因为每个调用必须独立重新计算给定x,y坐标的内存偏移量。
我的脚本需要持续运行,所以我试图从中获取所有可能的性能,忽略这么大的加速是非常可惜的。
所以我想知道是否有人可以对此有所了解。
是否真的存在绑定指针不完全顺序的情况,是否有办法强迫它们出现?
在这种情况下,rsGetElementAt()是否真的有必要,或者依靠预先定义的步幅继续使用绑定指针是否安全?
答案 0 :(得分:4)
对于简单的1D分配,绑定指针仅保证是连续的。应使用get / setElementAt _。
访问具有多个维度的任何类型对表现的评论:
rsGetElementAt_float()通常会胜过rsGetElementAt(),因为它知道类型并且可以避免查找stride。所有类型的get / set方法都是如此。
您正在测试哪个操作系统版本? 4.4对这类代码进行了一些重大改进,在很多情况下应该能够将地址计算从循环中拉出来。
操纵指针方法会强制某些GPU驱动程序回退到安全路径。
一些较新的驱动程序(4.4.1)将使用硬件地址计算单元完全删除开销。