RenderScript绑定指针与分配

mon*_*eci 5 android renderscript

RenderScript是否保证内存布局或跨越从Java层绑定的全局指针?

我在某处读到最好使用rsGetElementAt/rsSetElementAt函数,因为不保证布局.

其他地方据说在针对GPU优化时避免使用这些优化,而绑定指针则可以.


在我的特定情况下,我需要内核来访问许多周围像素的值.到目前为止,我已经完成了从Java层绑定的浮点指针.

Java的:

script.set_width(inputWidth);
script.bind_input(inputAllocation);
Run Code Online (Sandbox Code Playgroud)

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] ;
}
Run Code Online (Sandbox Code Playgroud)

这是对我实际做的简单的简化,只是为了通过一个例子轻松说明.实际上,我正在做更多的这些组合和同时使用多个输入图像,以至于如此预先计算"上方"和"下方"行的位置有助于处理大量事务时间.

只要内存保证顺序并按照您通常所期望的顺序排列,一切都很好,到目前为止我的测试设备上没有任何问题.


但是如果所有设备/处理器都无法保证这种内存布局,并且步幅实际上可能会有所不同,那么我的代码显然会中断,我将被迫使用rsGetElementAt,例如:

Java的:

script.set_input(inputAllocation);
Run Code Online (Sandbox Code Playgroud)

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) ;
}
Run Code Online (Sandbox Code Playgroud)

使用rsGetElementAt()(710 ms)的脚本的平均执行时间几乎是使用input [](390 ms)的内核的两倍,我猜是因为每个调用必须独立地重新计算内存偏移量给定的x,y坐标.

我的脚本需要连续运行,所以我试图从中获得所有可能的性能,忽略如此大的加速是非常可惜的.


所以我想知道是否有人可以对此有所了解.

是否真的有任何情况下绑定指针不会完全顺序,有没有办法强制它们?

在这种情况下,rsGetElementAt()是否真的有必要,或者依赖于预先定义的步幅继续使用绑定指针是否安全?

R. *_*ams 4

对于简单的一维分配,绑定指针仅保证是连续的。任何具有多于一维的类型都应使用 get/setElementAt_ 进行访问。

性能点评:

rsGetElementAt_float() 通常会优于 rsGetElementAt(),因为它知道类型并且可以避免查找步幅。所有类型化的 get/set 方法都是如此。

您正在哪个操作系统版本上进行测试?4.4 对此类代码进行了一些重大改进,在许多情况下应该能够将地址计算从循环中拉出来。

操纵指针方法将迫使某些 GPU 驱动程序回退到安全路径。

一些较新的驱动程序 (4.4.1) 将使用硬件地址计算单元来完全消除开销。