9

私は現在、cython の prange でループを並列化するための簡単な例に従おうとしています。openmpを許可してopenblas 0.2.14をインストールし、openblasに対してソースからnumpy 1.10.1とscipy 0.16をコンパイルしました。ライブラリのパフォーマンスをテストするために、次の例に従っています: http://nealhughes.net/parallelcomp2/。時間を計測する関数は、サイトからコピーされます。

import numpy as np
from math import exp 
from libc.math cimport exp as c_exp
from cython.parallel import prange,parallel

def array_f(X):

    Y = np.zeros(X.shape)
    index = X > 0.5
    Y[index] = np.exp(X[index])

    return Y

def c_array_f(double[:] X):

    cdef int N = X.shape[0]
    cdef double[:] Y = np.zeros(N)
    cdef int i

    for i in range(N):
        if X[i] > 0.5:
            Y[i] = c_exp(X[i])
        else:
            Y[i] = 0

    return Y


def c_array_f_multi(double[:] X):

    cdef int N = X.shape[0]
    cdef double[:] Y = np.zeros(N)
    cdef int i
    with nogil, parallel():
        for i in prange(N):
            if X[i] > 0.5:
                Y[i] = c_exp(X[i])
            else:
                Y[i] = 0

    return Y

コードの作成者は、次の 4 コアの速度向上を報告しています。

from thread_demo import *
import numpy as np
X = -1 + 2*np.random.rand(10000000) 
%timeit array_f(X)
1 loops, best of 3: 222 ms per loop
%timeit c_array_f(X)
10 loops, best of 3: 87.5 ms per loop 
%timeit c_array_f_multi(X)
10 loops, best of 3: 22.4 ms per loop

これらの例を自分のマシン (osx 10.10 を搭載した macbook pro) で実行すると、次のエクスポートのタイミングが得られます。OMP_NUM_THREADS=1

In [1]: from bla import *
In [2]: import numpy as np
In [3]: X = -1 + 2*np.random.rand(10000000)
In [4]: %timeit c_array_f(X)
10 loops, best of 3: 89.7 ms per loop
In [5]: %timeit c_array_f_multi(X)
1 loops, best of 3: 343 ms per loop

そしてOMP_NUM_THREADS=4

In [1]: from bla import *
In [2]: import numpy as np
In [3]: X = -1 + 2*np.random.rand(10000000)
In [4]: %timeit c_array_f(X)
10 loops, best of 3: 89.5 ms per loop
In [5]: %timeit c_array_f_multi(X)
10 loops, best of 3: 119 ms per loop

openSuse マシンでも同じ動作が見られるので、質問します。私のシステムの 2 つで 4 つのスレッドに対して同じコードの実行が遅くなるのに、作成者はどうすれば 4 倍の速度を上げることができるでしょうか。

を生成するためのセットアップ スクリプト*.c & .soも、ブログで使用されているものと同じです。

from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np

ext_modules=[
    Extension("bla",
              ["bla.pyx"],
              libraries=["m"],
              extra_compile_args = ["-O3", "-ffast-math","-march=native", "-fopenmp" ],
              extra_link_args=['-fopenmp'],
              include_dirs = [np.get_include()]
              ) 
]

setup( 
  name = "bla",
  cmdclass = {"build_ext": build_ext},
  ext_modules = ext_modules
)

なぜこれが起こるのか誰かが私に説明できれば素晴らしいでしょう.

4

1 に答える 1