I / O 차단 및 I / O 차단에 대한 기술적 세부 사항에 대해 웹을 검색 한 결과 비 차단 I / O가 I / O 차단보다 빠르다는 여러 사람을 발견했습니다. 예를 들어이 문서에서 .
차단 I / O를 사용하면 당연히 현재 차단 된 스레드는 다른 작업을 수행 할 수 없습니다. 차단 되었기 때문입니다. 그러나 스레드가 차단되기 시작하면 OS는 다른 스레드로 전환 할 수 있으며 차단 된 스레드에 대해 수행 할 작업이있을 때까지 다시 전환 할 수 없습니다. CPU를 필요로하고 차단되지 않은 다른 스레드가 시스템에있는 한 이벤트 기반 비 차단 접근 방식에 비해 CPU 유휴 시간이 더 이상 없어야합니다.
CPU가 유휴 상태 인 시간을 줄이는 것 외에도 주어진 시간 프레임에서 컴퓨터가 수행 할 수있는 작업 수를 늘리는 옵션이 하나 더 있습니다. 스레드 전환으로 인한 오버 헤드를 줄입니다. 하지만 어떻게 할 수 있습니까? 그리고 측정 가능한 효과를 보여줄만큼 오버 헤드가 충분히 큰가요? 이것이 어떻게 작동하는지에 대한 아이디어입니다.
- 파일의 내용을로드하기 위해 응용 프로그램은이 작업을 이벤트 기반 I / O 프레임 워크에 위임하여 파일 이름과 함께 콜백 함수를 전달합니다.
- 이벤트 프레임 워크는 파일을 메모리에 직접 기록하도록 하드 디스크의 DMA 컨트롤러를 프로그래밍하는 운영 체제에 위임합니다.
- 이벤트 프레임 워크를 사용하면 추가 코드를 실행할 수 있습니다.
- 디스크 대 메모리 복사가 완료되면 DMA 컨트롤러가 인터럽트를 발생시킵니다.
- 운영 체제의 인터럽트 핸들러는 파일이 메모리에 완전히로드되었음을 이벤트 기반 I / O 프레임 워크에 알립니다. 어떻게하나요? 신호 사용 ??
- 이벤트 I / O 프레임 워크 내에서 현재 실행중인 코드가 완료됩니다.
- 이벤트 기반 I / O 프레임 워크는 큐를 확인하고 5 단계의 운영 체제 메시지를 확인하고 1 단계에서받은 콜백을 실행합니다.
그게 어떻게 작동합니까? 그렇지 않은 경우 어떻게 작동합니까? 즉, 이벤트 시스템이 스택을 명시 적으로 터치 할 필요없이 작동 할 수 있다는 의미입니까 (예 : 스택을 백업하고 스레드를 전환하는 동안 다른 스레드의 스택을 메모리에 복사해야하는 실제 스케줄러)? 이것은 실제로 얼마나 많은 시간을 절약합니까? 그것에 더 있습니까?
답변
비 차단 또는 비동기 I / O의 가장 큰 장점은 스레드가 병렬로 작업을 계속할 수 있다는 것입니다. 물론 추가 스레드를 사용하여이 작업을 수행 할 수도 있습니다. 최고의 전체 (시스템) 성능에 대해 언급했듯이 여러 스레드가 아닌 비동기 I / O를 사용하는 것이 더 낫다고 생각합니다 (따라서 스레드 전환 감소).
병렬로 연결된 1000 개의 클라이언트를 처리하는 네트워크 서버 프로그램의 가능한 구현을 살펴 보겠습니다.
- 연결 당 하나의 스레드 (I / O를 차단할 수 있지만 비 차단 I / O 일 수도 있음).
각 스레드에는 메모리 리소스 (커널 메모리도 포함)가 필요하며 이는 단점입니다. 그리고 모든 추가 스레드는 스케줄러에 더 많은 작업을 의미합니다. - 모든 연결을위한 하나의 스레드.
스레드 수가 적기 때문에 시스템에서 부하를받습니다. 그러나 하나의 프로세서를 100 %로 구동하고 다른 모든 프로세서를 유휴 상태로 둘 수 있기 때문에 컴퓨터의 전체 성능을 사용할 수 없게됩니다. - 각 스레드가 일부 연결을 처리하는 몇 개의 스레드.
스레드 수가 적기 때문에 시스템에서로드가 걸립니다. 그리고 사용 가능한 모든 프로세서를 사용할 수 있습니다. Windows에서이 접근 방식은 스레드 풀 API에서 지원됩니다 .
물론 더 많은 스레드를 갖는 것은 그 자체로 문제가되지 않습니다. 아시다시피 저는 상당히 많은 수의 연결 / 스레드를 선택했습니다. 12 개의 스레드에 대해서만 이야기하는 경우 세 가지 가능한 구현간에 차이가있을 것 같지 않습니다 (이것은 또한 MSDN 블로그 게시물 에서 Windows의 프로세스 당 스레드 수가 2000 개로 제한됩니까? 에서 Raymond Chen이 제안한 내용이기도합니다 ).
버퍼링되지 않은 파일 I / O를 사용하는 Windows 에서 쓰기는 페이지 크기의 배수 크기 여야합니다. 나는 그것을 테스트하지 않았지만 이것이 버퍼링 된 동기 및 비동기 쓰기에 대해 쓰기 성능에 긍정적 인 영향을 미칠 수있는 것처럼 들립니다.
설명하는 1 ~ 7 단계는 작동 방식에 대한 좋은 아이디어를 제공합니다. Windows의 운영 체제 (비동기 I / O의 완료에 대해 알려 것 WriteFile
와 OVERLAPPED
이벤트 또는 콜백을 사용하여 구조). 콜백 함수는 예를 들어 코드가 WaitForMultipleObjectsEx
로 bAlertable
설정된 상태에서 호출 될 때만 호출 됩니다 true
.
웹에서 더 많은 정보 :
- MSDN 의 사용자 인터페이스 에 있는 다중 스레드 , 스레드 생성 비용도 곧 처리
- Section Threads and Thread Pools 는 “스레드는 비교적 생성하고 사용하기 쉽지만 운영 체제는이를 관리하는 데 상당한 시간과 기타 리소스를 할당합니다.”라고 말합니다.
- MSDN의 CreateThread 문서 에는 “하지만 프로세서 당 하나의 스레드를 만들고 응용 프로그램이 컨텍스트 정보를 유지하는 요청 대기열을 작성하면 응용 프로그램의 성능이 향상됩니다.”라고 말합니다.
- 이전 기사 스레드가 너무 많으면 성능이 저하되는 이유와 대처 방법
답변
I / O에는 하드 드라이브에서 데이터 읽기 및 쓰기, 네트워크 리소스 액세스, 웹 서비스 호출 또는 데이터베이스에서 데이터 검색과 같은 여러 종류의 작업이 포함됩니다. 플랫폼 및 작업 종류에 따라 비동기 I / O는 일반적으로 작업을 수행하기 위해 하드웨어 또는 저수준 시스템 지원을 활용합니다. 이는 CPU에 가능한 한 적은 영향을주지 않고 수행된다는 것을 의미합니다.
애플리케이션 수준에서 비동기 I / O는 스레드가 I / O 작업이 완료 될 때까지 기다려야하는 것을 방지합니다. 비동기 I / O 작업이 시작되는 즉시 시작된 스레드를 해제하고 콜백이 등록됩니다. 작업이 완료되면 사용 가능한 첫 번째 스레드에서 실행을 위해 콜백이 대기열에 추가됩니다.
I / O 작업이 동 기적으로 실행되면 작업이 완료 될 때까지 실행중인 스레드가 아무 작업도하지 않습니다. 런타임은 I / O 작업이 언제 완료되는지 알지 못하므로 대기 스레드에 CPU 시간을 주기적으로 제공합니다. 그렇지 않으면 실제 CPU 바인딩 작업을 수행하는 다른 스레드에서 사용할 수있는 CPU 시간입니다.
따라서 @ user1629468이 언급했듯이 비동기 I / O는 더 나은 성능을 제공하지 않고 오히려 더 나은 확장 성을 제공합니다. 이것은 웹 애플리케이션의 경우처럼 사용 가능한 스레드 수가 제한된 컨텍스트에서 실행할 때 분명합니다. 웹 응용 프로그램은 일반적으로 각 요청에 스레드를 할당하는 스레드 풀을 사용합니다. 장기 실행 I / O 작업에서 요청이 차단되면 웹 풀이 고갈되고 웹 응용 프로그램이 중지되거나 응답 속도가 느려질 위험이 있습니다.
제가 알아 차린 한 가지는 비동기 I / O가 매우 빠른 I / O 작업을 처리 할 때 최선의 선택이 아니라는 것입니다. 이 경우 I / O 작업이 완료되기를 기다리는 동안 스레드를 바쁘게 유지하지 않는 이점은 그다지 중요하지 않으며 작업이 한 스레드에서 시작되고 다른 스레드에서 완료된다는 사실은 전체 실행에 오버 헤드를 추가합니다.
여기 에서 비동기 I / O 대 멀티 스레딩 주제에 대해 최근에 작성한 더 자세한 연구를 읽을 수 있습니다 .
답변
AIO를 사용하는 주된 이유는 확장 성 때문입니다. 몇 가지 스레드의 맥락에서 볼 때 이점은 분명하지 않습니다. 그러나 시스템이 1000 개의 스레드로 확장되면 AIO는 훨씬 더 나은 성능을 제공합니다. 주의 할 점은 AIO 라이브러리가 더 이상 병목 현상을 일으키지 않아야한다는 것입니다.
답변
모든 형태의 멀티 컴퓨팅으로 인한 속도 향상을 가정하려면 여러 CPU 기반 작업이 여러 컴퓨팅 리소스 (일반적으로 프로세서 코어)에서 동시에 실행되거나 모든 작업이 다음의 동시 사용에 의존하지 않는다고 가정해야합니다. 즉, 일부 작업은 하나의 시스템 하위 구성 요소 (예 : 디스크 스토리지)에 의존하는 반면 일부 작업은 다른 시스템 (주변 장치에서 통신 수신)에 의존하고 다른 작업은 프로세서 코어를 사용해야 할 수 있습니다.
첫 번째 시나리오는 종종 “병렬”프로그래밍이라고합니다. 두 번째 시나리오는 종종 “동시”또는 “비동기”프로그래밍이라고합니다. “동시”는 때때로 운영 체제가 여러 작업의 실행을 인터리브 할 수 있도록 허용하는 경우를 지칭하는데도 사용됩니다. 직렬로 배치하거나 여러 리소스를 사용하여 병렬 실행을 수행 할 수 있습니다. 후자의 경우 “동시”는 일반적으로 작업 실행의 실제 동시성의 관점이 아니라 프로그램에서 실행이 작성되는 방식을 나타냅니다.
암묵적인 가정으로이 모든 것에 대해 말하기는 매우 쉽습니다. 예를 들어, 일부는 “비동기 I / O가 다중 스레드 I / O보다 빠릅니다.”와 같은 주장을 빠르게합니다. 이 주장은 여러 가지 이유로 모호합니다. 첫째, 특정 비동기 I / O 프레임 워크가 멀티 스레딩으로 정확하게 구현 된 경우 일 수 있습니다.이 경우 하나의 개념이 동일하고 다른 개념보다 “빠르다”고 말하는 것은 의미가 없습니다. .
둘째, 비동기 프레임 워크의 단일 스레드 구현 (예 : 단일 스레드 이벤트 루프)이있는 경우에도 해당 루프가 수행하는 작업에 대해 가정을해야합니다. 예를 들어, 단일 스레드 이벤트 루프로 할 수있는 한 가지 어리석은 일은 두 개의 서로 다른 순수 CPU 바인딩 작업을 비동기 적으로 완료하도록 요청하는 것입니다. 이상적인 단일 프로세서 코어 만있는 컴퓨터에서이 작업을 수행 한 경우 (최신 하드웨어 최적화 무시)이 작업을 “비동기 적으로”수행하는 것은 두 개의 독립적으로 관리되는 스레드 또는 단 하나의 단독 프로세스로 수행하는 것과 실제로 다르게 수행되지 않습니다. -차이는 스레드 컨텍스트 전환 또는 운영 체제 일정 최적화로 내려갈 수 있지만 두 작업이 모두 CPU로 이동하는 경우 두 경우 모두 비슷합니다.
당신이 마주 칠 수있는 비정상적이거나 어리석은 코너 케이스를 상상하는 것이 유용합니다.
예를 들어 위와 같이 “비동기”는 동시 일 필요가 없습니다. 정확히 하나의 프로세서 코어가있는 시스템에서 두 개의 CPU 바운드 작업을 “비동기 적으로”실행합니다.
다중 스레드 실행은 동시 일 필요가 없습니다. 단일 프로세서 코어가있는 머신에서 두 개의 스레드를 생성하거나 두 개의 스레드에 다른 종류의 부족한 리소스를 획득하도록 요청합니다 (예를 들어 하나만 설정할 수있는 네트워크 데이터베이스를 상상해보십시오. 한 번에 연결). 스레드의 실행은 인터리브 될 수 있지만 운영 체제 스케줄러는 적합하다고 생각하지만 단일 코어에서 전체 런타임을 줄일 수 없으며 (스레드 컨텍스트 전환으로 인해 증가 할 것입니다) 일반적으로 스레드보다 많은 스레드를 생성하는 경우 코어를 실행하거나 리소스가 유지할 수있는 것보다 리소스를 요청하는 스레드가 더 많습니다.) 이것은 다중 처리에서도 마찬가지입니다.
따라서 비동기 I / O 나 멀티 스레딩 모두 런타임 측면에서 성능 향상을 제공 할 필요가 없습니다. 속도를 늦출 수도 있습니다.
그러나 원격 데이터베이스와 같은 네트워크 연결 리소스에서 데이터를 검색하기 위해 네트워크 호출을 수행하고 일부 로컬 CPU 바운드 계산을 수행하는 특정 프로그램과 같이 특정 사용 사례를 정의하면 다음과 같은 추론을 시작할 수 있습니다. 하드웨어에 대한 특정 가정이 주어진 두 방법 간의 성능 차이.
질문 : 수행해야하는 계산 단계 수와이를 수행하기 위해 얼마나 많은 독립 자원 시스템이 있습니까? 독립적 인 시스템 하위 구성 요소를 사용해야하고 동시에 수행 할 경우 이점을 얻을 수있는 계산 단계의 하위 집합이 있습니까? 몇 개의 프로세서 코어가 있으며 여러 프로세서 또는 스레드를 사용하여 별도의 코어에서 작업을 완료하는 데 드는 오버 헤드는 얼마입니까?
작업이 독립적 인 하위 시스템에 크게 의존하는 경우 비동기 솔루션이 좋을 수 있습니다. 처리하는 데 필요한 스레드 수가 많아서 컨텍스트 전환이 운영 체제에서 사소하지 않은 경우 단일 스레드 비동기 솔루션이 더 나을 수 있습니다.
작업이 동일한 리소스 (예 : 동일한 네트워크 또는 로컬 리소스에 동시에 액세스해야하는 여러 필요)에 의해 바인딩 될 때마다 멀티 스레딩은 아마도 불만족스러운 오버 헤드를 유발할 것이며 단일 스레드 비동기식 은 그러한 리소스에서 더 적은 오버 헤드를 유발할 수 있습니다. 제한된 상황에서도 속도를 높일 수 없습니다. 이러한 경우 유일한 옵션 (속도 향상을 원할 경우)은 해당 리소스의 여러 복사본을 사용 가능하게 만드는 것입니다 (예 : 부족한 리소스가 CPU 인 경우 다중 프로세서 코어, 부족한 리소스 인 경우 더 많은 동시 연결을 지원하는 더 나은 데이터베이스) 연결이 제한된 데이터베이스 등).
또 다른 표현은 운영 체제가 두 작업에 대해 단일 리소스 사용을 인터리브하도록 허용하는 것이 단순히 한 작업이 리소스를 사용하고 다른 작업이 대기 한 다음 두 번째 작업이 연속적으로 완료되도록하는 것보다 빠를 수 없습니다 . 또한 인터리빙의 스케줄러 비용은 실제 상황에서 실제로 속도가 느려지는 것을 의미합니다. CPU, 네트워크 리소스, 메모리 리소스, 주변 장치 또는 기타 시스템 리소스의 인터리브 사용량이 발생하는지 여부는 중요하지 않습니다.
답변
비 차단 I / O의 가능한 구현 중 하나는 I / O를 차단하고 일부 콜백 메커니즘을 통해 I / O 발신자 스레드에 알리는 백그라운드 스레드 풀을 사용하여 정확히 말한 것입니다. 사실 이것이 glibc 의 AIO 모듈이 작동하는 방식입니다. 다음 은 구현에 대한 모호한 세부 정보입니다.
이것은 이식성이 뛰어난 좋은 솔루션이지만 (스레드가있는 한) 일반적으로 OS는 비 차단 I / O를보다 효율적으로 서비스 할 수 있습니다. 이 Wikipedia 기사 는 스레드 풀 외에 가능한 구현을 나열합니다.
답변
현재 protothread를 사용하여 임베디드 플랫폼에서 비동기 io를 구현하는 과정에 있습니다. 비 블로킹 io는 16000fps와 160fps에서 실행하는 것의 차이를 만듭니다. 비 블로킹 io의 가장 큰 이점은 하드웨어가 그 일을하는 동안 다른 일을하도록 코드를 구조화 할 수 있다는 것입니다. 장치 초기화도 병렬로 수행 할 수 있습니다.
남자 이름
답변
Node에서는 여러 스레드가 시작되지만 C ++ 런타임에서 하위 계층입니다.
“그래서 예 NodeJS는 단일 스레드이지만 이것은 반 사실입니다. 실제로는 이벤트 기반이며 백그라운드 작업자를 사용하는 단일 스레드입니다. 기본 이벤트 루프는 단일 스레드이지만 대부분의 I / O 작업은 별도의 스레드에서 실행됩니다. Node.js의 I / O API는 이벤트 루프를 수용하기 위해 설계 상 비동기 / 비 차단이기 때문입니다. “
“Node.js는 차단되지 않습니다. 즉, 모든 함수 (콜백)가 이벤트 루프에 위임되고 서로 다른 스레드에 의해 실행 (또는 실행될 수 있음)됩니다. 이는 Node.js 런타임에 의해 처리됩니다.”
https://itnext.io/multi-threading-and-multi-process-in-node-js-ffa5bb5cde98
“노드는 차단되지 않기 때문에 더 빠릅니다 …”설명은 약간의 마케팅이며 이것은 좋은 질문입니다. 효율적이고 확장 가능하지만 정확히 단일 스레드는 아닙니다.