DrawingProcess
드프 DrawingProcess
DrawingProcess
전체 방문자
오늘
어제
«   2025/06   »
일 월 화 수 목 금 토
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
  • 분류 전체보기 (966) N
    • Profile & Branding (24) N
      • Career (17) N
    • IT Trends (254)
      • Conference, Faire (Experien.. (31)
      • News (187)
      • Youtube (19)
      • TED (8)
      • Web Page (2)
      • IT: Etc... (6)
    • Contents (97)
      • Book (66)
      • Lecture (31)
    • Project Process (94)
      • Ideation (0)
      • Study Report (34)
      • Challenge & Award (22)
      • 1Day1Process (5)
      • Making (5)
      • KRC-FTC (Team TC(5031, 5048.. (10)
      • GCP (GlobalCitizenProject) (15)
    • Study: ComputerScience(CS) (72)
      • CS: Basic (9)
      • CS: Database(SQL) (5)
      • CS: Network (14)
      • CS: OperatingSystem (3)
      • CS: Linux (39)
      • CS: Etc... (2)
    • Study: Software(SW) (95)
      • SW: Language (29)
      • SW: Algorithms (1)
      • SW: DataStructure & DesignP.. (1)
      • SW: Opensource (15)
      • SW: Error Bug Fix (43)
      • SW: Etc... (6)
    • Study: Artificial Intellige.. (149)
      • AI: Research (1)
      • AI: 2D Vision(Det, Seg, Tra.. (35)
      • AI: 3D Vision (70)
      • AI: MultiModal (3)
      • AI: SLAM (0)
      • AI: Light Weight(LW) (3)
      • AI: Data Pipeline (7)
      • AI: Machine Learning(ML) (1)
    • Study: Robotics(Robot) (33)
      • Robot: ROS(Robot Operating .. (9)
      • Robot: Positioning (8)
      • Robot: Planning & Control (7)
    • Study: DeveloperTools(DevTo.. (83)
      • DevTool: Git (12)
      • DevTool: CMake (13)
      • DevTool: NoSQL(Elastic, Mon.. (25)
      • DevTool: Container (17)
      • DevTool: IDE (11)
      • DevTool: CloudComputing (4)
    • 인생을 살면서 (64)
      • 나의 취미들 (7)
      • 나의 생각들 (42)
      • 여행을 떠나자~ (10)
      • 분기별 회고 (5)

개발자 명언

“ 매주 목요일마다 당신이 항상 하던대로 신발끈을 묶으면 신발이 폭발한다고 생각해보라.
컴퓨터를 사용할 때는 이런 일이 항상 일어나는데도 아무도 불평할 생각을 안 한다. ”

- Jef Raskin

맥의 아버지 - 애플컴퓨터의 매킨토시 프로젝트를 주도

인기 글

최근 글

최근 댓글

티스토리

hELLO · Designed By 정상우.
DrawingProcess

드프 DrawingProcess

Study: Software(SW)/SW: Language

[C++] 병행 컴퓨팅: concurrency, thread...

2022. 6. 16. 17:10
반응형

병행 컴퓨팅 (concurrency)


  • 여러 개의 계산들을 연속적(하나씩 일을 마치는 것)으로가 아닌, 병행 처리하는 것을 말합니다.
  • 병행 시스템은 다른 계산들이 모두 끝날 때까지 기다리지 않고 계산을 진행할 수 있는 환경을 말하며, 즉 하나 이상의 계산은 동시에 진행이 가능합니다.
  • 프로그램 논리 구조 상에서 연산들 간의 의존 관계가 많을수록 병렬화가 어려워지고,
    반대로, 다른 연산의 결과와 관계없이 독립적으로 수행할 수 있는 구조가 많을수록 병렬화가 매우 쉬워집니다.
     
    • 쓰레드: CPU 코어에서 돌아가는 프로그램 단위. 한 프로세스 내에 있는 쓰레드끼리는 메모리 교환 가능.
    • 프로세스: 최소 한 개 쓰레드로 이루어져 있으며, 여러 개의 쓰레드로 구성(멀티 쓰레드). 프로세스끼리 메모리를 공유하지 않음.

 

std::thread


  • 이전에는 C++ 표준에 쓰레드가 없어서, 각 플랫폼 마다 다른 구현을 사용해야만 했습니다.
    • 예를 들어서 윈도우즈에서는 CreateThread 로 쓰레드를 만들지만 리눅스에서는 pthread_create 로 만듭니다.
  • 하지만 C++ 11 에서부터 표준에 thread가 추가되면서, 쓰레드 사용이 매우 편리해졌습니다.
  • 인자가 없는 함수, 인자를 가지는 함수, 람다 함수 등을 이용하여 쓰레드를 생성할 수 있습니다.
  • 참고로 리눅스에서 컴파일 하는 분은 컴파일 옵션에 -pthread 를 추가로 넣어야 합니다.
#include "spdlog/fmt/fmt.h"
#include <thread>

void func1()
{
    fmt::print("[T1] I will be dead\n");
}

void func2(int const i)
{
    fmt::print("[T2] I will be dead after {} seconds\n", i);
    std::this_thread::yield();
    std::this_thread::sleep_for(std::chrono::seconds(i));
    fmt::print("[T2] now I am dead\n", i);
}

int main()
{
    std::thread t1(func1);
    std::thread t2(func2, 5);
    std::thread t3([]()
                   { fmt::print("[T3] I am lambda thread\n"); });

    t1.join();
    t2.join();
    t3.join();

    return 0;
}
  • join 은, 해당하는 쓰레드들이 실행을 종료하면 리턴하는 함수 입니다.
    따라서 
    t1.join() 의 경우 t1 이 종료하기 전 까지 리턴하지 않습니다.
  • detach 는 말 해당 쓰레드를 실행 시킨 후, 잊어버리는 것 이라 생각하시면 됩니다.
    대신 쓰레드는 알아서 백그라운드에서 돌아가게 됩니다.
     
    • C++ 표준에 따르면, join 되거나 detach 되지 않는 쓰레드들의 소멸자가 호출된다면 예외를 발생시키도록 명시되어 있습니다.

+ std::cout, printf

std::cout << "쓰레드 " << hex << this_id << " 에서 " << dec << *start << " 부터 "
     << *(end - 1) << " 까지 계산한 결과 : " << sum << std::endl;
  • std::cout 
    • << 를 실행하는 과정 중간 중간에 계속 실행되는 쓰레드들이 바뀌면서 결과적으로 메세지가 뒤섞여서 나타나게 됩니다.
    • 따라서, std::cout 의 경우 std::cout << A; 이렇게 선언하여, A 의 내용이 출력되는 동안 중간에 다른 쓰레드가 내용을 출력할 수 없게 해야합니다.
      • 그 사이에 컨텍스트 스위치가 되더라도 다른 쓰레드가 내용을 출력할 수 없습니다.
  • printf
    •  "..." 안에 있는 문자열을 출력할 때, 컨텍스트 스위치가 되더라도 다른 쓰레드들이 그 사이에 메세지를 넣지 못하게 막습니다.
  •  

std::mutex, lock


  • 영어의 상호 배제 (mutual exclusion) 라는 단어에서 따온 단어 입니다.
  • m.lock() 은 뮤텍스 m의 사용권한을 갖는 것이며, 한 번에 한 쓰레드에서만 m 의 사용 권한을 갖습니다.
  • 이때 m 을 소유한 쓰레드가 m.unlock() 을 통해 사용권한을 반환할 수 있습니다.
    • 이때 m.lock() 과 m.unlock() 사이에 한 쓰레드만이 실행할 수 있는 코드 부분을 임계 영역(critical section) 이라고 부릅니다.
#include <iostream>
#include <mutex>  // mutex 를 사용하기 위해 필요
#include <thread>
#include <vector>

void worker(int& result, std::mutex& m) {
  for (int i = 0; i < 10000; i++) {
    m.lock();
    result += 1;
    m.unlock();
  }
}

int main() {
  int counter = 0;
  std::mutex m;  // 우리의 mutex 객체

  std::vector<std::thread> workers;
  for (int i = 0; i < 4; i++) {
    // std::ref() 는 특정 타입을 참조하는 객체를 만들며, &와 다르게 타입만 같다면 참조대상 교체 가능.
    // 주로 thread의 인자 또는 bind의 인자로 넘겨줄 때 사용함.
    workers.push_back(std::thread(worker, std::ref(counter), std::ref(m)));
  }

  for (int i = 0; i < 4; i++) {
    workers[i].join();
  }

  std::cout << "Counter 최종 값 : " << counter << std::endl;
}
  • 이때 뮤텍스를 취득한 쓰레드가 unlock 을 하지 않는다면? 다른 모든 쓰레드들이 기다리게 되므로 '데드락(deadlock) 상태'가 됩니다.따라서 취득한 뮤텍스는 반드시 반환해야 합니다.
    • 이는 포인터를 반드시 delete 해야하는 것과 유사하며, unique_ptr과 비슷한 해제패턴(lock_guard)으로 처리할 수 있습니다.
  • lock_guard 객체는 뮤텍스를 인자로 받아서 생성하면, lock_guard 가 소멸될 때 알아서 lock 했던 뮤텍스를 unlock 하게 됩니다.
std::mutex g_mutex;
// 락을 걸어야 할 장소
{ // scope 한정으로 락 범위를 좁힌다.
  std::lock_guard<std::mutex> lock(g_mutex);
  // 락이 필요한 연산
}
  • 이 외의 데드락 상황을 피하기 위한 가이드라인
    • 중첩된 Lock 을 사용하는 것을 피해라
    • Lock 을 소유하고 있을 때 유저 코드를 호출하는 것을 피해라
    • Lock 들을 언제나 정해진 순서로 획득해라

+ lock 사용을 위한 표준 클래스

  • std::lock_guard
  • std::unique_lock
  • std::shared_lock

 

생산자(Producer) 와 소비자(Consumer) 패턴


  • 생산자의 경우, 무언가 처리할 일을 받아오는 쓰레드를 의미합니다.
  • 소비자의 경우, 받은 일을 처리하는 쓰레드를 의미합니다.
  • TODO...(복잡쓰...)

 

쓰레드 간 통신


  • conditional_variable, atomic, future 등을 통해 쓰레드 간 통신, 쓰레드 간 리턴값 반환 등을 할 수 있습니다.

참고


  • [wiki] 병행 컴퓨팅: https://ko.wikipedia.org/wiki/%EB%B3%91%ED%96%89_%EC%BB%B4%ED%93%A8%ED%8C%85?tableofcontents=0
  • [씹어먹는 C++] 동시에 실행을 시킨다고? - C++ 쓰레드(thread): https://modoocode.com/269
  • [씹어먹는 C++] C++ 뮤텍스(mutex) 와 조건 변수(condition variable): https://modoocode.com/270
  • [네이버 블로그] std::ref: https://m.blog.naver.com/pkk1113/221711759046

반응형
저작자표시 비영리 변경금지 (새창열림)

'Study: Software(SW) > SW: Language' 카테고리의 다른 글

[C++] 객체지향 프로그래밍: static, explicit, mutable, default, delete...  (0) 2022.06.22
[C++] C++ Json 라이브러리 성능비교(벤치마크): JsonCpp, Nlohmann/json...  (0) 2022.06.16
[C++] 초심자가 자주 하는 C++ 실수  (0) 2022.06.15
[C++] 알고리즘 (#include <algorithm>): 있는 거 가져다 쓰자.  (0) 2022.06.15
[C++] 템플릿 메타 프로그래밍 (Template Meta-programming)  (0) 2022.06.14
    'Study: Software(SW)/SW: Language' 카테고리의 다른 글
    • [C++] 객체지향 프로그래밍: static, explicit, mutable, default, delete...
    • [C++] C++ Json 라이브러리 성능비교(벤치마크): JsonCpp, Nlohmann/json...
    • [C++] 초심자가 자주 하는 C++ 실수
    • [C++] 알고리즘 (#include <algorithm>): 있는 거 가져다 쓰자.
    DrawingProcess
    DrawingProcess
    과정을 그리자!

    티스토리툴바