본문 바로가기
프로그래밍/알고리즘

cin과 out의 시간 단축을 위한 몇 가지 팁

by 카프카뮈 2021. 8. 14.

https://www.acmicpc.net/problem/1620

 

1620번: 나는야 포켓몬 마스터 이다솜

첫째 줄에는 도감에 수록되어 있는 포켓몬의 개수 N이랑 내가 맞춰야 하는 문제의 개수 M이 주어져. N과 M은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수인데, 자연수가 뭔지는 알지? 모르면

www.acmicpc.net

오늘은 심심해서 백준에서 알고리즘 문제를 몇 개 풀어봤다. 

그러다가 재미있는 문제를 찾아서 풀어봤는데, 아무리 풀어도 시간초과가 해결이 안됨...

그래서 지인에서 알아보다가, 왜 내 제출이 시간초과가 나는지 알게 되었다.


1. cout의 endl 사용 시 이슈

우리가 iostream의 출력 함수를 사용할 경우, 아래와 같이 사용하게 된다.

#include<iostream>

using namespace std;

int main(void) {
    int n = 42;
    
    cout << n << endl;

    return 0;
}

그런데, 여기서 endl의 작동에 대해 내가 모르는 점이 있었다.

endl을 사용할 경우, 단순히 개행 문자만 넣어주는 것이 아니라, flush가 함께 작동한다. 

 

공식 문서에서도, 설명에서 "Inserts a newline character into the output sequence os and flushes it as if by calling os.put(os.widen('\n')) followed by os.flush()." 라고 언급하는 것을 볼 수 있다.

 

링크 를 보면, 직접 실험해서 포스팅해주신 결과도 존재한다.

일단 최고로 좋은 것은 printf 쓰기!! 다만 나의 경우 cpp 느낌나게 짜보려다가 실수를 크게 한 셈이 되겠다.

 

이를 해결하는 법은 간단하다.

endl 대신, 개행문자 "\n"을 마지막에 넣어주면 된다. 

 


2. cout과 cin의 최적화

위의 작동만 하면 끝일까? 그 상태로 cout/cin을 활용해 제출해 보았으나, 여전히 시간초과가 발생하였다.

그래서 printf로 바꾸려다가, 오기가 들어서 좀 더 최적화 방법을 검색해보았다.

그 결과 찾은 또다른 방법!! 먼저 코드를 보자.

#include<iostream>

using namespace std;

int main(void) {
    ios_base::sync_with_stdio(false); //1
    cin.tie(NULL); cout.tie(NULL);    //2
    
    int n = 42;
    
    cout << n << "\n";

    return 0;
}

위의 코드를 보면, main 함수에 두 라인이 추가된 것을 알 수 있다.

  1. ios::sync_with_stdio(false)는 c와 cpp 입출력의 synchronization 작동을 false로 설정한다.
    이 경우, 동기화를 위한 작업이 수행되지 않고 자체적인 버퍼에 값이 저장된다.
    물론 ps를 위한 코드에 스레드를 쓰지는 않지만...이는 thread safe하지 않은 로직이므로,
    만약 thread를 사용하는 코드에서 이 코드가 들어가면 입력 도중 thread의 context switching으로 인해
    의도하지 않은 값이 들어가거나 나올 수 있다. 혹은, 버퍼에 다른 스레드가 접근해 값을 조작할 수도 있다.
    그러나 상황에 맞게 사용!!
  2. cin과 cout의 tie를 NULL로 설정해 준다. 이 경우, 자동 flush를 막아 시간 복잡도에 이득을 준다.

해당 사항은 이 링크와, 스택오버플로우 게시글을 참고하였다.

 

실제로 해당 옵션을 껐을때와 켰을때의 차이는 분명하다.

직접 수행해 본 결과물.

스레드 동기화 옵션을 풀고 tie를 풀어준 결과 224ms에 문제가 통과되었으나, 

해당 옵션을 설정하지 않고 제출한 결과 가차없는 시간 초과...


결론

아무래도 나는 ps를 좀 예전에 했던 것도 있고, 콘솔에서 입출력을 할 때에는 scanf/printf를 자주 사용했다.

이 문제의 경우는 string으로 받아서 hash_map에 넣어 처리하는 게 편할까 싶어 cin/cout을 써봤는데,

생각보다 내가 cpp 사용이 미숙해 예상치 못한 어려움을 겪었다.


덧붙여서 근황.

오늘은 ucpc 2021에 참가해 즐거운 문제풀이 시간을 보냈다.

시간이 나면 그 중 풀었던 문제에 대해 간단한 글을 써볼까도 싶다.

왜 이렇게 잘하는 사람들이 많은지 좌절이 많았던 하루였다.

오예 18등!! 성현정보 파이팅ㅋㅋㅋㅋ

혹시 잘못된 내용이 있다면 지적 부탁드립니다.

반응형

'프로그래밍 > 알고리즘' 카테고리의 다른 글

N Queen 문제의 최적화 방법  (0) 2021.02.05

댓글