전체 글 262

[C++ Thread] 약속과 미래 객체, std::promise / std::future

C++11에 도입된 std::promise와 std::future 객체를 알아본다. 약속 객체 (std::promise) 약속 객체는 주로 비동기적으로 실행되는 다른 쓰레드로 부터 계산된 값이나 예외를 저장할 수 있는 공간을 가지고 있다. 약속 객체가 쓰레드의 완료로 저장한 값을 전달하기 위해 미래 객체가 필요하고 미래 객체는 약속 객체에 의해 생성된다. 또한 약속 객체는 결과 전달을 한번만 하도록 설계되었다. 템플릿 정의 template class promise; // 기본 템플릿 template class promise; // 쓰레드간 객체를 통신하기위해 사용한다. template class promise; // 상태없는 이벤트를 통신하기위해 사용한다. - 템플릿 인수에 전달받을 값의 타입을 명시하여..

[C++ Thread] memory order 와 atomic 객체

메모리 수정 순서와 동기화 방법을 제공하는 atomic 객체 ※ 다음 글들을 참고하였습니다. modoocode.com/271 en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering 메모리가 수정되는 순서에 관하여 - 단일 스레드에서 1) 동적 파이프라인 스케줄링에 의해 다음 함수를 컴파일하여 실행했을 시 a 대입과 b 대입의 순서에 대한 문제 #include int a = 0; int b = 1; int func(int* arr) { a = arr[1] + b; b = 5; return a; } int main() { int arr[5] = { 0,1,2,3,4 }; int result = func(arr); return 0; } 코드 흐름 상으로..

[컴퓨터 구조] 11. 캐시 성능 측정 및 향상

다단계 캐싱(multilevel caching) 여러 캐시를 계층적 구조로 사용하여 실패 손실을 줄이는 기술. 1 차 캐시에 데이터가 없다면 2차 캐시를 조회하게 되는데 2차 캐시에 데이터가 있다면 주 메모리 접근 시간보다 훨씬 작다. 보통 1차 캐시는 2차 캐시보다 작다. 1차 캐시는 CPU와 최대한 가깝도록 설계하여 적중 시간을 최소화하고 2차 캐시는 더 크게 설계하여 큰 블록에 대한 실패율을 감소시킨다. 적중된 캐시에 의한 정상적인 CPU 실행 시간은 다음과 같다. CPU 시간 = (CPU 클럭 사이클 + 메모리 지연 클럭 사이클) x 클럭 사이클 시간 메모리 지연 클럭 사이클은 읽기와 쓰기 행동에 의해 걸리는 시간의 합이다. 메모리 지연 클럭 사이클 = 읽기 지연 사이클 + 쓰기 지연 사이클 읽기..

[컴퓨터 구조] 10. 메모리 기술

메모리 계층 메모리는 계층구조를 가지는 형태로 발전해왔으며 CPU 프로세서와 가까울 수록 데이터 접근시간이 빠르고 비용이 비싸다. 메인 메모리 DRAM으로 구현되고 캐시는 SRAM으로 구현되며 USB와 같은 휴대 메모리는 플래시 메모리를 사용한다. 하드 디스크와 같은 가장 느린 저장장치는 자기 테이프로 구현되어있다. 메모리의 지역성 어떤 데이터를 접근하기 위해 기본적인 원리가 있는데, 최근에 참조한 데이터가 다시 참조할 가능성이 높다는 시간적 지역성과 최근에 참조한 데이터와 근처에 있는 주소의 데이터를 참조할 가능성이 높을 것이라는 공간적 지역성이 사용된다. 메모리 계층에서 데이터의 이동 메모리 계층구조는 여러 층으로 구성되어 있지만 데이터는 인접한 두 계층 사이에서만 한 번에 복사가 된다. 이런 두 계..

[C++ Thread] 생산자 소비자 문제

멀티 스레드를 이용하여 생산자-소비자 문제를 구현해보고 문제가 되는 부분을 해결해본다. 1. 생산자는 매 0.5마다 data chunk(char)를 큐에 넣는 것으로 데이터를 생산한다. 2. 소비자는 매번 마다 큐에 데이터가 있다면 자신의 데이터에 추가하고 업다면 1초 대기한다. n 생산자 m 소비자를 여러 쓰레드로 구현한다면 공유 변수 문제는 다음과 같고 쉽게 해결할 수 있다. - 공유 변수 : 큐를 접근할 때 하나의 쓰레만 읽고 쓸 수 있도록한다. - mutex의 사용으로 해결 #include #include #include #include #include #include #include #include using std::thread; using std::queue; using std::mutex;..

