### 结论
耗时严重不是由 Tensor.cpu().numpy() 引起的。
### 缘由
今天在运行 [RetinaFace](https://github.com/biubug6/Pytorch_Retinaface) 的 detect.py 时发现当 network 选择 **mobile0.25** 和 **resnet50** 时运行帧率相差很大,想定位下具体的耗时地方。
原代码自带计算网络推理耗时的部分:
```python
tic = time.time()
loc, conf, landms = net(img) # forward pass
print('net forward time: {:.4f}'.format(time.time() - tic))
```
发现在 1080x1920 图片上,**mobile0.25** 推理耗时 0.0070s, **resnet50** 推理耗时 0.011s,二者相差不大,而且不会成为影响最终帧率的原因。
采用上述代码逻辑,逐步二分定位整个代码的耗时。
最终发现 **boxes = boxes.cpu().numpy()** 一句在两种情况下耗时相差一个数量级,**resnet50** 版耗时 0.09s,**mobile0.25** 版耗时 0.007s,成为影响最终帧率的主要原因。
推测 Tensor.cpu().numpy() 耗时严重,继续定位。
**boxes** 变量在两种情况下 shape 都是[85200, 4],类型也都是 torch.cuda.FloatTensor,仅仅一个 copy 操作,加转 numpy,非常纳闷耗时不同的原因。
最终在 [这里](https://www.zhihu.com/question/351033388/answer/1250432139) 找到一个回答解决了这个疑问。
简而言之,**Pytorch 是异步执行,上面统计出的时间是假象**。
修改代码:
```python
torch.cuda.synchronize()
tic = time.time()
loc, conf, landms = net(img) # forward pass
torch.cuda.synchronize()
print('net forward time: {:.4f}'.format(time.time() - tic))
```
**resnet50** 版推理耗时 0.0967s,**mobile0.25** 版推理耗时 0.011s。
后续 **boxes = boxes.cpu().numpy()** 的耗时差异几乎可以忽略不计了。
这才能解释不同网络运行导致的帧率差异。

torch.cuda.synchronize 与 Tensor.cpu().numpy()