मैं एक साधारण गतिशील प्रणाली के अनुकरण को अनुकूलित करने की कोशिश कर रहा हूं जिसमें नेटवर्क की प्रतिक्रिया के साथ-साथ इसके पैरामीटर (वजन) सरल रैखिक समीकरणों के अनुसार विकसित होते हैं। सिमुलेशन को लाखों समय के चरणों के लिए चलाने की जरूरत है, लेकिन नेटवर्क का आकार आम तौर पर छोटा होगा। इसलिए, प्रदर्शन मैट्रिक्स-वेक्टर उत्पादों द्वारा कम किया जाता है बल्कि अस्थायी सरणी, बाध्य जांच और अन्य कम दिखाई देने वाले कारकों द्वारा किया जाता है। चूंकि मैं जूलिया के लिए नया हूं, इसलिए मैं प्रदर्शन को और अनुकूलित करने के लिए किसी भी संकेत की सराहना करता हूं।जूलिया: सरल गतिशील प्रणाली के सिमुलेशन को अनुकूलित करें
function train_network(A, T, Of, cs, dt)
N, I = size(T)
z = zeros(I)
r = zeros(N)
@inbounds for t in 1:size(cs, 1)
# precompute
Az = A*z
Ofr = Of*r
# compute training signal
@devec z += dt.*(Az + cs[t] - 0.5.*z)
I_teach = T*(Az + cs[t])
Tz = T*z
# rate updates
@devec r += dt.*(I_teach - Ofr - 0.1.*r)
# weight updates
for i in 1:I
@devec T[:, i] += dt.*1e-3.*(z[i].*r - T[:, i])
end
for n in 1:N
@devec Of[:, n] += dt.*1e-3.*(Tz.*r[n] - Of[:, n])
end
end
end
# init parameters
N, I = 20, 2
dt = 1e-3
# init weights
T = rand(N, I)*N
A = rand(I, I)
Of = rand(N, N)/N
# simulation time & input
sim_T = 2000
ts = 0:dt:sim_T
cs = randn(size(ts, 1), I)
@time train_network(A, T, Of, cs, dt)
साथ नेटवर्क (2.000.000 कदम) समय समय पैदावार
3.420486 seconds (26.12 M allocations: 2.299 GB, 6.65% gc time)
अद्यतन 1
दाऊद सैंडर्स द्वारा सलाह मुझे मिल गया के बाद डेवैक मैक्रो से छुटकारा पा लिया और लूप लिखा। यह वास्तव में सरणी आवंटन कम कर देता है और के बारे में 25% से प्रदर्शन को बढ़ा देता है, यहाँ नया नंबर दिए गए हैं:
2.648113 seconds (18.00 M allocations: 1.669 GB, 5.60% gc time)
छोटे नेटवर्क का आकार, बड़ा बढ़ावा। अद्यतन सिमुलेशन कोड का एक सारांश here पाया जा सकता है।
अद्यतन 2
स्मृति आवंटन की ज्यादातर मैट्रिक्स वेक्टर उत्पादों की वजह से कर रहे हैं। तो, क्रम में उन मैं एक में जगह BLAS आपरेशन, BLAS.genv !, जो 90% की एक और 25% और स्मृति आवंटन से समय कम कर देता है द्वारा उन उत्पादों की जगह की
1.990031 seconds (2.00 M allocations: 152.589 MB, 0.69% gc time)
छुटकारा पाने के लिए, अद्यतन कोड here ।
अद्यतन 3
सबसे बड़ा रैंक -1 अद्यतन भी यथा-स्थान BLAS कार्यों के लिए दो कॉल द्वारा बदला जा सकता है, अर्थात् BLAS.scal! स्केलिंग और BLAS.ger के लिए! रैंक -1 अपडेट के लिए। चेतावनी है कि दोनों कॉल काफी धीमी गति से कर रहे हैं एक से अधिक धागा इस्तेमाल किया जाता है (समस्या OpenBLAS साथ?), तो यह
blas_set_num_threads(1)
स्थापित करने के लिए 20 के एक नेटवर्क के आकार के लिए समय में एक 15% लाभ है सबसे अच्छा है , और आकार 50 के एक नेटवर्क के लिए 50% की बढ़त के कोई और अधिक स्मृति आवंटन कर रहे हैं, और नए समय
1.638287 seconds (11 allocations: 1.266 KB)
फिर रहे हैं, अद्यतन कोड here पाया जा सकता है।
अद्यतन 4
मैं अब तक परिणामों की तुलना करने के लिए एक बुनियादी Cython script लिखा था। मुख्य अंतर यह है कि मैं बीएलएएस के लिए किसी भी कॉल का उपयोग नहीं करता हूं लेकिन लूप होता है: निम्न स्तर के बीएलएएस कॉल इंजेक्शन करना साइथन में दर्द होता है, और छोटे नेटवर्क आकारों के लिए numpy dot पर बहुत अधिक ओवरहेड होता है (मैंने कोशिश की ...)।समय
CPU times: user 3.46 s, sys: 6 ms, total: 3.47 s, Wall time: 3.47 s
जो लगभग मूल संस्करण के समान है (जिसमें से अब तक 50% बंद हो गया है)।
'उप' फ़ंक्शन के साथ मैट्रिक्स स्लाइस को प्रतिस्थापित करने से थोड़ा बढ़ावा मिल सकता है, क्योंकि कोई भी टुकड़ा अस्थायी सरणी आवंटित करेगा। –
प्रिय कॉलिन, सुझाव के लिए धन्यवाद! क्या आपके पास इस व्यवहार के बारे में कोई संदर्भ है? मैंने सोचा कि मानक इंडेक्सिंग स्लाइस के लिए केवल एक छोटा सा रूप है, और उप अनिवार्य रूप से टुकड़ा है लेकिन पीछे आयामों के संबंध में थोड़ा अलग व्यवहार के साथ, सिमुलेशन कोड के संबंध में, सभी स्लाइसों को अब स्पष्ट लूप द्वारा प्रतिस्थापित किया जाता है, इसलिए मुझे यकीन नहीं है इस मामले में 'उप' का उपयोग कैसे करें। – user45893
जांचें [यहां] (http://julia.readthedocs.org/en/latest/manual/arrays/) और "सबएरे" पर एक शब्द खोज करें। किसी सरणी के किसी * तत्व * को इंडेक्स करना अस्थायी स्मृति आवंटित नहीं करता है। एक सरणी के किसी भी * टुकड़ा * इंडेक्सिंग टुकड़ा के अनुरूप एक अस्थायी सरणी बना देगा। 'sub' एक 'SubArray' बनाकर इसके आसपास हो जाता है जो अनिवार्य रूप से मूल सरणी को संदर्भित करने के लिए उपयोग किए गए सूचकांक का एक सेट है। 'SubArray' पर ऑपरेशंस स्मृति में अस्थायी सरणी बनाने के बजाय मूल सरणी का संदर्भ देता है, इसलिए मेरी मूल टिप्पणी। हालांकि, यदि आपके पास अब कोई स्लाइस नहीं है तो सभी आवश्यक नहीं :-) –