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


107

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

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

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

답변:


119

정적 런타임 메소드 인 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();
}

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


17
이것은 기본적으로 정확하지만 인텔의 "하이퍼 스레딩"으로 판매되는 프로세서의 성능에주의하십시오. 쿼드 코어에서는 4 개 대신 8 개를 반환하지만 실제로 4 개 스레드 후에 성능이 떨어지기 시작할 수 있습니다. 그래서 내 벤치 마크에
따르면

안녕, 그래, 몰랐어. 가능하다는 걸. 하지만 하나의 작업을 여러 작업 단위로 분할하고 최종 작업 단계에 대한 모든 부품 솔루션이 필요한 경우 어떻게 수행합니까? "yourThreads"가 여러 개있을 때 join ()을 사용하는 방법을 알 수 없습니다.이 여러 스레드를 어떻게 구별 할 수 있습니까? :) BTW : 스레드 풀링에 대한 링크를 통해 ibm.com/developerworks/library/j-jtp0730.html로 연결됩니다. :)
Andreas Hornig

5
여기에서 예제를보십시오. java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/… 스레드 풀을 만들고 관리하는보다 효율적인 방법을 알려줍니다. 처음에는 더 복잡하지만 대부분의 경우와 마찬가지로 더 복잡합니다. 더 간단하면 제한에 더 빨리 도달 할 수 있기 때문입니다.
Bill 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

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


안녕하세요 DaveC, 흠, 전에는 몰랐습니다. 그래서 이것을 살펴 보겠습니다. 사용 가능한 CPU 코어에 따라 확장 할 수 있습니까? 짧은 예에서는 볼 수 없기 때문입니다. 안드레아스
Andreas Hornig 2009

3
java.util.concurrent는 확장 성이 뛰어납니다
Kristopher Ives

4
사용 가능한 프로세서 수가있는 고정 크기 풀은 종종 CPU 바운드 프로세스에 최적입니다. 여기에있는 첫 번째 예는 필요한 모든 것입니다.
Peter Lawrey 2009

1
허용 된 답변의 첫 번째 의견에서 언급했듯이 두 가지 이유로보고 된 "프로세서"수의 절반을 사용하는 것이 좋습니다. 1. 하이퍼 스레딩을 사용하는 경우 실제 프로세서 수는보고 된 것의 절반입니다. , 및 2. 나머지 시스템 (OS 및 기타 프로그램)이 작동하도록 일부 처리 능력을 허용합니다.
Matthieu

10

옵션 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.



4

표준 방법은 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();
}

2
종료 통화가 마지막 시도에 넣어해야
크리스토프 후씨

1
@ChristopheRoussy 당신 말이 맞습니다, 그에 따라 스 니펫을 수정했습니다, 감사합니다!
fl0w

3

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


안녕하세요 Jason과 Eric (기본적으로 동일하기 때문에 두 답변 모두에 대해 하나의 댓글을 사용합니다). 좋습니다. 확인하는 것은 좋지만 이것이 첫 번째 부분입니다. 코어 수가 있으면이 코어 수만큼 스레드를 가변적으로 가져야합니다. 이 예제는 openbook.galileodesign.de/javainsel5/… (독일어!) 전에 시도 했으며 고정 스레드를 사용합니다. 하지만 듀얼 코어 환경에서 2 코어를 사용하고 쿼드 코어 환경에서 4 코어를 사용하여 동일한 프로그래밍을하고 싶습니다. 수동으로 변경하고 싶지 않습니다. 이게 가능해? 고마워! :)
Andreas Hornig 2009

@Andreas-내 게시물에 대한 업데이트를 참조하십시오. 문제를 명확히하는 데 도움이 될 것 같습니다.
JasCav 2009
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.