সিপিইউ কোর অনুযায়ী থ্রেড কীভাবে স্কেল করবেন?


107

আমি জাভাতে একাধিক থ্রেড সহ গাণিতিক সমস্যাটি সমাধান করতে চাই। আমার গণিত সমস্যাটি ওয়ার্ক ইউনিটে বিভক্ত হতে পারে, যা আমি বেশ কয়েকটি থ্রেডে সমাধান করতে চাই।

আমি এটিতে একটি নির্দিষ্ট পরিমাণ থ্রেডে কাজ করতে চাই না, তবে তার পরিবর্তে সিপিইউ কোরগুলির পরিমাণের সাথে মিলিত পরিমাণ থ্রেড। আমার সমস্যাটি হ'ল এটির জন্য আমি কোনও সহজ টিউটোরিয়াল খুঁজে পাইনি। আমি খুঁজে পাওয়া সমস্ত হ'ল স্থির থ্রেড সহ উদাহরণ।

কিভাবে এই কাজ করা যেতে পারে? আপনি উদাহরণ প্রদান করতে পারেন?

উত্তর:


119

আপনি স্ট্যাটিক রানটাইম পদ্ধতি ব্যবহার করে, দ্বারা জাভা ভার্চুয়াল মেশিন উপলব্ধ প্রসেস সংখ্যা নির্ধারণ করতে পারেন availableProcessors । একবার আপনি উপলব্ধ প্রসেসরের সংখ্যা নির্ধারণ করে নিলে, সেই সংখ্যার থ্রেড তৈরি করুন এবং সেই অনুযায়ী আপনার কাজটি বিভক্ত করুন।

আপডেট : আরও স্পষ্ট করার জন্য, একটি থ্রেড জাভাতে কেবল একটি অবজেক্ট, যাতে আপনি অন্য কোনও অবজেক্ট তৈরি করার মতো করে এটিকে তৈরি করতে পারেন। সুতরাং, আসুন আমরা বলি যে আপনি উপরের পদ্ধতিটি কল করেছেন এবং এটি দেখতে পান যে এটি 2 টি প্রসেসর ফেরায়। অসাধারণ. এখন, আপনি একটি লুপ তৈরি করতে পারেন যা একটি নতুন থ্রেড তৈরি করে এবং সেই থ্রেডটির জন্য কাজটি বিভক্ত করে এবং থ্রেডটি ছড়িয়ে দেয়। আমি যা বলতে চাইছি তা প্রদর্শনের জন্য এখানে কিছু স্যুইডোকোড দেওয়া হয়েছে:

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 টি থ্রেডের পরে আসলে বাদ পড়তে শুরু করতে পারে - তাই আমার নিজের
মানদণ্ডগুলি

হাই, ঠিক আছে, জানতেন না, এটি সম্ভব। তবে যখন আমি একটি কাজকে বেশ কয়েকটি ওয়ার্কুনিটে বিভক্ত করি এবং চূড়ান্ত ওয়ার্কস্টপের জন্য আমার সমস্ত অংশ সমাধানের প্রয়োজন হয়, এটি কীভাবে হয়? যখন আমার বেশ কয়েকটি "আপনার থ্রেডস" থাকে তবে আমি কীভাবে এর জন্য যোগদান () ব্যবহার করব, কারণ আমি দেখতে পাচ্ছি না, এই কয়েকটি থ্রেড কীভাবে আলাদা? :) বিটিডাব্লু: থ্রেড পুলিংয়ের আপনার লিঙ্কটি আমাকে আইবিএম / ডেভেলপ ওয়ার্কস / লাইব্রেরি / জেজেপিপি 077 এইচটিএমএল এর দিকে নিয়ে যায় :)
আন্দ্রেস

5
এখানে উদাহরণটি দেখুন: java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/… এটি আপনাকে থ্রেড পুল তৈরি এবং পরিচালনা করার জন্য আরও সুচিন্তিত উপায় বলবে ... মনে হতে পারে প্রথমে আরও জটিল, তবে বেশিরভাগ জিনিসের মতোই এটি আরও জটিল কারণ এটি যদি সহজতর হয় তবে আপনি কেবল সীমাবদ্ধতাগুলিকে শীঘ্রই আঘাত করতেন।
বিল কে

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

এটি আপনার নিজের থ্রেড পুলের সাথে লড়াই করার চেয়ে অনেক ভাল etc.


হাই ডেভিসি, হুঁ, এটি আগে জানা ছিল না, তাই আমি এটি একবার দেখব। এবং এটি উপলব্ধ সিপিইউ কোর অনুযায়ী মাপা যায়? কারণ আমি এটি আপনার ছোট উদাহরণগুলিতে দেখতে পাচ্ছি না। শুভেচ্ছা, আন্ড্রেয়াস
আন্দ্রেয়াস হর্নিগ

