如何制作' tqdm.set_postfix_str的更快呢?



当我使用tqdm时,我想要跟踪迭代期间计算的分数,因此我使用set_postfix_str方法。但我发现它会大大降低程序的速度:

from tqdm import tqdm
import time
N = 10000
pbar = tqdm(range(N), total=N, desc="N")
start = time.time()
for i in pbar:
pass
print("w/o set_postfix_str: {:.2f}".format(time.time() - start))
pbar = tqdm(range(N), total=N, desc="N")
start = time.time()
for i in pbar:
pass
pbar.set_postfix_str(s="{}".format(i))
print("w set_postfix_str: {:.2f}".format(time.time() - start))

输出:

N: 100% |██████████| 10000/10000 [00:00<00:00, 1239195.20/s)
w/o set_postfix_str: 0.01
N: 100% |██████████| 10000/10000 [/s 00:12<00:00, 774.67, 9999]
w set_postfix_str:

12.91我试图在tqdm中设置miniters,但它没有帮助。如何使它更快?

设置bar_format参数如何

import time
from tqdm import tqdm
N = 10000000 #I increased the number to see something in my machine
pbar = tqdm(range(N), total=N, desc="N")
start = time.time()
for i in pbar:
pass
print("w/o set_postfix_str: {:.2f}".format(time.time() - start))
pbar = tqdm(range(N), total=N, desc="N",bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt} {n_fmt}]')
start = time.time()
for i in pbar:
pass
print("w custom bar: {:.2f}".format(time.time() - start))

bar_format默认为'{l_bar}{bar}{r_bar}',在这种情况下,我们想改变{r_bar}部分,反过来默认为'| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, ' '{rate_fmt}{postfix}]',我尝试一些组合,只是传递后缀参数,但没有成功,所以显式地把所有在bar_format是我找到的解决方案,因此我们改变后缀部分我们想要的,在你的例子中相当于n_fmt,因此新的bar_format是

'{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt} {n_fmt}]'

和快速测试

C:UserscopperfieldDesktop>test.py
N: 100%|███████████████████████████| 10000000/10000000 [00:01<00:00, 5168526.86it/s]
w/o set_postfix_str: 1.93
N: 100%|██████████████████| 10000000/10000000 [00:01<00:00, 5320703.94it/s 10000000]
w custom bar: 1.88
C:UserscopperfieldDesktop>

结果快了一点有趣的是


进一步修修补补,也看着tqdm的源代码,为了不使用这个定制的酒吧的事,因为说我们想要的东西,循环计算,不是进度跟踪,如在上一个示例中,这个也set_postfix_str第二个参数refresh默认情况下是正确的,只是改变它为False,它仍将是缓慢而简单的情况,但并不是极端的数量,在我的测试中只慢了大约3倍

pbar = tqdm(range(N),total=N, desc="N")
start = time.time()
for i in pbar:
pbar.set_postfix_str(f"{i}",refresh=False)
print("w set_postfix_str refresh=False: {:.2f}".format(time.time() - start))

,在看了源代码之后,它所做的唯一的事情就是设置一个属性,所以让我们跳过中间的步骤,直接执行

pbar = tqdm(range(N),total=N, desc="N")
start = time.time()
for i in pbar:
pbar.postfix=f"{i}"
print("w .postfix: {:.2f}".format(time.time() - start))

这稍微改善了时间,现在只慢了约1.7倍

和快速测试

C:UserscopperfieldDesktop>test.py
N: 100%|██████████████████████████████████████████████████████████████| 10000000/10000000 [00:01<00:00, 5467326.75it/s]
w/o set_postfix_str: 1.83
N: 100%|█████████████████████████████████████████████████████| 10000000/10000000 [00:01<00:00, 5497884.24it/s 10000000]
w custom bar: 1.82
N: 100%|█████████████████████████████████████████████████████| 10000000/10000000 [00:05<00:00, 1874176.95it/s, 9999999]
w set_postfix_str refresh=False: 5.34
N: 100%|█████████████████████████████████████████████████████| 10000000/10000000 [00:03<00:00, 3088319.84it/s, 9999999]
w .postfix: 3.24
C:UserscopperfieldDesktop>

最新更新