“CPU 바운드”및“I / O 바운드”라는 용어는 무엇을 의미합니까?


답변:


452

매우 직관적입니다.

CPU가 더 빠르면 프로그램이 더 빨라지면 프로그램이 CPU에 바운드됩니다. 즉, 대부분의 시간을 단순히 CPU를 사용하여 계산합니다 (계산 수행). 새로운 π의 자릿수를 계산하는 프로그램은 일반적으로 CPU에 한정되며 크런치 숫자입니다.

I / O 서브 시스템이 더 빠르면 프로그램이 더 빨라지면 프로그램이 I / O에 바인드됩니다. 정확한 I / O 시스템의 의미는 다를 수 있습니다. 일반적으로 디스크와 디스크를 연결하지만 일반적으로 네트워킹 또는 통신도 일반적입니다. 병목 현상은 디스크에서 데이터를 읽는 것이므로 실제로 일부 파일에 대해 큰 파일을 살펴 보는 프로그램은 I / O 바운드가 될 수 있습니다. SSD에서 제공).


이것이 모바일 장치에서 HTTP 통신을 이해하는 것과 어떻게 관련이 있습니까? java.nio 작업 을 사용하여 CPU 사용량이 급증하는 것을 보았습니다 .
IgorGanapolsky 2016 년

I / O는 "입력 / 출력"입니다.
Cherade Che

246

CPU 바운드 는 프로세스 진행 속도가 CPU 속도에 의해 제한됨을 의미합니다. 작은 숫자를 곱하는 것과 같이 작은 숫자 집합에서 계산을 수행하는 작업은 CPU에 바인딩 된 것 같습니다.

I / O 바운드 는 프로세스가 진행되는 속도가 I / O 하위 시스템의 속도에 의해 제한됨을 의미합니다. 예를 들어, 파일의 행 수를 계산하는 것과 같이 디스크에서 데이터를 처리하는 작업은 I / O 바인딩 될 수 있습니다.

메모리 바운드 는 프로세스가 진행되는 속도가 사용 가능한 메모리 양과 해당 메모리 액세스 속도에 의해 제한됨을 의미합니다. 많은 양의 메모리 데이터를 처리하는 작업 (예 : 큰 행렬 곱하기)은 메모리 바운드 일 가능성이 높습니다.

캐시 바운드 는 프로세스 진행률이 사용 가능한 캐시의 양과 속도에 의해 제한되는 비율을 의미합니다. 캐시에 맞는 것보다 더 많은 데이터를 단순히 처리하는 작업은 캐시에 바인딩됩니다.

I / O 바운드는 메모리 바운드보다 느리고 캐시 바운드는 CPU 바운드보다 느립니다.

I / O 바인딩 솔루션은 반드시 더 많은 메모리를 확보 할 필요는 없습니다. 경우에 따라 액세스 알고리즘은 I / O, 메모리 또는 캐시 제한을 중심으로 설계 될 수 있습니다. 캐시 불명확 한 알고리즘을 참조하십시오 .


72

멀티 스레딩

이 답변에서는 다중 스레드 코드를 작성할 때 CPU와 IO 경계 작업을 구별하는 중요한 사용 사례를 조사합니다.

RAM I / O 바운드 예 : 벡터 합계

단일 벡터의 모든 값을 합하는 프로그램을 생각해보십시오.

#define SIZE 1000000000
unsigned int is[SIZE];
unsigned int sum = 0;
size_t i = 0;
for (i = 0; i < SIZE; i++)
    /* Each one of those requires a RAM access! */
    sum += is[i]

각 코어에 대해 어레이를 균등하게 분할하여 일반적인 최신 데스크톱에서는 유용성이 제한됩니다.

예를 들어, Ubuntu 19.04, CPU가 장착 된 Lenovo ThinkPad P51 랩탑 : Intel Core i7-7820HQ CPU (4 코어 / 8 스레드), RAM : 2x Samsung M471A2K43BB1-CRC (2x 16GiB) 결과는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

데이터를 플롯합니다 .

