bpb*_*own 5 python multithreading numpy blas python-3.3
我需要一些帮助来弄清楚如何在python中自动执行基准测试。
我正在测试通过python中的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")
Run Code Online (Sandbox Code Playgroud)
和numpy_test脚本:
#!/usr/bin/env python
#timing test for numpy dot product (using OpenBLAS)
#based on http://stackoverflow.com/questions/11443302/compiling-numpy-with-openblas-integration
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))
Run Code Online (Sandbox Code Playgroud)
但是分析这是一个非常手动的过程。
特别是,我无法dot_time从numpy_test外部包装例程返回值,因此无法以任何自动化方式分析测试结果。例如,我想绘制dot_time线程数与线程数的关系图,或评估dot_time/ numbers是否是常数。
如果我尝试通过定义python测试函数(避免使用上述os.system()方法),然后完全在python实例中进行类似的测试thread in thread_set,然后在循环中运行该测试函数,则该测试函数的所有实例都将继承相同的值OMP_NUM_THREADS(父python外壳的代码)。因此此测试失败:
#!/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)
Run Code Online (Sandbox Code Playgroud)
这样做会失败,因为每个实例都thread需要相同的时间,因为它test_numpy()总是继承OMP_NUM_THREADS父环境中的值,而不是继承设置的值os.environ()。但是,如果像这样的事情行得通,那么做我需要做的分析将是微不足道的。
在实际测试中,我将运行1000个以上的排列,因此自动化是关键。鉴于此,对于以下任何问题的解答,我将不胜感激:
您将如何dot_time从这样的子流程返回值()?是否有比读写文件更优雅的解决方案?
有没有更好的方法来构造这种(取决于环境变量)测试?
先感谢您。
你可以这样做:
import subprocess
os.environ['OMP_NUM_THREADS'] = '{:d}'.format(thread)
proc = subprocess.Popen(["numpy_test"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
Run Code Online (Sandbox Code Playgroud)
然后您将在 stdout 中看到脚本的输出numpy_test。总的来说,我相信subprocess.call并且subprocess.Popen更喜欢os.system。