कार्यात्मक प्रोग्रामिंग क्यों कर सकते हैं , और कम्प्यूटेशनल विज्ञान के लिए उपयोग किया जाना चाहिए , इसके लिए मेरे तर्क यहां दिए गए हैं । लाभ विशाल हैं, और विपक्ष जल्दी से दूर जा रहे हैं। मेरे दिमाग में केवल एक चोर है:
Con : C / C ++ / फोरट्रान में भाषा समर्थन की कमी
कम से कम C ++ में, यह con को गायब कर रहा है - C ++ 14/17 के रूप में कार्यात्मक प्रोग्रामिंग का समर्थन करने के लिए शक्तिशाली सुविधाएं जोड़ी गई हैं। आपको स्वयं कुछ पुस्तकालय / सहायता कोड लिखने की आवश्यकता हो सकती है, लेकिन भाषा आपकी मित्र होगी। एक उदाहरण के रूप में, यहां C ++: https://github.com/jzrake/ndarray-v2 में बहु-आयामी सरणियों को करने वाली एक (चेतावनी: प्लग) लाइब्रेरी है ।
इसके अलावा, यहां C ++ में कार्यात्मक प्रोग्रामिंग पर एक अच्छी पुस्तक का लिंक है , हालांकि यह विज्ञान अनुप्रयोगों पर केंद्रित नहीं है।
यहाँ मेरा सारांश है कि मेरा मानना है कि समर्थक हैं:
पेशेवरों :
- यथार्थता
- understandability
- प्रदर्शन
शुद्धता के संदर्भ में , कार्यात्मक कार्यक्रम स्पष्ट रूप से अच्छी तरह से सामने आते हैं : वे आपको अपने भौतिकी चर की न्यूनतम स्थिति को ठीक से परिभाषित करने के लिए मजबूर करते हैं, और फ़ंक्शन जो उस स्थिति को आगे बढ़ाता है:
int main()
{
auto state = initial_condition();
while (should_continue(state))
{
state = advance(state);
side_effects(state);
}
return 0;
}
आंशिक अंतर समीकरण (या ODE) को हल करना कार्यात्मक प्रोग्रामिंग के लिए एकदम सही है; आप बस एक शुद्ध फ़ंक्शन ( advance
वर्तमान समाधान) को अगले एक को उत्पन्न करने के लिए आवेदन कर रहे हैं ।
मेरे अनुभव में, फिजिक्स सिमुलेशन सॉफ्टवेयर खराब राज्य प्रबंधन के बोझ से दबे और बड़े हैं । आमतौर पर, एल्गोरिथम का प्रत्येक चरण एक साझा (प्रभावी रूप से वैश्विक) स्थिति के कुछ टुकड़े पर संचालित होता है। इससे यह मुश्किल हो जाता है, या असंभव भी हो जाता है, संचालन के सही क्रम को सुनिश्चित करने के लिए, सॉफ़्टवेयर को बगों के प्रति संवेदनशील बनाकर छोड़ देता है, जो सेग-दोष या इससे भी बदतर हो सकता है, त्रुटि शब्द जो आपके कोड को क्रैश नहीं करते हैं लेकिन चुपचाप इसके विज्ञान की अखंडता से समझौता करते हैं उत्पादन। भौतिकी सिमुलेशन में साझा स्थिति का प्रबंधन करने का प्रयास भी मल्टी-थ्रेडिंग को रोकता है - जो भविष्य के लिए एक समस्या है, क्योंकि सुपर कंप्यूटर उच्च कोर मायने रखता है, और MPI के साथ स्केलिंग अक्सर ~ 100k कार्यों में सबसे ऊपर है। इसके विपरीत, कार्यात्मक प्रोग्रामिंग साझा-स्मृति समानता को तुच्छता के कारण तुच्छ बनाता है।
एल्गोरिदम के आलसी मूल्यांकन के कारण कार्यात्मक प्रोग्रामिंग में भी प्रदर्शन में सुधार हुआ है (C ++ में, इसका मतलब संकलन समय पर कई प्रकार का निर्माण होता है - अक्सर फ़ंक्शन के प्रत्येक अनुप्रयोग के लिए एक)। लेकिन यह मेमोरी एक्सेस और आवंटन के ओवरहेड को कम कर देता है, साथ ही साथ वर्चुअल डिस्पैच को भी खत्म कर देता है - कंपाइलर को एक बार सभी फ़ंक्शन ऑब्जेक्ट्स को देखकर एक संपूर्ण एल्गोरिथ्म को ऑप्टिमाइज़ करने की अनुमति देता है। व्यवहार में, आप सीपीयू बनाम मेमोरी आवंटन के उपयोग को अनुकूलित करने के लिए मूल्यांकन बिंदुओं (जहां एल्गोरिदम परिणाम को मेमोरी बफर पर कैश किया जाता है) की विभिन्न व्यवस्थाओं के साथ प्रयोग करेंगे। एल्गोरिथ्म चरणों की उच्च स्थानीयता (नीचे उदाहरण देखें) की तुलना में यह आसान है क्योंकि आप आमतौर पर एक मॉड्यूल या वर्ग-आधारित कोड में देखेंगे।
फिजिकल स्टेट को ट्राईसेक्शुअल करने के साथ ही फंक्शनल प्रोग्राम्स को समझना आसान होता है । यह कहना है कि उनके वाक्यविन्यास को आपके सभी सहयोगियों द्वारा आसानी से समझा जा सकता है! लेखकों को अच्छी तरह से नामित कार्यों का उपयोग करने के लिए सावधान रहना चाहिए, और सामान्य तौर पर शोधकर्ताओं को प्रक्रियात्मक रूप से बजाय कार्यात्मक रूप से व्यक्त किए गए एल्गोरिदम को देखने का आदी होना चाहिए। मैं मानता हूँ कि नियंत्रण संरचनाओं की अनुपस्थिति को कुछ के लिए बंद किया जा सकता है, लेकिन मुझे नहीं लगता कि हमें कंप्यूटर पर बेहतर गुणवत्ता वाले विज्ञान करने में सक्षम भविष्य में जाने से रोकना चाहिए।
नीचे एक नमूना advance
फ़ंक्शन है, जो ndarray-v2
पैकेज का उपयोग करके परिमित-वॉल्यूम कोड से अनुकूलित है । to_shared
संचालकों पर ध्यान दें - ये मूल्यांकन बिंदु हैं जिन्हें मैं पहले बता रहा था।
auto advance(const solution_state_t& state)
{
auto dt = determine_time_step_size(state);
auto du = state.u
| divide(state.vertices | volume_from_vertices)
| nd::map(recover_primitive)
| extrapolate_boundary_on_axis(0)
| nd::to_shared()
| compute_intercell_flux(0)
| nd::to_shared()
| nd::difference_on_axis(0)
| nd::multiply(-dt * mara::make_area(1.0));
return solution_state_t {
state.time + dt,
state.iteration + 1,
state.vertices,
state.u + du | nd::to_shared() };
}