我需要帮助解决如何在Python中自动化基准测试的问题,涉及到IT技术。我正在测试通过numpy调用BLAS库时线程数量对性能的影响。在Linux环境中,OpenBLAS中的线程是通过环境变量OMP_NUM_THREADS控制的。我想进行一项测试,将OMP_NUM_THREADS从1逐步增加到最大值,在每个线程计数下测量程序运行时间,并最终处理所有线程计数的总时间。但遇到的问题是:虽然在Python中可以设置环境变量,但这只影响子进程或子shell。因此,我可以使用以下驱动代码正确地运行我的基准测试:
#!/usr/bin/env python # driver script for thread test
import os
thread_set =[1,2,4,8,16]
for thread in thread_set:
os.environ['OMP_NUM_THREADS']='{:d}'.format(thread)
os.system("echo $OMP_NUM_THREADS")
os.system("numpy_test")
以及numpy_test脚本:
#!/usr/bin/env python
#timing test for numpy dot product (using OpenBLAS)
#based on https://dev59.com/Hmgu5IYBdhLWcg3wRlL0
import sys
import timeit
setup = "import numpy; x = numpy.random.random((1000,1000))"
count = 5
t = timeit.Timer("numpy.dot(x, x.T)", setup=setup)
dot_time = t.timeit(count)/count
print("dot: {:7.3g} sec".format(dot_time))
然而,分析这个过程是一个非常手动的过程。
特别地,我无法将numpy_test
中的dot_time
值传回到我的外部包装函数,因此我无法以任何自动化方式分析测试结果。例如,我想绘制dot_time
与线程数之间的关系图,或者评估dot_time
/ 线程数是否恒定。
如果我尝试在Python实例内完全通过定义Python测试函数(避免上面的os.system()
方法),然后在thread in thread_set
循环内运行测试函数,则所有测试函数实例都会继承相同的OMP_NUM_THREADS
值(即父Python shell的值)。因此,这个测试失败了:
#!/usr/bin/env python
#attempt at testing threads that doesn't work
#(always uses inherited value of OMP_NUM_THREADS)
import os
import sys
import timeit
def test_numpy():
setup = "import numpy; x = numpy.random.random((1000,1000))"
count = 5
t = timeit.Timer("numpy.dot(x, x.T)", setup=setup)
dot_time = t.timeit(count)/count
print("dot: {:7.3g} sec".format(dot_time))
return dot_time
thread_set =[1,2,4,8,16]
for thread in thread_set:
os.environ['OMP_NUM_THREADS']='{:d}'.format(thread)
os.system("echo $OMP_NUM_THREADS")
time_to_run = test_numpy()
print(time_to_run)
这种方法会失败,因为每个thread
实例执行的时间都相同,test_numpy()
总是继承父环境中OMP_NUM_THREADS
的值,而不是通过os.environ()
设置的值。然而,如果类似于这样的解决方案有效,那么我需要进行的分析将变得非常简单。
在真正的测试中,我将运行几千个排列,所以自动化至关重要。基于此,我希望能得到以下任一问题的答案:
如何从子进程返回值(
dot_time
)?是否有更优雅的解决方案,而不是读/写文件?是否有更好的结构化方式来进行这种(依赖于环境变量)的测试?
提前感谢您的回答。
proc.comunicate()
中有拼写错误,应该是proc.communicate()
。 - bpbrown