본문 바로가기

iOS

[iOS] Concurrency Programing(동시성 프로그래밍이란)?

# 목차

  • 동시성 및 앱 설계
    • 스레드에서 벗어나기
      • 디스패치 대기열
      • 디스패치 소스
      • Operation 대기열
    • 비동기식 설계 기법
      • 앱의 예상 동작 정의
      • 실행가능한 작업단위 제외
      • 필욯나 대기열 식별
      • 효율성 향상을 위한 팁
      • 성능향상
    • 동시성 및 기타 기술
      • 스레드를 사용해야하는 경우

# 동시성 프로그래밍이란?(Concurrentcy Programming)

  • 동시성은 동시에 여러 일이 발생하는 개념이다.(멀티 스레드 환경에서여러가지 작업을 도잇에 처리하는 기술)

# 왜 동시성 프로그래밍이 만들어졌지?

멀티코어 CPU의 확산과 각 프로세서의 코어 수가 증가할 것이라는 인식으로 스프트웨어 개발자는 이를 활용할 수 있는 새로운 방법이 필요함 -> 과거에는 앱에 동시성을 도입하려면 하나이상의 스레드를 만들었는데 이는 코드를 작성하는게 너무 어려움 그리고 일반적으로 스레드와 함께 사용하는 동기화 캐머니즘은 성능향상을 보장치않고 솜프웨어 설계에 복잡성과 위험을 추가함 -> 그래서 apple은 이 문제를 해결하기위한 기술을 제공한다.

  • 동시성 및 응용 프로그램 설계(비동기식)
  • 작업 대기열(Object-C)개체를 사용해 작업을 캡슐화하고 수행하는 방법을 보여줌
  • DispatchQueues(C 기반 앱 작업을 동시에 실행해줌)
  • Dispatch Sources(시스템 이벤트를 비동기로 처리해줌)
  • Migraing Away from Threads(최신 기술로 기존 스레드 기반코드를 이주하기 위한 팁과 기술을 제공함)

# 용어 정리

  • Thread 는 code에 대한 별도의 실행결로를 나타내는데 사용됩니다. 크게 물리적인 쓰레드와와 소프트웨어의 내부적인 스레드 2가지가 있다.
  • Process 는 여러 스레드를 포함할 수 있는 실행 중인 실행 파일을 나타내- 는데 사용됩니다.
  • Task 는 수행해야하는 작업의 추상적인 개념을 나타내는데 사용됩니다.
  • core는 CPU의 핵심으로 CPU에서 일을 처리하는 녀석

자세한 용어사전들은 여기서 참고

# 동시성 및 앱 설계

컴퓨터 초기엔 컴퓨터가실행할 수 있는 단위가 시간당 최대 작업량이 CPU의 클럭속도에 의해 결정되었음
-> 따라서 칩 제조업체는 칩의 전체성능을 높일 수 있는 다른 방법을 모색함
->그래서 내린 결론)
프로세서 코어 수를 늘려서 CPU속도를 높이거나 칩 크기 또는 열 특성을 변경치 않고 단일 칩에 초당 더 많은 명령을 실행할 수 있도록 활용함
-> 근데 다중코어를 사용할라면 동시에 여러작업을 수행할 수 있는 소프트웨어가 필요함
-> 현재 OS X 또는 iOS와 같은 최신 멀티태스킹 운영체제의 경우 조어진 시간에 100개 이상의 프로그램이 실행될 수 있기에 예약시스템이 있어야함
-> 그러나 이러한 프로그램의 대부분은 실제 처리시간을 거의 소모하지않는 시스템 데몬? 또는 백그라운드? 응용 프로그램임 대신 실제로 필요한 건 개별 응용 프로그램이 추가코어를 보다 효과적으로 사용할 수 있는지임(아 뭔말이야…)

-> 앱이 다중코어를 사용하는 전통적인 방법은 다중스레드를 만드는것임
-> 근데 코어수가 증가하면 스레드솔루션에 문제가발생함
-> 스레드 코드가 임의의 수의 코어에 잘 확장되지않는다는것 고로 코어수만큼 스레드를 생성할수 없다.

