2010-09-02 15 views
16

मैं एक 32-बिट क्वाड-कोर Core2 सिस्टम पर इस स्केला कोड चल रहा हूँ:मेरे स्कैला वायदा अधिक कुशल क्यों नहीं हैं?

def job(i:Int,s:Int):Long = { 
    val r=(i to 500000000 by s).map(_.toLong).foldLeft(0L)(_+_) 
    println("Job "+i+" done") 
    r 
} 

import scala.actors.Future 
import scala.actors.Futures._ 

val JOBS=4 

val jobs=(0 until JOBS).toList.map(i=>future {job(i,JOBS)}) 
println("Running...") 
val results=jobs.map(f=>f()) 
println(results.foldLeft(0L)(_+_)) 

(हाँ, मैं जानते हैं कि ज्यादा अधिक कुशल तरीके पूर्णांकों की एक श्रृंखला योग करने के लिए कर रहे हैं करना ; यह सिर्फ सीपीयू को कुछ करने के लिए है)।

है कि मैं क्या करने के लिए कार्य सेट के आधार पर, कोड निम्नलिखित समय में चलता है:

JOBS=1 : 31.99user 0.84system 0:28.87elapsed 113%CPU 
JOBS=2 : 27.71user 1.12system 0:14.74elapsed 195%CPU 
JOBS=3 : 33.19user 0.39system 0:13.02elapsed 257%CPU 
JOBS=4 : 49.08user 8.46system 0:22.71elapsed 253%CPU 

मुझे आश्चर्य है कि यह वास्तव में "खेल में" 2 वायदा परे अच्छी तरह पैमाने पर नहीं है हूँ। मैं बहुत सारे मल्टीथ्रेड किए गए सी ++ कोड करता हूं और इसमें कोई संदेह नहीं है कि मुझे 4 कोर तक अच्छा स्केलिंग मिल जाएगा और देखें कि 3 9 0% सीपीयू उपयोग अगर मैंने इंटेल के टीबीबी या boost::threads के साथ इस तरह की चीज को कोड किया है (यह काफी अधिक वर्बोज़ होगा पाठ्यक्रम)।

तो: क्या हो रहा है और मैं 4 कोरों के लिए स्केलिंग कैसे प्राप्त कर सकता हूं, मैं देख सकता हूं? क्या यह स्कैला या जेवीएम में कुछ सीमित है? यह मेरे लिए होता है मैं वास्तव में नहीं जानता कि "कहाँ" स्कैला के वायदा दौड़ते हैं ... भविष्य में एक धागा पैदा होता है, या "फ्यूचर्स" उन्हें चलाने के लिए समर्पित थ्रेड पूल प्रदान करता है?

[मैं स्केला Debian/निचोड़ से 2.7.7 संकुल का उपयोग कर रहा धूप में Java6 (6-20-0lennny1) के साथ एक लेनी सिस्टम पर।]

अद्यतन:

सुझाव दिया रेक्स के जवाब में, मैंने ऑब्जेक्ट सृजन से बचने के लिए रिकोड किया।

def job(i:Long,s:Long):Long = { 
    var t=0L 
    var v=i 
    while (v<=10000000000L) { 
    t+=v 
    v+=s 
    } 
    println("Job "+i+" done") 
    t 
} 
// Rest as above... 

यह इतना तेज़ था कि मुझे किसी भी समय के लिए दौड़ने के लिए पुनरावृत्ति गणना में काफी वृद्धि हुई थी! परिणाम इस प्रकार हैं:

JOBS=1: 28.39user 0.06system 0:29.25elapsed 97%CPU 
JOBS=2: 28.46user 0.04system 0:14.95elapsed 190%CPU 
JOBS=3: 24.66user 0.06system 0:10.26elapsed 240%CPU 
JOBS=4: 28.32user 0.12system 0:07.85elapsed 362%CPU 

जो अधिक की तरह क्या मैं (, एक कार्य लगातार पहले अन्य दो सेकंड के एक जोड़े को पूरा करने के साथ हालांकि 3 नौकरियों मामले में एक छोटे से अजीब है) देखने की उम्मीद होता है।

इसे थोड़ा आगे बढ़ाकर, क्वाड-कोर हाइपरथ्रेडेड i7 पर बाद वाला संस्करण JOBS=8 के साथ x71.4 speedup बनाम जॉब्स = 1, 571% CPU उपयोग के साथ प्राप्त करता है।

+1

