首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Nvidia盾牌上正确计时Android RenderScript代码

如何在Nvidia盾牌上正确计时Android RenderScript代码
EN

Stack Overflow用户
提问于 2016-05-06 20:11:40
回答 2查看 633关注 0票数 7

我已经在RenderScript中实现了一个小的CNN,并想在不同的硬件上分析性能。在我的Nexus 7时代是合理的,但在NVIDIA盾,他们没有。

CNN (LeNet)是在一个队列中的9个层中实现的,计算是按顺序进行的。每一层都是单独计时的。

下面是一个示例:

代码语言:javascript
复制
       conv1  pool1 conv2  pool2 resh1 ip1    relu1  ip2    softmax
nexus7 11.177 7.813 13.357 8.367 8.097 2.1    0.326  1.557  2.667
shield 13.219 1.024 1.567  1.081 0.988 14.588 13.323 14.318 40.347

conv1和conv2 (卷积层)的时间分布对连接区的影响是相当大的。但在盾牌上,时间远远超出了2-4层的合理范围,似乎在接近尾声的时候聚集在一起。softmax层是一个相对较小的工作,所以40 is太大了。我的计时方法一定是错误的,否则其他事情正在发生。

运行这些层的代码如下所示:

代码语言:javascript
复制
double[] times = new double[layers.size()];
int layerindex = 0;
for (Layer a : layers) {

    double t = SystemClock.elapsedRealtime(); 
    //long t = System.currentTimeMillis(); // makes no difference

    blob = a.forward(blob); // here we call renderscript forEach_(), invoke_() etc

    //mRS.finish(); // makes no difference

    t = SystemClock.elapsedRealtime() - t; 
    //t = System.currentTimeMillis() - t; // makes no difference

    times[layerindex] += t; // later we take average etc

    layerindex++;
}

我的理解是,一旦forEach_()返回,作业就应该完成。无论如何,mRS.finish()应该提供一个最后的屏障。但放眼时代,唯一合理的解释是,工作仍然是在后台处理的。

这个应用程序非常简单,我只是运行测试从MainActivity和打印到logcat。Android将此应用程序作为发布版构建,并在通过USB连接的设备上运行。

(1)对RenderScript进程进行计时的正确方法是什么?(2)当forEach_()返回时,脚本生成的线程可以保证完成吗?(3)在我的测试应用程序中,我只是直接从MainActivity运行。这是一个问题吗(除了阻塞UI线程和使应用程序没有响应外)?如果这会影响时间或者导致奇怪,那么有什么合适的方法来设置这样的测试应用程序呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-06 20:52:52

我自己在RenderScript中实现了CNN,正如您解释的那样,如果您将每个进程作为不同的内核实现,则需要对每个层链接多个进程并多次调用它们。因此,我可以向您保证,forEach调用返回并不能真正保证流程已经完成。理论上,这只会安排内核,所有排队的请求实际上都会在系统确定最好的情况下运行,特别是当这些请求在tablet的GPU中被处理时。

通常,确保对内核真正运行有某种控制的唯一方法是在层间显式读取RS内核的输出,例如在内核的输出分配对象上使用.copyTo()。这个“强制”任何排队的RS作业尚未运行(该层的输出分配是依赖的),在那个时候执行。当然,这可能会引入数据传输开销,您的时间安排也不会完全准确--事实上,如果以这种方式计时,整个网络的执行时间肯定会低于各个层的总和。但据我所知,这是唯一可靠的方法来计时链中的单个内核,它将给您一些反馈,以找出瓶颈所在,并更好地指导您的优化,如果这就是您所追求的。

票数 3
EN

Stack Overflow用户

发布于 2016-05-13 22:29:55

也许有点离题:但是对于CNN来说,如果你可以用矩阵乘法作为基本计算块来构造你的算法,你实际上可以使用RenderScript IntrinsicBLAS,特别是BNNMSGEMM

优点:

  1. 8位矩阵乘法(BNNM)的高性能实现,可在N预览中使用。
  2. 当使用Build 24.0.0 rc3和更高版本时,通过rc3返回到Android2.3。
  3. 高性能GPU加速的Nexus5X和6P上的SGEMM与N预览构建NPC91K。
  4. 如果只使用RenderScript Intrinsics,则可以用java编写所有代码。

缺点:

  1. 您的算法可能需要重构,并需要基于2d矩阵乘法。
  2. 虽然在Android6.0中可用,但BNNM在6.0中的性能并不令人满意。因此,最好对BNNM使用支持库,并将targetSdkVersion设置为24。
  3. 目前只能在Nexus5X和Nexus6P中使用SGEMM GPU加速。它现在要求矩阵的宽度和高度是8的倍数。

如果BLAS适合你的算法,这是值得一试的。它很容易使用:

代码语言:javascript
复制
    import android.support.v8.renderscript.*;
    // if you are not using support lib:
    // import android.renderscript.*;

    private void runBNNM(int m, int n, int k, byte[] a_byte, byte[] b_byte, int c_offset, RenderScript mRS) {
        Allocation A, B, C;
        Type.Builder builder = new Type.Builder(mRS, Element.U8(mRS));
        Type a_type = builder.setX(k).setY(m).create();
        Type b_type = builder.setX(k).setY(n).create();
        Type c_type = builder.setX(n).setY(m).create();

        // If you are reusing the input Allocations, just create and cache them somewhere else.
        A = Allocation.createTyped(mRS, a_type);
        B = Allocation.createTyped(mRS, b_type);
        C = Allocation.createTyped(mRS, c_type);
        A.copyFrom(a_byte);
        B.copyFrom(b_byte);

        ScriptIntrinsicBLAS blas = ScriptIntrinsicBLAS.create(mRS);
        // Computes: C = A * B.Transpose
        int a_offset = 0;
        int b_offset = 0;
        int c_offset = 0;
        int c_multiplier = 1;
        blas.BNNM(A, a_offset, B, b_offset, C, c_offset, c_multiplier);
    }

SGEMM也是如此:

代码语言:javascript
复制
        ScriptIntrinsicBLAS blas = ScriptIntrinsicBLAS.create(mRS);
        // Construct the Allocations: A, B, C somewhere and make sure the dimensions match.
        // Computes: C = 1.0f * A * B + 0.0f * C
        float alpha = 1.0f;
        float beta = 0.0f;
        blas.SGEMM(ScriptIntrinsicBLAS.NO_TRANSPOSE, ScriptIntrinsicBLAS.NO_TRANSPOSE,
                   alpha, A, B, beta, C);
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37080673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档