티스토리 뷰

반응형


안녕하세요 :) Zedd입니다.

오늘은..!!!! Concurrency Programming에 대해서 알아볼건데 역시나 Apple문서를 일단 읽고 시작하겠습니다.

원문은 <Concurrency Programming Guide>을 참고해주세요 :)



Concurrency Programming Guide



Introduction

동시성(Concurrency)은 동시에(same time) 발생하는 여러가지 것들의 개념입니다. 멀티 코어 CPU의 확산과 각 프로세서의 코어 개수가 증가할 것이라는 인식 때문에, 소프트웨어 개발자는 코어를 활용 할 수 있는 새로운 방법이 필요합니다. OS X및 iOS와 같은 운영체제는 여러 프로그램을 동시에 실행 할 수 있지만, 대부분의 프로그램은 백그라운드에서 실행되며, 연속으로 프로세서 시간이 필요하지 않는 작업을 수행합니다. 컴퓨터를 계속 사용사용하고, 사용자의 주의를 끄는 것은 현재 forground 앱입니다. 앱이 수행해야 할 작업은 많지만, 사용가능한 코어의 일부만 사용중인경우, 추가 처리 리소스가 낭비됩니다. (사용 할 수 있는 코어가 더 있는데, 사용 안하면? 그런뜻같음..)


과거에는 앱에 동시성을 도입할 때, 하나 이상의 추가 쓰레드가 필요했습니다. 불행하게도, 쓰레드 코드를 작성하는 것은 어렵습니다. 쓰레드는 수동으로 관리해야하는 하위 수준 도구입니다. 앱의 최적의 쓰레드 수는 현재 시스템 부하 및 기본 하드웨어를 기반으로 동적으로 변경될 수 있으므로, 올바른 쓰레딩 솔류션 구현은 불가능하진 않지만 극도로 어려워집니다. 또한 일반적으로 쓰레드와 함께 사용되는 동기화 메커니즘은 성능 향상을 보장하지 않으면서 소프트웨어 설계에 복잡성과 위험을 추가합니다.


OS X와 iOS는 모두 전통적으로 쓰레드 기반 시스템과 앱에 있는 것 보다, 더 비동기적인 동시 태스크 실행 방식을 채택하고 있습니다. 직접 쓰레드를 작성하는 대신, 앱은 특정 태스크를 정의 한 다음, 시스템이 이를 수행하도록 해야합니다. 시스템이 쓰레드를 관리하게 함으로써 원시 쓰레드(raw threads)에서는 불가능한 수준의 확장성을 얻을 수 있습니다. 앱개발자는 보다 간단하고 효율적인 프로그래밍 모델을 얻을 수 있습니다. 


이 문서에서는 앱에서 동시성(Concurrency)을 구현하는 데 사용해야하는 technique과 technologies에 대해 설명합니다. 이 문서에서 설명하는 기술은 OS X및 iOS에서 사용할 수 있습니다. 


Organization of This Document

이 문서에는 다음 챕터들이 포함되어 있습니다.

  • Concurrency and Application Design 에는 비동기식 앱 설계의 기초와 사용자 정의 작업을 비동기 적으로 수행하기 위한 기술을 소개합니다.

  • Operation Queues는  

    Objective-C 객체를 사용하여 작업을 캡슐화하고 수행하는 방법을 보여줍니다.
  • Dispatch Queues는 

    C 기반 앱에서 동시에 작업을 실행하는 방법을 보여줍니다.
  • Dispatch Sources는 시스템 이벤트를 비동기적으로 처리하는 방법을 보여줍니다. 

  • Migrating Away from Threads는 기존 스레드 기반 코드를 새로운 기술로 마이그레이션하는 데 필요한 팁과 기술을 제공합니다.

이 글에서는 첫번째인, Concurrency and Application Design만 보려고 해요! 한 글에 담기는 넘나 많은것


A Note About Terminology(용어에 대한 참고사항)

