use*_*611 2 arrays renderscript
嗨,我是一个新手,并尝试在Renderscript中编码.我想知道如何使用渲染脚本在数组中执行元素的总和.有没有办法可以将输出传递回脚本以便顺序添加?我的问题陈述是:矢量和
描述:计算数组中值的总和.
输入:整数数组
输出:整数
任何帮助将非常感激!
我担心这比看起来要复杂一些,但我会尽力在这里解释一下你可以采取的实现这一目标的途径.
您要求的是更好地称为并行缩减算法,它可以实现像您的情况一样的数组求和,或任何其他可交换+关联运算符,当迭代地应用于数组时,它将"减少"为单个数.其他示例是查找大型数组的最大值或最小值.在CUDA和OpenCL中,有一个众所周知的计算模式,能够最好地使用并行线程,例如,如果你谷歌"CUDA减少",你将获得大量关于此算法的有用信息.
实现它的方法是反复将数组减半,一遍又一遍,直到最后得到一个元素.每次减少它时,每个新元素都是前两个元素的总和.这是一张更好地描绘此算法的图片:

例如,您从一个16元素数组开始.您运行该算法一次,最终得到一个8元素数组 - 其中这8个元素中的每一个都是原始数组中两个数字的总和.
再次运行它,最后得到4个元素 - 其中每个元素都是上一步中两个数字的总和.等等...
你一直这样做,直到你最终得到一个数字 - 你的总和.
一个低效的执行的renderScript这将是这样:
Java的:
int[] ints; // Your data is held here.
Allocation data = Allocation.createSized(rs, Element.I32(rs), ints.length, Allocation.USAGE_SCRIPT);
data.copy1DRangeFrom(0, ints.length, ints);
ScriptC_Reduce script = new ScriptC_Reduce(rs);
script.bind_data(data);
for (int stride = ints.length / 2; stride > 0; stride /= 2) {
script.set_stride(stride);
script.forEach_root(input, output);
}
data.copyTo(ints);
int totalsum = ints[0];
Run Code Online (Sandbox Code Playgroud)
的renderScript:
#pragma version(1)
#pragma rs java_package_name(...[your package here]...)
int stride;
int * data;
void root(const int32_t *v_in, int32_t *v_out, uint32_t x) {
if (x < stride) data[x] += data[x + stride];
}
Run Code Online (Sandbox Code Playgroud)
如果您之前使用过RS,您可能会注意到一些奇怪的事情:
但是,我在上面提到过,这是一个效率低下的实现.但它应该指向正确的方向.为了提高效率,您可能需要将数据拆分为更小的块以便单独计算,因为这里给出的算法将在每个迭代步骤中运行ints.length线程数,并且在非常大的数组上运行将导致一个很大的步骤,和AA 很多在每一步的空闲线程.
此外,这假设您的数组的长度恰好是2的幂,因此多个减半将导致恰好一个元素.对于其他大小的数组,您可能需要对数组进行0填充.再次,当处理非常大的数组时,0填充将需要大量浪费的内存.
因此,要解决这些问题,您可能希望将阵列拆分为多个块,例如每个64个元素.因此,如果您没有精确的数组长度,将"最后"块填充到64将不需要那么多内存.此外,您将需要更少的迭代步骤(以及更少的空闲线程)来减少64个元素.当然,64是我刚刚组成的神奇数字.尝试其他2的幂来查看它们的结果,你可能会看到更好的结果与其他块大小,如16或32.我怀疑性能与块大小将是非常依赖于硬件.
编辑:这假设RenderScript可以为运行它的设备使用GPU驱动程序,以便它可以实际启动大量并行线程.否则,像这样的仅CPU执行内核可能比处理数组线性更慢.