fra*_*ond 6 performance multithreading android timing renderscript
我在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
Run Code Online (Sandbox Code Playgroud)
时间的分布对于nexus来说是正确的,其中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++;
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,一旦forEach_()返回,该作业应该完成.无论如何,mRS.finish()应该提供最后的障碍.但从时代的角度来看,唯一合理的解释是,工作仍然在后台处理.
该应用程序非常简单,我只是从MainActivity运行测试并打印到logcat.Android Studio将应用程序构建为版本,并在通过USB连接的设备上运行.
(1)为RenderScript进程计时的正确方法是什么?(2)当forEach_()返回时,脚本产生的线程是否可以保证完成?(3)在我的测试应用程序中,我只是直接从MainActivity运行.这是一个问题(除了阻止UI线程并使应用程序无响应)?如果这会影响时间或导致奇怪,那么设置这样的测试应用程序的正确方法是什么?
我自己在 RenderScript 中实现了 CNN,正如您所解释的,如果您将它们分别实现为不同的内核,则它确实需要链接多个进程并forEach_*()为每个层调用不同的时间。因此,我可以向您保证,forEach 调用返回并不能真正保证该过程已完成。理论上,这只会调度内核,并且只要系统认为最好,所有排队的请求就会实际运行,特别是当它们在平板电脑的 GPU 中处理时。
通常,确保对真正运行的内核拥有某种控制权的唯一方法是显式读取各层之间 RS 内核的输出,例如通过使用.copyTo()该内核的输出分配对象。这会“强制”任何尚未运行的排队 RS 作业(该层的输出分配依赖于该作业)在那时执行。当然,这可能会带来数据传输开销,并且您的计时不会完全准确 - 事实上,如果以这种方式计时,整个网络的执行时间肯定会低于各个层的总和。但据我所知,这是对链中各个内核进行计时的唯一可靠方法,它会给您一些反馈,以找出瓶颈所在,并更好地指导您的优化(如果这就是您所追求的)。
| 归档时间: |
|
| 查看次数: |
543 次 |
| 最近记录: |