IT/CS

[OS] 동시성과 병렬성

KimCookieYa 2023. 5. 26. 17:15

동시성과 병렬성

동시성은 여러 작업이 동시에 진행되는 것처럼 보이는 개념이다. 하나의 CPU 코어에서 여러 작업을 번갈아가며 실행하면서 동시성을 구현할 수 있다. 이때 작업 간에는 시간적인 겹침이 발생하며, 각 작업은 작은 단위의 실행을 번갈아가며 처리한다. 동시성은 프로그램의 응답성을 향상시키고 작업의 순서나 우선순위를 조절하는 데에 활용된다. 쓰레드를 이용하여 동시성을 구현할 수 있다.

 

반면에 병렬성은 여러 작업이 실제로 동시에 실행되는 것을 의미한다. 병렬성은 여러 CPU 코어 또는 다중 처리 장치를 활용하여 작업을 동시에 처리함으로써 성능을 향상시킨다. 병렬성은 동시에 실행 가능한 독립적인 작업들을 분할하고 병렬로 처리함으로써 작업을 빠르게 완료할 수 있다. 병렬성은 주로 CPU 집약적인 작업을 가속화하는 데에 활용된다.

 

즉, 동시성은 여러 작업이 동시에 진행되는 것처럼 보이는 개념이며, 병렬성은 여러 작업이 실제로 동시에 실행되는 개념이다. 동시성은 시간적 겹침을 통해 작업을 번갈아가며 처리하고, 병렬성은 작업을 동시에 병렬로 처리한다. 둘은 프로그램의 성능과 확장성을 향상시키는 데에 중요한 역할을 한다.

 

그러나 단일 단일 프로세스 환경에서는 병렬성을 구현할 수 없다. 병렬 처리를 위해서는 다중 코어 시스템이 필요하다. 다중 코어를 활용하는 멀티스레딩 또는 멀티프로세싱 등을 통해 병렬성을 구현할 수 있다.

다중 코어 시스템

다중 코어 시스템에서는 각각의 코어가 완전히 독립적으로 동시에 작업을 실행시킬 수 있으므로, 하나의 프로세스 내에서 여러 개의 쓰레드가 각각의 코어에서 병렬로 실행될 수 있다. 이 경우에는 병렬성이 실현된다.

 

반면, 하나의 프로세서에서 여러 개의 쓰레드를 생성하여 실행할 때는 해당 프로세서에 속한 단일한 코어에서 쓰레드가 번갈아가며 실행되므로, 동시성이 구현되지만, 병렬성은 구현되지 않는다.

 

따라서 병렬성을 실현하기 위해서는 다중 코어 시스템이 필요하며, 각각의 코어에서 독립적으로 작업을 실행해야 한다.

특정 코어에서 쓰레드 실행하기

쓰레드는 일반적으로 프로세스 내에서 생성된다. 따라서, 하나의 프로세스에서 쓰레드를 생성할 때는 기본적으로 해당 프로세스에 속한 단일한 코어에서 쓰레드가 실행된다. 그러나 다중 코어 시스템에서는 특정 코어에 쓰레드를 바인딩(bind)하여 실행하도록 지정할 수 있다. 이를 통해 특정 작업을 특정 코어에 할당하고, 다른 작업을 다른 코어에 할당하여 병렬로 실행할 수 있다.

 

쓰레드를 특정 코어에 바인딩하는 방법은 OS나 프로그래밍 언어에 따라 다를 수 있다. 일반적으로 OS나 쓰레드 관련 라이브러리는 쓰레드 스케줄링을 담당하며, 쓰레드를 적절하게 코어에 할당하여 실행합니다. 이를 통해 다중 코어 시스템에서 쓰레드를 병렬로 실행할 수 있다.

 

아래는 C 언어에서 POSIX 스레드(pthread)를 사용하여 쓰레드를 특정 코어에 바인딩하는 간단한 예제이다. 이 예제는 Linux 기반 시스템에서 동작한다.

 

  • 예제 코드
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* threadFunction(void* arg) {
    // 쓰레드에서 실행될 작업
    printf("Thread is running on core %d\n", sched_getcpu());
    sleep(1);
    return NULL;
}

int main() {
    pthread_t thread;
    cpu_set_t cpuset;

    // 쓰레드를 생성하기 전에 CPU 집합을 초기화
    CPU_ZERO(&cpuset);
    // 바인딩할 코어를 선택하여 CPU 집합에 추가
    CPU_SET(1, &cpuset); // 예시로 코어 1에 바인딩

    // 쓰레드 생성 후 바인딩
    pthread_create(&thread, NULL, threadFunction, NULL);
    pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);

    // 메인 쓰레드의 실행 작업
    printf("Main thread is running on core %d\n", sched_getcpu());
    sleep(1);

    pthread_join(thread, NULL); // 쓰레드 종료 대기

    return 0;
}

 

이 예제에서는 pthread_create 함수를 사용하여 쓰레드를 생성하고, pthread_setaffinity_np 함수를 사용하여 쓰레드를 특정 코어에 바인딩한다. CPU_SET 매크로를 사용하여 바인딩할 코어를 지정할 수 있다. 위의 예제에서는 코어 1에 쓰레드를 바인딩하고 있다.

 

쓰레드의 작업은 threadFunction 함수에서 실행되며, 간단히 현재 실행 중인 쓰레드가 어느 코어에서 동작하고 있는지를 출력한다. 메인 쓰레드도 마찬가지로 현재 실행 중인 쓰레드가 어느 코어에서 동작하는지를 출력한다.

 

실행해보면, 쓰레드와 메인 쓰레드가 각각 다른 코어에서 실행되는 것을 확인할 수 있다. 하지만, 이 예제는 특정 코어에 바인딩하는 방법을 보여주기 위한 간단한 예제일 뿐이며, 다양한 환경에서의 동작을 보장하지는 않는다. 실제로 쓰레드 바인딩은 시스템 의존적인 기능이므로, 사용하는 운영체제 및 환경에 따라 세부적인 동작 방식이 달라질 수 있다.