입출력 속도 향상

2022. 12. 19. 22:34백준(c , c++)

728x90

cin/cout을 사용하고자 한다면, cin.tie(NULL) sync_with_stdio(false)를 둘 다 적용해 주고, endl 대신 개행문자(\n)를 쓰자. 단, 이렇게 하면 더 이상 scanf/printf/puts/getchar/putchar 등 C의 입출력 방식을 사용하면 안 된다.

 

scanf(), printf()를 사용하면 이 입출력 자체가 매우 빠른 편이라 쉽게 통과하지만, 다른 언어의 경우는 조금 사정이 다르다

 

1) ios-base::sync_with_stdio(false);

C++와 C 표준 스트림의 동기화 해제

기본적으로 C++에서는 C++와 C의 표준 스트림이 동기화가 되어있다. 

즉, C와 C++가 동일한 버퍼를 공유한다는 것

 

이러한 동기화는 성능을 저하시키는 원인이 되지만, 두 스트림의 동기화는 우리가 입출력에 있어 C와 C++의 IO(Input-Output)을 혼용하여 쓸 때 매우 합리적이고 스레드로부터 안전하기 때문에 원래는 동기화 상태로 두는 것이 올바르긴 하다.

동기화를 해제하면 c스타일대로 하던 c++스타일대로 하던 한가지로만 해야함.

 

2) cin.tie(NULL);

입력과 출력 연결을 끊어주기

기본적으로 입력과 출력은 연결되어있다.

기본적으로 입력 요청이 들어오면 그 전에 출력 작업이 있었을 경우(출력 버퍼에 내용이 있는 경우) 버퍼를 비워(flush) 출력을 하게 된다. 

<입출력 연결을 안끊은 경우>

	int a;
	for (int i = 0; i < 10; i++) {
		cout << i << "번 째 입력\n";
		cin >> a;
	}
	return 0;

<입출력 연결을 끊은 경우>

	cin.tie(NULL);
 
	int a;
	for (int i = 0; i < 10; i++) {
		cout << i << "번 째 입력\n";
		cin >> a;
	}
	return 0;

 

운영체제마다 다른데 , 윈도우는 기본적으로 출력 하자마자 버퍼링 없이 콘솔에 출력이 된다.
그래서 끊든 말던 영향을 받지 않지않지만 
반대로 리눅스 계열의 경우 줄(개행)을 입력 받을 때 까지 버퍼링이 되어 영향을 받는다.

 

백준 채점 서버는 우분투다 .

-> 출력문만 동일하면 되기 때문에 굳이 입력 후에 해당 값을 매 번 출력 해줄 필요가 없다.

    즉, 매번 출력을 flushing 시키지 않고 나중에 한 번에 비우도록 하는 것이다.

그래서 예제출력 결과와 내 출력 결과가 달라도 통과되는 것이다.

 

 

3) endl 대신 개행문자(\n)를 쓰기

endl은 단순히 개행(줄바꿈)만 해주는 것이 아니라 출력 버퍼를 비우는 역할까지 한다.

endl 을 쓰면  tie을 끊어주는 것의 효과를 볼 수가 없다.

이 출력 버퍼를 비우는 작업도 상당히 시간을 잡아먹는 작업이기 때문에 마지막 한 번에 출력을 비우는 것이 좋다.

(물론 버퍼가 꽉 차면 알아서 비워준다.)

 

 

 

728x90