2009-12-16 3 views
3

N 개의 실시간 데이터 독립적 작업 세트가 있습니다. 각 작업은 일부 디지털 데이터 스트림을 처리합니다. 각 작업에 대한 데이터 스트림은 입력 포트에서 나오고 결과 스트림은 출력 포트로 보내집니다.스레드 또는 프로세스? 데이터 독립적 인 작업을 사용하는 것이 더 낫습니다.

1) 계산 상 덜 집중적 인 것 : 프로세스 또는 스레드 형태의 작업?
2) 사용 가능한 실제 CPU 코어 수에 따라 최선의 선택이 결정됩니까?

미리 감사드립니다.

+1

관심있는 플랫폼은 무엇입니까? –

+0

다중 플랫폼 소프트웨어, Linux에 가장 관심이 있음, 2 Quad-Xeon – psihodelia

+2

다른 질문을 드리겠습니다. 하나의 프로세스와 많은 스레드가 있으면 코어 덤프가 발생하고 모든 작업이 중단됩니다. 또는 많은 프로세스가 있으며, 하나의 프로세스가 고르면 다른 프로세스가 작동합니다. –

답변

2

실제로 작업 사이에 국가의 많은 양을 공유 할 필요가없는 경우는, 다음 프로세스는 더 좋은 옵션이 될 가능성이 높다. 스레딩에 포함 된 작업 간의 밀접한 결합으로 실시간 보장을 제공하는 것이 훨씬 어려워집니다. 잠금 기능을 사용하면 실시간 동작을 증명하는 것이 훨씬 어려워집니다.

요약하면 프로세스가 기본 옵션이어야합니다. 확실한 이유가있는 경우에만 스레드로 전환하십시오.

3

스레드는 프로세스 내에서 동일한 메모리 공간을 공유하기 때문에 오버 헤드가 약간 적지 만 프로그램에 영향을 미치지 않을 정도로 작을 수 있습니다. 확실한 방법을 알기위한 유일한 방법은 어느 것이 더 오래 걸릴지 측정하는 것입니다.

+0

이들은 동일한 메모리 공간을 공유하지만 운영 체제는 프로세스의 스레드를 이렇게 배치합니다. , 그들은 모두 하나의 물리적 CPU에서만 실행됩니다. 즉, 다중 CPU 구성에서 일부 CPU는 유휴 상태를 유지합니다. 하지만 확실하지는 않습니다. 현대 리눅스 NUMA가 더 나은로드 밸런스를 제공 할 수도 있습니다. – psihodelia

+0

스트림이 독립적 인 경우 스레드는 별도 프로세스를 사용할 때 o/s가 처리하는 단일 프로세스 내에서 리소스를 조정하는 오버 헤드가 있습니다. –

0

스레드.

배포와 같은 다양한 유형의 오버 헤드를 단순화합니다. 어떤 시점에서는 상호 작용 (예 : 공통 로그 작성 또는 공통 관리 콘솔 사용)이 필요할 수 있기 때문에 미래 보장이됩니다.

+2

스레드를 사용하면 특히 사용자가 상호 작용하도록하려는 경우 더욱 세밀한 버그가 허용됩니다. –

2

이 질문에 대한 답변은 없습니다. 두 가지 예를 들자면, 리눅스는 별개의 프로세스를 사용하는 경향이있다. 커널 개발자들은 프로세스 전환 최적화에 많은 노력을 기울였습니다. 스레드는 꽤 나중에 추가되었고 거의 주목받지 못한 것 같습니다. 결과적으로 리눅스에서는 별도의 프로세스가 상당히 저렴하고 대신 쓰레드를 사용하면 막대한 비용을 절약 할 수 있습니다.

이와 대조적으로 Windows의 현재 구현은 Windows NT로 돌아갑니다. Windows NT는 처음부터 스레드가있는 OS/2에 상당히 근거를 두었습니다. 프로세스 전환은 Linux에서와 같은 정도로 최적화되지 않은 것 같습니다. 그런 배경에서 기대할 수 있듯이 Windows에서는 프로세스 스위치와 스레드 스위치의 차이가 훨씬 큽니다. 결과적으로 여러 프로세스 대신 여러 스레드에 코드를 작성함으로써 훨씬 많은 것을 얻을 수 있습니다.

+0

성명을 진술 해 주시겠습니까? 어쩌면 웹 링크일까요? – psihodelia

+0

증명해야 할 진술은 다음 중 어느 것입니까? 스레드 전환 속도의 벤치 마크는 일반적으로 Windows 제품 라인의 유산을 다루는 사이트와 다른 사이트에 있습니다. –

+0

스레드 대 프로세스에 대한 논의는 E S Raymond의 'The Art of Unix Programming'을 읽어보십시오. –

0

1) 계산 상 덜 집중적 인 것은 무엇입니까? 프로세스 또는 스레드 형태의 작업입니까?

일반적으로 밝기는 동일합니다. VERY EXOTIC 조건에서는 스레드가 덜 집중적 일 수 있습니다.

2) 사용 가능한 실제 CPU 코어 수에 따라 최선의 선택이 결정됩니까?

다른 CPU 코어에서 실행되는 2 개 이상의 스레드 마녀는 훨씬 더 천천히 단일 코어 시스템입니다. 슈퍼 스칼라 아키텍처의 문제입니다.

프로세스는 99.9 %에서 최상의 선택입니다.

또한 스레딩 환경을 디버깅하기가 어렵습니다.

+0

두 개 이상의 스레드 마녀가 다른 CPU 코어에서 실행됩니다. - 아마도 두 개의 다른 물리적 CPU를 의미할까요? – psihodelia

+0

아니요, x86 아키텍처에서와 동일합니다. –

1

