【发布时间】:2016-05-06 20:11:40
【问题描述】:
我已经在 RenderScript 中实现了一个小型 CNN,并且想要分析不同硬件上的性能。在我的 Nexus 7 上,时间是有意义的,但在 NVIDIA Shield 上却没有。
CNN (LeNet) 在 9 层中实现,驻留在队列中,计算是按顺序执行的。每一层都是单独计时的。
这是一个例子:
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 层是一个相对较小的工作,所以 40ms 太大了。一定是我的计时方法有问题,或者有其他问题。
运行层的代码如下所示:
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 Studio 将应用构建为一个版本,并在通过 USB 连接的设备上运行。
(1) 对 RenderScript 进程进行计时的正确方法是什么? (2)当forEach_()返回时,是不是保证了脚本产生的线程执行完毕? (3) 在我的测试应用程序中,我只是直接从 MainActivity 运行。这是一个问题吗(除了阻塞 UI 线程并使应用程序无响应)?如果这会影响时间或导致奇怪,那么设置这样的测试应用程序的正确方法是什么?
【问题讨论】:
-
卷积神经网络。
标签: android multithreading performance timing renderscript