용어도 정리해주는;;;Apple센스;;
동시성(concurrency)에 대한 토론을 시작하기 전에 혼동을 피하기 위해 관련용어를 정의해야합니다. UNIX시스템이나 구형 OS X기술에 익숙한 개발자는 이 문서에서 “task(작업)”, “process(프로세스)” 및 “thread(쓰레드 또는 스레드...)”라는 용어가 약간 다르게 사용된다는 것을 알 수 있습니다. 이 문서에서는 다음 뜻?으로 이 용어들을 사용합니다. 


● “task(작업)”이라는 용어는 수행해야 할 추상적인 작업 개념을 나타내기 위해 사용됩니다.

● “process(프로세스)”라는 용어는 실행 중인 실행파일(running executable)을 지칭하며, 여러 쓰레드를 포함 할 수 있습니다. 

● thread(쓰레드)”라는 용어는 코드 실행을 위한 별도의 실행 경로(path)를 지칭하기 위해 사용됩니다. OS X의 쓰레드에 대한 기본 구현은 POSIX 쓰레드 API를 기반으로 합니다.


Concurrency and Application Design

ㄱㄱ


컴퓨팅 초기에는 컴퓨터가 수행 할 수 있는 단위 시간 당 최대 작업량이 CPU의 클럭 속도에 의해 결정되었습니다. 그러나 첨단 기술과 프로세서 설계가 더욱 소형화됨에 따라, 열(heat) 및 기타 물리적 제약이 프로세서의 최대 클럭 속도를 제한하기 시작했습니다. 그래서 칩 제조업체는 칩의 총 성능을 향상시키는 다른 방법을 모색했습니다. 그들의 해결책은 각 칩의 프로세서 코어 수를 늘리는 것이었습니다. 코어수를 늘리면, CPU의 속도를 높이거나 칩 크기 또는 열(heat)특성을 변경하지 않고도 단일 칩에서 초당 더 많은 명령을 실행 할 수 있습니다. 유일한 문제는 여분의 코어를 이용하는 방법이었습니다. 


여러개의 코어를 활용하려면, 여러가지 작업을 동시에 수행 할 수 있는 소프트웨어가 필요합니다. 

OS X또는 iOS와 같은 최신 멀티 태스킹 운영체제의 경우, 주어진 시간에 100개 이상(ㄷㄷ..)의 다른 코어에 프로그램이 실행될 수 있으므로, 각 프로그램을 다른 코어에 스케쥴링 할 수 있어야 합니다. 그러나 이러한 프로그램의 대부분은 시스템 데몬이거나, 실제 처리 시간을 거의 소비 하지 않는 백그라운드 앱입니다. 대신 실제로 필요한 것은 개별 앱이 여분의 코어를 보다 효과적으로 사용하는 방법입니다. 


앱이 여러 코어를 사용하는 전통적인 방법은 여러 쓰레드를 만드는 것입니다.

그러나 코어 수가 늘어나면, 스레드 된 솔류션에 문제가 있습니다. 가장 큰 문제는 쓰레드 된 코드가 임의의 수의 코어에 맞게 확장되지 않았다는 것입니다. 코어와 프로그램이 잘 돌아갈 것으로 기대하는 것 만큼 많은 쓰레드를 생성 할 수 없습니다. 알아야 할 것은, 효과적으로 사용 할 수 있는 코어의 수는 앱 자체에서 계산하기 어려운 수준입니다. 비록 여러분이 숫자를 정확하게 맞춘다고 할지라도, 여전히 너무나 많은 쓰레드를 프로그래밍하고, 그것들을 효과적으로 운영하고, 그것들이 서로 간섭하지 못하게해야합니다.


따라서 문제를 요약하자면, 앱이 다양한 컴퓨터 코어들의 수를 이용할 수 있는 방법이 필요합니다. 단일 앱이 수행하는 작업량 또는 변화하는 시스템 조건을 수용할 수 있도록 동적으로 확장 할 수 있어야 합니다. 그리고 솔루션은 이러한 코어를 활용하는데 필요한 작업량을 늘리지 않도록 충분히 간단해야 합니다.