작업 단위가 CPU 바운드 인 경우 일반적으로 프로세스의 모든 스레드가 (최소한 Linux에서는) 동일한 코어에서 실행되기 때문에 프로세스를 사용하는 것이 가장 좋습니다. CPU 코어 당 프로세스를 사용하면 각 프로세스가 실제 CPU 코어를 확보 할 수 있습니다.

스레드의 장점은 상태를 공유하기가 쉽기 때문에 블로킹없이 파일을 다운로드하거나 데이터베이스에 쿼리를 보내는 것이 정말로 필요한 경우 스레드가 더 나은 옵션이 될 수 있다는 것입니다.

사실 저는 여러분이 유용 할 수있는 뭔가를 작성하는 중입니다. 몇 가지 작업자 프로세스를 생성하고 종료/종료/종료되면 다시 시작하는 관리자입니다. 그것은 꽤 많이 준비, 그래서 여기있다 :

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <string> 

void termination_handler(int signum) 
{ 
    printf("pid %d : signal %d caught in pid %d\n", getpid(), signum, getpid()); 
    kill(0, SIGTERM); 
    exit(1); 
} 

int main(int argc ,char** argv) 
{ 
    if (argc > 1) 
    { 
     printf("pid %d : Worker code running\n", getpid()); 
     sleep(10); 
    } 
    else 
    { 
     printf("pid %d : manager started\n", getpid()); 
     // manager 
     const int MAX_INSTANCES = 3; 
     int numInstances = 0; 

     struct sigaction new_action; 
     /* Set up the structure to specify the new action. */ 
     new_action.sa_handler = termination_handler; 
     sigemptyset(&new_action.sa_mask); 
     new_action.sa_flags = 0; 
     sigaction(SIGKILL, &new_action, NULL); 
     sigaction(SIGTERM, &new_action, NULL); 
     sigaction(SIGINT, &new_action, NULL); 

     int status; 
     int w; 
     do 
     { 
      while (numInstances < MAX_INSTANCES) 
      { 
       int pid = fork(); 
       if (pid < 0) 
       { 
        printf("fork failed\n"); 
        exit(1); 
       } 
       else 
       { 
        if (pid == 0) 
        { 
         char * const argv1[] = { (char*) argv[0], (char*)"worker",(char *) 0 }; 
         char * const envp1[] = { (char *) 0 }; 
         std::string prog = argv[0]; 
         execve(prog.c_str(), argv1, envp1); 
        } 
        else 
        { 
         numInstances++; 
        } 
       } 
      }   

      w = waitpid(0, &status, WUNTRACED | WCONTINUED); 
      if (w == -1) 
      { 
       perror("waitpid"); 
       exit(EXIT_FAILURE); 
      } 

      if (WIFEXITED(status)) 
      { 
       printf("pid %d : child %d exited, status=%d\n",getpid(), w, WEXITSTATUS(status)); 
       numInstances--; 
      } 
      else if (WIFSIGNALED(status)) 
      { 
       printf("pid %d : child %d killed by signal %d\n",getpid(), w, WTERMSIG(status)); 
       numInstances--; 
      } 
      else if (WIFSTOPPED(status)) 
      { 
       printf("pid %d : child %d stopped by signal %d\n",getpid(), w, WSTOPSIG(status)); 
      } 
      else if (WIFCONTINUED(status)) 
      { 
       printf("pid %d : child %d continued\n", getpid(), w); 
      } 
     } 
     while (true); 
     //! WIFEXITED(status) && !WIFSIGNALED(status)); 

     printf("pid %d : manager terminated\n", getpid()); 
    } 
    return 0; 
} 
+0

Linux 댓글은 오래된 것입니다. 이것은 2.5/2.6 커널 이전 (2003 년 말, 2004 년 초반) NPTL은 스케줄러에서 스레드와 작업 사이에 일대일 관계를 제공하며 응용 프로그램이 CPU 바운드인지 아닌지에 관계없이 CPU 바운드 및 독립적으로 실행되는 코드 조각 사이에서 발생해야하는 조정이 포함됩니다. – charstar

1

"올바른"답변이 없다는 답변에 동의합니다. 응용 프로그램 요구 사항에 따라 달라집니다. 분명한 선택이 없다면 나의 개인적인 선택은 실이 될 것입니다.

하지만 효율성 측면에 대해 궁금해했고 어젯밤 집에 가기 전에 정말 간단한 어리 석음 테스트를 작성했습니다. "응용 프로그램"은 간단한 나누기 검사를 사용하여 소수의 수를 계산했습니다. 따라서 순수하게 CPU가 다른 공유 리소스에 대한 경합없이 바인딩되었습니다. 따라서 컨텍스트 스위치의 비용에만 중점을 둡니다. 쿼드 코어 1.86GHz 제온에서 64 개의 인스턴스 (스레드/프로세스)를 실행해도 아무런 차이가 없었습니다. 각 과제는 소수 10,000,000까지 카운트. 두 경우 모두 총 시간은 333 초입니다.

집에서 자전거 타기를하면서, 나는 리소스 경쟁이 없었기 때문에 컨텍스트 스위치가 최소화 될 것이라고 생각했습니다. 모든 스레드/프로세스는 풀 타임 슬라이스로 실행됩니다. 그래서 인위적으로 (Win32) 의도했던대로 Sleep (0)을 사용하여 매 100 회씩 컨텍스트를 강제로 전환했습니다. 그 후 동일한 테스트가 스레드 버전의 경우 343 초, 프로세스 버전의 경우 350 초가 걸렸습니다. 따라서 스레드 버전은 약 1.7 %의 속도 향상을 보였습니다. 집에 관해 쓰는 무엇이라도 정말로.

관련 문제