그러나 실행 간에는 많은 차이가 있습니다. 그러나 이미 8GiB에 있기 때문에 어레이 크기를 훨씬 더 늘릴 수 없으며 오늘날 여러 번 실행되는 통계에 대한 기분이 들지 않습니다. 그러나 이것은 많은 수동 실행을 한 후 일반적인 실행처럼 보입니다.

벤치 마크 코드 :

곡선의 모양을 완전히 설명하기에 충분한 컴퓨터 아키텍처를 알지 못하지만 한 가지 분명합니다. 8 개의 스레드를 모두 사용하기 때문에 계산이 순진하게 예상대로 8 배 빠르지 않습니다! 어떤 이유로 든 2와 3 스레드가 최적이었고 더 많이 추가하면 속도가 훨씬 느려집니다.

이것을 8 배 더 빠른 CPU 바운드 작업과 비교해보십시오. 시간의 결과에서 '실제', '사용자'및 'sys'는 무엇을 의미합니까?

모든 프로세서가 RAM에 연결되는 단일 메모리 버스를 공유하는 이유는 다음과 같습니다.

CPU 1   --\    Bus    +-----+
CPU 2   ---\__________| RAM |
...     ---/          +-----+
CPU N   --/

따라서 메모리 버스는 CPU가 아닌 병목 현상이 빠르게 발생합니다.

두 개의 숫자를 추가하면 단일 CPU주기가 걸리고 메모리 읽기 는 2016 하드웨어에서 약 100 개의 CPU주기가 필요하기 때문에 발생 합니다.

따라서 입력 데이터의 바이트 당 수행되는 CPU 작업이 너무 작으므로이를 IO 바인딩 프로세스라고합니다.

계산 속도를 높이는 유일한 방법은 새로운 메모리 하드웨어 (예 : 다중 채널 메모리)를 사용 하여 개별 메모리 액세스 속도를 높이는 것 입니다.

예를 들어 더 빠른 CPU 클럭으로 업그레이드하는 것은 그리 유용하지 않습니다.

다른 예

CPU 또는 IO 바운드인지 확인하는 방법

비-RAM IO 디스크, 네트워크 같은 바인딩 : ps aux다음 theck 경우 CPU% / 100 < n threads. 그렇다면 IO 제한입니다. 예를 들어 차단 read은 데이터를 기다리는 중이며 스케줄러는 해당 프로세스를 건너 뜁니다. 그런 다음 추가 도구를 사용 sudo iotop하여 정확히 어떤 IO가 문제인지 결정하십시오.

또는 실행이 빠르고 스레드 수를 매개 변수화하면 timeCPU 바운드 작업의 스레드 수가 증가함에 따라 성능이 향상 되는 것을 쉽게 알 수 있습니다 . '실제', '사용자'및 'sys'의 의미 시간의 출력 (1)?

RAM-IO 바운드 : RAM 대기 시간이 CPU%측정에 포함되므로 알기가 어렵습니다 .

일부 옵션 :

GPU

입력 데이터를 일반 CPU 읽기 가능 RAM에서 GPU로 전송할 때 GPU에 IO 병목 현상이 발생합니다.

따라서 GPU는 CPU 바운드 응용 프로그램의 CPU보다 우수 할 수 있습니다.

그러나 일단 데이터가 GPU로 전송되면 GPU가 다음과 같은 이유로 CPU보다 빠른 속도로 해당 바이트에서 작동 할 수 있습니다.

  • 대부분의 CPU 시스템보다 더 많은 데이터 지역화 기능이 있으므로 일부 코어의 경우 다른 코어 시스템보다 빠르게 데이터에 액세스 할 수 있습니다.

  • 즉시 작동 할 준비가되지 않은 데이터를 건너 뛰어 데이터 병렬 처리를 활용하고 대기 시간을 희생합니다.

    GPU는 큰 병렬 입력 데이터에서 작동해야하므로 현재 데이터가 제공 될 때까지 기다리지 않고 사용 가능한 다음 데이터로 건너 뛰고 CPU와 같은 다른 모든 작업을 차단하는 것이 좋습니다.

