2012-05-24 16 views
5

पर एक मुखौटा सरणी जोड़ने का सबसे प्रभावी तरीका मेरे पास एक "मुखौटा सरणी" है जिसे मैं किसी अन्य सरणी में जोड़ना चाहता हूं - दूसरे शब्दों में, मेरे पास 3 एरे, A, B और mask हैं। मेरा सवाल यह है कि मास्क को स्टोर करने के लिए सबसे प्रभावी (निष्पादन समय के मामले में) क्या है (लॉजिकल सरणी के रूप में, लोगों और शून्यों की वास्तविक सरणी के रूप में)?किसी अन्य फोर्टन

program main 
    implicit None 
    include 'mpif.h' 
    integer, parameter :: ntry=10000 
    integer, parameter :: asize=1000000 
    real,dimension(asize) :: A,B,maskr 
    logical,dimension(asize) :: mask 
    real*8 :: dd,dt,dtave,dtbest 
    integer i 

    do i=1,asize 
    maskr(i)=mod(i,2) 
    mask(i)=.False. 
    if(mod(i,2).eq.0) mask(i)=.True. 
    enddo 

    A=1.0; B=1.0 
    dtbest=1d33 
    dtave=0.0 
    do i=1,ntry 
    dt=mpi_wtime() 
    call add_arrays_logical(asize,A,B,mask) 
    dt=mpi_wtime()-dt 
    dtbest=min(dt,dtbest) 
    dtave=dtave+dt 
    enddo 
    print*,"==== logical ===" 
    print*,"Average",dtave/ntry 
    print*,"Best",dtbest 

    A=1.0; B=1.0 
    dtbest=1d33 
    dtave=0.0 
    do i=1,ntry 
    dt=mpi_wtime() 
    call add_arrays_real(asize,A,B,maskr) 
    dt=mpi_wtime()-dt 
    dtbest=min(dt,dtbest) 
    dtave=dtave+dt 
    enddo 
    print*,"==== Real ===" 
    print*,"Average",dtave/ntry 
    print*,"Best",dtbest 

    A=1.0; B=1.0 
    dtbest=1d33 
    dtave=0.0 
    do i=1,ntry 
    dt=mpi_wtime() 
    where(mask) A=A+B 
    dt=mpi_wtime()-dt 
    dtbest=min(dt,dtbest) 
    dtave=dtave+dt 
    enddo 
    print*,"==== Where ====" 
    print*,"Average",dtave/ntry 
    print*,"Best",dtbest 

    end 

    subroutine add_arrays_logical(n,A,B,mask) 
    integer n 
    real A(n),B(n) 
    logical mask(n) 
    do i=1,n 
    if(mask(i))then 
     A(i)=A(i)+B(i) 
    endif 
    enddo 
    end 

    subroutine add_arrays_real(n,A,B,mask) 
    integer n 
    real A(n),B(n),mask(n) 
    do i=1,n 
    A(i)=A(i)+mask(i)*B(i) 
    enddo 

    end 

मेरे परिणाम:

(gfortran -O2)

संपादित

यहाँ (यदि आप mpif77 है) आप के साथ चारों ओर खेल सकते हैं एक खिलौना कार्यक्रम है

==== logical === 
Average 1.52590200901031483E-003 
Best 1.48987770080566406E-003 
==== Real === 
Average 1.78022863864898680E-003 
Best 1.74498558044433594E-003 
==== Where ==== 
Average 1.48216445446014400E-003 
Best 1.44505500793457031E-003 

(gfortran -O3 -ffast-गणित -funroll-लूप)

==== logical === 
Average 1.47997992038726811E-003 
Best 1.44982337951660156E-003 
==== Real === 
Average 1.40655457973480223E-003 
Best 1.37186050415039063E-003 
==== Where ==== 
Average 1.48403010368347165E-003 
Best 1.45006179809570313E-003 

(pfg90 फास्ट) - एक बहुत पुरानी मशीन पर

==== logical === 
Average 5.4871437072753909E-003 
Best 5.4519176483154297E-003 
==== Real === 
Average 4.6096980571746831E-003 
Best 4.5847892761230469E-003 
==== Where ==== 
Average 5.3572671413421634E-003 
Best 5.3288936614990234E-003 

(pfg90 -O2) - एक बहुत पर compilers उदाहरण के लिए छोरों vectorize करने की क्षमता - - पुराने मशीन

