2015-12-24 10 views
9

हास्केल में, "as" -operator (कभी-कभी उपनाम के रूप में जाना जाता है) नामक एक भाषा सुविधा होती है। दी आप एक समारोह उदाहरण के लिए एक सूची इनपुट के रूप में लेता है और सब पूंछ वापसी चाहता है कि है, तो आप के रूप में इस लागू कर सकते हैं:क्या प्रोलॉग के पास हास्केल की तरह उपनाम "ऑपरेटर" है?

tails [email protected](_:xs) = a : tails xs 
tails [] = [[]] 

@ सुनिश्चित करता है कि आप दोनों के लिए एक संदर्भ है कि विचार पीछा कर रहा है पूरे तर्क के साथ ही पैरामीटर की संरचना के कुछ हिस्सों का संदर्भ। एक नई वस्तु का आवंटन, खेतों को संशोधित करने, आदि देखें में परिणाम - अगर संकलक द्वारा अनुकूलित नहीं - यह बुद्धिमान प्रदर्शन के लिहाज से (इसे और अधिक, एक प्रदर्शन हैक है, क्योंकि एक सरणी (x:xs) पुनर्निर्माण) पहली पंक्ति के शरीर में, जाएगा अधिक जानकारी के लिए here

मैं सोच रहा था अगर Prolog कुछ बराबर है: उदाहरण के लिए यदि आप Prolog में पूंछ लागू करना चाहते हैं, यह नीचे दिए तरीक़े से किया जा सकता:

tails([H|T],[[H|T]|TA]) :- 
    tails(T,TA). 
tails([],[[]]). 

लेकिन अगर वहाँ था यह और अधिक कुशल हो सकता है एक " के रूप में "की तरह -operator:

tails([email protected][_|T],[L|TA]) :- %This does not compile 
    tails(T,TA). 
tails([],[[]]). 

वहाँ किसी भी तरह के निर्माण है, या एक भाषा विस्तार?

+2

प्रोलॉग में आप उपनाम से बच सकते हैं। बस 'पूंछ (एल, [एल | टीए]) का उपयोग करें: - एल = [_ | टी], ... '। – Bakuriu

+0

मैं सहमत हूं, लेकिन यह अच्छा होगा अगर यह सिर में संभव था। (मुझे पता है कि मैं परेशान हूं: एस) –

उत्तर

8

टी एल; डॉ: अच्छा विचार है ! स्पीडअप ~ 20% तक सीमित है (अधिकांश सूची आकारों के लिए)।

इस जवाब में, हम तीन अलग अलग विधेय कि @ की तरह डेटा पुन: उपयोग के बारे में अलग-अलग हो तुलना:

 
list_tails([], [[]]).    % (1) like `tails/2` given by the OP ... 
list_tails([E|Es], [[E|Es]|Ess]) :- %  ....... but with a better name :-) 
    list_tails(Es, Ess). 

list_sfxs1(Es, [Es|Ess]) :-   % (2) "re-use, mutual recursion" 
    aux_list_sfxs1(Es, Ess).   %  "sfxs" is short for "suffixes" 

aux_list_sfxs1([], []). 
aux_list_sfxs1([_|Es], Ess) :- 
    list_sfxs1(Es, Ess). 

list_sfxs2([], [[]]).    % (3) "re-use, direct recursion" 
list_sfxs2(Es0, [Es0|Ess]) :- 
    Es0 = [_|Es], 
    list_sfxs2(Es, Ess). 

क्रम को मापने के लिए, हम निम्न कोड का उपयोग करें:

 
:-( dif (D, sicstus), current_prolog_flag (dialect ,D) 
    ; use_module (library(between)) 
). 

run_benchs(P_2s, P_2, L, N, T_ms) :- 
    between (1, 6, I), 
    L  is 10 ^ I, 
    N is 10^(8-I), 
    length (Xs, L), 
    member (P_2, P_2s), 
    garbage_collect , 
    call_walltime(run_bench_core(P_2,Xs,N), T_ms). 

run_bench_core(P_2, Xs, N) :- 
    between(1, N, _), 
    call (P_2, Xs, _), 
    false . 
run_bench_core(_, _, _). 

को मापने के लिए

: 2, हम call_time/2 की call_ walltime /2 -एक भिन्नता का उपयोग
 
call_walltime(G, T_ms) :- 
    statistics (walltime , [T0|_]), 
    G, 
    statistics(walltime, [T1|_]), 
    T_ms is T1 - T0. 

