C++ scanf 와 cin 의 입출력 속도 비교, 입출력 속도 높이기
카테고리: Cpp
태그: Cpp Programming
🚀 C의 입출력 함수(scanf, printf)와 C++의 입출력 함수(cin, count)
cin, cout 은 scanf, printf 보다 2 배 이상 느리다. 따라서 입출력을 해야하는 코딩테스트 문제를 풀이할 때 이점을 염두해두고 풀이해야 한다.
- 그냥 scanf, printf 사용하기
- cin, cout 을 사용할 것이라면 C와 C++ 사이의 버퍼 동기화를 끊는다.
백준 문제들은 프로그래머스와 다르게 직접 입력을 받는 코드를 넣어야 하고 결과를 출력함으로써 채점이 된다. 그래서 풀이는 올바르더라도 어떤 입출력 함수를 썼느냐에 따라 시간 초과⏰ 결과가 나올 수도 있다.
‘\n’가 endl 보다 훨씬 빠르다는 것은 알고 있었지만 cin, cout 이 scanf, printf 보다 느리다는 것은 처음 알게 되었다. scanf, printf 가 cin, cout 보다 실행 속도가 2 배 이상 빠르기 때문에 그냥 scanf, printf 를 쓰면 간단하지만 나는 cin 과 cout 이 더 가독성 좋게 느껴지고 편해서 더 선호하는 편이다. cin 과 cout 의 입출력 속도를 scanf, printf 의 속도에 가깝게 크게 향상시킬 수 있는 코드가 있다! C++로 백준 문제 풀이하시는 분들의 코드에 많이들 들어가는 코드여서 궁금했었는데 cin, cout 입출력을 향상시키는 코드였다니!!
- 속도 비교
- getchar 👉 scanf 👉 cin
🚀 cin, cout 의 입출력 속도 높이기
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
C와 C++ 사이의 버퍼 동기화를 끊어 cin, cout이 독립적인 버퍼를 갖게하는 방식으로 입출력 속도를 scanf, printf 못지 않게 크게 향상시킨다.
cin, cout 을 사용하기 전 위 3 줄 코드를 앞서 넣어주면 된다. 다만 주의사항이 있다.
- 동기화를 끊기 때문에 생길 수 있는 문제점
- 1️⃣ C의 버퍼와 C++ 버퍼가 별개로 독립되기 때문에 scanf, printf, getchar 같은 C의 입출력 함수와 cin, cout 을 섞어쓰면 입출력의 순서가 올바르지 못하게 나올 수 있다.
- 2️⃣ 멀티 쓰레드 환경에선 예상하지 못한 결과가 도출될 수 있다. (동기화를 끊음으로써 Thread unsafe 상태가 되기 떄문에 race condition이 발생할 수 있음)
코딩 테스트를 풀이하는건 싱글 쓰레드 환경에서 하니 문제 없을 요소지만 현업에선 멀티 쓰레드 환경일 수 있을테니 scanf, printf 사용을 지향해야 할 것 같다.
🔥 ios::sync_with_stdio(false);
기본적으로 true 즉 동기화 상태가 디폴트 상태이다. 즉, 평소엔 C와 C++ 입출력 방식을 제한 없이 섞어쓸 수 있는 것이다. C++의 버퍼(iostream)와 C의 버퍼(stdio)를 모두 사용하고 동기화가 되어 있기 때문에 딜레이가 발생하는 것인데 위 코드로 동기화를 끊을 수 있다. 즉, C와 C++의 버퍼가 서로 독립되는 것이다. 이렇게 사용하는 버퍼 수가 줄어듬으로써 속도가 향상된다.
- 주의사항
- C의 입출력 함수 쓰지 않기 (독립되어 섞어쓰면 안됨)
- 싱글 쓰레드 환경에서만 사용하기
🔥 cin.tie(NULL); cout.tie(NULL);
cin 을 cout 으로부터 untie 하기 👉 동기화처럼 이 과정도 입출력 속도를 상승시킨다.
cin, cout이 서로 tie 가 되어 있는 상태가 디폴트 상태라고 한다.
std::cout << "Enter name:";
std::cin >> name;
tie
cin과 cout이 묶여있으면- 다른 스트림에서 입력 혹은 출력 작업을 하기 전에 자동으로 flush (콘솔에 표시 visible on the console) 되도록 한다.
- 예를 들어 입력 스트림(cin)에서 입력 작업을 하려면 그 전에 미리 출력 스트림(cout)에 있는 것들이 비워지면서 콘솔창에 표시(flush)된다는 이야기인 것 같다. 즉, “Enter name:”이 먼저 출력한 이후에 입력을 받도록
- cout.tie(NULL);은 그 반대인가 그럼?
- 다른 스트림에서 입력 혹은 출력 작업을 하기 전에 자동으로 flush (콘솔에 표시 visible on the console) 되도록 한다.
untie
cin과 cout이 묵여있지 않으면- 다른 스트림에서 입력 혹은 출력 작업을 하기 전에 자동으로 flush (콘솔에 표시) 되도록 신경써주지 않는다.
- untie 해주면 위 코드에서 이름을 먼저 입력받고난 후에 “Enter name:”이 출력될 수 있다. 버퍼가 가득 차거나 수동적으로 flush 를 시켜주기 전까지는 출력이 되지 않는다.
- 다른 스트림에서 입력 혹은 출력 작업을 하기 전에 자동으로 flush (콘솔에 표시) 되도록 신경써주지 않는다.
🚀 참고 및 출처
- 뽕뽑기님 블로그 https://codecollector.tistory.com/381
- 쌍문동 믹서기님 블로그 https://cupjoo.tistory.com/97
- 숨창고님 블로그 https://su-m.tistory.com/7
- hyunjin님 블로그 https://hegosumluxmundij.tistory.com/54
- 코딩친구님 블로그 https://codingfriend.tistory.com/21
- https://stackoverflow.com/questions/31162367/significance-of-ios-basesync-with-stdiofalse-cin-tienull
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기