[C++ Thread] 공유 변수와 경쟁 조건

멀티 쓰레드를 이용한 프로그래밍을 할 경우 공유 자원을 병행적으로 읽고 쓰기 때문에 경쟁 조건 (race condition)이 발생할 수 있다. Worker Thread 예제 #include #include #include #include #include #include using std::thread; class Worker { public: int _total = 0; Worker() {} void DoWork(int* out) { for (int i = 0; i < _total; ++i) *out += 1; } }; int main() { Worker* workers = new Worker[5]; for (int i = 0; i < 5; ++i) workers[i]._total = 100000000..

[C++ Thread] C++ Thread 관리하기

C++ Thread를 관리하는 방법 쓰레드도 엄연한 운영체제 자원으로 프로세스보다는 가볍지만 메모리를 할당받아 스택 메모리, 레지스터를 사용한다. 자동적으로 레지스터가 복구되고 스택이 팝 되는 일반 함수의 종료와 다르게 쓰레드 "객체"는 함수 종료 후 다른 쓰레드에서 계산 결과를 전달하는 등을 위해 자동적으로 자원을 반납하지 않는다. 즉 객체가 소멸되지 않는 이상 자원은 할당되어 있는 상태이다. 쓰레드의 생성 fork thread는 추가적으로 생성하는 자원이다. 왜냐하면, 모든 프로그램은 시작시 진입 프로시저를 가지고 보통 main 함수가 그러한 프로시저이다. 즉 추가적인 thread를 생성하지 않는다면 main 함수가 유일한 쓰레드가 된다. 여기서 추가적으로 생성하는 thread는 main 쓰레드의 자..

[C++ Thread] C++ Thread 생성하기

쓰레드란 Thread 프로세스를 구성하는 독립적인 실행을 보장하는 객체이다. 프로세스의 흐름을 더 작은 단위로 나누고 프로세스에 할당된 자원, 데이터 세그먼트, 힙에 할당된 객체 등을 공유하여 사용할 수 있다. 쓰레드는 독립적인 실행을 보장하므로 자신이 실행하는 함수가 존재한다. 함수의 실행을 위해 자동 변수(쓰레드 로컬) 변수를 사용하기 위한 스택 메모리를 사용하게 된다. 프로세스 단위가 작으므로 문맥 교환에 더 적은 비용이 들기 때문에 멀티 쓰레드 프로그래밍이 자주 사용된다. 운영체제는 여러 쓰레드를 실행하기 위해 CPU의 전체 하드웨어 실행 시간를 나누어 각 쓰레드에게 CPU 사용가능 시간을 부여한다. 이를 타임 퀀텀(time quantum)이라고 한다. 또한 운영체제의 스케줄러가 쓰레드 실행 순서..

[Modern C++] (6) 람다 표현식

람다 표현식 Lambda - 보통 함수와 같은 의미를 지니는 표현식이다. - 클로저 Closure는 람다에 의해 만들어진 실행 시점의 객체이다. 갈무리 모드 Capture mode에 따라 갈무리된 자료의 복사본 혹은 참조를 가질 수 있다. - 클로저 클래스는 람다에 대해 컴파일러가 만든 고유한 클래스이다. 보통 STL 함수의 인수로 많이 사용된다. std::vector container; std::find_if(container.begin(), container.end(), [](int val) {return 0 < val && val < 10; }); 1. 기본 갈무리 모드를 피하라 기본 갈무리 모드 중 하나는 참조에 의한 갈무리 모드와 값에 의한 갈무리 모드가 있다. 두 모드에 내재된 위험성은 참조대..

Advanced C++ 2021.04.20

[컴퓨터 구조] 9. 명령어 수준 병렬성

명령어 수준 병렬성(instruction-level parallelism, ILP) 파이프라이닝은 명령어 사이의 병렬성을 이용하는 기법이다. 병렬 수준을 높이기 위한 방법은 다음 두 가지가 있다. 1. 파이프라인 깊이를 증가시켜 더 많은 명령어들을 중첩시키는 방법 2. 매 파이프라인 단계에서 다수의 명령어를 내보내는 방법 다중 내보내기 Multiple Issue : 다수의 명령어를 내보내어 동시에 둘 이상의 명령어를 처리한다. - 다중 내보내기 (multiple issue) 방법은 매 단계마다 다수의 명령어를 내보내면 명령어 실행 속도가 클럭 속도보다 빨라질 수 있다. 즉 CPI가 1보다 작아질 수 있어 명령어 1개를 실행하는 속도가 클럭 주기보다 빠른 것이다. 정적 다중 내보내기 static multi..