==== logical === 
Average 5.4929971456527714E-003 
Best 5.4569244384765625E-003 
==== Real === 
Average 5.5974062204360965E-003 
Best 5.5701732635498047E-003 
==== Where ==== 
Average 5.3811835527420044E-003 
Best 5.3341388702392578E-003 
बेशक

, कुछ चीजें हैं जो इस को प्रभावित कर सकता है, इसलिए वहाँ कैसे कुछ इस तरह हासिल किया जाना चाहिए के बारे में एक सामान्य नियम के है?

उत्तर

3

यदि फ्लॉप द्वारा आप फ्लोटिंग पॉइंट ऑपरेशंस का मतलब रखते हैं तो पहला विकल्प स्पष्ट रूप से बेहतर होता है क्योंकि उस मामले में आपके पास 1 फ्लॉप प्रति लूप पुनरावृत्ति है जहां मास्क (एन) ==.true है। । जबकि दूसरे विकल्प के लिए आपके पास मास्क (एन) के मूल्य पर ध्यान दिए बिना प्रति लूप प्रति 2 फ्लॉप हैं।

ओटीओएच, यदि आप इस फ़ंक्शन को निष्पादित करने में व्यतीत समय को कम करने में रुचि रखते हैं, तो आप अपने डेटा पर दोनों संस्करणों का परीक्षण क्यों नहीं करते हैं और परीक्षण तेज है?

तुम भी जहां निर्माण

where(mask) A = A + B 
+0

जिस कोड के साथ मैं काम कर रहा हूं वह f77 है (मेरी पसंद नहीं) - इसलिए मैं उस कारण से 'कहां' से परहेज कर रहा हूं। – mgilson

+0

और हाँ, मेरा मतलब फ़ंक्शन में बिताए गए समय के संदर्भ में है। मैं संपादित करूंगा। – mgilson

+0

मैं उत्तर दे सकता हूं जो 'gfortran' का उपयोग कर तेज़ी से है क्योंकि यह एकमात्र संकलक है जिसकी मुझे वास्तव में आसान पहुंच है - लेकिन कोड सभी प्रकार के प्लेटफार्मों के साथ सभी प्रकार के प्लेटफार्मों पर चलने वाला है, इसलिए मैं सोच रहा था कि क्या इस तरह की चीज़ के लिए अंगूठे का नियम है। अगर अंगूठे का नियम नहीं है, तो शायद इसके बारे में चिंता करने योग्य नहीं है ... – mgilson

5

क्यों "कहां" का उपयोग नहीं करते?

where (mask) A = A + B 

शायद मास्क का उपयोग करना सबसे तेज़ है लेकिन निश्चित रूप से जानने का एकमात्र तरीका मापना है।

+0

जिस कोड के साथ मैं काम कर रहा हूं वह f77 है (मेरी पसंद नहीं) - इसलिए मैं उस कारण से 'कहां' से परहेज कर रहा हूं। – mgilson

+0

आपको क्यों लगता है कि 'मास्क' का उपयोग करके 'मास्कर' से तेज होगा? मैंने सोचा होगा कि 'मास्क' 'मास्कर' की तुलना में अधिक विकृत स्मृति पहुंच का कारण बन जाएगा ... – mgilson

+0

@mgilson: यह "विकृत" क्यों होगा? आप अभी भी ए, बी, और मास्क पर अनुक्रमिक रूप से पुनरावृत्त कर रहे हैं। मुट्ठी के मामले में आप ए और बी के हर तत्व को छू नहीं रहे हैं, लेकिन क्या? – janneb

0

के बारे में कैसे A = A + maskr*B एक संस्करण है जहाँ आप फोरट्रान 90 + का उपयोग की जांच करना चाहें? यह आपके मुखौटा की दुर्लभता के बावजूद सभी तीन सरणी स्कैन करने की लागत पर पूरी तरह से किसी भी सशर्त व्यवहार को हटा देता है।

1

इसे पहले से निर्धारित करने का कोई पूर्ण तरीका नहीं है, क्योंकि यह संकलक, मंच और समस्या पर निर्भर है। केवल एक उदाहरण के रूप में, पॉलीहेड्रॉन की वेबसाइट पर विभिन्न फोरट्रान कंपाइलर्स के माध्यम से बेंचमार्क देखें।

... हालांकि इंटेल के मानकों के साथ कुछ ख्याल रखना, क्योंकि कभी-कभी "मजाकिया" चीजें होती हैं (उदाहरण के लिए कुछ साल पहले इंटेल को न्याय विभाग द्वारा 10 मिलियन अमरीकी डालर का जुर्माना लगाया गया था, जो किसी अन्य पर अपने कंपाइलर को जानबूझकर/गुप्त रूप से लगाता था इंटेल सीपीयू आदि की तुलना में)।