좋은 소식은 Apple의 운영체제가 이러한 모든 문제에 대한 해결책을 제공한다는것이며, 이 장에서는 이 솔루션을 구성하는 기술과 이를 활용하기 위해 당신이 만든 코드를 수정하는 방법을 살펴보겠습니다.


The Move Away from Threads

쓰레드는 수년 간 사용되어왔으며, 계속 사용되고는 있지만 확장 가능한 방식으로 여러 작업을 실행하는 일반적인 문제를 해결하지 못합니다. 

쓰레드를 활용할 경우, 확장 가능한 솔루션을 구축해야하는 부담이 전적으로 개발자인 여러분에게 있습니다

시스템 조건이 변경됨에 따라, 동적으로 해당 수를 생성하고 조정할 쓰레드 수를 결정해야 합니다. 또 다른 문제는 앱이 해당 쓰레드를 생성하고 유지보수하는 데 드는 비용의 대부분을 떠맡는다는 것입니다.


동시성(concurrency)문제를 해결하기 위해, OS X와 iOS는 쓰레드에 의존하는 대신, 비동기 설계 접근 방식을 사용합니다. 비동기 기능은 운영체제에 여러해 동안 존재해왔으며, 디스크에서 데이터를 읽는 것과 같이 오랜시간이 걸릴 수 있는 작업을 시작하는게 종종 사용됩니다. 호출 될 때 비동기 함수는 백그라운드에서 일부 작업을 수행하여 실행중인 task를 시작하지만, 해당 작업이 실제로 완료되기 전에 반환됩니다. 일반적으로 이 작업에는 백그라운드 쓰레드를 가져오고, 해당 쓰레드에서 원하는 task를 시작한 다음, task가 완료될 때, 호출자에게 알림을 보내는 작업이 포함됩니다. 과거에는 원하는 작업에 대해 비동기 함수가 존재하지 않는 경우, 자체적으로 비동기 함수를 작성하여 고유의 쓰레드를 생성해야 했습니다. 하지만 이제 OS X와 iOS는 직접 쓰레드를 관리하지 않고도 비동기식으로 모든 작업을 수행 할 수 있도록 해주는 기술을 제공합니다.


비동기식으로 task를 시작하는 기술 중 하는 GCD(Grand Central Dispatch) 입니다. 이 기술은 일반적으로 자신의 앱에서 쓰는 쓰레드 관리 코드를 사용하여 해당 코드를 시스템 수준으로 “이동”시킵니다.

실행할 작업을 저의하고, 이를 적절한 dispatch queue에 추가하기만 하면 됩니다. GCD는 필요한 쓰레드를 생성하고 해당 쓰레드에서 실행되도록 작업을 스케쥴링합니다. 쓰레드 관리가 이제 시스템의 “일부”이므로 GCD는 작업 관리 및 실행에 대한 전체적인 접근 방식을 제공하여, 전통적인 쓰레드보다 더 나은 효율성을 제공합니다.



Operation queues는 dispatch queues와 매우 유사한 Objective-C객체입니다. 실행 할 작업을 정의한 다음, operation queue에 추가하여 해당 작업의 스케줄링 및 실행을 처리합니다. GCD와 마찬가지로 operation queue는 모든 쓰레드 관리를 처리하여 시스템에서 가능한 한 신속하고 효율적으로 작업을 실행하도록 합니다.


다음 섹션에서는 앱에서 사용 할 수 있는 dispatch queues, operation queues 및 기타 관련 비동기 기술에 대해 자세히 설명합니다.


Dispatch Queues


