gpt4 book ai didi

android - 在处理 Java for 循环和 C 指针内存访问时,Renderscript 突然神秘地变慢了很多

转载 作者:行者123 更新时间:2023-11-29 16:04:51 25 4
gpt4 key购买 nike

我正在使用装有 Android 4.3 的 Nexus 4 设备。此问题也可以在运行 Android 4.2.2 的 Lenovo K900 中重现。

代码不是在 GPU 上运行,而是在 CPU 上运行,因为我通过 ADB 检查了 CPU 使用率,它显示运行程序时 CPU 使用率超过 90%。

在贴代码之前,我尽量总结一下我遇到的问题。在我的项目中,我需要连续处理一个(或多个)图像并将处理后的结果存储到另一个缓冲区中。根据我使用的算法的性质,我需要按图像行并行化图像处理操作(同时处理不同的图像行)。为此,我创建了一个只有行索引的分配,并使用这个分配来调用 foreach 函数。我还在 RS 端创建了一个全局指针,并在 Java 端将另一个 1D Allocation 绑定(bind)到它,以便 RS 代码可以使用这个指针将结果写入缓冲区。同时,每次运行我还需要多次执行foreach函数。所以在Java中调用foreach函数的时候,我在Java端放在了一个for循环中。但是,我遇到了一件很奇怪的事情。我先贴代码。

在 MainActivity.java 中:

package com.example.slowrs;

import java.io.IOException;
import java.io.InputStream;

import com.example.slowrs.R;

import android.os.Bundle;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.Type;
import android.app.Activity;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.*;
import android.renderscript.*;

public class MainActivity extends Activity implements Button.OnClickListener{
private Bitmap mBitmap;
private RenderScript mRS;
private ScriptC_test mTestScript;

private Allocation mImgAlloc;
private Allocation mRowAlloc;

private TextView mTextView;
private ImageView imgView;

private String TAG = "test";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mRS = RenderScript.create(this);

mBitmap = getImageFromAssetsFile("input.png");
imgView = (ImageView)findViewById(R.id.display);
imgView.setImageBitmap(mBitmap);
imgView.setOnClickListener(this);

mTextView = (TextView)findViewById(R.id.label);

mImgAlloc = Allocation.createFromBitmap(mRS, mBitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
tb.setX(1); tb.setY(mImgAlloc.getType().getY());
Type type = tb.create();
// Parallelize w.r.t this
mRowAlloc = Allocation.createTyped(mRS, type, Allocation.USAGE_SCRIPT);

Type.Builder tb1 = new Type.Builder(mRS, Element.I32(mRS));
tb1.setX(mImgAlloc.getType().getX()*mImgAlloc.getType().getY()); tb1.setY(1);
Type type1 = tb1.create();
Allocation newBufferAlloc = Allocation.createTyped(mRS, type1, Allocation.USAGE_SCRIPT);

mTestScript = new ScriptC_test(mRS, getResources(), R.raw.test);
mTestScript.set_image(mImgAlloc);
mTestScript.bind_buffer(newBufferAlloc);
mTestScript.set_imgWidth(mImgAlloc.getType().getX());
}

public void onClick(View v) {
// TODO Auto-generated method stub
Log.i(TAG, "touched");

long timeBeforeExe = System.nanoTime();

for(int i = 0; i < 150; i++){
mTestScript.forEach_slowTest(mRowAlloc);
}

long ct = System.nanoTime();
long offset = ct - timeBeforeExe;
float offsetInMs = (float)(offset)/1000000;
mTextView.setText("Time: " + Float.toString(offsetInMs) + "ms");
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

private Bitmap getImageFromAssetsFile(String fileName)
{
Bitmap image = null;
AssetManager am = getResources().getAssets();
try
{
InputStream is = am.open(fileName);
image = BitmapFactory.decodeStream(is);
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}

return image;
}
}

在测试.rs中:

#pragma version(1)
#pragma rs java_package_name(com.example.slowrs)
#pragma rs_fp_relaxed

int* buffer;
rs_allocation image;
int imgWidth;

void __attribute__((kernel)) slowTest(uchar in, uint32_t x, uint32_t y){
for(int col = 0; col < imgWidth; col++){
const uchar4 rightImgNextPixel = *(const uchar4*)rsGetElementAt(image, col, y);
buffer[y * imgWidth + col] = rightImgNextPixel.x + 10;
//buffer[y * imgWidth + col] = 10;
}
}

在activity_main.xml(布局)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/toplevel">

<ImageView
android:id="@+id/display"
android:layout_width="320dip"
android:layout_height="266dip" />

<TextView
android:id="@+id/label"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="Time:"
android:padding="2dp"
android:textSize="16sp"
android:gravity="center" />
</LinearLayout>
</RelativeLayout>

我粘贴的三个文件包含重现此问题的所有内容。基本上,我在代码中所做的是将图像加载到 Allocation 并将其显示在屏幕上。一旦点击图像,onClick() 函数就会运行并调用 foreach 函数。

input.png

只是一个普通的 640*480 png 文件,我放在项目的 assets 文件夹中。任何具有相同大小的图像都可以。

我遇到的问题如下。当我轻轻点击图像(大约每秒一次)时,一切都是文件,UI 上的文本显示整个图像处理过程非常快速地完成(在几毫秒内)。但是,如果我更快地点击图像(尽可能快,基本上每秒点击 5 到 6 次),情况就会发生变化。 UI 上的文本显示某些点击需要超过 500 毫秒才能完成(在 Nexus 4 上),而其他点击仍需要几毫秒。据我所见,slower pass 比 fast pass 慢了 100 多倍,这很奇怪。

经过一些测试,我发现有两件事可以让这种突然的减速消失。我要么做

for(int i = 0; i < 1; i++){
mTestScript.forEach_slowTest(mRowAlloc);
}

即在 Java 中使 for 循环更小,或者,

void __attribute__((kernel)) slowTest(uchar in, uint32_t x, uint32_t y){
for(int col = 0; col < imgWidth; col++){
const uchar4 rightImgNextPixel = *(const uchar4*)rsGetElementAt(image, col, y);
//buffer[y * imgWidth + col] = rightImgNextPixel.x + 10;
buffer[y * imgWidth + col] = 10;
}
}

在缓冲区中设置新值时不要引用 rightImgNextPixel.x。两者中的任何一个都会使减速消失。你可以自己测试一下。但是,我无法解释其中任何一个的原因。

这是怎么回事?这个问题让我发疯,严重影响了图像处理任务的性能。请帮忙,谢谢!

最佳答案

您没有测量实际执行时间。尝试添加 rs.finish() 或从您的操作中读取结果。 RS 是异步的,它将操作排队直到缓冲区填满或需要结果。因此内核启动的循环只是排队。

相关,我建议使用内核的返回值来写入输出缓冲区或 rsSetElementAt_uchar4 而不是绑定(bind)全局指针。 RS 不保证 2D 内存的布局,在某些情况下,由于内存的步长与宽度不同,此代码不会生成正确的结果。

关于android - 在处理 Java for 循环和 C 指针内存访问时,Renderscript 突然神秘地变慢了很多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19958970/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com