Android RenderScript绑定指针与分配

Android RenderScript绑定指针与分配,android,renderscript,Android,Renderscript,RenderScript是否保证从Java层绑定的全局指针的内存布局或跨步 我读到最好使用rsGetElementAt/rsSetElementAt函数,因为布局没有保证 但据说在针对GPU优化时可以避免这些,而绑定指针是可以的 在我的特殊情况下,我需要内核来访问周围许多像素的值。到目前为止,我已经很好地使用了从Java层绑定的浮点指针 爪哇: 卢比: 这是对我实际所做工作的一个微不足道的简化,只是简单地用一个例子来说明。事实上,我正在做更多的这些组合,同时处理多个输入图像,如此之多,以至于简

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

我读到最好使用rsGetElementAt/rsSetElementAt函数,因为布局没有保证

但据说在针对GPU优化时可以避免这些,而绑定指针是可以的


在我的特殊情况下,我需要内核来访问周围许多像素的值。到目前为止,我已经很好地使用了从Java层绑定的浮点指针

爪哇:

卢比:

这是对我实际所做工作的一个微不足道的简化,只是简单地用一个例子来说明。事实上,我正在做更多的这些组合,同时处理多个输入图像,如此之多,以至于简单地预先计算“上方”和“下方”行的位置可以大大缩短处理时间

只要保证内存是连续的,并且顺序与您通常期望的相同,一切都很好,到目前为止,我的测试设备没有任何问题


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

爪哇:

卢比:

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

我的脚本需要连续运行,所以我正在尝试从中获得所有可能的性能,如果忽略如此可观的加速,那将是一件非常遗憾的事情


所以我想知道是否有人能解释一下

是否真的存在绑定指针不完全连续的情况,是否有办法强制它们完全连续


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

对于简单的1D分配,绑定指针只能保证是顺序的。任何具有多个维度的类型都应使用get/setElementAt\访问

对业绩的评论:

rsGetElementAt_float()的性能通常优于rsGetElementAt(),因为它知道类型,并且可以避免查找stride。这适用于所有类型化的get/set方法

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

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


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

很好,我真的很高兴听到在新的Android版本上有改进。到目前为止,我只在API 16-18上进行了测试。因此,我可能会对脚本进行分支,并将指针版本定位到API<19,因为这仍然要快得多,尽管我会更新它们以使用线性1D分配来保证它们的布局——然后在我可以测试它们之后,利用您在针对API>=19的不同脚本上提到的更新的get/set优化。这也许会奏效。非常感谢。因为它是在设备上编译的,所以不需要根据API级别派生脚本。您现有的脚本应该只在API19设备上获得性能增益,即使它们是根据旧的API编译的。
script.set_width(inputWidth);
script.bind_input(inputAllocation);
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] ;
}
script.set_input(inputAllocation);
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) ;
}