dispatch queues는 사용자 지정 작업을 실행하기 위한 C기반 매커니즘입니다. dispatch queues는 작업을 순차적으로 또는 동시에 수행하지만, 항상 first-in, first-out(FIFO라고 하죠?)로 수행합니다. 즉, dispatch queues는 항상 큐에 추가된 것과 동일한 순서로 작업을 큐에서 제외하고 시작합니다. Serial dispatch queues는 한번에 하나의 작업만 실행하며 해당 task가 완료될 때 까지 기다린 후, 새 task를 시작합니다. 반대로 concurrent dispatch queues는 이미 시작된 작업이 완료될 때 까지 기다리지 않고, 가능한 많은 작업을 시작합니다.


Dispatch queues는 각각의 다른 이점(benefits)이 있습니다. 


  • Dispatch queues는 이해하기 쉽고 간단한 인터페이스를 제공합니다. 
  • Dispatch queues는 자동 및 전체적인 쓰레드 pool관리 기능을 제공합니다. 
  • Dispatch queues는 튜닝된 어셈블리의 속도를 제공합니다.(이걸..어떻게 번역해야할지..They provide the speed of tuned assembly. )
  • Dispatch queues는 쓰레드 스택이 앱 메모리에 남아있지 않기 때문에 훨씬 효율적입니다. 
  • Dispatch queues는 로드가 걸리면 커널에 트랩되지 않습니다. (They do not trap to the kernel under load.)
  • Dispatch queues에 작업(task)을 비동기적으로 전달해도 대기열을 교착상태로 만들 수 없습니다
  • Dispatch queues는 투쟁(contention)하에 우아하게(진짜 gracefully라고 나와있음..) 확장됩니다. 
  • Serial dispatch queues는 lock 및 기타 동기화 primitives보다 더 효율적인 대안을 제공합니다. (primitives는 세마포어나..뮤텍스 그런건가)
dispatch queue에 제출하는 작업은 함수 또는 블록 객체 내에 캡슐화되어야 합니다. 
블록객체는 OS X v10.6및 iOS 4.0에 도입된 C언어 기능으로, 개념적으로 포인터와 유사하지만 몇가지 추가적인 이점이 있습니다.
블록을 자신만의 어휘 범위에서(own lexical scope)정의하는 대신에 일반적으로 다른 함수나 메소드의 다른 변수에 액세스 할 수 있도록 다른 기능이나 메소드 내부에 블록을 정의합니다. 블록을 원래 범위 밖으로 이동하여 heap으로 복사할 수도 있습니다. dispatch queue에 블록을 제출하면, 블록이 복사됩니다. 이러한 모든 의미는 상대적으로 적은 코드로 매우 동적인 작업을 구현할 수 있게 합니다.
dispatch queue는 GCD기술의 일부이며 C런타임의 일부입니다. 


Dispatch Sources

(디스패치 큐는 진짜..많이 들어봤는데 디스패치 소스는 처음들어보네요 @_@)
Dispatch sources는 특정 타입의 시스템 이벤트를 비동기적으로 처리하기 위한 C기반 메커니즘입니다. Dispatch sources는 특정타입의 시스템 이벤트에 대한 정보를 캡슐화하고 해당 이벤트가 발생할 때 마다 특정 블록객체 또는 함수를 Dispatch queue로 전송합니다. Dispatch sources를 사용하여 다음 타입의 시스템 이벤트를 모니터링 할 수 있습니다. 

  • Timers - 타이머

  • Signal handlers - 신호 핸들러..?

  • Descriptor-related events - 디스크립터 관련 이벤트

  • Process-related events - 프로세스 관련 이벤트

  • Mach port events - 마이크로커널 포트 이벤트(순간 마하가 왜 여기서 나와..?했음 )

  • Custom events that you trigger - 당신이 트리거 한 커스텀 이벤트
Dispatch sources는 GCD기술의 일부입니다.

Operation Queues