आप भविष्य में आज चाहते हैं, बस अधीर हैं! गंभीरता से, रेक्स ने सिर पर नाखून मारा, आप कचरा संग्रह बेंचमार्क कर रहे हैं, वायदा दक्षता नहीं। –

+1

हे ... बहुत सच है।जब मैंने इस सवाल को प्रस्तुत किया तो मैं लंबे समय तक स्कैला का उपयोग नहीं कर रहा था, और शायद इसके आसपास के चरम प्रचार के कुछ बहुत ही भरोसेमंद था। – timday

+0

akka.dispatch.Future के साथ परीक्षण को फिर से चलाने की देखभाल? –

उत्तर

14

मेरा अनुमान है कि कचरा कलेक्टर इसके अलावा अतिरिक्त काम कर रहा है। तो आप कचरा कलेक्टर का प्रबंधन कर सकते हैं द्वारा सीमित हैं। परीक्षण को फिर से चलाने का प्रयास करें जो कोई ऑब्जेक्ट नहीं बनाता है (उदाहरण के लिए रेंज/मैप/फोल्ड के बजाय थोड़ी देर लूप का उपयोग करें)। यदि आप वास्तविक अनुप्रयोग जीसी को भारी रूप से प्रभावित करेंगे तो आप समांतर जीसी विकल्पों के साथ भी खेल सकते हैं।

+0

यूप, यह मामला प्रतीत होता है; कोड के दूसरे संस्करण और परिणाम अद्यतन में परिणाम देखें। मुद्दा मूल रूप से बिगइंट्स के भारी उपयोग के कुछ कोड में आया था, इसलिए ऑब्जेक्ट सृजन को खत्म करने का अधिक मौका नहीं था। इस बात की सराहना नहीं की थी कि इस तरह के सामान के कितने प्रभाव हो सकते हैं ... स्कैला कोड में बहुत स्पष्ट नए-आईएनजी की आवश्यकता को खत्म करने के लिए प्रतीत होता है, इसलिए यह अभी भी भूलना आसान है। – timday

+0

क्या संकलक इस 'नए' को दूर नहीं करना चाहिए? –

+2

@Elazar - अंततः विशेषज्ञता के साथ, यह _may_ वस्तु निर्माण के बिना चलाने के लिए (या कुछ समान) के लिए संभव हो सकता है। अभी के लिए, हालांकि, यह अपरिहार्य है: कोड सामान्य है, इसलिए आपको इसके लिए ऑब्जेक्ट बनाना है, भले ही यह केवल आदिम पर एक रैपर है। –

2

(i to 500000000 by s).view.map(_.toLong).foldLeft(0L)(_+_) 

view के आवेदन करने के लिए माना जाता है की कोशिश करो (के रूप में मैं आईडी समझा) सरल रैपर उपलब्ध कराने के द्वारा बार-बार यात्रा और ऑब्जेक्ट निर्माण से बचने के लिए।

ध्यान दें कि आप गुना के बजाय reduceLeft(_+_) का उपयोग कर सकते हैं।

+0

मैं अभी भी 2.7.7 पर हूं; देखें मेरे लिए रेंज का सदस्य नहीं है (उम्मीद है कि 2.8 एक दिन डेबियन संग्रह में बदल जाएगा; मैं स्रोत से निर्माण करने के लिए आलसी हूं, और मेरे पास सभी स्कैला किताबें हैं 2.7)। यह देखने में खुशी हुई कि इस क्षेत्र में कुछ सुधार किए जा रहे हैं। (और हाँ, आमतौर पर जब तक कुछ अच्छा कारण नहीं होता है तब तक मैं फोल्ड को कम करना पसंद करता हूं; इस मामले में ऐसा इसलिए था क्योंकि फ़ंक्शन में कुछ चरम i/s पैरामीटर की कमी नहीं होगी, कमीशन ऑपरेशन के लिए एक या शून्य तत्व नहीं होंगे)। – timday

+0

हाँ, मैंने देखा कि, भी। आप एक tgz में स्कैला 2.8.1 डाउनलोड कर सकते हैं जिसे आपको कहीं भी अनपैक करना होगा (उदा। '/ Usr/share/')। फिर उपफोल्डर 'बिन' में स्क्रिप्ट में सिम्लिंक बनाएं और आप सोना हैं। मैं वास्तव में दिलचस्पी लेता हूं कि तीन प्रकार आपकी मशीन पर 2.8.1 पर कैसे प्रदर्शन करते हैं (मेरे पास क्वाड-कोर नहीं है)। – Raphael

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