TTY에서 사용할 때 프로그램 속도가 상당히 느려집니다.

TTY에서 사용할 때 프로그램 속도가 상당히 느려집니다.

그래서 C++로 작성된 프로그램이 있습니다.

모든 계산을 수행하는 데 시간이 얼마나 걸렸는지 알 수 있으며 매우 무거운 멀티 스레드 계산을 많이 수행합니다.

방금 동일한 시스템에서 프로그램을 실행하는 경우 TTY에서 시작하면 모든 계산을 수행하는 데 약 20-21초가 걸리고 GNOME 터미널에서 시작하면 약 0.2초밖에 걸리지 않는다는 것을 확인했습니다.

그 원인은 무엇입니까? 문자 그대로 동일한 컴퓨터에 있는 동일한 파일입니다.

답변1

일부 배경 이론

글쎄 , ++ CTRL와 GNOME 터미널 이후에 작업하는 것은 모두 동일한 개념을 다르게 구현한 것입니다.ALTF1에뮬레이션소위 전체 화면 터미널.

전자를 Linux에서는 가상 터미널(VT)이라고 부르거나 일반적으로 그냥 "콘솔"이라고 부릅니다. x86 호환 플랫폼(즉, "IBM PC" 유산의 플랫폼)의 하드웨어 비디오 카드에서 제공하는 특별한 "텍스트 전용" 비디오 모드를 사용합니다. 후자는 GUI 애플리케이션입니다.

둘 다 "터미널 장치"에서 기대하는 일련의 기능을 지원하여 실행되는 응용 프로그램을 제공합니다(자세한 내용 및 추가 지침—여기).

당면한 문제

자, 이제 인지된 느림으로 넘어가겠습니다.

귀하의 문제의 핵심은 귀하의 프로그램이 소위 "차단" I/O를 수행한다는 것입니다. 즉, 다음과 같은 일을 할 때마다

std::cout << "Hello, world" << endl;

귀하의 코드에서 먼저 귀하의 응용 프로그램에 연결된 C++ 표준 라이브러리의 코드가 시작되어 표시된 항목으로 전송된 내용의 출력을 처리합니다.개울.

특정 처리(그리고 가장 일반적으로 일부 버퍼링) 후에 이 데이터는 실제로 프로그램의 실행 프로세스를 떠나 프로그램이 출력을 보내는 모든 미디어에 실제로 출력되어야 합니다. Linux(및 기타 Unix 호환 시스템)에서는 전용 커널을 통해 커널을 호출해야 합니다.시스템 호출(또는시스템콜줄여서) 이름이 write().

따라서 C++ stdlib는 결국 write()syscall을 만들고 완료될 때까지 기다립니다. 즉, 커널이 "좋아, 데이터 수신자가 데이터를 획득했다고 말했습니다."라고 다시 말할 때까지 기다립니다.

추론할 수 있듯이 프로그램이 출력하는 데이터의 수신자는 프로그램을 실행하는 터미널(에뮬레이터)입니다. 이는 Linux VT 또는 테스트의 GNOME 터미널 인스턴스입니다. (커널이 실행 중인 터미널 에뮬레이터에 바로 데이터를 보내지 않기 때문에 전체 그림은 더 복잡하지만 설명을 복잡하게 만들지는 않겠습니다.)

따라서 해당 syscall이 완료되는 속도는 write()데이터 수신자가 이를 처리하는 속도에 따라 크게 달라집니다! 귀하의 경우에는 GNOME 터미널이 훨씬 더 빠릅니다.

제가 생각하는 차이점은 VT 드라이버가 전송되는 모든 데이터를 성실하게 렌더링하고 스크롤하는 등의 작업을 하는 반면, GNOME 터미널은 (터미널의 화면 크기에 맞는 모든 것) 데이터의 꼬리 부분만 렌더링하여 들어오는 데이터의 버스트를 최적화하고 대부분의 GUI 터미널 에뮬레이터가 가지고 있는 소위 "스크롤 버퍼"에 휴식을 취합니다.

해야 할 일

이를 수행하는 데 중요한 점은 프로그램이 계산과 함께 I/O를 수행하자마자 "벽시계" 타이머를 사용하여 프로그램의 계산 속도를 측정하면 일반적으로 해당 I/O의 속도를 측정할 수 있다는 것입니다. 아, 계산 속도가 아니군요.

I/O는 까다롭다는 점에 유의하십시오. 프로세스가선점(해당 리소스가 다른 프로세스로 넘겨지면서 중지됨) OS는 하드 디스크 드라이브와 같은 일부 I/O 리소스가 쓰기에 사용 가능해질 때까지 기다릴 때마다 OS에 의해 중단됩니다.

따라서 계산의 "원시" 성능을 측정하는 확실한 방법은 모든 I/O를 비활성화하는 기능을 프로그램에 두는 것입니다. 이것이 가능하지 않거나 구현하기 너무 추악한 경우 최소한 다음과 /dev/null같은 프로그램을 실행하여 모든 출력을 소위 "널 장치"로 지정해 보십시오.

$ ./program >/dev/null

널 장치는 단순히 전달된 모든 데이터를 삭제합니다. 그렇습니다. C++ stdlib에 의해 수행되는 각 I/O 라운드는 여전히 커널에 도달하지만 적어도 거의 일정한(그리고 거의 즉각적인) 쓰기 속도를 갖게 됩니다.

두 가지 조치가 모두 필요한 경우그리고생성된 데이터를 처리하려면 소위 RAM 디스크를 생성하고 출력을 거기에 있는 파일로 리디렉션하는 것을 고려하십시오.

측정에 대해 한 가지 더: 상용 OS(예: Ubuntu 등)를 실행하는 겉보기에 유휴 시스템인 경우에도 CPU는 결코 잠들지 않습니다. 항상 백그라운드에서 작업을 수행하는 일부 작업이 있습니다. 이는 I/O가 없거나 일종의 "비활성화된" I/O(위에 설명된 대로)가 있어도 계산 성능을 측정하면 각 실행에서 여전히 다른 결과가 생성된다는 것을 의미합니다.

이를 보완하기 위해 좋은 벤치마킹이란 동일한 입력 데이터를 사용하여 계산을 수천 번 실행하고 실행 횟수에 대한 결과를 평균화하는 것을 의미합니다.

관련 정보