कठोर परिवर्तन - पायथन - speedup - पायथन, प्रदर्शन, numpy, कठोर निकायों

मेरे पास कठोर परिवर्तन की गणना करने के तेज़ तरीके के बारे में प्रश्न हैं (हाँ, मुझे पता है कि मैं बस पुस्तकालय का उपयोग कर सकता हूं लेकिन इसे खुद से कोड करने की आवश्यकता है)।

मुझे दी गई छवि में हर x, y के लिए x "और y" की गणना करने की आवश्यकता है। मेरा मुख्य अड़चन सभी निर्देशांक के लिए डॉट उत्पाद है (इसके बाद प्रक्षेप कोई समस्या नहीं है)। वर्तमान में मैंने तीन विकल्प लागू किए हैं:

  1. सूची समझ

    result = np.array([[np.dot(matrix, np.array([x, y, 1])) for x in xs] for y in ys])
    
  2. सरल डबल-for पाश

    result = np.zeros((Y, X, 3))
    for x in xs:
    for y in ys:
    result[y, x, :] = np.dot(matrix, np.array([x, y, 1]))
    
  3. np.ndenumerate

    result = np.zeros((Y, X, 3))
    for (y, x), value in np.ndenumerate(image):
    result[y, x, :] = np.dot(matrix, np.array([x, y, 1]))
    

512x512 छवियों में सबसे तेज़ तरीका सूची समझ (लगभग 1.5x से अधिक तेज) है np.ndenumerate (लूप के लिए 1.1x तेज डबल)।

क्या इसे तेजी से करने का कोई तरीका है?

उत्तर:

जवाब के लिए 3 № 1

से उधार this postबनाने का विचार 1D के बजाय सरणियाँ 2D या 3D जाल और उन पर मक्खी के साथ का उपयोग कर broadcasted स्मृति दक्षता के लिए संचालन और इस प्रकार प्रदर्शन लाभ प्राप्त करते हैं, यहाँ एक दृष्टिकोण है -

out = ys[:,None,None]*matrix[:,1] + xs[:,None]*matrix[:,0] + matrix[:,2]

यदि आप सभी सूचकांकों को कवर कर रहे हैं xs तथा ys के लिए 512x512 आकार की छवियां, हमने उन्हें बनाया होगा np.arange, इस तरह -

ys = np.arange(512)
xs = np.arange(512)

रनटाइम टेस्ट

कार्य परिभाषाएं -

def original_listcomp_app(matrix, X, Y): # Original soln with list-compr.
ys = np.arange(Y)
xs = np.arange(X)
out = np.array([[np.dot(matrix, np.array([x, y, 1])) for x in xs] 
for y in ys])
return out

def indices_app(matrix, X, Y):        # @Eric"s soln
coords_ext = np.empty((Y, X, 3))
coords_ext[...,[1,0]] = np.rollaxis(np.indices((Y, X)), 0, start=3)
coords_ext[...,2] = 1
result = np.matmul(coords_ext,matrix.T)
return result

def broadcasting_app(matrix, X, Y):  # Broadcasting based
ys = np.arange(Y)
xs = np.arange(X)
out = ys[:,None,None]*matrix[:,1] + xs[:,None]*matrix[:,0] + matrix[:,2]
return out

समय और सत्यापन -

In [242]: # Inputs
...: matrix = np.random.rand(3,3)
...: X,Y = 512, 512
...:

In [243]: out0 = original_listcomp_app(matrix, X, Y)
...: out1 = indices_app(matrix, X, Y)
...: out2 = broadcasting_app(matrix, X, Y)
...:

In [244]: np.allclose(out0, out1)
Out[244]: True

In [245]: np.allclose(out0, out2)
Out[245]: True

In [253]: %timeit original_listcomp_app(matrix, X, Y)
1 loops, best of 3: 1.32 s per loop

In [254]: %timeit indices_app(matrix, X, Y)
100 loops, best of 3: 16.1 ms per loop

In [255]: %timeit broadcasting_app(matrix, X, Y)
100 loops, best of 3: 9.64 ms per loop

जवाब के लिए 3 № 2

आप उपयोग कर सकते हैं np.indices तथा np.rollaxis एक 3 डी सरणी उत्पन्न करने के लिए, जहां coords[i, j] == [i, j]। यहां निर्देशांक को स्विचिंग की आवश्यकता होती है

तो फिर तुम सब करना है 1 आप मांगते हैं, और उपयोग करते हैं @

coords_ext = np.empty((Y, X, 3))
coords_ext[...,[1,0]] = np.rollaxis(np.indices((Y, X)), 0, start=3)
coords_ext[...,2] = 1

# convert to column vectors and back for matmul broadcasting
result = (matrix @ coords_ext[...,None])[...,0]

# or alternatively, work with row vectors and do it in the other order
result = coords_ext @ matrix.T

संबंधित सवाल
सबसे लोकप्रिय