मैं वर्तमान में साइथन में मूल मैट्रिक्स वेक्टर गुणा को लागू करने की कोशिश कर रहा हूं (larger project to reduce computation के हिस्से के रूप में) और यह पता लगाना कि मेरा कोड Numpy.dot
से 2x धीमी है।मैट्रिक्स वेक्टर गुणा के मेरे साइथन कार्यान्वयन में 2x मंदी का कारण क्या है?
मुझे आश्चर्य है कि क्या ऐसा कुछ है जो मुझे याद आ रहा है जिसके परिणामस्वरूप मंदी हुई है। मैं अनुकूलित साइथन कोड लिख रहा हूं, परिवर्तनीय प्रकार घोषित कर रहा हूं, संगत सरणी की आवश्यकता है, और कैश मिस से परहेज कर रहा हूं। मैंने साइथन को एक रैपर के रूप में रखने और देशी सी कोड को कॉल करने का प्रयास किया (नीचे देखें)।
मुझे आश्चर्य है: मेरे कार्यान्वयन को तेज करने के लिए मैं और क्या कर सकता हूं ताकि इस मूल ऑपरेशन के लिए जल्द से जल्द NumPy चल सके?
Cython कोड है कि मैं का उपयोग कर रहा है beow:
import numpy as np
cimport numpy as np
cimport cython
DTYPE = np.float64;
ctypedef np.float64_t DTYPE_T
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def matrix_vector_multiplication(np.ndarray[DTYPE_T, ndim=2] A, np.ndarray[DTYPE_T, ndim=1] x):
cdef Py_ssize_t i, j
cdef Py_ssize_t N = A.shape[0]
cdef Py_ssize_t D = A.shape[1]
cdef np.ndarray[DTYPE_T, ndim=1] y = np.empty(N, dtype = DTYPE)
cdef DTYPE_T val
for i in range(N):
val = 0.0
for j in range(D):
val += A[i,j] * x[j]
y[i] = val
return y
मैं इस फ़ाइल (seMatrixVectorExample.pyx
) संकलन कर रहा हूँ निम्न स्क्रिप्ट का उपयोग कर:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np
ext_modules=[ Extension("seMatrixVectorExample",
["seMatrixVectorExample.pyx"],
libraries=["m"],
extra_compile_args = ["-ffast-math"])]
setup(
name = "seMatrixVectorExample",
cmdclass = {"build_ext": build_ext},
include_dirs = [np.get_include()],
ext_modules = ext_modules
)
और का उपयोग कर निम्नलिखित प्रदर्शन का आकलन करने के लिए परीक्षण स्क्रिप्ट:
import numpy as np
from seMatrixVectorExample import matrix_vector_multiplication
import time
n_rows, n_cols = 1e6, 100
np.random.seed(seed = 0)
#initialize data matrix X and label vector Y
A = np.random.random(size=(n_rows, n_cols))
np.require(A, requirements = ['C'])
x = np.random.random(size=n_cols)
x = np.require(x, requirements = ['C'])
start_time = time.time()
scores = matrix_vector_multiplication(A, x)
print "cython runtime = %1.5f seconds" % (time.time() - start_time)
start_time = time.time()
py_scores = np.exp(A.dot(x))
print "numpy runtime = %1.5f seconds" % (time.time() - start_time)
n_rows = 10e6
और n_cols = 100
के साथ एक परीक्षण मैट्रिक्स के लिए मैं मिलता है:
cython runtime = 0.08852 seconds
numpy runtime = 0.04372 seconds
संपादित करें: ऐसा नहीं है कि मंदी भी बनी रहती है जब मैं देशी सी कोड में आव्यूह गुणन को लागू उल्लेख के लायक है, और केवल उपयोग एक रैपर के रूप में साइथन।
void c_matrix_vector_multiplication(double* y, double* A, double* x, int N, int D) {
int i, j;
int index = 0;
double val;
for (i = 0; i < N; i++) {
val = 0.0;
for (j = 0; j < D; j++) {
val = val + A[index] * x[j];
index++;
}
y[i] = val;
}
return;
}
और यहाँ Cython आवरण, जो सिर्फ y
, A
और x
के पहले तत्व के लिए सूचक भेजता है। :
import cython
import numpy as np
cimport numpy as np
DTYPE = np.float64;
ctypedef np.float64_t DTYPE_T
# declare the interface to the C code
cdef extern void c_multiply (double* y, double* A, double* x, int N, int D)
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def multiply(np.ndarray[DTYPE_T, ndim=2, mode="c"] A, np.ndarray[DTYPE_T, ndim=1, mode="c"] x):
cdef int N = A.shape[0]
cdef int D = A.shape[1]
cdef np.ndarray[DTYPE_T, ndim=1, mode = "c"] y = np.empty(N, dtype = DTYPE)
c_multiply (&y[0], &A[0,0], &x[0], N, D)
return y
[यह] (http://stackoverflow.com/questions/10442365/why-is-matrix-multiplication-faster-with-numpy-than-with-ctypes-in-python) प्रश्न/उत्तर संबंधित उत्तर के शीर्ष कारणों से संबंधित विभिन्न कारणों से संबंधित है। इसकी जांच - पड़ताल करें। – russianfool
@russianfool धन्यवाद! मैंने वास्तव में उस प्रश्न के उत्तर के माध्यम से पढ़ा था, लेकिन दिए गए कारण इस समस्या से प्रासंगिक नहीं हैं क्योंकि मै मैट्रिक्स-मैट्रिक्स गुणा के बजाय मैट्रिक्स-वेक्टर गुणा से निपट रहा हूं। मैं इसे अपने प्रश्न में स्पष्ट कर दूंगा। –
कुछ हद तक मुझसे संबंधित लगता है; अर्थात्, बीएलएएस/अनियंत्रित लूप के बारे में बिट्स पढ़ें। आप एक मैट्रिक्स-वेक्टर गुणा कार्यान्वयन [यहां] (http://www.netlib.org/clapack/cblas/cgemv.c) पा सकते हैं, और यह निश्चित रूप से ऐसा लगता है कि आपके पास उस डेटा के आधार पर विभिन्न अनुकूलित संस्करण हैं जो आप हैं गुजर रहा है। एक तरफ ध्यान दें, मैं distutils से बहुत परिचित नहीं हूँ ... क्या आप -O2 को अतिरिक्त_कंपाइल_र्ग में से एक के रूप में पास कर सकते हैं? यदि यह हुड के तहत -ओ 2 के साथ संकलित नहीं है, तो प्रदर्शन की तुलना करने के लिए यह समझ में नहीं आता है। – russianfool