如何在python / numpy中自动执行BLAS的环境变量相关基准测试?

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_timenumpy_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个以上的排列,因此自动化是关键。鉴于此,对于以下任何问题的解答,我将不胜感激:

  1. 您将如何dot_time从这样的子流程返回值()?是否有比读写文件更优雅的解决方案?

  2. 有没有更好的方法来构造这种(取决于环境变量)测试?

先感谢您。

Bi *_*ico 2

你可以这样做:

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