따라서 다음과 같은 경우 GPU가 CPU보다 빠를 수 있습니다.

  • 고도로 병렬화 가능 : 서로 다른 데이터 청크를 동시에 별도로 처리 할 수 ​​있음
  • 입력 바이트 당 많은 수의 연산이 필요합니다 (예 : 바이트 당 하나의 덧셈을 수행하는 벡터 덧셈과 달리)
  • 많은 입력 바이트가 있습니다

이러한 디자인 선택은 원래 3D 렌더링의 응용 프로그램을 대상으로 했으며 OpenGL의 쉐이더 란 무엇이며 무엇을 위해 필요한가?

  • 버텍스 쉐이더 : 1x4 벡터 묶음에 4x4 행렬 곱하기
  • 프래그먼트 셰이더 : 삼각형이있는 상대 위치를 기준으로 삼각형의 각 픽셀의 색상을 계산합니다.

따라서 우리는 이러한 응용 프로그램이 CPU에 바인딩되어 있다고 결론지었습니다.

프로그래밍 가능한 GPGPU의 출현으로 CPU 바운드 작업의 예인 여러 GPGPU 애플리케이션을 관찰 할 수 있습니다.

또한보십시오:

CPython 글로벌 정수기 잠금 (GIL)

빠른 사례 연구로서, 파이썬 GIL (Global Interpreter Lock) : CPython의 GIL (Global Interpreter Lock) 이란 무엇입니까?

이 CPython 구현 세부 사항은 여러 Python 스레드가 CPU 바운드 작업을 효율적으로 사용하지 못하게합니다. 의 CPython 문서는 말한다 :

CPython 구현 세부 사항 : CPython에서는 Global Interpreter Lock으로 인해 한 번에 하나의 스레드 만 Python 코드를 실행할 수 있습니다 (특정 성능 지향 라이브러리가이 한계를 극복 할 수 있음에도 불구하고). 당신이 멀티 코어 시스템의 컴퓨팅 자원을보다 효율적으로 사용할 수 있도록 응용 프로그램을 원하는 경우 사용하는 것이 좋습니다 multiprocessing또는 concurrent.futures.ProcessPoolExecutor. 그러나 여러 I / O 바운드 작업을 동시에 실행하려는 경우 스레딩은 여전히 ​​적절한 모델입니다.

따라서 여기에 CPU 바운드 컨텐츠가 적합하지 않고 I / O 바운드가있는 예가 있습니다.


1
이봐, 어떻게 그렇게 유능하고 이런 글을 썼어?
Mikayil Abdullayev

1
트윗 담아 가기 나는 "중요한 질문"에만 대답하는 경향이 있으며 새로운 관련 자료를 배우면서 계속해서 질문에 답하는 경향이 있습니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

31

CPU 바운드는 프로그램이 CPU 또는 중앙 처리 장치에 의해 병목 현상을 발생시키는 반면, I / O 바운드는 프로그램이 디스크, 네트워크에 대한 읽기 또는 쓰기 등의 입 / 출력에 의해 병목 현상이 발생했음을 의미합니다.

일반적으로 컴퓨터 프로그램을 최적화 할 때 병목 현상을 찾아 제거합니다. 프로그램이 CPU에 속한다는 것을 알면 불필요하게 다른 것을 최적화하지 않아도됩니다.

[그리고 "병목 현상"이란 프로그램이 다른 것보다 느리게 만드는 것을 의미합니다.]


21

같은 생각을 표현하는 또 다른 방법 :

  • CPU 속도를 높여도 프로그램 속도가 향상되지 않으면 I / O 바인딩 된 것일 수 있습니다 .

  • I / O 속도를 높이면 (예 : 더 빠른 디스크 사용) 도움이되지 않으면 프로그램이 CPU에 바인딩 된 것일 수 있습니다.

(다른 리소스를 고려해야하기 때문에 "아마도"를 사용했습니다. 메모리가 한 예입니다.)


11