-> 결론은 응용 프로그램이 다양한 수의 컴퓨터 코어 활용을 할 수 있는 방법이 필요함
단일 응용프로그램에서 수행하는 작업의 양도 변화하기에 이 조건을 수용할 수 있는 동적확장을 할 수 있어야함, 추가로 충분히 단순해야 코어를 활용하는데 필요한 작업량이 증가하지 않도록 충분히 단순해야하는데 이에대한 솔루션을 Apple의 운영체제가 제공해줌

# 쓰레드는 수년동안 사용했는데 왜 현재는 다른걸로 대체됬을까?

확장하는데 문제가 발생함.
시스템 조건이 변경됨에 따라 즉, 앱이 업데이트될때마다 해당 쓰레드 수를 동적으로 생성하고 조정할 스레드수를 정해줘야함 ex) ARC를 수동으로 init deinit을 설정해주는것과 같은것…
근데 업데이트 될때마다? 추가로 이 스레드가 추가될 수록 유지비용도 추가된다는것
=> 수지타산 따져보니 돈이 마이들것같아 시스템을 개발한것으로 보임.

# Apple은 현재 어떤방식으로 취하고 있나?

스레드에서 벗어나 비동기식 설계를 취하고 있따.이는 동시성 문제를 해결하며
디스크에서 데이터를 읽는것과 같이 시간이 오래걸릴 수 있는 작업에 자주 사용됨 … 그러나 지금

-> 작업을 비동기적으로 시작하는 기술 중 하나인 GCD(Grand Central Dispatch)이다.
-> 이 기술은 일반적으로 자체 응용 프로그램에서 작성하는 스레드 코드를 가져와서 해당 코드를 시스템 수준으로 이동함
-> 실행하려는 작업을 정의하고 적절한 디스패치 대기열에 추가하기만 하면됨
-> GCD는 필요한 스레드를 만들고 해당 스레드 에서 실행되도록 작업을 예약함
-> 스레드관리가 이제 시스템일부라서 GCD는 작업관리 및 실행에 대한 전체적인 접근 방식을 제공하여 기존스레드보다 더나음 효율성을 제공함
-> Operation Queue는 Dispatch Queue와 유사하게작동하는 Objective-C개체이다.

# GCD(grand central disaptch)

  • 개발자가 작업만 정해주면 시스템이 알아서 스레드를 관리해줌
  • Dispatch Queue는 GCD기술중 일부임
  • GCD = Dispatch 프레임워크
    • Dispatch 프레임워크
      • Queue
      • WorkItem
      • Group
      • QoS
      • Source
      • Semaphore

# 비동기작업(Operation Queue) 사용법

  • 실행하려는 작업을 정의한 후 해당 작업의 예약 및 실행을 처리하는 작업 대기열에 추가함
  • GCD와 마찬가지로 Operaion Queue은 모든 스레드 관리를 처리하여 시스템에서 작업이 최대한 빠르고 효율적을 실행되도록 함

# Dispatch Queue

  • 디스패치 큐는 사용자지정 작업을 실행하기 위한 C기반 매커니즘임
  • 작업을 순차적으로 또는 동시에 실행하지만 항상 선입 선출순서도 실행함
    (즉, 디스패치 대기열은 항상 대기열에 추가된 것과 동일한 순서로 작업을 대기열에서 빼고 시작함)
  • 동기적 Queue는 한번에 하나의 작업만 실행하고 대기열에서 제거하고 직업을 시작하기 전에 해당 작업이 완료될때까지 기다린다.
  • 동시 디스패치 큐는 이미 시작된 작업이 완료될떄까지 기다리지않고 가능한 많은 작업을 시작함
  • 여기에 작업을 넘길떄 2가지를 꼭 정해줘야함
    • 단일 스레드(single thread) or 다중 스레드(multi thread)
    • 동기(sync) or 비동기(async)

# Dispatch Queue이점

  • 아주 간단한 프로그래밍 인터페이스를 제공함
  • 자동 및 전체적 스레드 풀 관리를 제공함
  • 조정된 조립속도를 제공함
  • 스레드 스택이 응용프로그램에 남아있지않기에 메모리 효율이 좋음
  • 로드 중인 커널에 트랩되지않음
  • 디스패치 큐에 대한 작업의 비동기 디스패치는 큐를 교착상태로 만들수 없음
  • 경합 상태에서 원활하게 확장됨
  • 동기적 디스패치큐는 잠금 및 기타 동기화 프리미티브에 대한 보다 효율적인 대안을 제공함

# Dispatch Source

