2012-12-04 9 views
11

कंप्यूटर भाषा बेंचमार्क गेम की F# entry for Threadring में एक प्रतीत होता है बेकार रेखा: if false then()। जब मैं इस पंक्ति पर टिप्पणी करता हूं, तो प्रोग्राम 50000000 के इनपुट के लिए बहुत तेजी से चलता है (~ 2 एस बनाम ~ 55s) और उसी परिणाम का उत्पादन करता है। यह कैसे काम करता है? यह रेखा क्यों है? नो-ऑप होने के साथ क्या संकलक वास्तव में कर रहा है?कंप्यूटर भाषा बेंचमार्क गेम की एफ # थ्रेडिंग एंट्री में "अगर झूठी तब()" का असर क्या है?

कोड:

let ringLength = 503 

let cells = Array.zeroCreate ringLength 
let threads = Array.zeroCreate ringLength 
let answer = ref -1 

let createWorker i = 
    let next = (i+1)%ringLength 
    async { let value = cells.[i] 
      if false then() 
      match value with 
      | 0 -> answer := i+1 
      | _ -> 
       cells.[next] <- value - 1 
       return! threads.[next] } 

[<EntryPoint>] 
let main args = 
    cells.[0] <- if args.Length>0 then int args.[0] else 50000000 
    for i in 0..ringLength-1 do 
     threads.[i]<-createWorker i 

    let result = Async.StartImmediate(threads.[0]) 
    printfn "%d" !answer 
    0 

उत्तर

7

गणना अभिव्यक्ति तो if false then() शामिल अतुल्यकालिक कार्यप्रवाह अलग ढंग से एक सा अनुवाद हो जाता है। रेखा के साथ, यह async.Combine का उपयोग करता है।

async.Delay(fun() -> 
    value = cells.[i] 
    async.Combine 
    (async.Return(if false then()) 
     async.Delay(fun() -> 
     match value with (...)))) 

अनुवाद सम्मिलित करता Combine क्योंकि (संभावित) अतुल्यकालिक गणना if पाश द्वारा किया निम्नलिखित कोड के साथ जोड़ा जा करने की जरूरत है: की तरह थोड़ा सरलीकृत कोड लग रहा है। अब, अगर आप if हटाना आप की तरह कुछ मिलता है: अंतर

async.Delay(fun() -> 
    value = cells.[i] 
    match value with (...)))) 

है कि अब एक बहुत अधिक काम समारोह Delay के लिए पारित में तुरंत किया जाता है।

संपादित करें: मैंने सोचा था कि क्योंकि कोड Async.StartImmediate बजाय Async.Start का उपयोग करता है, लेकिन यह मामला हो प्रतीत नहीं होता है यह एक अंतर का कारण बना। असल में, मुझे समझ में नहीं आता कि कोड एसिंक्रोनस वर्कफ़्लो का उपयोग क्यों करता है ...

EDIT II।: मैं मोनो के बारे में पूरी तरह से निश्चित नहीं हूं, लेकिन यह निश्चित रूप से एफ # इंटरैक्टिव में दोहराता है - वहां, Combine वाला संस्करण लगभग 4 गुना धीमा है (जो कि मैं आवंटन ओवरहेड की वजह से अपेक्षा करता हूं)।

9

मैंने मूल रूप से यह कोड लिखा था। मुझे लाइन को जोड़ने का सटीक कारण याद नहीं है, लेकिन मुझे लगता है कि इसके बिना, ऑप्टिमाइज़र ऐसा कुछ करेगा जो मैंने सोचा था कि बेंचमार्क गेम की भावना से बाहर था। पहली जगह में एसिंक का उपयोग करने का कारण अगली एसिंक को पूंछ-कॉल निरंतरता प्राप्त करना है (जो यह सी # मोनो से इतना बेहतर प्रदर्शन करता है)। - जोमो

+0

एक आधिकारिक उत्तर (जैसे यह है) के लिए +1 है, लेकिन मुझे उत्सुकता है कि आप उद्देश्य पर _a benchmark_ के प्रदर्शन को दंडित करना चाहते हैं ... – ildjarn

+2

इस पर विचार करना, मुझे विश्वास है कि मैं चाहता था एसिंक को दिखाने के लिए जो एक ही वैध थ्रेड पर निरंतरता साझा करते हुए अलग वैध निष्पादन संदर्भ होते हैं (गो गोरोटाइन जाने के लिए समान उपयोग पैटर्न बनाते हैं)। लाइन के बिना, एफ # पूरी चीज को प्रभावी रूप से एक समय-लूप में खोल देगा। यह बेंचमार्क के लिए बेवकूफ होगा, लेकिन जैसे ही आप कुछ वास्तविक के लिए कोड का उपयोग करने का प्रयास करेंगे, प्रदर्शन 20x या इससे भी कम हो जाएगा। –

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