프로그램이 I / O를 기다리는 경우 (예 : 디스크 읽기 / 쓰기 또는 네트워크 읽기 / 쓰기 등) CPU는 프로그램이 중지 된 경우에도 다른 작업을 자유롭게 수행 할 수 있습니다. 프로그램 속도는 대부분 IO가 얼마나 빨리 발생할 수 있는지에 달려 있으며 속도를 높이려면 I / O 속도를 높여야합니다.

프로그램이 많은 프로그램 명령을 실행 중이고 I / O를 기다리지 않으면 CPU 바인딩이라고합니다. CPU 속도를 높이면 프로그램이 더 빨리 실행됩니다.

두 경우 모두 프로그램 속도를 높이는 열쇠는 하드웨어 속도를 높이는 것이 아니라 필요한 IO 또는 CPU의 양을 줄이거 나 CPU를 많이 사용하면서 I / O를 수행하도록 프로그램을 최적화하는 것입니다. 물건.


6

I / O 바운드는 계산을 완료하는 데 걸리는 시간이 입력 / 출력 작업이 완료되기를 기다리는 데 소요 된 기간에 의해 주로 결정되는 조건을 나타냅니다.

이것은 CPU 바인딩 작업과 반대입니다. 이 상황은 데이터 요청 속도가 데이터 소비 속도보다 느리거나 데이터를 처리하는 것보다 데이터를 요청하는 데 더 많은 시간이 소요되는 경우에 발생합니다.


6

IO 바운드 프로세스 : 계산보다 IO 작업에 더 많은 시간을 소비하고 짧은 CPU 버스트가 많습니다. CPU 바운드 프로세스 : 계산에 더 많은 시간을 보내고 CPU 버스트가 거의 없음


2

Microsoft의 의견을 참조하십시오.

비동기 프로그래밍의 핵심은 비동기 작업을 모델링하는 Task 및 Task 개체입니다. 그것들은 async 및 await 키워드에 의해 지원됩니다. 대부분의 경우이 모델은 매우 간단합니다.

  • I / O 바인딩 코드의 경우 비동기 메서드 내에서 작업 또는 작업을 반환하는 작업을 기다립니다.

  • CPU 바인딩 코드의 경우 Task.Run 메서드를 사용하여 백그라운드 스레드에서 시작된 작업을 기다립니다.

await 키워드는 마술이 일어나는 곳입니다. 대기 한 메소드의 호출자에게 제어권을 부여하고 궁극적으로 UI가 응답하거나 서비스가 탄력적입니다.

I / O- 바운드 예 : 웹 서비스에서 데이터 다운로드

private readonly HttpClient _httpClient = new HttpClient();

downloadButton.Clicked += async (o, e) =>
{
    // This line will yield control to the UI as the request
    // from the web service is happening.
    //
    // The UI thread is now free to perform other work.
    var stringData = await _httpClient.GetStringAsync(URL);
    DoSomethingWithData(stringData);
};

CPU 바운드 예 : 게임 계산 수행

private DamageResult CalculateDamageDone()
{
    // Code omitted:
    //
    // Does an expensive calculation and returns
    // the result of that calculation.
}

calculateButton.Clicked += async (o, e) =>
{
    // This line will yield control to the UI while CalculateDamageDone()
    // performs its work.  The UI thread is free to perform other work.
    var damageResult = await Task.Run(() => CalculateDamageDone());
    DisplayDamage(damageResult);
};

위의 예제는 비동기를 사용하고 I / O 바운드 및 CPU 바운드 작업을 기다리는 방법을 보여줍니다. 작업 수행시기를 식별 할 수있는 핵심은 I / O 바운드 또는 CPU 바운드입니다. 코드 성능에 큰 영향을 미치고 잠재적으로 특정 구문을 잘못 사용할 수 있기 때문입니다.

다음은 코드를 작성하기 전에 물어봐야 할 두 가지 질문입니다.

데이터베이스의 데이터와 같은 코드가 코드를 "대기"하고 있습니까?

  • 귀하의 답변이 "예"이면 귀하의 업무는 I / O에 구속됩니다.

코드가 매우 비싼 계산을 수행합니까?

  • "예"라고 대답하면 작업이 CPU에 국한된 것입니다.

