성댕쓰 똑똑한 생활

고정 헤더 영역

글 제목

메뉴 레이어

성댕쓰 똑똑한 생활

메뉴 리스트

  • 홈
  • 태그
  • 방명록
  • 분류 전체보기 (172)
    • 똑똑한 재테크 (1)
      • 올웨더 자산배분 (1)
    • 똑똑한 개발 (170)
      • Hazel 게임엔진개발 (0)
      • Algorithm 과 Data Structure (51)
      • C++ (18)
      • C# (8)
      • 개발로그 (0)
      • Image Processing (2)
      • C++ 게임개발 (60)
      • 컴퓨터 그래픽스 (10)
      • 수학 (13)
      • 영어 (8)

검색 레이어

성댕쓰 똑똑한 생활

검색 영역

컨텐츠 검색

똑똑한 개발

  • Lock free stack #3

    2021.08.31 by 성댕쓰

  • Lock free stack #2

    2021.08.26 by 성댕쓰

  • Lock free stack

    2021.08.25 by 성댕쓰

  • Lock-based stack, queue

    2021.08.11 by 성댕쓰

  • Thread local storage

    2021.08.11 by 성댕쓰

  • 메모리 모델

    2021.08.10 by 성댕쓰

  • CPU 파이프라인

    2021.08.09 by 성댕쓰

  • 캐시

    2021.08.07 by 성댕쓰

  • Future

    2021.08.07 by 성댕쓰

  • Condition variable

    2021.08.07 by 성댕쓰

Lock free stack #3

