왜 I / O를 기다려야합니까?


28

디스크 작업이 느리다는 것은 항상 알려져 있으며 그 이유는 무엇인지 잘 알고 있습니다. 여기서 질문은 왜 우리가 I / O를 기다려야하는지 또는 왜 IOWait 등과 같은 것이 있습니까?

필자는 백그라운드에서 일부 I / O 작업을 수행 할 때 컴퓨터가 기본적으로 속도가 훨씬 느리다는 것을 알았습니다. 특히 Linux를 사용할 때 더 긴 I / O 작업을 수행하는 경우 OS가 완료 될 때까지 거의 사용할 수 없게됩니다.

실제로 기사 에서이 주제를 찾았습니다. 스 니펫이 있습니다.

I / O 대기는 12.1 %입니다. 이 서버에는 8 개의 코어가 있습니다 (cat / proc / cpuinfo를 통해). 이것은 (1/8 코어 = 0.125)에 매우 가깝습니다.

기본적으로 컴퓨터가 많이 느려지는 것을 의미합니다. 왜 그렇습니까? 나는 정상적인 컴퓨터가 적어도 2 코어, 때로는 4 또는 때로는 하이퍼 스레딩 또는 그와 같은 것으로 인해 더 많은 코어를 가지고 있음을 의미합니다. 그러나 이제 문제는 CPU가 실제로 거기에 머물러 있어야하는 이유는 실제로 IO를 기다리는 것 외에는 아무것도하지 않습니까? 프로세스 관리의 기본 아이디어 또는 아키텍처를 의미합니다. 이제 OS를 책임지는 사람인지 또는 하드웨어 부분으로 내려 오는지 알지 못하지만 CPU가 대기하거나 대기하는 것이 가능해야합니다. 실제로 다른 많은 작업을 수행하고 준비가되면 IO 프로세스로 돌아가는 동안 정기적으로 확인하십시오. 실제로, 이것이 어려운 작업이고 CPU가 기다려야한다면 왜 그렇지 않습니까? 그러면 하드웨어가 더 효율적으로 관리 했습니까? 예를 들어 프로세스를 다시 시작하자마자 기다리는 작은 CPU의 종류가있을 수 있습니다. 그러면 프로세스가 반복되어 프로세스가 반복되어 우리는 가지고 있지 않을 것입니다. 실제로 데이터 복사 프로세스를 위해 전체 CPU 코어를 전담하는 것입니다. :에스

이제는 관찰자 관점에서 지금 그것을 적용하고 있으며 주제에 대해 깊이 다루지 않았지만 CPU가 HDD 속도로 작동 해야하는 이유를 이해하지 못합니다. 다른 작업을 수행하고 준비가되면 HDD로 돌아옵니다. 이 아이디어는 IO 작업이나 복사 프로세스 등을 필요로하는 응용 프로그램의 속도를 높이는 것이 아니라 해당 작업을 수행하는 동안 CPU 소비에 최소한의 영향 만 미치므로 OS가 다른 프로세스와 사용자를 위해이를 사용할 수 있도록하는 것입니다. 일부 복사 작업을 수행 할 때 일반적인 컴퓨터 지연을 느낄 필요가 없습니다 ...


41
"다른 일을 할 수있는 동안"과 같은? 데이터 작업이 필요합니다. 해당 데이터가 CPU L1 캐시에 없으면 L2 캐시에서 데이터를 가져와야합니다. L2 캐시에 없으면 L3에서 가져와야합니다 (있는 경우). 온 다이 캐시에 전혀 없으면 주 메모리에 액세스해야합니다. 주 메모리에 없으면 ...에서 HDD에 액세스해야합니다.
Oded

39
컴퓨터 다른 일을합니다. 커널은 IO 작업이 완료 될 때까지 스레드를 차단하여 다른 스레드 / 프로세스가 실행되도록합니다. 그러나 모든 것이 디스크 IO에서 대기 중이라면 다른 조치는 없습니다.
대령 삼십 2

6
프로그램이 I / O 타워에 도달하여 프리즈 비를 보낼 때까지 기다려야합니다!
Almo

1
@immibis 맞아요! :)
Almo

2
일반적으로 최신 OS는 사용자가하지 않는 불만을 처리합니다. IO 작업은 적절한 하드웨어로 전달되고 하드웨어에 의해 인터럽트가 생성되어 작업이 완료되었음을 나타냅니다. IO를 기다리는 프로세스는 일반적으로 대기하는 동안 차단됩니다 (변경 가능). 많은 프로세스가 IO를 기다리고 있고 다른 프로세스에 CPU가 수행 할 작업이 없으면 할 일이 많지 않습니다. 또한 mem-swap Hell로 끝날 수 있습니다. CPU, 메모리 및 IO를 효율적으로 활용하기 위해 프로그램을 작성하려면 특별한 기술이 필요하며, 실행중인 작업도 가장 효과적인 작업에 영향을줍니다.
nategoose

