सीपीयू कोर के अनुसार थ्रेड्स कैसे स्केल करें?


107

मैं जावा में कई थ्रेड्स के साथ एक गणितीय समस्या को हल करना चाहता हूं। मेरी गणित की समस्या को कार्य इकाइयों में अलग किया जा सकता है, जिसे मैं कई थ्रेड्स में हल करना चाहता हूं।

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

यह कैसे किया जा सकता है? क्या आप उदाहरण प्रदान कर सकते हैं?

जवाबों:


119

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

अद्यतन : आगे स्पष्ट करने के लिए, थ्रेड जावा में सिर्फ एक ऑब्जेक्ट है, इसलिए आप इसे वैसे ही बना सकते हैं जैसे आप कोई अन्य ऑब्जेक्ट बनाएंगे। तो, मान लें कि आप उपरोक्त विधि को कॉल करते हैं और पाते हैं कि यह 2 प्रोसेसर देता है। बहुत बढ़िया। अब, आप एक लूप बना सकते हैं जो एक नया थ्रेड उत्पन्न करता है, और उस थ्रेड के लिए कार्य को विभाजित करता है, और थ्रेड को बंद करता है। यहाँ कुछ psuedocode को प्रदर्शित करने का मतलब है:

int processors = Runtime.getRuntime().availableProcessors();
for(int i=0; i < processors; i++) {
  Thread yourThread = new AThreadYouCreated();
  // You may need to pass in parameters depending on what work you are doing and how you setup your thread.
  yourThread.start();
}

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


17
यह मूल रूप से सही है, लेकिन इंटेल के "हाइपर-थ्रेडिंग" के साथ विपणन किए गए प्रोसेसर पर प्रदर्शन के बारे में सावधान रहें। क्वाड-कोर पर, यह 4 के बजाय 8 वापस आ जाएगा, लेकिन आपका प्रदर्शन वास्तव में 4 थ्रेड्स के बाद छोड़ना शुरू हो सकता है - इसलिए मेरे अपने बेंचमार्क मुझे बताए :)
xcut

हाय, ठीक है, पता नहीं था, कि यह संभव है। लेकिन जब मैंने एक कार्य को कई कार्यपूर्तियों में विभाजित किया और मुझे अंतिम कार्यस्थान के लिए सभी भाग समाधान की आवश्यकता है, तो यह कैसे किया जाता है? जब मेरे पास कई "अपने थ्रेड्स" हैं, तो मैं इसके लिए जुड़ने () का उपयोग कैसे करूं, क्योंकि मैं नहीं देखता कि ये कितने धागे अलग-अलग हैं? :) BTW: थ्रेड पूलिंग के लिए आपकी लिंक मुझे
ibm.com/developerworks/library/j-jtp0730.html

5
उदाहरण यहां देखें: java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/… यह आपको थ्रेड पूल बनाने और प्रबंधित करने का अधिक सुव्यवस्थित तरीका बताएगा ... यह लग सकता है पहले से अधिक जटिल, लेकिन अधिकांश चीजों के साथ, यह अधिक जटिल है क्योंकि अगर यह सरल था तो आप जल्द ही सीमाएं मार लेंगे।
बिल K

62

आप शायद इस सामान के लिए java.util.concurrent ढांचे को भी देखना चाहते हैं। कुछ इस तरह:

ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// Do work using something like either
e.execute(new Runnable() {
        public void run() {
            // do one task
        }
    });

या

    Future<String> future = pool.submit(new Callable<String>() {
        public String call() throws Exception {
            return null;
        }
    });
    future.get();  // Will block till result available

यह अपने स्वयं के थ्रेड पूल आदि की तुलना में बहुत अच्छा है।


हाय डेवीसी, हम्म, यह पहले नहीं पता था, इसलिए मुझे इस पर एक नज़र होगी। और यह उपलब्ध सीपीयू कोर के अनुसार बढ़ाया जा सकता है? क्योंकि मैं आपको छोटे उदाहरणों में नहीं देख सकता। सबसे अच्छा संबंध है, एंड्रियास
एंड्रियास हॉर्निग

3
java.util.concurrent अत्यधिक स्केलेबल है
क्रिस्टोफर Ives

4
उपलब्ध प्रोसेसर की संख्या के साथ एक निश्चित आकार का पूल अक्सर सीपीयू बाध्य प्रक्रियाओं के लिए इष्टतम होता है। यहां पहला उदाहरण आपको बस इतना करना है।
पीटर लॉरी

1
जैसा कि स्वीकृत उत्तर की पहली टिप्पणी में कहा गया है, रिपोर्ट किए गए "प्रोसेसर्स" की आधी संख्या का उपयोग दो कारणों से करना बेहतर होगा: 1. यदि आपके पास हाइपर-थ्रेडिंग है, तो प्रोसेसर की वास्तविक संख्या आधी है जो रिपोर्ट की गई है , और 2. यह सिस्टम के बाकी हिस्सों (ओएस और अन्य कार्यक्रमों) के लिए कुछ प्रसंस्करण शक्ति देता है।
मैथ्यू जूल