operation queue는 concurrent dispatch queue와 Cocoa equivalent하며 NSOperationQueue클래스에 의해 구현됩니다.
dispatch queues는 항상 FIFO순서로 작업을 실행하지만, operation queue는 작업의 실행 순서를 결정할 때 다른 요인을 고려합니다.
이러한 요소 중 가장 중요한 것은 주어진 작업이 다른 작업의 완료 여부에 의존(depends on)하는지 여부입니다
task를 정의 할 때, 종속성을 구성하고 이를 사용하여 task에 대한 복잡한 실행 순서 그래프를 만들 수 있습니다.

operation queue에 제출하는 task는 NSOperation클래스의 인스턴스여야 합니다. Operation 객체는 수행 할 task와 해당 task를 수행하는데 필요한 데이터를 캡슐화 하는 Objective-C객체입니다. 기본적으로 NSOperation클래스는 추상 기본 클래스이기 때문에, 일반적으로 사용자 지정 하위 클래스를 정의하여 task를 수행합니다. 그러나 Foundation프레임워크에는 task를 수행하기 위해 만들고 사용 할 수 있는 몇가지 구체적인 하위 클래스가 포함되어 있습니다.


Operation 객체는 KVO(key-value observing)알림을 생성하므로, 작업 진행 상황을 모니터링 하는 유용한 방법이 될 수 있습니다.

operation queues는 항상 operation을 동시에 실행하지만, 종속성을 사용하여 필요할 때 순차적으로 실행되도록 할 수 있습니다.


Asynchronous Design Techniques

동시성(concurrency)을 지원하기 위해 코드를 재설계하는 것을 고려하기 전에, 그렇게 해야하는지 여부를 자문해야 합니다. 동시성은 주 쓰레드가 사용자 이벤트에 자유롭게 응답할 수 있도록 함으로써 코드의 응답성을 향상시킬 수 있습니다. 동일한 시간 내에 더 많은 코어를 활용하여 더 많은 작업을 수행함으로써 코드의 효율성을 향상시킬 수도 있습니다. 그러나 오버헤드가 증가하고, 코드의 전체적인 복잡성이 증가하므로 코드 작성 및 디버그가 더 어려워집니다.


복잡성을 추가하기 때문에, 동시성은 제품주기가 끝날 때 앱에 접목 할 수 있는 기능이 아닙니다

올바르게 하려면, 앱에서 수행하는 작업과 이러한 작업을 수행하는데 사용 된 데이터 구조를 신중하게 고려해야합니다. 코드가 잘못 실행되면 코드 실행속도가 이전보다 느려지고, 사용자의 응답 속도가 느려질 수 있습니다. 따라서 설계주기 초반에 몇가지 목표를 세우고 취해야 할 접근법에 대해 생각해보는 것이 좋습니다.


모든 앱마다 요구사항이 다르며, 수행 할 task집합이 다릅니다. 문서가 앱 및 관련 작업을 설계하는 방법을 정확하게 알려주는 것은 불가능합니다. 그러나 다음 섹션에서는 설계 프로세스 중에 올바른 선택을 하는데 도움이 되는 지침을 제공하려고 합니다 :)


Define Your Application’s Expected Behavior


앱에 동시성을 추가하는 것에 대해 생각하기 전에, 항상 앱의 올바른 동작으로 간주되는 것을 정의하여 시작해야합니다. 앱의 예상동작을 이해하면, 설계를 나중에 검증 할 수 있습니다. 또한 동시성을 도입하여 얻을 수 있는 예상 성능 이점에 대한 아이디어를 제공해야합니다.


가장 먼저 해야할 일은 앱이 수행하는 task와 각 task와 관련된 객체 또는 데이터 구조를 열거하는 것입니다

처음에는 사용자가 메뉴 항목을 선택하거나 button을 클릭 할 때 수행되는 task로 시작하고자 할 수 있습니다. 이러한 task는 개별 동작을 제공하며 잘 정의 된 시작점과 끝점을 갖습니다. 또한 Timer기반 작업과 같이 사용자 상호 작용 없이 앱이 수행 할 수 있는 다른 타입의 작업을 열거해야 합니다.