ऐसा कहा है, कुछ विचार:

1) कुछ रणनीतियों, एक "लागत की स्थापना की" बड़ा है, जबकि अन्य उच्च "निष्पादन लागत" है। यही है, संकलक/कोड को cpu/microinstructions को सही बिट भेजने के लिए कुछ समय लगता है, जो अलग-अलग रणनीतियों के साथ अलग-अलग समय लेता है। इस प्रकार, लघु सरणी जोड़ते समय एक रणनीति बेहतर हो सकती है, जबकि कोई अन्य लंबे सरणी के साथ बेहतर कर सकता है।

उन मामलों के लिए तुलनात्मक मुद्दे हो सकते हैं जहां आपका मास्क "घना" बनाम "स्पैस" है (नीचे भी देखें)।

2) आपके बेंचमार्क पैरामीटर बहुत छोटे हैं। बेंचमार्किंग के लिए अंगूठे का एक नियम यह है कि इसे कम से कम कुछ-दस सेकंड exe की आवश्यकता होनी चाहिए। आपके मानक के साथ, निष्पादन के समय इतने छोटे होते हैं कि घड़ी के इत्यादि में किसी भी छोटे अंतर के बड़े सापेक्ष प्रभाव हो सकते हैं। स्पष्टता के साथ इसे देखने के लिए, उन मामलों के लिए मानक लिनपैक बेंचमार्क चलाएं जिन्हें दूसरे, 1-2 सेकंड और 7-10 सेकंड के अंश की आवश्यकता होती है। आम तौर पर, उस उदाहरण के लिए 1 सेकंड से कम परिणाम व्यर्थ हैं।

3) F90/95 संरचनाओं (ForAll, Where, आदि) की तुलना में कुछ स्थितियों के तहत कुछ संरचनाओं पर F77 चलाने के लिए यह संभव है (या कम से कम, परीक्षण नहीं किया गया है)।

यदि आपका कंपाइलर सरणी अनुभागों को इंडेक्स के रूप में उपयोग करने की अनुमति देता है, तो कभी-कभी (उदाहरण के लिए जब मास्क "स्पैस" होता है) पहले एक पूर्णांक सरणी बनाने के लिए बेहतर होता है जो सरणी इंडेक्स को सही करता है, और फिर केवल सत्य जोड़ें सरणी खंड उदाहरण के लिए, अगर इंटीजर iIndex (:) धारण करता है। ट्राउ। मास्क के सूचकांक मान, फिर ए (iIndex ("सीमाएं") जैसे कुछ (+ IIndex ("सीमाएं")) काफी कुशल हो सकते हैं, क्योंकि लॉजिकल के साथ इंडेक्स बनाने की लागत सामान्य अंकगणितीय परिचालन की तुलना में छोटी है। तो अतिरिक्त "सेट अप" लागत के बावजूद, यदि यह एक "छेड़छाड़" समस्या है, तो वहां केवल कुछ ही जोड़ों की आवश्यकता हो सकती है। गुणात्मक और उच्च अंकगणित भी अधिक "महंगी" हैं, और यहां तक ​​कि स्पैर विविधताओं के साथ भी अधिक स्पष्ट हैं। यह एक तरह का "घर बनाया गया" कहां है/सभी निर्माण के लिए।

संयोग से, एक ही संकलक (स्पष्ट रूप से) के साथ भी exe में अंतर हो सकता है। उदाहरण के लिए, फास्ट कोड बनाने में बस फोर्ट्रान काफी अच्छा काम करता है, यह फोटान/ग्रहण (विंडोज़ पर) की तुलना में जीसीसी/जीएफओटरन का उपयोग करता है, जो जीसीसी/जीएफओटरान (कम से कम मेरी मशीनों में से एक पर भी) का उपयोग करता है। यह "इंटरलिंग" मिंगडब्ल्यू या साइगविन इत्यादि के विभिन्न तरीकों के कारण हो सकता है, और यह भी हो सकता है, उदाहरण के लिए, विशिष्ट चिप्स और निर्देश सेट आदि के लिए फोर्ट्रान का व्यापक अनुकूलन। इनमें से कुछ मुद्दे लिनक्स पर नहीं उठते हैं आदि, और इसलिए "मंच" मामलों का एक उदाहरण भी है।

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