답변:


19

설명하는 I / O 구성표가 현재 컴퓨터에서 사용되고 있습니다.

CPU가 실제로 거기에 머물러 있어야하는 이유는 실제로 IO를 기다리는 것 외에는 아무것도하지 않는 것입니다.

:이 간단한 가능한 I / O의 방법으로 프로그램 된 I / O . 많은 임베디드 시스템과 로우 / 엔드 마이크로 프로세서에는 단일 입력 명령과 단일 출력 명령 만 있습니다. 프로세서는 읽거나 쓰는 모든 문자에 대해 명시적인 명령 시퀀스를 실행해야합니다.

그러나 실제로 많은 다른 작업을 수행하고 준비가되면 IO 프로세스로 돌아가는 동안 CPU가 대기하거나 정기적으로 확인할 수 있어야합니다.

많은 개인용 컴퓨터에는 다른 I / O 구성표가 있습니다. 장치가 준비 될 때까지 긴밀한 루프를 기다리지 않고 ( 대기 중 대기 ) CPU는 I / O 장치를 시작하여 완료되면 인터럽트를 생성하도록 요청합니다 ( 인터럽트 구동 I / O ).

인터럽트 구동 I / O는 프로그래밍 된 I / O와 비교하여 한 단계 발전하지만 전송되는 모든 문자에 대해 인터럽트가 필요하며 비용이 많이 듭니다.

예를 들어 프로세스를 다시 시작하자마자 기다리는 작은 CPU의 종류가있을 수 있습니다. 그러면 프로세스가 반복되어 프로세스가 반복되어 우리는 가지고 있지 않을 것입니다. 실제로 데이터 복사 프로세스를 위해 전체 CPU 코어를 전용으로 ...

많은 문제에 대한 해결책은 다른 사람이 그 일을하도록하는 것입니다! :-)

DMA 컨트롤러 / 칩 (직접 메모리 액세스)은 프로그래밍 된 I / O를 허용하지만 다른 사람이이를 수행하도록합니다!

DMA를 사용하면 CPU는 몇 개의 레지스터 만 초기화하면되며 전송이 완료되고 인터럽트가 발생할 때까지 다른 작업을 수행 할 수 있습니다.

DMA조차 완전히 자유롭지는 않습니다. 고속 장치는 메모리 참조 및 장치 참조 ( 사이클 스틸 링 )를 위해 많은 버스 사이클을 사용할 수 있으며 CPU는 대기해야합니다 (DMA 칩은 항상 버스 우선 순위가 높습니다).

I / O 대기는 12.1 %입니다. 이 서버에는 8 개의 코어가 있습니다 (cat / proc / cpuinfo를 통해). 이것은 (1/8 코어 = 0.125)에 매우 가깝습니다.

나는이에서 생각 : 이해 디스크 I / O - 때 걱정해야 하는가?

이상하지 않습니다 : 시스템 (mySQL)은 데이터를 조작하기 전에 모든 행을 가져와야하며 다른 활동은 없습니다.

여기에는 컴퓨터 아키텍처 / OS 문제가 없습니다. 예제가 설정된 방식입니다.

기껏해야 RDBMS 조정 문제 또는 SQL 쿼리 문제 (인덱스 누락, 잘못된 쿼리 계획, 잘못된 쿼리 ...) 일 수 있습니다.


24

OS에 디스크 읽기 / 쓰기를 디스패치하도록 지시 한 다음 다른 작업을 수행 한 다음 나중에 완료되었는지 확인하는 비동기 IO를 작성할 수 있습니다. 새로운 것과는 거리가 멀다. 오래된 방법은 IO에 다른 스레드를 사용하는 것입니다.

그러나 읽기가 실행되는 동안해야 할 일이 있어야하며 결과를 위해 전달한 버퍼를 건드릴 수 없습니다.

모든 것이 IO를 차단한다고 가정 할 때 훨씬 쉽게 프로그래밍 할 수 있습니다.

당신이 차단 읽기 함수를 호출 할 때 당신은 알고 때까지 반환하지 않습니다 뭔가 읽고 바로 당신이 그것에 처리를 시작할 수 있습니다 후되었습니다.

전형적인 읽기 루프는 좋은 예입니다

//variables that the loop uses
char[1024] buffer;
while((read = fread(buffer, 1024, 1, file))>0){
    //use buffer
}

