C11: sleep for vs yield

코드를 살펴보는데, INLINE_CODE_0 猛的引入眼帘,__INLINE_CODE_1__BOLD_4yield이 처음 보는 것 같고, 예전엔 눈에 띄지 않았던 것 같아요

매뉴얼을 확인하지 않고 가장 먼저 떠오르는 것은 비동기 변환과 관련이 있는지인데, __INLINE_CODE_0__boost 라이브러리의 코루틴 구현에 이 단어가 사용되었으므로 여기서는 코루틴과는 상관없고, 제어 로직은 일반 스레드와 관련이 있는 것 같습니다

문서

yield

이 함수의 정확성은 구현에 의존하며, 특히 사용 중인 OS 스케줄러 메커니즘과 시스템 상태에 따라 달라집니다. 예를 들어, 먼저 온(FIFO) 실시간 스케줄러(Linux의 SCHED_FIFO)는 현재 스레드를 일시 중단하고 동일 우선순위의 다른 스레드가 없는 경우 큐의 맨 뒤로 배치합니다 (다른 스레드가 없으면 yield 효과 없음).

sleep_for

지정된 sleep_duration 동안 현재 스레드의 실행을 차단합니다 이 함수는 스케줄링 지연이나 리소스 충돌로 인해 sleep_duration보다 오래 블록될 수 있습니다 표준 라이브러리는 안정적인 클럭으로 시간을 측정하는 것을 권장합니다. 구현에서 시스템 시간을 사용하면 대기 시간 또한 클럭 조정에 민감할 수 있습니다.

분석

두 함수 모두 현재 스레드를 더 이상 점유하지 않도록 하는 것인데, 실행 결과는 플랫폼에 따라 다를 수 있나? 여기서도 여전히 엉망진창이다. 코드를 실행해서 결과를 확인해 보자.

ThinkPad 노트북(Visual Studio 커뮤니티 에디션 2022), 텐센트 클라우드 S2 표준 서버 (gcc8.5)

실행 플랫폼 함수 1회/μs 2회/μs 3회/μs
Windows sleep_for 9872 1884 11302
Windows yield 119 100 100
Linux sleep_for 171 168 167
Linux yield 101 102 101

운영체제 구현 방식에 따라 고정밀 슬립 모드에서는 __INLINE_CODE_0__稳定性差异巨大,如果想要高精度的休眠,使用__INLINE_CODE_1__이 더 적합합니다

시간 정밀도가 __INLINE_CODE_0__일 때, 두 차이는 뚜렷하지 않다

#include <iostream>
#include <chrono>
#include <thread>
 
// 建议其他线程运行一小段时间的“忙睡眠”
void little_sleep(std::chrono::microseconds us)
{
    auto start = std::chrono::high_resolution_clock::now();
    auto end = start + us;
    do {
        std::this_thread::yield();
    } while (std::chrono::high_resolution_clock::now() < end);
}
 
int main()
{
    auto start = std::chrono::high_resolution_clock::now();
 
    little_sleep(std::chrono::microseconds(100));
    std::this_thread::sleep_for(std::chrono::microseconds(100));
 
    auto elapsed = std::chrono::high_resolution_clock::now() - start;
    std::cout << "waited for "
              << std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()
              << " microseconds\n";
}

참조

Licensed under CC BY-NC-SA 4.0
마지막 수정: 2025년 05월 28일 09:47
금융 IT 프로그래머의 이것저것 만지작거리기와 일상의 중얼거림
Hugo로 만듦
JimmyStack 테마 사용 중