3
java.util.concurrent অত্যন্ত স্কেলেবল
ক্রিস্টোফার ইভস

4
উপলব্ধ প্রসেসরের সংখ্যার সাথে একটি নির্দিষ্ট আকারের পুলটি প্রায়শই সিপিইউ বাউন্ড প্রক্রিয়াগুলির জন্য অনুকূল। এখানে প্রথম উদাহরণটি আপনার করা দরকার।
পিটার লরি

1
গৃহীত উত্তরের প্রথম মন্তব্যে যেমন বলা হয়েছে, দু'টি কারণে রিপোর্ট করা "প্রসেসর" এর অর্ধেক সংখ্যার ব্যবহার করা ভাল হবে: ১. আপনার যদি হাইপার-থ্রেডিং থাকে তবে প্রসেসরের আসল সংখ্যা রিপোর্টের অর্ধেক , এবং 2. এটি সিস্টেমের বাকী অংশের জন্য কিছু প্রক্রিয়াকরণ শক্তি (ওএস এবং অন্যান্য প্রোগ্রাম) দেয়।
ম্যাথিউউ

10

বিকল্প 1:

নিউ ওয়ার্ক স্টিলিংপুল থেকেExecutors

public static ExecutorService newWorkStealingPool()

সমস্ত উপলভ্য প্রসেসরকে তার লক্ষ্য সমান্তরালতা স্তর হিসাবে ব্যবহার করে একটি ওয়ার্ক-স্টিলিং থ্রেড পুল তৈরি করে।

এই এপিআই দিয়ে আপনার কোনও সংখ্যক কোর পাস করার দরকার নেই ExecutorService

গ্রেপকোড থেকে এই 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)

এর সাথে এনট্রেডগুলি প্রতিস্থাপন করুন 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

স্ট্যান্ডার্ড উপায় হ'ল রানটাইম.জেটআরটাইম ()। উপলভ্য প্রসেসর () পদ্ধতি। বেশিরভাগ স্ট্যান্ডার্ড সিপিইউতে আপনি এখানে সর্বোত্তম থ্রেড গণনা (যা আসল সিপিইউ কোর গণনা নয়) ফিরিয়ে দেবেন। অতএব এটি আপনি যা খুঁজছেন তা।

উদাহরণ:

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

এই জাতীয় নির্বাহক পরিষেবাটি বন্ধ করতে ভুলবেন না (বা আপনার প্রোগ্রামটি প্রস্থান করবে না):

service.shutdown();

ভবিষ্যতের ভিত্তিক এমটি কোড কীভাবে সেটআপ করবেন তা এখানে একটি দ্রুত রূপরেখা (অফটপিক, উদাহরণের জন্য):

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
ক্রিস্টোফের রস আপনি ঠিক বলেছেন, আমি সেই অনুযায়ী স্নিপেট পরিবর্তন করেছি, আপনাকে ধন্যবাদ!
fl0w

3

রানটাইম ক্লাসে উপলভ্য প্রসেসরস () নামে একটি পদ্ধতি রয়েছে। আপনার কতটি সিপিইউ রয়েছে তা নির্ধারণ করতে আপনি এটি ব্যবহার করতে পারেন। যেহেতু আপনার প্রোগ্রামটি সিপিইউ বাউন্ডড, আপনি সম্ভবত উপলব্ধ সিপিইউতে (সর্বাধিক) একটি থ্রেড রাখতে চান।


হাই জেসন এবং এরিক (আপনার উত্তরগুলির উভয়ের জন্য আমি একটি মন্তব্য ব্যবহার করি, কারণ এটি মূলত একই) ঠিক আছে, এটি পরীক্ষা করে দেখতে ভাল, তবে এটি প্রথম অংশ হবে। যখন আমার কাছে মূল গণনা রয়েছে তখন থ্রেডগুলি এই পরিমাণ কোরের মতো চলক হিসাবে থাকতে হবে। আমি এই উদাহরণটি ওপেনবুক.গাইলিওলডসাইন.ডি / জাভাইনেল ৫/২ (জার্মান!) এর আগে চেষ্টা করেছিলাম এবং এটি একটি স্থির থ্রেড ব্যবহার করে। তবে আমি ডুয়াল-কোর পরিবেশে 2 কোর এবং কোয়াড-কোর পরিবেশে 4 টি কোর ব্যবহার করে একই প্রোগ্রামিং করতে চাই। আমি নিজে এটি পরিবর্তন করতে চাই না। এটা কি সম্ভব? ধন্যবাদ! :)
Andreas Hornig

@ আন্ড্রেয়াস - আমার পোস্টে আমি যে আপডেট করেছি তা দেখুন। আমি মনে করি এটি বিষয়টি পরিষ্কার করতে সহায়তা করবে।
জেসকাভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.