그렇지 않으면 현재 함수 상태 (보통 콜백 + userData 포인터 형태)를 저장하고 + 읽기 작업의 식별자를 select()유형 루프로 다시 전달해야 합니다. 작업이 완료되면 읽기 작업의 식별자를 콜백 + 데이터 포인터에 매핑하고 완료된 작업의 정보로 콜백을 호출합니다.

void callback(void* buffer, int result, int fd, void* userData){
    if(result<=0){
    //done, free buffer and continue to normal processing
    }
    //use buffer

    int readID = async_read(fd, buffer, userData->buff_size);
    registerCallback(readId, callback, userData);
}

이것은 또한 비동기 읽기를 사용하여 종료 될 수있는 모든 함수가 비동기 연속을 처리 할 수 ​​있어야한다는 것을 의미합니다. 그것은 대부분의 프로그램에서 사소한 변경 사항이므로 비동기 C #을 시도하는 사람들에게 물어보십시오.


그러나 동기식 IO 대 비동기식 IO는 일반적인 속도 저하의 원인이 아닙니다. 페이지 스와핑도 IO에서 대기해야하는 작업입니다. 스케줄러는 IO가 하나 인 경우 IO를 기다리지 않는 다른 프로그램으로 전환합니다 ( IO 대기는 프로세서가 유휴 상태이고 IO 작업이 보류 중일 때 ).

실제 문제는 하드 드라이브와 CPU 모두 동일한 채널을 사용하여 RAM과 통신한다는 것입니다 . 메모리 버스. 그리고 RAID를 사용하지 않으면 데이터를 가져올 단일 디스크 만 있습니다. 그래픽 집약적 인 응용 프로그램을 사용하는 경우 GPU와의 통신에도 방해가됩니다.

다시 말해 실제 병목 현상은 아마도 소프트웨어가 아닌 하드웨어에있을 수 있습니다.


6
"동기 IO와 비동기 IO는 일반적인 속도 저하의 원인이 아닙니다." 그렇다면 왜 기본에 관한 질문 일 때 상대적으로 고급 주제에 집중하기로 결정 했습니까?
svick

1
당신은 아마 DMA에 대해 뭔가 언급해야한다
알렉 청록

2
재미있는 사실 : 실제로 콜백을 처리하지 않고도 I / O를 수행하는 동안 프로그램이 다른 작업을 수행 할 수 있도록하는 매우 오래된 메커니즘이 있습니다. 이를 thread 라고 합니다 .
user253751

2
동기화 / 비동기 IO의 장단점에 대해 잘 설명합니다. 그러나 이것이 감속의 이유라고 확신합니까? 일반적으로 IO로드가 심한 경우 속도가 느리게 설계된 소프트웨어 때문이거나 그렇지 않은 경우 시스템이 느린 단일 디스크 (예 : 비 SSD)를 사용하고 모든 것이 동시에 액세스하려고하기 때문에 발생합니다. . 메모리 버스의 포화 상태를 비난하기 전에 디스크가 요청을 처리하는 능력에 병목 현상을 일으켰습니다. 최신 메모리 버스를 포화 시키려면 실제로 고급 스토리지 가 필요합니다 .
aroth

9

I / O를 기다리는 동안 다른 것들을 처리하는 것은 가능한 한 능률적으로 가깝고 능률적이라고 믿습니다. 컴퓨터가 12.1 %의 시간 동안 만 I / O를 기다리고 있다는 것을 알면 실제로 많은 다른 작업을 병렬로 수행하고 있음을 의미합니다. 실제로 다른 작업을 수행하지 않고 I / O를 기다려야하는 경우 시간의 99.9 %를 기다리는 것이므로 I / O 속도가 느립니다.

더 많은 일을 병렬로 수행하는 유일한 방법은 사용자가 다음에 무엇을하고 싶을 지 예측하는 것입니다. 그러나 우리는 아직 그러한 예측을 잘하지 못합니다. 따라서 사용자가 하드 드라이브에서 특정 섹터를 읽어야하는 작업을 수행하고 해당 섹터가 캐시에없는 경우 OS는 해당 섹터를 읽는 매우 긴 프로세스를 시작합니다. 그 동안해야 할 다른 일이 있는지 확인하려고합니다. 다른 섹터를 원하는 다른 사용자가 있으면 해당 요청도 대기열에있게됩니다. 어느 시점에서 모든 요청이 대기열에 들어 갔으며, 우리가 할 수있는 것은 아무것도 없지만, 첫 번째 요청이 충족 될 때까지 기다렸다가 계속 진행하십시오. 그것은 단지 인생의 사실입니다.

