2010-05-19 18 views
14

संलग्न सरल जावा कोड को सही पैरामीटर के साथ शुरू करते समय सभी उपलब्ध सीपीयू कोर लोड करना चाहिए। तो उदाहरण के लिए, आप इसेयह जावा कोड सभी CPU कोर का उपयोग क्यों नहीं करता है?

जावा VMTest 8 पूर्णांक 0

के साथ शुरू और यह 8 धागे कि पाशन और एक पूर्णांक के लिए 2 जोड़ने की तुलना में और कुछ भी नहीं शुरू कर देंगे। कुछ जो रजिस्टरों में चलता है और न ही नई मेमोरी आवंटित करता है।

अब हम जिस समस्या का सामना कर रहे हैं वह यह है कि हमें इस सरल कार्यक्रम (पाठ्यक्रम के 24 धागे के साथ) चलाने पर 24 कोर मशीन लोड (एएमडी 2 सॉकेट प्रत्येक 12 कोर) नहीं मिलती है। इसी तरह की चीजें प्रत्येक 12 धागे या छोटी मशीनों के 2 कार्यक्रमों के साथ होती हैं।

तो हमारा संदेह यह है कि जेवीएम (लिनक्स x64 पर सूर्य जेडीके 6u20) अच्छी तरह से स्केल नहीं करता है।

क्या कोई भी इसी तरह की चीजें देखता है या उसे चलाने की क्षमता है और रिपोर्ट करता है कि यह उसकी मशीन (> = 8 कोर केवल कृपया) पर अच्छा प्रदर्शन करता है या नहीं? विचार?

मैंने 8 कोर के साथ अमेज़ॅन ईसी 2 पर भी कोशिश की, लेकिन वर्चुअल मशीन वास्तविक बॉक्स से अलग दिखती है, इसलिए लोडिंग पूरी तरह से अजीब व्यवहार करती है।

package com.test; 

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.concurrent.TimeUnit; 

public class VMTest 
{ 
    public class IntTask implements Runnable 
    { 
     @Override 
     public void run() 
     { 
      int i = 0; 

      while (true) 
      { 
       i = i + 2; 
      } 
     } 
    } 
    public class StringTask implements Runnable 
    { 
     @Override 
     public void run() 
     { 
      int i = 0; 

      String s; 
      while (true) 
      { 
       i++; 
       s = "s" + Integer.valueOf(i); 
      } 
     } 
    } 
    public class ArrayTask implements Runnable 
    { 
     private final int size; 
     public ArrayTask(int size) 
     { 
      this.size = size; 
     } 
     @Override 
     public void run() 
     { 
      int i = 0; 

      String[] s; 
      while (true) 
      { 
       i++; 
       s = new String[size]; 
      } 
     } 
    } 

    public void doIt(String[] args) throws InterruptedException 
    { 
     final String command = args[1].trim(); 

     ExecutorService executor = Executors.newFixedThreadPool(Integer.valueOf(args[0])); 
     for (int i = 0; i < Integer.valueOf(args[0]); i++) 
     { 
      Runnable runnable = null; 
      if (command.equalsIgnoreCase("int")) 
      { 
       runnable = new IntTask(); 
      } 
      else if (command.equalsIgnoreCase("string")) 
      { 
       runnable = new StringTask(); 
      } 
      Future<?> submit = executor.submit(runnable); 
     } 
     executor.awaitTermination(1, TimeUnit.HOURS); 
    } 

    public static void main(String[] args) throws InterruptedException 
    { 
     if (args.length < 3) 
     { 
      System.err.println("Usage: VMTest threadCount taskDef size"); 
      System.err.println("threadCount: Number 1..n"); 
      System.err.println("taskDef: int string array"); 
      System.err.println("size: size of memory allocation for array, "); 
      System.exit(-1); 
     } 

     new VMTest().doIt(args); 
    } 
} 
+0

अतिरिक्त जानकारी। बस पता चला कि जेडीके का 64 बिट संस्करण 32 बिट संस्करण (लगभग 45%) की तुलना में कोर मार्ग को बेहतर (लगभग 9 0%) लोड करता है। जो अजीब है, क्योंकि ओएस और एएमडी सीपीयू 32 बिट का समर्थन करते हैं और मैं उस परीक्षण के दौरान कोई मेमोरी ऑपरेशन नहीं चलाता हूं। – ReneS

+1

बस समझने के लिए - आप invokeAll (..) विधि का उपयोग क्यों नहीं करते? और आप कॉलबेल का उपयोग क्यों नहीं करते हैं, जहां तक ​​मुझे पता है, रननेबल java.concurrent का हिस्सा नहीं है? – InsertNickHere

+0

आपको अन्य चल रही प्रक्रियाओं के लिए भी देखना चाहिए। क्या आपने सीपीयू समय लेने वाले अन्य प्रोगाम्स/प्रक्रियाओं के साथ "साफ" रन बनाया था? – InsertNickHere

उत्तर

10

मुझे आपके कोड में कुछ भी गलत नहीं दिख रहा है।

हालांकि, दुर्भाग्य से, आप जावा में प्रोसेसर एफ़िनिटी निर्दिष्ट नहीं कर सकते हैं। तो, यह वास्तव में ओएस तक छोड़ा गया है, जेवीएम नहीं। यह सब कुछ है कि आपका ओएस धागे को कैसे संभालता है।

आप अपने जावा थ्रेड को अलग प्रक्रियाओं में विभाजित कर सकते हैं और उन्हें एक कोर प्रति प्रक्रिया डालने के लिए देशी कोड में लपेट सकते हैं। यह निश्चित रूप से संचार को जटिल करता है, क्योंकि यह अंतर-थ्रेड के बजाय अंतर-प्रक्रिया होगी। वैसे भी, यह बोंक काम जैसे लोकप्रिय ग्रिड कंप्यूटिंग अनुप्रयोगों के बारे में है।

