본문 바로가기
개발/C++ (98,03,11,14,17,20,23)

Modern C++ : std::chrono 시간 측정 (11, 14, 17, 20)

by snowoods 2025. 9. 5.

Modern C++

시간 측정 (Time Measurement with std::chrono)

 

개요

std::chrono는 C++11에서 도입된 시간 관련 연산을 위한 라이브러리로, 정밀한 시간 측정, 시간 지연, 시간 간격 계산 등을 위한 다양한 유틸리티를 제공합니다. 이 라이브러리는 타입 안전성과 정밀한 시간 제어가 필요한 애플리케이션에 적합합니다.

 

C++ 버전별 주요 키워드 도입 시기

  • C++11: std::chrono 네임스페이스, std::chrono::duration, std::chrono::time_point, std::chrono::system_clock, std::chrono::steady_clock, std::chrono::high_resolution_clock
  • C++14: 시간 리터럴 지원 (1s, 100ms 등)
  • C++17: floor, ceil, round, abs 함수 추가
  • C++20: std::chrono::utc_clock, std::chrono::tai_clock, std::chrono::gps_clock 등 추가

 

내용 설명

std::chrono는 다음과 같은 주요 컴포넌트로 구성됩니다:

  1. 시간 단위 (Durations):
    • std::chrono::duration: 시간의 길이를 나타내는 템플릿 클래스
    • 미리 정의된 단위: nanoseconds, microseconds, milliseconds, seconds, minutes, hours
  2. 시계 (Clocks):
    • std::chrono::system_clock: 시스템의 실시간 시계 (wall-clock)
    • std::chrono::steady_clock: 단조 증가하는 시계 (시간이 절대 감소하지 않음)
    • std::chrono::high_resolution_clock: 가장 높은 정밀도를 제공하는 시계
  3. 시간 포인트 (Time Points):
    • std::chrono::time_point: 특정 시점을 나타내는 클래스
    • 시계와 기간을 조합하여 특정 시점을 표현

 

예제 코드

#include <chrono>
#include <cstdint>
#include <iostream>
#include <random>
#include <vector>

// 사용할 시계 타입 정의
using ClockType = std::chrono::steady_clock;
// 시간 측정 단위 정의 (마이크로초)
using ClockRes = std::chrono::microseconds;

namespace
{
constexpr auto NUM_ELEMENTS = size_t{1'000'000U};
};

int main()
{
    // 1. 벡터 생성 및 0으로 초기화
    auto my_vector = std::vector<std::int32_t>(NUM_ELEMENTS, 0U);

    // 2. 난수 생성기 초기화
    auto seed = std::random_device{};
    auto gen = std::mt19937{seed()};
    auto dist = std::uniform_int_distribution<std::int32_t>{-10, 10};

    // 3. 시간 측정 시작
    const auto start_time = ClockType::now();

    // 4. 벡터에 난수 채우기
    for (std::size_t i = 0; i < my_vector.size(); ++i)
    {
        my_vector[i] = dist(gen);
    }

    // 5. 시간 측정 종료
    const auto end_time = ClockType::now();

    // 6. 경과 시간 계산 및 출력
    const auto elapsed_time =
        std::chrono::duration_cast<ClockRes>(end_time - start_time).count();
    std::cout << "벡터 초기화에 걸린 시간: " << elapsed_time << " 마이크로초\n";

    return 0;
}

 

실행 결과

프로그램을 실행할 때마다 약간 다른 실행 시간이 측정됩니다. 예시 출력:

벡터 초기화에 걸린 시간: 2456 마이크로초

 

활용팁

  1. 시계 선택 가이드:
    • 정확한 경과 시간 측정이 필요할 때: std::chrono::steady_clock
    • 실제 시간이 필요할 때: std::chrono::system_clock
    • 가장 높은 정밀도가 필요할 때: std::chrono::high_resolution_clock
  2. 시간 단위 변환:
  3. auto duration = std::chrono::seconds(120); auto minutes = std::chrono::duration_cast<std::chrono::minutes>(duration); std::cout << minutes.count() << "분\n"; // 2분 출력
  4. 시간 리터럴 (C++14 이상):
  5. using namespace std::chrono_literals; auto timeout = 500ms; // 500 밀리초 auto long_wait = 2h + 30min; // 2시간 30분
  6. 성능 측정 시 주의사항:
    • 벤치마크 시에는 여러 번 실행하여 평균을 내는 것이 좋습니다.
    • 최적화 수준(-O2, -O3 등)에 따라 실행 시간이 크게 달라질 수 있습니다.
    • 첫 실행은 캐시 미스로 인해 더 오래 걸릴 수 있으니, 워밍업 루프를 고려하세요.
  7. 시간 포인트 비교:
  8. auto now = ClockType::now(); // 어떤 작업 수행... auto later = ClockType::now(); if (later > now) { // 시간이 지남 auto elapsed = later - now; std::cout << "경과 시간: " << std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count() << "ms\n"; }
  9. 타임아웃 구현:
  10. auto start = ClockType::now(); auto timeout = 5s; // 5초 타임아웃 while (/* 조건 */) { if (ClockType::now() - start > timeout) { std::cout << "타임아웃!\n"; break; } // 작업 계속... }
  11. duration 반올림/내림/올림 및 절대값 (C++17 이상):
    C++17부터 std::chrono::duration 객체를 더 쉽게 다룰 수 있는 floor, ceil, round, abs 함수가 추가되었습니다.
    • std::chrono::floor<Unit>(d): dUnit 단위로 내림합니다.
    • std::chrono::ceil<Unit>(d): dUnit 단위로 올림합니다.
    • std::chrono::round<Unit>(d): dUnit 단위로 반올림합니다.
    • std::chrono::abs(d): d의 절대값을 구합니다. (C++17부터 duration 지원)
    #include <iostream>
    #include <chrono>
    
    int main() {
        using namespace std::chrono;
        using namespace std::chrono_literals;
    
        auto d = 4500ms; // 4.5초
    
        // 1초 단위로 내림, 올림, 반올림
        auto sec_floor = floor<seconds>(d);
        auto sec_ceil = ceil<seconds>(d);
        auto sec_round = round<seconds>(d);
    
        std::cout << "Original: " << d.count() << "ms\n";
        std::cout << "floor<seconds>: " << sec_floor.count() << "s\n";   // 4s
        std::cout << "ceil<seconds>: " << sec_ceil.count() << "s\n";    // 5s
        std::cout << "round<seconds>: " << sec_round.count() << "s\n";   // 5s
    
        // 음수 duration의 절대값
        auto neg_d = -1500ms;
        auto abs_d = abs(neg_d);
        std::cout << "\nOriginal negative: " << neg_d.count() << "ms\n";
        std::cout << "abs: " << abs_d.count() << "ms\n"; // 1500ms
    }

    실행 결과
  12. Original: 4500ms floor<seconds>: 4s ceil<seconds>: 5s round<seconds>: 5s Original negative: -1500ms abs: 1500ms