편집하다:

I / O를 수행하는 동안 다른 작업을 수행하는 방법의 문제에 대한 해결책을 찾는 것은 유쾌한 일입니다. 동시에 유휴 상태에서 다른 작업을 수행하는 방법에 대한 문제가되기 때문입니다. 컴퓨터가없는 동안 할 일을 찾을 수 있기 때문에 놀라운 위업이 될 것입니다.

알다시피, 이것이 일어나는 일입니다. 컴퓨터가 99.99 % 만 앉아 있고 아무 것도하지 않습니다. 당신이 할 일을 줄 때, 그것은 간다. 그렇게 할 때 I / O를 기다려야한다면 거기에 앉아 기다립니다. I / O를 수행하는 동안해야 할 일이 있다면 그렇게합니다. 그러나 I / O 이외의 다른 작업이 없으면 거기에 앉아 I / O가 완료 될 때까지 기다려야합니다. SETI @ Home에 등록하는 것 외에는이 문제를 해결할 방법이 없습니다.


12.1 %의 예는 웹 사이트에서 가져온 것이며 8 개의 코어가있는 서버에서 가져온 것입니다. 거의 하나의 전체 코어가 해당 작업을 위해 예약되었다는 생각이 들었습니다. 잘 지내고 있지만 코어가 하나 밖에 없다면 어떻게해야합니까? : /
Arturas M

3
@ArturasM 웹 사이트의 내용을 잘못 이해했거나 웹 사이트 작성자가 무언가를 잘못 이해했습니다. 단일 코어 만있는 컴퓨터 는 I / O를 기다리는 데 더 적은 시간을 소비합니다 (IO를 기다리지 않는 다른 작업은 다른 코어에서 실행 중이지만 한 코어는 유휴 상태 인 경우 단일 코어에서 모두 실행해야하므로) 핵심). I / O는 대기 여부에 관계없이 일정 시간이 걸립니다. 대기 할 시간이 있으면 해당 시간과 관련이없는 증상입니다.
Random832

6

OS (매우 낮은 수준의 임베디드 시스템 또는 이와 유사한 것이 아닌 경우)은 이미 이것을 처리합니다. 응용 프로그램이 I / O를 기다려야하는 경우 일반적으로 해당 I / O를 차단하고 다른 스레드 또는 응용 프로그램은 유효한. 스케줄러가 어느 것을 결정합니다.

실제로 대기 시간을 누적하는 다른 스레드 또는 응용 프로그램이 실행 되지 않는 경우에만 가능합니다 . 에서 기사는 인용 하면 12.1 %가, 나머지는 아무것도되지 않은 상태에서 I / O를 완료하기위한 하나 개의 코어가 기다리고 의미 87.4 %의 유휴 대 기다리고 있습니다 경우입니다 (링크에 대한 @manlio 감사는) 조금도. 해당 시스템에 수행 할 작업, 바람직하게는 여러 작업을 제공하면 대기 비율이 낮아집니다.

오늘날의 응용 프로그램 설계의 목표 중 하나는 단일 응용 프로그램 만 실행 중이고 해당 단일 응용 프로그램이 I / O를 기다리고있는 경우에도 응용 프로그램이 다른 작업을 계속 수행 할 수 있도록하는 것입니다. 스레드는 이것에 대한 하나의 접근 방식, 비 차단 I / O에 대한 접근 방식이지만, 실제로 수행중인 작업의 종류, 실제로 기다리는 데이터없이 무언가를 얻을 수 있는지 여부에 달려 있습니다.

Linux를 사용할 때 더 긴 I / O 작업을 수행하는 경우 OS가 완료 될 때까지 거의 사용할 수 없게됩니다.

이는 일반적으로 일부 I / O 바운드 상황을 나타냅니다. 나는 충분한 CPU 처리를 할 수 없기 때문에 시스템이 느려지지 않는다고 감히 말한다. 많은 시간이 그 당시 사용량이 많은 HDD의 데이터에 의존하기 때문에 속도가 느릴 수 있습니다. 실행하려는 응용 프로그램 일 수도 있지만 실행 파일, 라이브러리 파일, 아이콘, 글꼴 및 기타 리소스를로드해야합니다. 이미 실행 중이지만 메모리의 일부를 스왑 아웃했으며 이제 다시 스왑 인해 야하는 응용 프로그램 일 수 있습니다. 어떤 이유로 든 다른 데몬은 로그 파일에 줄을 써야 할뿐만 아니라 실제로 요청에 응답하기 전에 해당 로그 파일을 플러시해야한다고 생각하는 데몬 일 수 있습니다.

