thread 라는 용어 는 코드에 대한 별도의 실행 경로를 나타내는 데 사용
process 라는 용어 는 여러 스레드를 포함할 수 있는 실행 중인 실행 파일을 나타내는 데 사용
task 이라는 용어 는 수행해야 하는 작업의 추상적 개념을 나타내는 데 사용
스레드에 의존하는 대신 OS X 및 iOS는 비동기식 설계 접근 방식 을 취합니다.
작업을 비동기적으로 시작하는 기술 중 하나는 GCD(Grand Central Dispatch) 입니다. 이 기술은 일반적으로 자체 응용 프로그램에서 작성하는 스레드 관리 코드를 가져와서 해당 코드를 시스템 수준으로 이동합니다. 실행하려는 작업을 정의하고 적절한 디스패치 대기열에 추가하기만 하면 됩니다.
GCD는 필요한 스레드를 만들고 해당 스레드에서 실행되도록 작업을 예약합니다. 스레드 관리가 이제 시스템의 일부이기 때문에 GCD는 작업 관리 및 실행에 대한 전체적인 접근 방식을 제공하여 기존 스레드보다 더 나은 효율성을 제공합니다.
Operation Queues
Dispatch Queues
Dispatch Sources
디스패치 소스는 특정 유형의 시스템 이벤트를 비동기적으로 처리하기 위한 C 기반 메커니즘입니다. 디스패치 소스는 특정 유형의 시스템 이벤트에 대한 정보를 캡슐화하고 해당 이벤트가 발생할 때마다 특정 블록 개체 또는 기능을 디스패치 대기열에 제출합니다. 디스패치 소스를 사용하여 다음 유형의 시스템 이벤트를 모니터링할 수 있습니다.
동시성은 기본 스레드가 사용자 이벤트에 자유롭게 응답할 수 있도록 하여 코드의 응답성을 향상시킬 수 있습니다.
더 많은 코어를 활용하여 같은 시간에 더 많은 작업을 수행함으로써 코드의 효율성을 향상시킬 수도 있습니다.
애플리케이션에 동시성을 추가하는 것에 대해 생각하기 전에 항상 애플리케이션의 올바른 동작이라고 생각하는 것을 정의하는 것으로 시작해야 합니다. 애플리케이션의 예상 동작을 이해하면 나중에 디자인을 검증할 수 있습니다. 또한 동시성을 도입하여 얻을 수 있는 예상 성능 이점에 대한 아이디어도 제공해야 합니다.
가장 먼저 해야 할 일은 애플리케이션이 수행하는 작업과 각 작업과 관련된 개체 또는 데이터 구조를 열거하는 것입니다.
처음에는 사용자가 메뉴 항목을 선택하거나 버튼을 클릭할 때 수행되는 작업으로 시작할 수 있습니다. 이러한 작업은 별개의 동작을 제공하며 시작점과 끝점이 잘 정의되어 있습니다. 또한 타이머 기반 작업과 같이 응용 프로그램이 사용자 상호 작용 없이 수행할 수 있는 다른 유형의 작업도 열거해야 합니다.
상위 수준 작업 목록을 얻은 후에는 각 작업을 작업을 성공적으로 완료하기 위해 수행해야 하는 단계 집합으로 더 세분화하기 시작합니다. 이 수준에서는 데이터 구조 및 개체에 대해 수행해야 하는 수정 사항과 이러한 수정 사항이 응용 프로그램의 전체 상태에 미치는 영향에 주로 관심을 기울여야 합니다. 또한 개체와 데이터 구조 간의 종속성을 기록해야 합니다. 예를 들어, 작업이 객체 배열에 대해 동일한 변경을 수행하는 경우, 한 객체에 대한 변경이 다른 객체에 영향을 미치는지 여부를 주목할 가치가 있습니다. 개체를 서로 독립적으로 수정할 수 있는 경우 해당 수정을 동시에 수행할 수 있습니다.
애플리케이션의 작업에 대한 이해를 바탕으로 코드가 동시성을 통해 이점을 얻을 수 있는 위치를 이미 식별할 수 있어야 합니다.
작업에서 하나 이상의 단계 순서를 변경하면 결과가 변경되는 경우 해당 단계를 연속적으로 계속 수행해야 할 수 있습니다. 그러나 순서를 변경해도 출력에 영향을 주지 않는다면 해당 단계를 동시에 수행하는 것을 고려해야 합니다. 두 경우 모두 수행할 단계를 나타내는 실행 가능한 작업 단위를 정의합니다. 그런 다음 이 작업 단위는 블록 이나 작업 개체를 사용하여 캡슐화하고 적절한 대기열에 전달하는 것이 됩니다.
식별한 각 실행 가능한 작업 단위에 대해 최소한 처음에는 수행되는 작업의 양에 대해 너무 걱정하지 마십시오. 스레드를 회전시키는 데는 항상 비용이 있지만 디스패치 큐와 작업 큐의 장점 중 하나는 많은 경우 이러한 비용이 기존 스레드보다 훨씬 적다는 것입니다.
따라서 스레드를 사용하는 것보다 대기열을 사용하여 더 작은 작업 단위를 더 효율적으로 실행할 수 있습니다. 물론 항상 실제 성과를 측정하고 필요에 따라 작업 크기를 조정해야 하지만 처음에는 작업이 너무 작게 간주되어서는 안 됩니다
작업이 개별 작업 단위로 분할되고 블록 개체 또는 작업 개체를 사용하여 캡슐화되었으므로 해당 코드를 실행하는 데 사용할 대기열을 정의해야 합니다
. 주어진 작업에 대해 생성한 블록 또는 작업 개체와 작업을 올바르게 수행하기 위해 실행해야 하는 순서를 검사합니다.
블록을 사용하여 작업을 구현한 경우 직렬 또는 동시 디스패치 대기열에 블록을 추가할 수 있습니다. 특정 주문이 필요한 경우 항상 직렬 디스패치 대기열에 블록을 추가합니다.
특정 주문이 필요하지 않은 경우 필요에 따라 동시 디스패치 대기열에 블록을 추가하거나 여러 다른 디스패치 대기열에 추가할 수 있습니다.
작업 개체를 사용하여 작업을 구현한 경우 대기열 선택이 개체 구성보다 덜 흥미로운 경우가 많습니다. 연산 개체를 순차적으로 수행하려면 관련 개체 간의 종속성을 구성해야 합니다. 종속성은 종속된 개체가 작업을 완료할 때까지 한 작업이 실행되지 않도록 합니다.
코드를 모듈식 작업으로 분해하는 것은 애플리케이션에서 동시성을 시도하고 개선하는 가장 좋은 방법입니다. 그러나 이 설계 접근 방식은 모든 경우에 모든 응용 프로그램의 요구 사항을 충족하지 않을 수 있습니다. 작업에 따라 응용 프로그램의 전체 동시성을 추가로 개선할 수 있는 다른 옵션이 있을 수 있습니다. 이 섹션에서는 디자인의 일부로 사용할 다른 기술에 대해 간략히 설명합니다.
OS X에서 OpenCL(Open Computing Language) 은 컴퓨터의 그래픽 프로세서에서 범용 계산을 수행하기 위한 표준 기반 기술입니다. OpenCL은 대규모 데이터 세트에 적용하려는 잘 정의된 계산 세트가 있는 경우 사용하기에 좋은 기술입니다. 예를 들어 OpenCL을 사용하여 이미지의 픽셀에 대한 필터 계산을 수행하거나 한 번에 여러 값에 대한 복잡한 수학 계산을 수행하는 데 사용할 수 있습니다. 즉, OpenCL은 데이터를 병렬로 조작할 수 있는 문제 세트에 더 적합합니다.
OpenCL은 대규모 데이터 병렬 작업을 수행하는 데 적합하지만 보다 범용적인 계산에는 적합하지 않습니다. GPU에서 작동할 수 있도록 데이터와 필요한 작업 커널을 모두 준비하고 그래픽 카드로 전송하는 데는 적지 않은 노력이 필요합니다. 마찬가지로 OpenCL에 의해 생성된 결과를 검색하는 데도 적지 않은 노력이 필요합니다. 결과적으로 시스템과 상호 작용하는 모든 작업은 일반적으로 OpenCL과 함께 사용하지 않는 것이 좋습니다. 예를 들어 OpenCL을 사용하여 파일이나 네트워크 스트림의 데이터를 처리하지 않습니다. 대신 OpenCL을 사용하여 수행하는 작업은 그래픽 프로세서로 전송되고 독립적으로 계산될 수 있도록 훨씬 더 독립적이어야 합니다.
작업 대기열과 디스패치 대기열이 작업을 동시에 수행하는 데 선호되는 방법이지만 만병 통치약은 아닙니다. 응용 프로그램에 따라 사용자 지정 스레드를 만들어야 하는 경우가 있을 수 있습니다. 사용자 정의 스레드를 생성하는 경우 가능한 한 적은 수의 스레드를 직접 생성하도록 노력해야 하며 다른 방법으로 구현할 수 없는 특정 작업에만 해당 스레드를 사용해야 합니다.
스레드는 여전히 실시간으로 실행되어야 하는 코드를 구현하는 좋은 방법입니다. 디스패치 큐는 가능한 한 빨리 작업을 실행하기 위해 모든 시도를 하지만 실시간 제약을 해결하지는 않습니다. 백그라운드에서 실행되는 코드에서 더 예측 가능한 동작이 필요한 경우 스레드가 여전히 더 나은 대안을 제공할 수 있습니다.
스레드 프로그래밍과 마찬가지로 항상 스레드를 신중하게 사용해야 하며 절대적으로 필요한 경우에만 사용해야 합니다.