के परीक्षण करने के लिए ऊपर दिए गए कोड विविधताओं रखते हैं ...

  • ... अलग अलग सूची का उपयोग कर लंबाई L ...
  • ... और प्रत्येक परीक्षा के लिए बार N के एक नंबर (चल बेहतर सटीकता)।

     
    ?- run_benchs([list_sfxs1,list_sfxs2,list_tails], P_2, L, N, T_ms). 
        P_2 = list_sfxs1, L*N = 10*10000000, T_ms = 7925 
    ; P_2 = list_sfxs2, L*N = 10*10000000, T_ms = 7524 
    ; P_2 = list_tails, L*N = 10*10000000, T_ms = 6936 
    ; 
        P_2 = list_sfxs1, L*N = 100*1000000, T_ms = 6502 
    ; P_2 = list_sfxs2, L*N = 100*1000000, T_ms = 5861 
    ; P_2 = list_tails, L*N = 100*1000000, T_ms = 5618 
    ; 
        P_2 = list_sfxs1, L*N = 1000*100000, T_ms = 6434 
    ; P_2 = list_sfxs2, L*N = 1000*100000, T_ms = 5817 
    ; P_2 = list_tails, L*N = 1000*100000, T_ms = 9916 
    ; 
        P_2 = list_sfxs1, L*N = 10000*10000, T_ms = 6328 
    ; P_2 = list_sfxs2, L*N = 10000*10000, T_ms = 5688 
    ; P_2 = list_tails, L*N = 10000*10000, T_ms = 9442 
    ; 
        P_2 = list_sfxs1, L*N = 100000*1000, T_ms = 10255 
    ; P_2 = list_sfxs2, L*N = 100000*1000, T_ms = 10296 
    ; P_2 = list_tails, L*N = 100000*1000, T_ms = 14592 
    ; 
        P_2 = list_sfxs1, L*N = 1000000*100, T_ms = 6955 
    ; P_2 = list_sfxs2, L*N = 1000000*100, T_ms = 6534 
    ; P_2 = list_tails, L*N = 1000000*100, T_ms = 9738. 
    

    फिर, हम पहले की क्वेरी संस्करण 4.3 का उपयोग दोहराने:

सबसे पहले, हम संस्करण 7.3.14 (64-बिट) का उपयोग करें।2 (64-बिट):

 
?- run_benchs([list_sfxs1,list_sfxs2,list_tails], P_2, L, N, T_ms). 
    P_2 = list_sfxs1, L*N = 10*10000000, T_ms = 1580 
; P_2 = list_sfxs2, L*N = 10*10000000, T_ms = 1610 
; P_2 = list_tails, L*N = 10*10000000, T_ms = 1580 
; 
    P_2 = list_sfxs1, L*N = 100*1000000, T_ms = 710 
; P_2 = list_sfxs2, L*N = 100*1000000, T_ms = 750 
; P_2 = list_tails, L*N = 100*1000000, T_ms = 840 
; 
    P_2 = list_sfxs1, L*N = 1000*100000, T_ms = 650 
; P_2 = list_sfxs2, L*N = 1000*100000, T_ms = 660 
; P_2 = list_tails, L*N = 1000*100000, T_ms = 740 
; 
    P_2 = list_sfxs1, L*N = 10000*10000, T_ms = 620 
; P_2 = list_sfxs2, L*N = 10000*10000, T_ms = 650 
; P_2 = list_tails, L*N = 10000*10000, T_ms = 740 
; 
    P_2 = list_sfxs1, L*N = 100000*1000, T_ms = 670 
; P_2 = list_sfxs2, L*N = 100000*1000, T_ms = 650 
; P_2 = list_tails, L*N = 100000*1000, T_ms = 750 
; 
    P_2 = list_sfxs1, L*N = 1000000*100, T_ms = 12610 
; P_2 = list_sfxs2, L*N = 1000000*100, T_ms = 12560 
; P_2 = list_tails, L*N = 1000000*100, T_ms = 33460. 

सारांश:

  • उर्फ-thingy कर सकते हैं और में सुधार करता है प्रदर्शन में काफी
  • ऊपर परीक्षणों में SICStus Prolog SWI-Prolog की तुलना में, 10X speedup देता है!

फ़ुटनोट 1: नियम सिर में (@)/2 डालने की स्टंट क्यों करते हैं? गैर-idiomatic प्रोलॉग कोड के साथ समाप्त करने के लिए?
फुटनोट 2: हम कुल रनटाइम में रुचि रखते हैं। क्यूं कर? चूंकि कचरा-संग्रहण लागत बड़े डेटा आकारों के साथ दिखाती है!
फ़ुटनोट 3: जवाब अनुक्रम दिया पठनीयता के कारण के बाद कार्रवाई की गई है।
फुटनोट 4:release 4.3.0 के बाद से उपलब्ध है। वर्तमान लक्ष्य आर्किटेक्चर में IA-32 और AMD64 शामिल हैं।

+0

मुझे आश्चर्य है कि सिर में ऐसी चीज डालने से अतिरिक्त अनुकूलन नहीं हो सकता है। 'पूंछ' के लिए, यह वास्तव में उपयोगी नहीं है, लेकिन अब आप चेक को स्थगित कर चुके हैं जो * भविष्यवाणी करने से पहले * किया जा सकता था। फिर भी, प्रभावशाली उत्तर +1। –

+0

इसके अलावा मैं सोच रहा हूं कि संकलक को यह सुनिश्चित करने के लिए सुधार नहीं किया जा सकता था कि '[ई | एसएस]' का उपयोग दो बार किया जाता है और इस प्रकार एक "निहित" उपनाम बनाते हैं। –

+3

@ विलेममैन ओन्सेम। हां, सिद्धांत रूप में, प्रोलॉग कंपाइलर्स * ऐसा कर सकता था। ओटीओएच आलसी मूल्यांकन (जैसे हास्केल) के साथ एक शुद्ध कार्यात्मक भाषा में यह और भी सीधा आगे है। प्रोलॉग संकलन मुश्किल है, अगर आप यह सुनिश्चित करना चाहते हैं कि संकलित और एनालॉग व्याख्या कोड कभी ** कभी ** अलग तरीके से व्यवहार न करें। बहुत सारी सूक्ष्मता/विवरणों को सही देखभाल करने की आवश्यकता है। एसआईसीस्टस जेआईटी अपेक्षाकृत नया है ... और बहुत प्रभावशाली है! – repeat

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