특정 유형의 시스템이벤트를 비동기적으로 처리하기위한 C기반 매커니즘임

  • 타이머(Timer)
  • Signal handlers(신호 처리기)
  • Descriptor-related events(설명자 관련 이벤트)
  • Process-related events(프로세스 관련 이벤트)
  • Mach port events(마하 포트 이벤트)
  • Custom events that you trigger(트리거 하는 사용자 지정 이벤트)

# Operation Queues

https://developer.apple.com/documentation/foundation/nsoperation
동시 디스패치 대기열과 동일하며 클래스에 의해 구현됨

  • Operation Queue에 제출하는 작업은 Operation Class의 인스턴스여야함
  • 작업개체는 KVO알림을 생성하며 이는 작업진행상황을 모니터링하는데 유용하게쓰일 수 있음
  • Operation Queue는 항상 동시에 실행하지만 종속성을 사용하여 필요할떄는 순차적으로 실행할 수 있음

# 비동식 설계시 주의할점 및 장단점

동시성을 지원하는 코드는 꼭 필요한 상황인지 자문해야한다.

  • 장점
    • 기본스레드가 사용자 이벤트에 자유롭게 응답이 가능함
    • 더많은 코어 활용으로 같은 시간에 더많은 작업을 수행할 수 있어 코드 효율이 좋다
  • 단점
    • 오버헤드가 발생할 수 있음
    • 코드의 전바적인 복잡성이 증가하여 디버그가 어려울 수 있다.(출처불명확)

# 동시성 추가하기전 앱 구현 방법

  1. 개체 또는 데이터 구조를 열거한다.
    • 사용자가 메뉴 항목을 선택하거나 버튼을 클릭할때 수행되는 작업으로 시작할 수 있음 이는 별개의 도작을 제공하며 시작과 끝점이 잘정의되어있음
    • 또한 타이머기반 작업과 같이 응요프로그램이 사용자 상호작용 없이 수행할 수 있는 다른 유형의 작업도 열거해야함
  2. 작업목록을 파악하고 성공적으로 완료하기위해 수행하는 단계집합을 세분화함
    • 데이터구조 및 개체에 대해 수정사항과 이 수정이 응용프로그램에 미치는 영향을 파악해야함
    • 데이터 구조와 개체간의 종속성을 기록해야함

# 동시성을 사용할지 말지에 대해서 기준을 어떻게 잡나?

  • 작업에서 하나이상의 단계순서를 변경했을때 결과가 변경되는경우 해당 단계를 동기적으로 수행해야할 필요가 있음
    반대로
  • 순서를 변경해도 출력에 영향을 주지않는다면 비동기로 수행하는 것을 고려해야함

# 효율성 향상을 위한 팁?

단순히 코드를 더 작은 작업으로 분해하고 대기열에 추가하는것 외에도 대기열을 사용해 코드의 전체효율성을 향상시키는 다른 방법이 있음

  • 메모리 사용량이 요인인 경우 작업내에서 직접 값을 계산하는걸 고려해라
    • 응용프로그램이 이미 메모리에 바인딩된경우 지금 직접 값을 계산하는 것이 기본 메모리에서 캐시된 값을 로드하는 것보다 빠를 수 있음 값으 계싼하는 것은 주 메모리보다 훨씬 빠른 주어진 프로세서 코어의 레지스터와 캐시를 직접 사용함.
  • 직렬 작업을 초기에 식별하고 더 많은 동시작업을 수행할 수 있도록 한다.
    • 작업이 일부 공유리소스에 의존하기때문이 직렬로 실행되야하는 경우 아키텍처를 변경해 해당 공유 리소스를 제거하는것을 고려하자
  • 자물쇠를 사용하지 마세요
    • 디스패치큐 및 작업 큐에서 제공하는 상황에 잠금은 필요없다. 일부 공유리소스를 보호하기위해 잠금을 사용하는대신 직렬 대기열을 지정하거나 작업 개체 종속성을 사용해 올바른 순서로 작업을 실행해야함
  • 가능하면 시스템 프레임워크에 의존하세요
    • 프레임워크는 번들이기 때문에 NSBundle클래스를 사용하거나 Core Foundation의 CFBundle(절차 코드의 경우)을 사용하여 해당 내용에 액세스할 수 있습니다. 이 해당 API를 사용하면 노력을 절약할 수 있고 가능한 최대의 동시성을 제공할 가능성이 높다.

# reference