[java] CPU 코어에 따라 스레드를 확장하는 방법은 무엇입니까?

Java에서 여러 스레드로 수학적 문제를 해결하고 싶습니다. 내 수학 문제는 여러 스레드에서 풀고 싶은 작업 단위로 나눌 수 있습니다.

고정 된 양의 스레드가 작업하는 대신 CPU 코어의 양과 일치하는 양의 스레드를 원합니다. 내 문제는 인터넷에서 이것에 대한 쉬운 튜토리얼을 찾을 수 없다는 것입니다. 내가 찾은 모든 것은 고정 스레드가있는 예제입니다.

어떻게 할 수 있습니까? 예를 들어 줄 수 있습니까?



답변

정적 런타임 메소드 인 availableProcessors를 사용하여 Java Virtual Machine에서 사용 가능한 프로세스 수를 판별 할 수 있습니다 . 사용 가능한 프로세서 수를 결정했으면 해당 수의 스레드를 만들고 그에 따라 작업을 분할합니다.

업데이트 : 좀 더 명확히하기 위해 스레드는 Java의 객체 일 뿐이므로 다른 객체를 생성하는 것처럼 만들 수 있습니다. 따라서 위의 메서드를 호출하고 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();
}

자신 만의 스레드를 만드는 방법에 대한 자세한 내용은 이 튜토리얼을 참조하십시오 . 또한 스레드 생성을 위해 스레드 풀링 을 살펴볼 수도 있습니다 .


답변

이 항목에 대한 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

이것은 자신의 스레드 풀 등에 대처하는 것보다 훨씬 좋습니다.


답변

옵션 1:

newWorkStealingPool fromExecutors

public static ExecutorService newWorkStealingPool()

사용 가능한 모든 프로세서를 대상 병렬 처리 수준으로 사용하여 작업 도용 스레드 풀을 만듭니다.

이 API를 사용하면 .NET Core에 코어 수를 전달할 필요가 없습니다 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 :

Executors또는 에서 newFixedThreadPool API 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.


답변

Doug Lea (동시 패키지 작성자)는 관련이있을 수있는이 문서를 보유하고 있습니다.
http://gee.cs.oswego.edu/dl/papers/fj.pdf

Fork Join 프레임 워크가 Java SE 7에 추가되었습니다. 다음은 몇 가지 추가 참조입니다.

http://www.ibm.com/developerworks/java/library/j-jtp11137/index.html
기사 by Brian Goetz

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


답변

표준 방법은 Runtime.getRuntime (). availableProcessors () 메소드입니다. 대부분의 표준 CPU에서는 여기에 최적의 스레드 수 (실제 CPU 코어 수가 아님)를 반환합니다. 그러므로 이것은 당신이 찾고있는 것입니다.

예:

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();
}


답변

Runtime 클래스에는 availableProcessors ()라는 메서드가 있습니다. 이를 사용하여 보유한 CPU 수를 파악할 수 있습니다. 프로그램이 CPU 바운드이기 때문에 사용 가능한 CPU 당 하나의 스레드를 갖고 싶을 것입니다.


답변