작업이 I / O 바운드 인 경우 async를 사용하고 Task.Run 없이 기다리십시오 . 태스크 병렬 라이브러리를 사용해서는 안됩니다. 이에 대한 이유는 Async in Depth 기사 설명되어 있습니다.

가지고있는 작업이 CPU에 종속되어 있고 응답 성을 염려한다면 async 및 await를 사용하고 Task.Run을 사용하여 다른 스레드에서 작업을 시작하십시오. 작업이 동시성 및 병렬 처리에 적합한 경우 작업 병렬 라이브러리 사용도 고려해야합니다 .


2

실행 중 산술 / 논리적 / 부동 소수점 (A / L / FP) 성능이 대부분 프로세서의 이론적 최고 성능 (제조업체에서 제공하고 데이터의 특성에 의해 결정됨)에 거의 근접하면 애플리케이션이 CPU에 바인딩됩니다. 프로세서 : 코어 수, 주파수, 레지스터, ALU, FPU 등).

불가능한 말을하지 않기 때문에 실제 응용 프로그램에서는 엿보기 성능을 달성하기가 매우 어렵습니다. 대부분의 응용 프로그램은 실행의 다른 부분에서 메모리에 액세스하며 프로세서는 여러주기 동안 A / L / FP 작업을 수행하지 않습니다. 이를 메모리와 프로세서 사이의 거리로 인해 Von Neumann Limitation 이라고 합니다.

CPU 최고 성능에 가깝게하려면 주 메모리의 데이터가 필요하지 않도록 캐시 메모리에있는 대부분의 데이터를 재사용하는 것이 좋습니다. 이 기능을 이용하는 알고리즘은 행렬 행렬 곱셈입니다 (두 행렬을 캐시 메모리에 저장할 수있는 경우). 행렬의 크기 n x n가 FP 인 2 n^3경우 2 n^2FP 수의 데이터 만 사용 하는 작업에 대해 수행 해야하기 때문에 발생 합니다. 반면에 매트릭스 추가 n^2는 동일한 데이터를 가진 FLOP 만 필요하므로 매트릭스 곱셈보다 CPU 바운드 또는 메모리 바운드 응용 프로그램이 적습니다 .

다음 그림에는 Intel i5-9300H에서 행렬 추가 및 행렬 곱셈에 대한 순진 알고리즘으로 얻은 FLOP가 나와 있습니다.

행렬 덧셈과 행렬 곱셈의 FLOP 비교

예상대로 행렬 곱셈의 성능은 행렬 덧셈보다 큽니다. 이 결과는 이 저장소 에서 실행 test/gemm하여 test/matadd사용할 수 있습니다 .

이 효과에 대해 J. Dongarra가 제공 한 비디오 를 보는 것도 좋습니다 .


1

I / O 바운드 프로세스 :-프로세스 수명의 대부분이 I / O 상태로 소비되는 경우 프로세스는 a / o 바운드 프로세스입니다.

CPU 바운드 프로세스 :-프로세스 수명의 대부분이 CPU에 소비되면 CPU 바운드 프로세스입니다.


8
계산기는 어떻게 IO 바인딩 프로세스입니까? 확실히 그것은 CPU 바운드입니다. 계산기가 네트워크 또는 디스크에 액세스하여 차단하는 데 대부분의 시간을 소비하면 문제가 있다고 제안합니다.
rickerbh 2016 년

6
계산기 예제가 명확하다고 생각했습니다. 대부분의 경우 사용자가 버튼을 누를 때까지 기다렸다가 I / O를 기다립니다.
psp

1
@psp는 옳지 만 계산기 예제는 "calculator"라는 이름 때문에 여전히 io-bound로보기 어렵다. 즉, 프로그램의 주요 목적은 긴 CPU 계산을 수행하는 것이지만 데스크톱에서 계산기를 보면 매우 간단한 계산으로 나노초가 걸리는 계산 만 수행합니다. 따라서 사용자 입력을 기다리는 대부분의 시간은 IO입니다.
Calicoder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.