10

विकल्प 1:

newWorkStealingPool सेExecutors

public static ExecutorService newWorkStealingPool()

सभी उपलब्ध प्रोसेसरों को अपने लक्ष्य समांतरता स्तर के रूप में उपयोग करते हुए एक कार्य-चोरी धागा पूल बनाता है।

इस API के साथ, आपको कोर की संख्या को पास करने की आवश्यकता नहीं है ExecutorService

Grepcode से इस API का कार्यान्वयन

/**
     * Creates a work-stealing thread pool using all
     * {@link Runtime#availableProcessors available processors}
     * as its target parallelism level.
     * @return the newly created thread pool
     * @see #newWorkStealingPool(int)
     * @since 1.8
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

विकल्प 2:

newFixedThreadPool API सेExecutors या other newXXX constructors, जो लौटाता हैExecutorService

public static ExecutorService newFixedThreadPool(int nThreads)

nThreads से प्रतिस्थापित करें Runtime.getRuntime().availableProcessors()

विकल्प 3:

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue<Runnable> workQueue)

Runtime.getRuntime().availableProcessors()पैरामीटर के रूप में पास करें maximumPoolSize


8

डग ले (समवर्ती पैकेज के लेखक) के पास यह पत्र है जो प्रासंगिक हो सकता है: http://gee.cs.oswego.edu/dl/papers/fj.pdf

कांटा ज्वाइन फ्रेमवर्क जावा एसई 7 में जोड़ा गया है। नीचे कुछ और संदर्भ दिए गए हैं:

http://www.ibm.com/developerworks/java/library/j-jtp11137/index.html गोएटेज़ का लेख

http://www.oracle.com/technetwork/articles/java/fork-join-422606.html


4

मानक तरीका Runtime.getRuntime ()। AvailableProcessors () विधि है। अधिकांश मानक सीपीयू पर आपने यहां इष्टतम थ्रेड काउंट (जो वास्तविक सीपीयू कोर काउंट नहीं है) लौटाया होगा। इसलिए यह वही है जो आप ढूंढ रहे हैं।

उदाहरण:

ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

इस तरह निष्पादक सेवा को बंद करने के लिए मत भूलना (या आपका प्रोग्राम बाहर नहीं निकलेगा):

service.shutdown();

यहाँ सिर्फ एक त्वरित रूपरेखा है कि भविष्य आधारित MT कोड (चित्रण के लिए ऑफटॉपिक) कैसे सेट किया जाए:

CompletionService<YourCallableImplementor> completionService = 
    new ExecutorCompletionService<YourCallableImplementor>(service);
    ArrayList<Future<YourCallableImplementor>> futures = new ArrayList<Future<YourCallableImplementor>>();
    for (String computeMe : elementsToCompute) {
        futures.add(completionService.submit(new YourCallableImplementor(computeMe)));
    }

फिर आपको इस बात पर नज़र रखने की ज़रूरत है कि आप कितने परिणाम की उम्मीद करते हैं और उन्हें इस तरह से पुनः प्राप्त करते हैं:

try {
  int received = 0;
  while (received < elementsToCompute.size()) {
     Future<YourCallableImplementor> resultFuture = completionService.take(); 
     YourCallableImplementor result = resultFuture.get();
     received++; 
  }
} finally {
  service.shutdown();
}

2
शटडाउन कॉल अंत में कोशिश में रखा जाना चाहिए
क्रिस्टोफ रूसो

1
@ChristopheRoussy तुम बहुत सही हो, मैंने स्निपेट को तदनुसार संशोधित किया है, धन्यवाद!
fl0w

3

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


हाय जेसन और एरिक (मैं आपके दोनों जवाबों के लिए एक टिप्पणी का उपयोग करता हूं, क्योंकि यह मूल रूप से समान है)। ठीक है, यह जांचना अच्छा है, लेकिन यह पहला भाग होगा। जब मेरे पास कोर की गिनती होती है, तो मुझे कोर की इस राशि के रूप में थ्रेड्स को चर के रूप में होना चाहिए। मैंने ओपनबुक.गैलिलेसोडाइन.डे / जेवेंसेल 5/… (जर्मन!) से पहले इस उदाहरण की कोशिश की और यह एक निश्चित धागे का उपयोग करता है। लेकिन मैं चाहता हूं कि दोहरे कोर वातावरण में 2 कोर और क्वाड-कोर वातावरण में 4 कोर का उपयोग करके समान प्रोग्रामिंग हो। मैं इसे मैन्युअल रूप से बदलना नहीं चाहता। क्या यह संभव है? धन्यवाद! :)
एंड्रियास हॉर्निग

@ और - मैं अपने पोस्ट के लिए किए गए अद्यतन देखें। मुझे लगता है कि इस मुद्दे को स्पष्ट करने में मदद मिलेगी।
जसकाव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.