쓰지 않는 포인터를 모아 놨다가 한 번에 소멸시키는 로직을 shared_ptr ref count를 이용해 더 이상 참조하는 곳이 없으면 메모리 free하는 로직으로 바꿔보자. template class LockFreeStack { struct Node { Node(const T& value) : data(make_shared(value)), next(nullptr) { } shared_ptr data; shared_ptr next; }; public: void Push(const T& value) { shared_ptr node = make_shared(value); node->next = std::atomic_load(&_head); while (std::atomic_compare_exchange_we..

똑똑한 개발/C++ 게임개발 2021. 8. 31. 22:05

Lock free stack #2

이전 글 lock free stack에서 풀지 못한 메모리 누수현상을 해결해보자. 전체 코드는 아래와 같다. template class LockFreeStack { struct Node { Node(const T& value) : data(value), next(nullptr) { } T data; Node* next; }; public: void Push(const T& value) { Node* node = new Node(value); node->next = _head; while (_head.compare_exchange_weak(node->next, node) == false) { } } // 1) head를 읽는다. // 2) head->next 읽기 // 3) head = head -> ne..

똑똑한 개발/C++ 게임개발 2021. 8. 26. 21:58

Lock free stack

Lock free stack을 구현해보자. 먼저 링크드 리스트 자료구조를 이용해 stack을 만든다. template class LockFreeStack { struct Node { Node(const T& value) : data(value) { } T data; Node* next; }; public: void Push(const T& value) { Node* node = new Node(value); node->next = _head; _head = node; } private: atomic _head; }; 위 코드가 싱글 쓰레드에서 작동할 때는 문제가 없다. 그러나 멀티 쓰레드 환경에서 작동하면, _head를 여러 쓰레드에서 동시에 접근 가능할 때 문제가 생긴다. 예를 들어 1)node->ne..

똑똑한 개발/C++ 게임개발 2021. 8. 25. 22:04

Lock-based stack, queue

lock 이용한 concurrent stack, queue를 만들어보자 concurrent stack #include template class LockStack { public: LockStack() {} LockStack(const LockStack&) = delete; LockStack& operator=(const LockStack&) = delete; void Push(T value) { lock_guard lock(_mutex); _stack.push(std::move(value)); _condVar.notify_one(); } bool TryPop(T& value) { lock_guard lock(_mutex); if (_stack.empty()) return false; value = st..

똑똑한 개발/C++ 게임개발 2021. 8. 11. 20:55

Thread local storage

게임서버가 구동되면 일감이 균등하게 분배되어 있다가도 어느 순간 특정 영역에 일감이 몰리기도 한다. 일감이 몰리면 필연적으로 경합이 일어난다. TLS는 쓰레드마다 가지고 있는 저장소이다. 경합지역에서 큼지막하게 데이터를 가지고 와서 TLS에서 자유롭게 사용하는 개념이다. TLS와 스택은 다르다. 스택은 스코프를 넘어가면 소멸한다. 반면 TLS는 heap 영역 데이터 처럼 소멸하지 않는다. 그러나 다른 쓰레드에서는 사용할 수 없다. // C++11 이전 방식 window api이용 // _declspec(thread) int32 value; thread_local int32 LThreadId = 0; void ThreadMain(int32 threadId) { LThreadId = threadId; whi..

똑똑한 개발/C++ 게임개발 2021. 8. 11. 19:46

메모리 모델

c+11에서 추가된 것 중 가장 중요한 것은 memory model이다. 메모리 절대 법칙 atomic 연산에 한해, 모든 쓰레드가 동일 객체에 대해서 동일한 수정 순서를 관찰한다. 동일한 수정 순서를 관찰한다의 의미는? 시간의 흐름을 거슬러서 관찰할 수 없다는 뜻. 가시성은 해결되지 않는다. 예를 들어, 0을 관찰하고 2를 관찰했다면, 다른쓰레드 또는 같은 쓰레드가 다시 관찰할 때 절대 0을 관찰 할 수 없다. 그러나 만약 2 관찰 이후 시간이 흘러도 1이나 5가 관찰되지 않을 수는 있다. 또한 0,2,1,5 모두 거쳐 관찰되지 않을 수 있다. 예를 들어, 0 관찰이후 다음에 5가 관찰될 수 있다. 원자적 연산이란? CPU가 한 번에 연산한다 -> 원자적 연산 int64 num; void Thread_..

똑똑한 개발/C++ 게임개발 2021. 8. 10. 22:44

CPU 파이프라인

다음의 코드를 살펴보자. int32 x = 0; int32 y = 0; int32 r1 = 0; int32 r2 = 0; volatile bool ready; void Thread_1() { while (!ready) ; y = 1; // store y r1 = x; // load x } void Thread_2() { while (!ready) ; x = 1; // store x r2 = y; // load r2 } int main() { int32 count = 0; while (true) { ready = false; count++; x = y = r1 = r2 = 0; thread t1(Thread_1); thread t2(Thread_2); ready = true; t1.join(); t2.jo..

똑똑한 개발/C++ 게임개발 2021. 8. 9. 22:10

캐시

컴퓨터 구조중 하나인 캐시와 파이프라인에 대해 알아보자. RAM에서 CPU로 데이터 전송하는 비용이 크다. 이를 줄이고자 캐시를 도입했다. 캐시는 임시저장소 같은 곳이다. 코어에는 연산을 담당하는 ALU부분과 캐시부분이 있고 캐시는 여러 부분, 피라미드 구조로 되어있다. 레지스터는 용량은 작고 빨라서, L2는 용량은 크지만 상대적으로 느려서 피라미드 구조다. CPU는 사용한 리소스를 캐시에 저장해 놓는다. 캐시를 찾았는데 원하는 내용이 없으면 RAM에서 찾는다. 캐시를 만드는 캐시 철학 1) Temporal locality : 최근에 사용한 정보를 다시 사용할 가능성이 높다. 2) Spatial locality : 사용한 정보 근처에 있는 정보를 사용할 가능성이 높다.(ex. vector 메모리 접근) ..

똑똑한 개발/C++ 게임개발 2021. 8. 7. 19:15

Future

future는 비동기 방식으로 일을 처리할 때 유용하게 사용할 수 있다. 기존 쓰레드와 비교하여 보면 어렵지 않게 알 수 있다. #include int64 Calculate() { int64 sum = 0; for (int32 i = 0; i 둘 중 알아서 골라서 실행 std::future future = std::async(std::launch::async, Calculate); // TODO int64 sum = future.get()..

똑똑한 개발/C++ 게임개발 2021. 8. 7. 18:41

Condition variable

이전에 작성한 코드에서 queue size를 출력하면 계속해서 사이즈가 늘어나는 것을 볼 수 있다. void Producer() { while (true) { { unique_lock lock(m); q.push(100); } ::SetEvent(handle); } } void Consumer() { while (true) { ::WaitForSingleObject(handle, INFINITE); unique_lock lock(m); if (q.empty() == false) { int32 data = q.front(); q.pop(); cout

똑똑한 개발/C++ 게임개발 2021. 8. 7. 12:54

추가 정보

인기글

최신글

페이징

이전
1 ··· 9 10 11 12 13 14 15 ··· 17
다음
TISTORY
성댕쓰 똑똑한 생활 © Magazine Lab
페이스북 트위터 인스타그램 유투브 메일

티스토리툴바