अन्यथा, आप धागे को निर्धारित करने के लिए ओएस की दया पर हैं।

+0

यह सवाल नहीं था और कम धागे के साथ 2 वीएम चलाना इस खेल को ज्यादा नहीं बदलता है। – ReneS

+0

प्रति थ्रेड के साथ एक जेवीएम प्रति कोर चलाने के बारे में कैसे? आप अपना प्रश्न बदलना चाहेंगे क्योंकि मैंने जवाब दिया "यह जावा कोड सभी CPU कोर का उपयोग क्यों नहीं करता?" –

+0

गलतफहमी के बारे में खेद है, लेकिन सवाल यह है: "... यह जावा कोड ..."। यह आसान है, कोई लॉकिंग नहीं, कोई सिंक्रनाइज़ेशन नहीं, कोई स्मृति आवंटन नहीं है और अभी भी 100% सीपीयू उपयोग नहीं है। यह एक्स समवर्ती और स्वतंत्र धागे बनाना चाहिए। – ReneS

4

मुझे लगता है कि यह JVM/OS के लिए निहित है और आवश्यक रूप से आपका कोड नहीं है। सूर्य से विभिन्न जेवीएम प्रदर्शन ट्यूनिंग दस्तावेज़ देखें, उदा। http://ch.sun.com/sunnews/events/2009/apr/adworkshop/pdf/5-1-Java-Performance.pdf जो एफ़िनिटी सेट करने के लिए लिनक्स पर numactl का उपयोग करने का सुझाव देता है।

शुभकामनाएं!

+0

इस विकल्प को एफ़िनिटी समस्या (यदि कार्यान्वित किया गया है) को हल करना चाहिए – Justin

+0

स्लाइड्स और प्रोग्राम के संकेत के लिए धन्यवाद। कोशिश करेंगे। – ReneS

+0

कुछ सामान करने लगता है, लेकिन यह मुश्किल है। अतिरिक्त झंडे जैसे -XX: + UseTLAB और -XX: + उपयोग करें, जिसे अंतर्निहित आर्किटेक्चर के साथ काम करने के लिए वीएम पर लागू किया जा सकता है। – ReneS

0

मैंने सी पर भी ध्यान दिया है कि एक तंग लूप में अक्सर ऐसे मुद्दे होते हैं। आप ओएस के आधार पर बहुत विशाल मतभेद भी देखेंगे।

आपके द्वारा उपयोग किए जा रहे रिपोर्टिंग टूल के आधार पर, यह कुछ कोर सेवाओं द्वारा उपयोग किए गए CPU की रिपोर्ट नहीं कर सकता है।

जावा बहुत दोस्ताना होने लगता है। आप लिनक्स में एक ही चीज़ का प्रयास कर सकते हैं लेकिन कुछ प्राथमिक संख्या में प्रक्रिया प्राथमिकता सेट करें और देखें कि यह कैसे कार्य करता है।

ऐप के अंदर थ्रेड प्राथमिकताओं को सेट करने से थोड़ा सा मदद मिल सकती है यदि आपका जेवीएम हरे धागे का उपयोग नहीं कर रहा है।

बहुत सारे चर।

+1

धन्यवाद, लेकिन कोई भी वीएम विंडोज, लिनक्स, सोलारिस, मैकोज़ जैसे विशिष्ट प्लेटफ़ॉर्म पर कम से कम मेरे ज्ञान के लिए हरे धागे का उपयोग नहीं कर रहा है। – ReneS

+0

@ReneS पिछले कुछ वर्षों में मैंने केबल बॉक्स और स्पेक्ट्रम विश्लेषकों में एम्बेडेड जावा पर काम किया है - मैं इस तरह की कुछ धारणाएं करता हूं - मैं बस इतना कह रहा था कि विचार करने के लिए बहुत कुछ था। –

+0

आपकी टिप्पणी के लिए कोई समस्या नहीं है और धन्यवाद, मेरी जावा दुनिया में उम्र के लिए कभी भी हरी धागे नहीं देखी गई हैं। – ReneS

1

uname -a 2.6.18-194.11.4।EL5 # 1 SMP मंगल सितं, 21 05:04:09 EDT 2010 x86_64 x86_64 x86_64 जीएनयू/लिनक्स

इंटेल (आर) जिऑन (आर) सीपीयू E5530 @ 2.40GHz http://browse.geekbench.ca/geekbench2/view/182101

जावा 1.6.0_20-B02

16cores, कार्यक्रम 100% cpu भस्म के रूप में vmstat द्वारा दिखाए गए

दिलचस्प बात यह है कि मैं इस लेख के लिए आया था, क्योंकि मैं शक कर रहा हूँ अपने आवेदन सभी कोर का उपयोग नहीं कर रहा है के रूप में CPU उपयोग कभी नहीं बढ़ जाती है लेकिन प्रतिक्रिया समय

बिगड़ती शुरू होता है
2

स्पष्ट रूप से आपका वीएम तथाकथित "क्लाइंट" मोड में चल रहा है, जहां सभी जावा थ्रेड्स को एक देशी ओएस थ्रेड में मैप किया जाता है और इसके परिणामस्वरूप एक सिंगल सीपीयू कोर द्वारा चलाया जाता है। -server स्विच के साथ JVM को आज़माने का प्रयास करें, इससे समस्या ठीक होनी चाहिए।

आप एक मिलता है: Error: no 'server' JVM पाया आपको JRE के bin करने के लिए एक JDK के jre\bin निर्देशिका से server निर्देशिका कॉपी करना होगा।