상위 수준의 task목록을 얻은 후에는 각 task를 성공적으로 완료하기 위해서 취해야하는 일련의 단계로 세분화하세요. 이 레벨에서는 데이터 구조와 객체에 대해 수정해야 할 사항과 이러한 수정이 앱의 전체 상태에 미치는 영향에 주로 염두해야합니다. 또한 객체와 데이터구조 사이의 모든 종속성을 기록해야 합니다. 

예를들어, task가 객체배열에 동일한 변경을 가하는 경우, 한 객체에 대한 변경이 다른 객체에 영향을 미치는지 여부는 주목할 가치가 있습니다. 객체가 서로 독립적으로 수정 될 수 있는 경우, 해당 객체를 “동시에” 수정 할 수 있습니다.


Factor Out Executable Units of Work 

앱의 task를 이해했으므로, 코드가 동시성의 이점을 얻을 수 있는 “위치" 식별할 수 있어야 합니다. task에서 하나 이상의 단계의 순서를 변경하면, 결과가 변경되므로 해당 단계를 연속적으로 수행해야합니다. 순서를 변경해도 결과에 영향을 미치지 않으면, 해당 단계를 동시에 수행하는 것을 고려해야합니다.

두 경우 모두 수행 할 단계를 나타내는 실행 가능 작업단위를 정의합니다. 그런 다음 작업단위가 블록 또는 operation객체를 사용하여 캡슐화 된 후 해당 큐에 디스패치 됩니다. 


식별한 각 작업의 실행 단위마다 실행되는 작업”량”에 관해서는 적어도 초기에는 걱정하지 마세요. 쓰레드를 회전시키는데에는 항상 비용이 들지만, dispatch queues 및 operation queues경우, 이러한 비용이 기존 쓰레드보다 훨씬 적습니다. 따라서 쓰레드를 사용 할 수 있는 것보다 더 작은 작업단위를 큐를 사용하여 보다 효율적으로 실행 할 수 있습니다. 물론 실제 성능을 측정하고, 필요에 따라 task크기를 조정해야하지만, 처음에는 task를 너무 작게 간주해서는 안됩니다.


Identify the Queues You Need

이제 task가 개별 작업 단위로 나누어져 블록 객체 또는 Operation객체를 사용하여 캡슐화되었으므로, 해당 코드를 실행하는데 사용할 큐를 정의해야합니다. 주어진 task의 경우, task를 올바르게 수행하려면 생성한 블록이나 Operation객체와 해당 task를 실행해야하는 순서를 검토하세요.


블록을 사용하여 task를 구현한 경우, 블록은 Serial 또는 concurrent dispatch queue에 추가 할 수 있습니다. 특정 순서가 필요한 경우, 블록을 Serial dispatch queue에 항상 추가합니다. 특정 순서가 필요하지 않은 경우, 블록을 concurrent dispatch queue에 추가하거나 필요에 따라 여러개의 다른 dispatch queue에 추가할 수 있습니다. 


Operation객체를 사용하여 task를 구현한 경우, 큐를 선택하는 것이 객체 구성보다 덜 흥미로운 경우가 많습니다. Serial로 Operation객체를 수행하려면, 관련 객체간의 종속성을 구성해야합니다. 종속성은 종속된 객체가 작업을 완료할 때 까지 하나의 Operation이 실행되지 못하도록 합니다.

Tips for Improving Efficiency


