새소식

반응형
Python/성능

동시성(Concurrency) vs 병렬성(Parallelism): 차이점 한 번에 정리!

  • -
반응형

 

동시성(Concurrency) vs 병렬성(Parallelism)

시스템 설계에서 자주 헷갈리는 개념인 **동시성(Concurrency)**과 **병렬성(Parallelism)**에 대해 이야기해보려고 합니다.

 

비슷해 보이지만 완전히 다른 이 개념들을 예제와 함께 쉽게 풀어볼게요. 끝까지 읽으면 두 개념의 차이와 실세계 적용 사례를 확실히 이해할 수 있을 거예요! 🚀


🧩 1. 동시성(Concurrency)이란?

동시성은 여러 작업을 동시에 관리하는 개념입니다. 하지만 꼭 여러 작업이 "한 번에 실행"되는 건 아니에요. CPU가 빠르게 작업을 전환하며 진행 상황을 만들어가는 것이 핵심입니다.

💡 예제

예를 들어, 음악을 들으면서 코딩을 하는 상황을 생각해보세요. 단일 CPU는 한 번에 한 작업만 처리할 수 있지만, 아주 빠르게 두 작업을 번갈아 실행하면서 우리가 "동시에 된다"고 느끼는 것이죠. 🎵💻

🔍 동시성은 어떻게 작동할까?

CPU는 **컨텍스트 전환(context switching)**을 통해 동시성을 구현합니다:

  1. 현재 작업의 상태(레지스터, 프로그램 카운터 등)를 저장
  2. 다음 작업의 상태를 불러와 실행
  3. 이 과정을 초고속으로 반복!

⚠️ 하지만 컨텍스트 전환에는 오버헤드가 있어서 너무 자주 전환하면 성능이 저하될 수 있어요.

📌 실세계 사례

  • 웹 브라우저: 페이지 렌더링, 이미지 로드, 사용자 클릭 처리
  • 웹 서버: 여러 클라이언트 요청을 동시에 처리
  • 채팅 앱: 메시지 수신, UI 업데이트, 메시지 전송을 동시에 수행
  • 비디오 게임: 그래픽, 입력, 물리 연산, 사운드를 동시에 관리

🐍 파이썬 코드 예제 (threading 사용)

import threading
import time

def task(name):
    for i in range(3):
        print(f"{name} - Step {i+1}")
        time.sleep(0.5)  # 작업 대기 시뮬레이션

# 스레드 생성
t1 = threading.Thread(target=task, args=("Task A",))
t2 = threading.Thread(target=task, args=("Task B",))
t3 = threading.Thread(target=task, args=("Task C",))

# 스레드 시작
t1.start()
t2.start()
t3.start()

# 모든 스레드가 끝날 때까지 대기
t1.join()
t2.join()
t3.join()

출력 예시 (중첩 실행):

Task A - Step 1
Task B - Step 1
Task C - Step 1
Task A - Step 2
Task B - Step 2
Task C - Step 2
...

스레드가 서로 번갈아 실행되면서 동시성이 구현되는 걸 볼 수 있습니다.

반응형

⚡ 2. 병렬성(Parallelism)이란?

병렬성은 여러 작업을 진짜로 동시에 실행하는 것입니다. 이를 위해 작업을 여러 개의 작은 조각으로 나누고, 각 조각을 여러 CPU 코어나 GPU에 분산해서 처리합니다. 즉, 단일 CPU로는 불가능하고 멀티코어 환경이 필수입니다. 🖥️⚙️

🔍 병렬성은 어떻게 작동할까?

  1. 작업을 독립적인 하위 작업으로 분할
  2. 각 하위 작업을 별도의 코어에 할당
  3. 모든 코어가 동시에 실행 후 결과를 합침

📌 실세계 사례

  • 머신 러닝: 데이터 배치를 여러 GPU에서 병렬 훈련
  • 비디오 렌더링: 프레임을 나눠 동시에 렌더링
  • 웹 크롤러: 여러 URL을 나눠 동시에 크롤링
  • 빅 데이터 처리: Apache Spark로 대규모 로그 분석
  • 과학 시뮬레이션: 날씨 모델링 계산을 여러 코어로 분산

🐍 파이썬 코드 예제 (multiprocessing 사용)

from multiprocessing import Pool
import time

def compute_sum(segment):
    return sum(segment)

if __name__ == "__main__":
    array = list(range(1000000))  # 큰 배열
    segment_size = len(array) // 4  # 4개로 분할
    segments = [array[i:i + segment_size] for i in range(0, len(array), segment_size)]

    start_time = time.time()
    
    # 병렬 처리
    with Pool(processes=4) as pool:
        results = pool.map(compute_sum, segments)
    
    total = sum(results)
    print(f"총합: {total}")
    print(f"소요 시간: {time.time() - start_time:.2f}초")

설명:

  • 배열을 4개로 나누고, 4개의 프로세스가 병렬로 합계를 계산합니다.
  • 멀티코어 CPU에서 실행하면 속도가 훨씬 빨라지는 걸 경험할 수 있어요! 🚀

🔄 3. 동시성과 병렬성의 조합

이 두 개념을 조합하면 네 가지 상황이 나옵니다:

  • 동시적이지만 병렬 아님: 단일 코어에서 여러 작업을 번갈아 처리 (예: 음악 듣기 + 코딩)
  • 병렬적이지만 동시 아님: 한 작업을 여러 코어로 분할 (예: 비디오 렌더링)
  • 둘 다 아님: 순차 실행 (예: 단일 코어에서 하나씩 실행)
  • 동시성 + 병렬성: 여러 작업을 동시에 관리하면서 멀티코어로 병렬 처리 (예: 게임 엔진)

🎯 4. 언제 무엇을 사용할까?

 

특징 동시성(Concurrency)  병렬성(Parallelism)
목적 여러 작업을 효율적으로 관리 여러 작업을 동시에 실행
필요 조건 단일 코어로도 가능 멀티코어 필요
예시 웹 서버, 채팅 앱 머신 러닝, 비디오 렌더링
파이썬 도구 threading multiprocessing

 

동시성은 작업이 겹칠 때 CPU를 바쁘게 유지하며 응답성을 높이고,

 ✅ 병렬성은 작업을 나눠 속도를 극대화해요.

상황에 맞게 선택하면 시스템 성능을 최적화할 수 있답니다!

🏁 마무리

이제 동시성과 병렬성의 차이점이 확실해졌나요? 😃 실제 프로젝트에서 이 개념을 적용하면 성능을 최적화할 수 있습니다. 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.