如何在C++中让程序占用指定时长的CPU时间(排除离线时间)
如何编写累计占用指定CPU时间的程序(排除离线时间)
你的问题核心是混淆了墙钟时间和CPU时间:std::chrono::high_resolution_clock统计的是从程序启动到现在的实际流逝时间(包含sleep、上下文切换等不占用CPU的离线时间),而你需要统计的是线程/进程实际占用CPU执行指令的时间。
下面分平台给出解决方案:
POSIX平台(Linux、macOS等)
使用clock_gettime函数,指定CLOCK_THREAD_CPUTIME_ID(统计当前线程的CPU时间)或CLOCK_PROCESS_CPUTIME_ID(统计整个进程的CPU时间),这些时钟只会统计线程/进程实际在CPU上运行的时间,sleep、上下文切换等离线时间不会被计入。
修改后的代码:
#include <chrono> #include <thread> #include <iostream> #include <cmath> #include <time.h> int main() { struct timespec start_cpu; // 初始化当前线程的CPU时间起点 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start_cpu); while (true) { struct timespec current_cpu; clock_gettime(CLOCK_THREAD_CPUTIME_ID, ¤t_cpu); // 计算累计占用的CPU时间(转换为秒) double elapsed_cpu = (current_cpu.tv_sec - start_cpu.tv_sec) + (current_cpu.tv_nsec - start_cpu.tv_nsec) / 1e9; if (elapsed_cpu >= 5.0) { break; } // 执行消耗CPU的计算任务 volatile double d = 0; for (int n = 0; n < 10000; ++n) { d += std::sqrt(n); } std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "wake" << std::endl; } std::cout << "累计CPU时间已达5秒" << std::endl; return 0; }
编译时需链接实时库(部分新版本GCC可省略):g++ -o cpu_time cpu_time.cpp -lrt
Windows平台
使用GetThreadTimes函数,获取线程的内核态和用户态CPU时间,两者之和就是线程实际占用的CPU时间,同样不会包含离线时间。
修改后的代码:
#include <chrono> #include <thread> #include <iostream> #include <cmath> #include <windows.h> int main() { FILETIME create_time, exit_time, kernel_time, user_time; // 获取当前线程的初始CPU时间 GetThreadTimes(GetCurrentThread(), &create_time, &exit_time, &kernel_time, &user_time); // 辅助函数:将FILETIME转换为微秒 auto filetime_to_us = [](FILETIME ft) -> uint64_t { return (static_cast<uint64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime; }; uint64_t start_cpu = filetime_to_us(kernel_time) + filetime_to_us(user_time); while (true) { GetThreadTimes(GetCurrentThread(), &create_time, &exit_time, &kernel_time, &user_time); uint64_t current_cpu = filetime_to_us(kernel_time) + filetime_to_us(user_time); // 计算累计CPU时间(FILETIME单位是100纳秒,转换为秒) double elapsed_cpu = (current_cpu - start_cpu) / 1e6; if (elapsed_cpu >= 5.0) { break; } // 消耗CPU的计算任务 volatile double d = 0; for (int n = 0; n < 10000; ++n) { d += std::sqrt(n); } std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "wake" << std::endl; } std::cout << "累计CPU时间已达5秒" << std::endl; return 0; }
核心逻辑说明
- 不管是主动调用
sleep让出CPU,还是被动被操作系统上下文切换,这些时间段内线程并未占用CPU执行指令,所以对应的CPU时间统计不会增加 - 只有当线程在执行计算任务时,CPU时间才会累计,直到达到你设定的5秒配额
内容的提问来源于stack exchange,提问作者Frontier_Setter
相关产品推荐
相关产品推荐

