9

Cythonを使用して最適化したい次のコードがあります。

sim = numpy.dot(v1, v2) / (sqrt(numpy.dot(v1, v1)) * sqrt(numpy.dot(v2, v2))) 
dist = 1-sim
return dist

.pyxファイルを作成してコンパイルしましたが、コードを実行しても、パフォーマンスに大きな改善は見られません。Cythonのドキュメントによると、c_typesを追加する必要があります。Cythonによって生成されたHTMLファイルは、ボトルネックがドット積であることを示しています(もちろんこれは予想されます)。これは、内積のC関数を定義する必要があることを意味しますか?はいの場合、どうすればよいですか?

編集:

いくつかの調査の後、私は次のコードを思いついた。改善はごくわずかです。私はそれを改善するために私ができることがあるかどうかわかりません:

from __future__ import division
import numpy as np
import math as m
cimport numpy as np
cimport cython

cdef extern from "math.h":
    double c_sqrt "sqrt"(double)

ctypedef np.float reals #typedef_for easier readding

cdef inline double dot(np.ndarray[reals,ndim = 1] v1, np.ndarray[reals,ndim = 1] v2):
  cdef double result = 0
  cdef int i = 0
  cdef int length = v1.size
  cdef double el1 = 0
  cdef double el2 = 0
  for i in range(length):
    el1 = v1[i]
    el2 = v2[i]
    result += el1*el2
  return result

@cython.cdivision(True)
def distance(np.ndarray[reals,ndim = 1] ex1, np.ndarray[reals,ndim = 1] ex2):
  cdef double dot12 = dot(ex1, ex2)
  cdef double dot11 = dot(ex1, ex1)
  cdef double dot22 = dot(ex2, ex2)
  cdef double sim = dot12 / (c_sqrt(dot11 * dot22))
  cdef double dist = 1-sim    
  return dist 
4

2 に答える 2

13

一般的な注意として、cython内からnumpy関数を呼び出して他にほとんど何もしていない場合、通常、わずかなゲインしか見られません。通常、Pythonレベルで明示的なforループを使用するコードを静的に入力している場合にのみ大幅なスピードアップが得られます(すでにNumpy C-APIを呼び出しているものではありません)。

カウンターの静的型付け、numpy配列の入力など、ラップアラウンドとboundscheckをFalseに設定して、ドット積のコードを書き、関数のclibバージョンをインポートしてsqrtから、並列を活用してみてください。prangeopenmpを利用するためのloop( )。

于 2012-05-29T00:20:57.613 に答える
0

式を変更できます

sim = numpy.dot(v1, v2) / (sqrt(numpy.dot(v1, v1)) * sqrt(numpy.dot(v2, v2))) 

sim = numpy.dot(v1, v2) / sqrt(numpy.dot(v1, v1) * numpy.dot(v2, v2))
于 2012-05-28T17:18:24.720 に答える