작은 task로 코드를 추가하고, 큐에 추가하는 것 이외에도 큐를 사용하여 코드의 전체 효율성을 향상 시킬 수 있는 다른 방법이 있습니다. 


  • 메모리 사용량이 중요한 경우, task내에서 직접 값을 계산하는 것을 고려하세요. 앱이 이미 메모리 바운드이면 계산값(computing values)은 main memory에서 캐시된 값을 로드하는 것보다 더 빠를 수도 있습니다. (직접 계산하는게 메인 메모리에서 로드하는 것보다 더 빠를 수 있다!) 계산값은 지정된 프로세서 코어의 레지스터 및 캐시를 직접 사용하며 이는 main memory보다 훨씬 빠르빈다. 물론 테스트에서 이것이(직접 계산하는 것이) 성능에서 승리했다는 것을 나타냈을 때만 이를 수행해야합니다. 

  • Serial task를 조기에(early) 식별(identify)하고, 동시 작업을 보다 효율적으로 수행 할 수 있도록 하세요. 일부 공유 리소스를 사용하기 때문에, 작업을 연속적으로 실행해야하는 경우, 해당 공유 리소스를 제거하기 위해 아키텍쳐를 변경하는것이 좋습니다. 리소스를 필요로 하거나 리소스를 모두 제거하는 각 클라이언트에 대해 리소스의 복사본을 만드는 것을 고려할 수 있습니다. 

  • lock을 사용하지 마세요. dispatch queues 및 operation queues에 의해 제공되는 자원은 대부분의 상황에서 lock을 불필요하게 만듭니다. 일부 공유 자원을 보호하기 위해 lock을 사용하는 대신, Serial큐를 지정(또는 operation 오브젝트 종속성을 사용하여(or use operation object dependencies)) 올바른 순서로 task를 실행하세요.(헙..제가 사용해본적은..없지만..Swift에도 뮤텍스랑 세마포어가 있다고 들었는데 그걸 쓰려면 lock을 해야하는것 아닌가..!!! 그걸 쓰지말라는건가?)

  • 가능할 때마다 시스템 프레임워크에 의존하세요. 동시성을 얻는 가장 좋은 방법은 시스템 프레임워크가 제공하는 내장 된 동시성을 이용하는 것입니다. 많은 프레임워크는 쓰레드와 다른 기술을 내부적으로 사용하여 동시 동작을 구현합니다. task를 정의 할 때, 기존 프레임워크가 원하는 것과 정확하게 동시에 수행하는 함수 또는 메소드를 정의하는 지 확인하세요. 이 API를 사용하면 노력을 줄일 수 있으며, 가능한 최대의 동시성을 제공할 가능성이 큽니다. 

Performance Implications

Operation queues, dispatch queues dispatch sources 많은 코드를 동시에 쉽게 실행 있도록 제공됩니다. 그러나 이러한 기술이 앱의 효율성이나 응답성을 향상시키는 것은 아닙니다.(??) 필요에 따라 효과적이며 앱의 다른 리소스에 과도한 부담을 주지 않는 방식으로 큐를 사용하는 것은 당신의 책임입니다. 예를들어, 10000개의operation 객체를 만들어, operation queue 전송할 수는 있지만, 앱에서 중요한 메모리를 할당 있으므로 페이징 성능저하가 발생할 있습니다.


큐나 쓰레드를 사용하여 코드에 동시성을 도입하기 전에, 항상 앱의 현재 성능을 반영하는 일련의 기본 메트릭(metrics) 수집해야합니다. 변경사항을 도입한 후에는 추가 메트릭을 수집하고, 이를 기존 메트릭과 비교하여 앱의 전체 효율성이 향상되었는지 확인해야합니다. 동시성 도입으로 인해 앱의 효율성이 떨어지거나 응답성이 떨어지면 가능한 performance tool 이용하여 잠재적인 원인을 확인해야합니다.


Concurrency and Other Technologies

코드를 모듈화 된 task로 분해하는 것이 앱의 동시성을 향상시키는 가장 좋은 방법입니다. 그러나 이 설계 방법은 모든 경우의 모든 앱의 요구를 만족시키지 못할 수도 있습니다. task에 따라 앱의 전체 동시성을 추가로 향상시킬 수 있는 다른 옵션이 있을 수 있습니다. 이 섹션에서는 설계의 일부로 사용할 다른 기술에 대해 간략히 설명합니다. 

OpenCL and Concurrency

