我不太确定如何在 PyTorch 中测量 CPU 上深度模型的执行时间,仅用于推理。我在这里列出了其中一些,但它们可能不准确。如果需要,请更正它们,并在需要时提及更多。我在 PyTorch 版本 1.3.1 和 Intel Xeon 上运行,具有 64GB RAM、3.5GHz 处理器和 8 个内核。
我们应该使用time.time()?
with torch.no_grad():
wTime = 0
start = torch.cuda.Event(enable_timing=True)
end = torch.cuda.Event(enable_timing=True)
out = model(input) # JUST FOR WARMUP
start.record()
for i in range(200):
input = torch.rand(1,1,2048,2048).to(device)
# beg = time.time() DO NOT USE FOR GPU
got = net_amplifier(low,for_amplifier)
# wTime+=time.time()-beg DO NOT USE FOR GPU
end.record()
torch.cuda.synchronize()
print('execution time in MILLISECONDS: {}'.format(start.elapsed_time(end)/200))
Run Code Online (Sandbox Code Playgroud)
对于此代码执行是在 GPU 上完成的。如果我必须在 CPU 上运行它们,应该进行哪些更改?会time.time()吗?
volatile?
input = Variable(torch.randn(1, 3, 227, 227), volatile=True)
model(input)
Run Code Online (Sandbox Code Playgroud)
是否应该清除页面缓存?
sudo sh -c "/bin/echo 1 > /proc/sys/vm/drop_caches"我应该删除nn.Sequential()并直接放入前部吗
所有使用 copy_ 的方法都需要一些时间来执行,尤其是在 CPU 上这可能会很慢。此外,nn.Sequential() 模块比仅在前向传递时执行它们要慢。我认为这是由于在执行 Sequential 模块时需要创建一些开销。
我在同一个链接上不明白的另一件事是
如果您遇到这些小数字的性能问题,您可以尝试使用 torch.set_flush_denormal(True) 在 CPU 上禁用非正规浮点数。
应该torch.set_num_threads(int)用吗?如果是,可以提供演示代码吗?
文档中These context managers are thread local, so they won’t work if you send work to another thread using the :module:`threading` module, etc.给出的含义是什么。
请列出在 CPU 中计算执行时间的更多问题。 谢谢
- 我们应该使用 time.time() 吗?
是的,CPU没问题
- 我们应该使用 volatile 吗?
正如你所说,它已被弃用。由于0.4.0 torch.Tensor已与torch.Variable(它也已弃用)合并,因此torch.no_grad应使用上下文管理器。
- 是否应该清除页面缓存?
我不这么认为,除非你知道这是一个问题
- 我应该删除 nn.Sequential() 并直接放入前部吗
不,torch.nn.Sequential您的模型应该没有或可以忽略不计的性能负担。它的前进只是:
def forward(self, input):
for module in self:
input = module(input)
return input
Run Code Online (Sandbox Code Playgroud)
如果您遇到这些小数字的性能问题,您可以尝试使用 torch.set_flush_denormal(True) 在 CPU 上禁用非正规浮点数。
刷新非正规数字(下溢的数字)意味着严格替换它们,0.0如果您有很多非常小的数字,这可能有助于提高您的性能。PyTorch 文档给出的示例:
>>> torch.set_flush_denormal(True)
True
>>> torch.tensor([1e-323], dtype=torch.float64)
tensor([ 0.], dtype=torch.float64)
>>> torch.set_flush_denormal(False)
True
>>> torch.tensor([1e-323], dtype=torch.float64)
tensor(9.88131e-324 *
[ 1.0000], dtype=torch.float64)
Run Code Online (Sandbox Code Playgroud)
应该使用 torch.set_num_threads(int) 吗?如果是,可以提供演示代码吗?
根据本文档,如果您不分配太多线程(可能最多与 CPU 中的内核数一样多,因此您可以尝试 8 个),这可能会有所帮助。
所以这段代码开头的部分可能会有所帮助:
torch.set_num_threads(8)
Run Code Online (Sandbox Code Playgroud)
您可能想检查数字,看看每个值是否有帮助以及有多大帮助。
这些上下文管理器是线程本地的,因此如果您使用 :module:
threading模块等将工作发送到另一个线程,它们将无法工作,如文档中所述。
如果您使用模块 liketorch.multiprocessing并运行torch.multiprocessing.spawn(或类似)并且您的进程之一不会进入上下文管理器块,则不会关闭渐变(在 的情况下torch.no_grad)。此外,如果您使用 Python 的线程,则只有遇到块的线程才会关闭(或打开,这取决于)渐变。
这段代码会让你一目了然:
import threading
import torch
def myfunc(i, tensor):
if i % 2 == 0:
with torch.no_grad():
z = tensor * 2
else:
z = tensor * 2
print(i, z.requires_grad)
if __name__ == "__main__":
tensor = torch.randn(5, requires_grad=True)
with torch.no_grad():
for i in range(10):
t = threading.Thread(target=myfunc, args=(i, tensor))
t.start()
Run Code Online (Sandbox Code Playgroud)
哪些输出(顺序可能会有所不同):
0 False
1 True
2 False
3 True
4 False
6 False
5 True
7 True
8 False
9 True
Run Code Online (Sandbox Code Playgroud)
还要注意torch.no_grad()in__main__对产生的线程没有影响(也不会torch.enable_grad)。
请列出在 CPU 中计算执行时间的更多问题。
转换为torchscript(请参阅此处)可能会有所帮助,从针对您的架构的源代码构建 PyTorch 以及它的功能和大量其他内容,这个问题太宽泛了。