2017-09-06 5 views
5

का तेज़ इंटरपोलेशन मैं 3-आयामी सरणी के अंदर डेटा के एक अक्ष को अलग करना चाहता हूं। अलग-अलग वैल के लिए दिए गए एक्स-मान थोड़ा भिन्न होते हैं लेकिन उन्हें सभी को समान एक्स-मानों पर मैप किया जाना चाहिए।एक सरणी अक्ष

के बाद दिए गए एक्स-मूल्यों समान नहीं हैं, वर्तमान में मैं निम्न कार्य करें:

import numpy as np 
from scipy import interpolate 

axes_have = np.ones((2, 72, 2001)) 
axes_have *= np.linspace(0, 100, 2001)[None,None,:] 
axes_have += np.linspace(-0.3, 0.3, 144).reshape((2, 72))[:,:,None] 

arr = np.sin(axes_have) 
arr *= np.random.random((2, 72))[:,:,None] 

axis_want = np.linspace(0, 100, 201)  

arr_ip = np.zeros((2, 72, 201)) 
for i in range(arr.shape[0]): 
    for j in range(arr.shape[1]): 
     ip_func = interpolate.PchipInterpolator(axes_have[i,j,:], arr[i,j,:], extrapolate=True) 
     arr_ip[i,j,:] = ip_func(axis_want) 

दो नेस्टेड for -loops का उपयोग करते हुए आश्चर्य बहुत धीमी है।

क्या गति में सुधार करने का कोई तरीका है? शायद कुछ NumPy सरणी जादू या समांतरता करके।

+0

क्या आप 'arr' का नमूना जोड़ सकते हैं? – DJK

+0

मेरे उदाहरण में एक त्रुटि हुई, जो अभी तय है। अब 'एआर' दिया जाना चाहिए। – leviathan

उत्तर

5

मैंने कुछ प्रारंभिक परीक्षण किया है और ऐसा लगता है कि आपके समय का विशाल हिस्सा वास्तविक इंटरपोलेशन फ़ंक्शंस उत्पन्न करने में व्यतीत होता है। ऐसा लगता है कि वेक्टरेशन केवल एक टन की गति नहीं करेगा, लेकिन यह समानांतरता को आसान बनाता है (जो उपज गति बढ़ता है)। यहां एक उदाहरण दिया गया है।

import numpy as np 
from scipy import interpolate 
import timeit 
import multiprocessing 



def myfunc(arg): 
    x, y = arg 
    return interpolate.PchipInterpolator(x, 
             y, 
             extrapolate=True) 

p = multiprocessing.Pool(processes=8) 
axes_have = np.ones((2, 72, 2001)) 
axes_have *= np.linspace(0, 100, 2001)[None, None, :] 
axes_have += np.linspace(-0.3, 0.3, 144).reshape((2, 72))[:, :, None] 

arr = np.sin(axes_have) 
arr *= np.random.random((2, 72))[:, :, None] 

axis_want = np.linspace(0, 100, 201) 

arr_ip = np.zeros((2, 72, 201)) 
s_time1 = timeit.default_timer() 
for i in range(arr.shape[0]): 
    for j in range(arr.shape[1]): 
     ip_func = interpolate.PchipInterpolator(axes_have[i, j, :], 
               arr[i, j, :], 
               extrapolate=True) 
     arr_ip[i, j, :] = ip_func(axis_want) 
elapsed1 = timeit.default_timer() - s_time1 

s_time2 = timeit.default_timer() 
flatten_have = [y for x in axes_have for y in x] 
flatten_arr = [y for x in arr for y in x] 
interp_time = timeit.default_timer() 
funcs = p.map(myfunc, zip(flatten_have, flatten_arr)) 
interp_elapsed = timeit.default_timer() - interp_time 
arr_ip = np.asarray([func(axis_want) for func in funcs]).reshape(2, 72, 201) 
elapsed2 = timeit.default_timer() - s_time2 

print("Elapsed 1: {}".format(elapsed1)) 
print("Elapsed 2: {}".format(elapsed2)) 
print("Elapsed interp: {}".format(interp_elapsed)) 

ठेठ परिणाम (ध्यान दें साथ में चलाना बिना काफी ठीक उसी गति है कि vectorized कार्यान्वयन और मैं 2 कोर है, इसलिए अपने क्रम मोटे तौर पर (मूल समय/कोर के #) होना चाहिए):

Elapsed 1: 10.4025919437 
Elapsed 2: 5.11409401894 
Elapsed interp: 5.10987687111 

मुझे गलत मत समझो, ऐसा करने के लिए एक एल्गोरिदमिक तरीका हो सकता है, लेकिन यह तत्काल गति उत्पन्न करने का सबसे आसान तरीका है, क्योंकि समस्या शर्मनाक समानांतर है।

संबंधित मुद्दे