각 언어별 input method 비교

  • bupjae
    bupjae

    golang 에서의 시간 초과 오류 사태를 맞이한 후 여기저기 떠돌다가 입력 방식에 따라 시간 차이가 클 수 있다는 취지의 글을 보게 되었습니다.

    이 글을 보고, 입력 방식에 따른 시간을 재 보게 되었습니다.

    • 입력: 10,000,000 개의 0~1023 범위의 정수; 한 줄에 하나의 정수가 주어진다.
    • 출력: 입력으로 받은 정수의 합
    • 측정 방식: time [execute cmdline] < input.txt
    • 테스트 환경:
      • Intel® Xeon(R) CPU E5-1650 0 @ 3.20GHz × 12
      • 32GB ram
      • ubuntu 14.04
    • 컴파일 환경
      • C/C++: g++ 4.8.2
      • Java: OpenJDK 1.7.0 64-bit
      • go: go1.3 linux/amd64
    언어 입력방식 수행시간(초)
    C/C++ scanf 0.798
    C/C++ getchar(*) 0.390
    C++ std::cin 2.051
    C++ std::ios::sync_with_stdio(false) + std::cin 0.796
    java java.util.Scanner 6.068
    java java.io.BufferedReader(*) 0.934
    golang fmt.Scan 44.557
    golang bufio.Reader + fmt.Fscan 9.899
    golang bufio.Scanner(*) 1.299

    (*): 문자(열) -> 정수 변환 필요

    제가 처음에 시도한 방식이라면 시간 초과 오류가 날 수 밖에 없는 것 같습니다.
    아울러, 혹시 java 쓰시는 분이 계시다면, java.util.Scanner 역시 피하시는게 좋을 것 같습니다. (내부적으로 regex를 매우 많이 이용하기 때문인 것으로 보입니다)

    수정 이력:

    • chongkong님의 제안으로 std::ios::sync_with_stdio(false)+std::cin 를 추가했습니다.
    • ipkn님의 제안으로 컴파일 환경을 추가했습니다.
    • chongkong님의 제안으로 getchar를 추가했습니다.

    10년 전
13개의 댓글이 있습니다.
  • wookayin
    wookayin

    이 글을 위키로!!


    10년 전 link
  • 일루
    일루

    입력사이즈가 큰 많은 문제들에 'std::cin은 느릴 수 있으니 scanf를 사용하세요' 라는 주의문구가 써 있는 것을 생각한다면 1.299도 좀 위험할지도 모르겠네요 :)


    10년 전 link
  • chongkong
    chongkong

    cin을 사용할 때 std::ios::sync_with_stdio(false)를 하면 빨라지는 걸로 알고 있는데 이 점도 혹시 비교대상이 넣어주실 수 있나요 ㅎㅎ


    10년 전 link
  • wookayin
    wookayin

    시간 측정용(?) 레퍼런스 문제를 만들어서 거기에 코드를 올리고 소요시간을 submission 리스트로 관리해보는건 혹시 어떨까요!


    10년 전 link
  • bupjae
    bupjae

    chongkong // sync_with_stdio(false) 상태에서 같은 프로그램을 수행해봤습니다. 확실히 성능이 훨씬 좋아져서 scanf 에 근접했습니다.


    10년 전 link
  • ipkn
    ipkn

    컴파일러 버전도 있어야하지않을까요?


    10년 전 link
  • kcm1700
    kcm1700

    cout에서 endl 사용하면 많이 느립니다. C++ 표준에서는 endl이 있으면 flush를 강제한다고 합니다.

    27.7.3.8 Standard basic_ostream manipulators [ostream.manip]

    Effects: Calls os.put(os.widen(’\n’)), then os.flush()


    10년 전 link
  • kwangswei
    kwangswei

    좋아요 있으면 한 열번 쯤 누르고 싶군요!! 짝짝짝


    10년 전 link
  • kwangswei
    kwangswei

    덧붙여 wookayin 님 아이디어 좋은 것 같습니다!


    10년 전 link
  • chongkong
    chongkong

    일일히 getchar로 파싱하는 경우도 비교해주실 수 있나요?
    inline int getint() {
    int ret = 0, ch;
    for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar());
    for (ret = ch - '0', ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar()) {
    ret = ret * 10 + ch - '0';
    }

    return ret;

    }


    10년 전 link
  • bupjae
    bupjae

    chongkong // 역시 직접 한 글자씩 읽는 속도는 못 따라오는군요


    10년 전 link
  • zzapcoder
    zzapcoder

    아니 이런 방법이?!


    10년 전 link
  • cjkis
    cjkis

    cin은 자바한테도 밀리네 ㅋ_ㅋ


    10년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.