OS X에서 OpenCL(Open Computing Language)은 컴퓨터 그래픽 프로세서에 일반적인 계산을 수행하기 위한 표준 기반 기술입니다.(말이 너무 어렵다..) OpenCL은 커다란 데이터 집합에 적용 할 수 있도록 잘 정의 된 계산 집합이 있는 경우, 사용 할 수 있는 좋은 기술입니다. 예를들어 OpenCL을 사용하여 이미지의 픽셀에 대한 필터 계산을 수행하거나 이미지의 픽설계산을 사용하여 여러 값에 대한 복잡한 계산을 한번에 수행 할 수 있습니다. 바꾸어 말하면, OpenCL은 데이터를 병렬로 조작 할 수 있는 문제 Set에 집중되어 있습니다.


OpenCL은 대용량 데이터의 병렬 연산을 수행하는데 적합하지만, 보다 일반적인 목적의 계산에는 적합하지 않습니다. 데이터와 필요한 작업 커널(work kernel)을 GPU에서 작동 할 수 있도록 그래픽 카드로 준비하고 전송하는데 노력은 그리 중요하지 않습니다. 마찬가지로, OpenCL에 의해 생성된 결과를 검색하는데 필요한 노력이 필요하지 않습니다. 결과적으로 시스템과 상호작용하는 모든 작업은 일반적으로 OpenCL과 함께 사용하지 않는 것이 좋습니다. 예를들어 OpenCL을 사용하여 파일이나 네트워크 스트림의 데이터를 처리하지 마십시오. OpenCL을 사용하여 수행하는 작업은 그래픽 프로세서로 전송되고 독집적으로 계산될 수 있도록 훨씬 더 독립적이어야 합니다.

OpenCL및 사용방법에 대한 자세한 내용은 OpenCL Programming Guide for Mac를 참고하세요.

(.....아니 OpenCL을 이용해서 네트워크 처리 이런걸 해볼 생각을 한번도 안해봐서...........할 수 있구나......허허)


When to Use Threads(언제 쓰레드를 사용해야하는가)

operation queues와 dispatch queues은 task를 동시에 수행하는 기본 방법이지만, 만병통치약이 아닙ㄴ디ㅏ. 앱에 따라 사용자 정의 쓰레드를 만들어야 할 때가 있을 수 있습니다. 커스텀 쓰레드를 만드는 경우, 가능한 한 적은 수의 쓰레드를 생성하려고 노력해야 합니다. 다른 방법으로는 구현할 수 없는 특정 task에만 이 쓰레드를 사용해야합니다.


쓰레드는 실시간으로 실행해야하는 코드를 구현하는 좋은 방법입니다. dispatch queues은 가능한 한 빨리 task를 실행하려고 시도하지만, 실시간 제약조건을 처리하지는 않습니다. 백그라운드에서 실행되는 코드에서보다 예측가능한 동작이 필요한 경우 쓰레드가 여전히 더 나은 대안을 제공할 수 있습니다(오............그렇구낭)


다른 쓰레드 프로그래밍과 마찬가지로 절대적으로 필요한 경우에만 항상 쓰레드를 적절하게 사용해야합니다. 쓰레드 사용방법에 대한 자세한 내용은 Threading Programming Guide를 참고하세요. 


저는 쓰레드는 이제 거의 안쓰이는?...그런건줄 알았는데 뭔가 실시간으로 제약조건을 주고싶을 때는 쓰레드를 사용하면 좋고 그런거는 몰랐네요 :)

아무튼 다음글은 Operation queue와 Dispatch queue를..!




제 중고등학교 시절에 정말 많은 힘을 받았던 Avicii였는데..그리고 지금도 노래 너무나도 잘 듣고 있었는데 진짜 너무너무 안타깝고 가슴이 아프네요. 하늘에서 편히 쉬시길 Lonely Together가 정말 슬프게 들리네요. 하늘에서 마음껏 음악 하셨으면 좋겠어요. 마음이 굉장히 무거운 하루네요 휴


반응형