iotopI / O 용량이 프로세스에 할당되는 방식을 확인하고 프로세스의 ioniceI / O 우선 순위를 설정 하는 등의 도구를 사용할 수 있습니다 . 예를 들어 데스크톱 시스템에서는 모든 idle대화 형 응용 프로그램을 예약 클래스 로 분류 하여 일부 대화 형 응용 프로그램에 I / O 대역폭이 필요한 순간 ​​대화 형 응용 프로그램이 완료 될 때까지 일괄 처리가 일시 중단됩니다.


5

응용 프로그램 코드에 따라 다릅니다. 귀하의 코드가 Linux에서 실행되고 있다고 가정합니다.

멀티 스레딩 (예 : POSIX pthreads )을 사용하여 계산 바운드 스레드가 일부 계산을 수행하는 동안 다른 IO 바운드 스레드가 IO를 수행하고 대기 할 수 있습니다. 심지어 응용 프로그램이 실행 한 수 여러 프로세스 와 통신 프로세스 간 통신 을 참조하십시오 (IPC)를 파이프 (7) , FIFO (7) , 소켓 (7) , 유닉스 (7) , shm_overview (7) , sem_overview (7) , mmap (2) , eventfd (2)고급 Linux 프로그래밍 등 읽기 ...

당신이 사용할 수있는 IO 비 - 블로킹 (non-blocking) 통과 등을 O_NOBLOCK위해 열 (2) 등 등 등 ...; 그런 다음 poll (2) 및 / 또는 SIGIO signal (7) ...을 사용하고 read (2) 등 의 EWOULDBLOCK오류를 처리해야 합니다 .

POSIX 비동기 IO를 사용할 수 있습니다. aio (7)를 참조하십시오.

파일 액세스의 경우, 페이지 캐시에 힌트를 줄 수 있습니다 ( 예 : mmap (2) 뒤에 madvise (2)posix_fadvise (2) 사용) . 리눅스 고유의 readahead (2) 참조

그러나 결국 하드웨어 병목 현상 (버스, RAM 등)에 도달하게됩니다. ionice (1) 도 참조하십시오


1

논란의 여지가있는 다른 관점을 추가합니다.

Linux 운영 체제의 일반적인 문제입니다. 구체적으로 지연 ( "Linux mouse lag"검색). Windows에는이 문제가 없습니다. 이중 부팅 Windows 7 및 Linux Mint가 있습니다. Windows에서 집중적 인 디스크 작업을 수행 할 때도 Windows가 매끄럽게 느껴지고 마우스가 정상적으로 움직입니다. 리눅스에서는 정반대의 느낌이 들지 않아 정상적인 웹 브라우징 중에도 스무딩 및 마우스가 때때로 지연됩니다.

아마도이 두 시스템의 철학과 역사가 다르기 때문일 것입니다. Windows는 기본적으로 그래픽 운영 체제 인 일반 사용자를 위해 설계되었습니다. 또한 Windows 사용자의 경우 시스템이 원활하지 않고 마우스가 움직이지 않는 것이 문제가 있다는 신호입니다. 따라서 Microsoft 프로그래머는 시스템이 느리게 느껴지는 경우를 최소화하기 위해 전체 시스템을 설계하기 위해 열심히 노력했습니다. 그와 반대로 Linux는 처음에는 그래픽 시스템이 아니며 데스크톱은 타사에 추가 된 것입니다. 그리고 Linux는 원칙적으로 명령 줄을 사용하는 해커를 위해 설계되었습니다. 일을 철학으로하십시오. 리눅스는 단순히 부드러운 행동을 염두에두고 설계된 것이 아니며, 감정은 여기서 중요하지 않습니다.

참고 : Windows가 Linux보다 낫다는 말은 아닙니다. 복잡한 환경에서는 이러한 시스템의 높은 수준의 동작 / 느낌을 유발할 수있는 전반적인 철학이 다릅니다.


시스템의 신중한 구성 (예 : 배고픈 프로세스에서 nice& 사용 ) ionice으로 Linux 마우스 지연을 피하거나 줄일 수 있습니다 . 그리고 리눅스를 사용하는 거의 (내 컴퓨터를 ... 과부하 경우를 제외하고)이 리눅스 마우스 지연을 경험하지 않습니다
실레 Starynkevitch을

BTW, Linux는 대부분 서버 OS입니다.
Basile Starynkevitch

작업 관리자와 리소스 모니터가 메모리 사용량이 적고 CPU 및 디스크 활동이 낮을 때에도 Windows 7에서 UI 및 마우스 지연이 발생했습니다.
8bittree
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.