0

在优化以下代码方面有什么建议吗?代码首先对图像进行灰度、反转然后阈值处理(代码不包括在内,因为它很简单)。然后它对每一行和每一列的元素求和(所有元素都是 1 或 0)。然后它找到具有最高值的行和列的行和列索引。

该代码应该找到图像的质心并且它可以工作,但我想让它更快

我正在为 API 23 开发,因此不能使用缩减内核。

Java 片段:

private int[] sumValueY = new int[640];
private int[] sumValueX = new int[480];

rows_indices_alloc = Allocation.createSized( rs, Element.I32(rs), height, Allocation.USAGE_SCRIPT);
col_indices_alloc = Allocation.createSized( rs, Element.I32(rs), width, Allocation.USAGE_SCRIPT);

public RenderscriptProcessor(RenderScript rs, int width, int height)
{
   mScript.set_gIn(mIntermAllocation);

   mScript.forEach_detectX(rows_indices_alloc);
   mScript.forEach_detectY(col_indices_alloc);

   rows_indices_alloc.copyTo(sumValueX);
   col_indices_alloc.copyTo(sumValueY);
 }

Renderscript.rs 片段:

#pragma version(1)
#pragma rs java_package_name(org.gearvrf.renderscript)
#include "rs_debug.rsh"
#pragma rs_fp_relaxed

const int mImageWidth=640;
const int mImageHeight=480;

int32_t maxsX=-1;
int32_t maxIndexX;

int32_t maxsY=-1;
int32_t maxIndexY;

rs_allocation gIn;

void detectX(int32_t v_in, int32_t x, int32_t y) {

    int32_t sum=0;

    for ( int i = 0; i < (mImageWidth); i++) {

       float4 f4 = rsUnpackColor8888(rsGetElementAt_uchar4(gIn, i, x));
       sum+=(int)f4.r;
    }

    if((sum>maxsX)){

        maxsX=sum;
        maxIndexX = x;
    }
}

void detectY(int32_t v_in, int32_t x, int32_t y) {

     int32_t sum=0;

     for ( int i = 0; i < (mImageHeight); i++) {

        float4 f4 = rsUnpackColor8888(rsGetElementAt_uchar4(gIn, x, i));
        sum+=(int)f4.r;
     }

     if((sum>maxsY)){
         maxsY=sum;
         maxIndexY = x;
     }

}

任何帮助,将不胜感激

4

1 回答 1

0
float4 f4 = rsUnpackColor8888(rsGetElementAt_uchar4(gIn, x, i));
sum+=(int)f4.r;

这会从 int 转换为 float,然后再转换回 int。我认为你可以通过这样做来简化:

sum += rsGetElementAt_uchar4(gIn, x, i).r;

我不知道你之前的阶段是如何工作的,因为你还没有发布它们,但你应该尝试生成打包值以在此处阅读。因此,要么将灰度通道放入 .rgba 中,要么使用单通道格式,然后使用 rsAllocationVLoad_uchar4 一次获取 4 个值。

此外,尝试将之前的阶段与这一阶段结合起来,如果您不需要这些计算的中间结果,那么执行一次内存加载然后在寄存器中进行这些转换可能会更便宜。

您还可以使用线程操作的值的数量。您可以尝试让每个内核处理 width/2、width/4、width/8 元素并查看它们的性能。这将为 GPU 提供更多的线程,尤其是在较低分辨率的图像上,但需要权衡更多的缩减步骤。

您在 maxsX/maxsY 和 maxIndexX/maxIndexY 变量上还有一个多写者竞争条件。如果您关心确切的正确答案,所有这些写入都需要使用原子。我想也许您发布了错误的代码,因为您没有存储到 *_indices_alloc 中,而是在最后从它们中复制。因此,实际上您应该将所有总和存储到其中,然后使用单线程函数或带有原子的内核来获得绝对最大和最大索引。

于 2017-04-02T17:59:24.210 回答