linux下cpu多核运行程序以及运行时间统计

一、多核心运行程序

在linux下我们可以指定线程或者进程运行在指定的cpu核心上,操作方法如下:

1)运行进程指定cpu核心

taskset -c 2 ./app //-c指定运行的cpu核心号,从0计数,查看效果如下:

2)运行线程指定cpu核心

主要是设置线程的属性,具体代码如下,详看main函数。

#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>
#include <time.h>void* thread_func0(void* arg) {int iterations = 1000000000; // 迭代次数double a = 3.14159; // 乘法操作的乘数double b = 2.71828; // 乘法操作的被乘数double sum = 0.0; // 加法操作的累加器struct timespec start, end;clock_gettime(CLOCK_MONOTONIC, &start);// 执行乘法运算for (int i = 0; i < iterations; ++i) {double c = a * b;sum += c; // 将乘法结果加到累加器上}clock_gettime(CLOCK_MONOTONIC, &end);double time_spent = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;printf("cpu0 Performed %d in %f seconds\n", iterations, time_spent);printf("cpu0 Resulting sum: %f\n", sum);return NULL;
}void* thread_func1(void* arg) {int iterations = 1000000000; // 迭代次数double a = 3.14159; // 乘法操作的乘数double b = 2.71828; // 乘法操作的被乘数double sum = 0.0; // 加法操作的累加器struct timespec start, end;clock_gettime(CLOCK_MONOTONIC, &start);// 执行乘法运算for (int i = 0; i < iterations; ++i) {double c = a * b;sum += c; // 将乘法结果加到累加器上}clock_gettime(CLOCK_MONOTONIC, &end);double time_spent = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;printf("cpu1 Performed %d in %f seconds\n", iterations, time_spent);printf("cpu1 Resulting sum: %f\n", sum);return NULL;
}int main() {pthread_t thread0, thread1; // 为每个线程使用不同的变量pthread_attr_t attr0, attr1; // 为每个线程属性使用不同的变量unsigned long mask0 = 1UL << 2; // 将线程绑定到CPU核心2unsigned long mask1 = 1UL << 3; // 将线程绑定到CPU核心3// 初始化线程属性pthread_attr_init(&attr0);pthread_attr_init(&attr1);pthread_attr_setaffinity_np(&attr0, sizeof(mask0), &mask0);pthread_create(&thread0, &attr0, thread_func0, NULL);pthread_attr_setaffinity_np(&attr1, sizeof(mask1), &mask1);pthread_create(&thread1, &attr1, thread_func1, NULL);// 等待线程0和线程1完成pthread_join(thread0, NULL);pthread_join(thread1, NULL);return 0;
}

编译后运行效果如下(代码指定了2和3,从0计数):

3)两者的优先级

代码中的线程属性设置cpu核心为2和3,进程以cpu核心0来运行,实际运行在核心2和3上。

测试代码用上述不变,运行命令为:taskset -c 0 ./app

因此,可得结论:在进程和线程都指定运行的cpu核心时,以线程为准。

二、多核心运行的时间测量需要注意的事项

1)多核计时异常

在测试运行时间时,遇到一个问题,最开始我使用的时间测试代码如下:

clock_t start = clock();//测量开始时间
//功能代码
//...
clock_t end = clock();// 测量结束时间
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;

这个代码在测试单核运行的代码时,时间是对的,但是使用多核运行时,发现这个代码统计的时间是我实际手机计时的2倍,怀疑是该函数统计了本程序对所有cpu的占用时间,即双核的时间。

后修改时间测量代码如下:

struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
//功能代码
//...
clock_gettime(CLOCK_MONOTONIC, &end);
double time_spent = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;

测试时间和手机测试的一致。

2)clock()clock_gettime() 比较

clock()clock_gettime() 都是 C 语言标准库中用于获取时间的函数,但它们在用途和行为上有一些重要的区别:

  1. 定义和来源

    • clock() 函数定义在 <time.h> 头文件中,它测量的是程序占用 CPU 的时间(也称为 CPU 时间或处理器时间)。它返回程序启动以来的时钟周期数,这个值是通过处理器的时钟周期来计算的。
    • clock_gettime() 函数是 POSIX.1-2001 标准的一部分,也定义在 <time.h> 中,它提供了更精确的时间测量。它可以测量多种类型的时间,包括实时时间(系统时间)、进程时间、线程时间等。
  2. 时间类型

    • clock() 只能测量程序占用 CPU 的时间。
    • clock_gettime() 可以测量多种时间,通过指定不同的时钟 ID 来获取不同类型的时间。例如:
      • CLOCK_REALTIME:返回以系统实时时间为基础的时间,受系统时间的更改影响。
      • CLOCK_MONOTONIC:返回一个单调时钟,它以系统启动为基础,不受系统时间更改的影响,适合测量时间间隔。
      • CLOCK_PROCESS_CPUTIME_ID:返回调用进程占用的 CPU 时间总和。
      • CLOCK_THREAD_CPUTIME_ID:返回调用线程占用的 CPU 时间。
  3. 精度

    • clock() 的精度受限于系统和硬件,通常以秒为单位,精度较低。
    • clock_gettime() 通常提供更高的精度,可以测量到纳秒级别。
  4. 返回值

    • clock() 返回一个 clock_t 类型的值,表示程序占用 CPU 的时钟周期数。如果失败,返回 ((clock_t) -1)
    • clock_gettime() 成功时返回 0,失败时返回 -1,并设置 errno 以指示错误。
  5. 使用场景

    • clock() 适用于需要测量程序执行时间的场景,但它不适用于测量墙上时钟时间(实际时间)。
    • clock_gettime() 适用于需要高精度时间测量的场景,包括但不限于测量墙上时钟时间、系统时间、进程或线程的 CPU 时间。
  6. 多线程环境

    • 在多线程环境中,clock() 可能无法准确反映单个线程的 CPU 时间,因为它测量的是整个进程的 CPU 时间。
    • clock_gettime() 通过 CLOCK_THREAD_CPUTIME_ID 可以准确测量单个线程的 CPU 时间。
  7. 系统依赖性

    • clock() 是 C 语言标准的一部分,几乎所有的 C 语言环境都支持。
    • clock_gettime() 是 POSIX 标准的一部分,可能在非 POSIX 兼容的系统上不可用或需要特定的编译器标志。

总结来说,clock_gettime() 提供了更多的功能和更高的精度,是现代 C 语言编程中推荐的时间测量函数。而 clock() 由于其较低的精度和对多线程支持的限制,在现代编程中使用较少。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/415273.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

两句话讲清楚离线安装docker镜像

两句话讲清楚离线安装docker镜像 文章目录 两句话讲清楚离线安装docker镜像写在前面解决方案 写在前面 背景&#xff1a;银河麒麟、离线环境&#xff0c;装吧&#xff0c;一装一个不吱声。 准备&#xff1a; 首先&#xff0c;你要有个docker&#xff0c;安装好了才能搞镜像是不…

C++:构造函数与析构函数

一.类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数&#xff0c;如下图&#xff1a; 其中最重要的就是我们表格中的前四个函数&#xff0c;本篇文章我们主要介绍前三个。默认成员函数很重要&#xff0c;也比较复杂…

下载xhsell连接Linux系统

一、下载安装xshell 1、下载 免费版的网址&#xff1a;家庭/学校免费 - NetSarang Website 2、安装 选择自己想要下载的文件夹位置 创建一个新的文件夹即可 不想注册可以直接选择后来先进行试用 二、连接Linux虚拟机 1、点击加号新建会话 2、输入你要连接的虚拟机的IP地址…

4、Django Admin对自定义的计算字段进行排序

通常&#xff0c;Django会为模型属性字段&#xff0c;自动添加排序功能。当你添加计算字段时&#xff0c;Django不知道如何执行order_by&#xff0c;因此它不会在该字段上添加排序功能。 如果要在计算字段上添加排序&#xff0c;则必须告诉Django需要排序的内容。你可以通过在…

【综合架构】Part 5.2 Ansible

使用设备&#xff1a;管理设备-m01-10.0.0.61 1 概述 自动化运维工具&#xff1a;可实现批量管理、批量分发、批量执行、维护... Ansible 是由 Python语言 所编写 2 管理架构 Inventory 主机清单&#xff1a;被管理主机的ip列表、分类。ad-hoc模式&#xff1a;命令行批量管理…

迁移学习之领域偏移(domain shift)

实际应用中很多任务的数据的标注成本很高&#xff0c;无法获得充足的训练数据&#xff0c;这种情况可以 使用迁移学习&#xff08;transfer learning)。假设 A、B 是两个相关的任务&#xff0c;A 任务有很多训练数 据&#xff0c;就可以把从A任务中学习到的某些可以泛化知识迁移…

《信息技术 云计算 边缘云通用技术要求》国家标准发布,九州未来参编

日前&#xff0c;2024年第17号国家标准公告发布&#xff0c;由全国信标委云计算标准工作组组织制定、九州未来作为行业专家单位参编的《信息技术 云计算 边缘云通用技术要求》国家标准正式获批发布。 边缘云作为云计算技术的有效补充和拓展&#xff0c;能够实现将云计算能力拓展…

java常用类

目录 1 String类 1字符串的构造方法&#xff1a; 2.常量池 3 .字符串的比较 1 equals 2 equalsIgnorecase 3.字符串长度&#xff1a; 4.拼接字符串 5.获取单个字符&#xff1a; 6.子字符串的索引&#xff08;首个&#xff09; 7.截取字符串 8.将String的转换为数组&…

设计模式 -- 迭代器模式(Iterator Pattern)

1 问题引出 编写程序展示一个学校院系结构&#xff1a;需求是这样&#xff0c;要在一个页面中展示出学校的院系组成&#xff0c;一个学校有多个学院&#xff0c; 一个学院有多个系 传统方式实现 将学院看做是学校的子类&#xff0c;系是学院的子类&#xff0c;这样实际上是站在…

服务器数据恢复—如何应对双循环RAID5阵列的数据丢失问题?

服务器存储数据恢复环境&#xff1a; 一台存储中有一组由7块硬盘组建的RAID5阵列&#xff0c;存储中还有另外3块盘是raid中掉线的硬盘&#xff08;硬盘掉线了&#xff0c;管理员只是添加一块的新的硬盘做rebuild&#xff0c;并没有将掉线的硬盘拔掉&#xff09;。整个RAID5阵列…

F12控制台输入警告?

信息如下&#xff1a; Warning: Don’t paste code into the DevTools Console that you don’t understand or haven’t reviewed yourself. This could allow attackers to steal your identity or take control of your computer. Please type ‘allow pasting’ below and …

Type-C接口诱骗取电快充方案

Type-C XSP08Q 快充协议芯片是一种新型电源管理芯片&#xff0c;主要负责控制充电电流和电压等相关参数&#xff0c;从而实现快速充电功能。Type-C XSP08Q快充协议是在Type-C接口基础上&#xff0c;加入了XSP08Q协议芯片的支持&#xff0c;很大程度上提升了充电速度。 正常情况…

css实现卡片右上角的状态

1、成品展示 2、html部分 <div class"itemBox"><div class"status">{{ statusList[item.status] }}</div> </div> 3、css部分 .itemBox {position: relative;overflow: hidden; } .status {height: 25px;line-height: 25px;bac…

【实战教程】用 Next.js 和 shadcn-ui 打造现代博客平台

你是否梦想过拥有一个独特、现代化的个人博客平台&#xff1f;今天&#xff0c;我们将一起动手&#xff0c;使用 Next.js 和 shadcn-ui 来创建一个功能丰富、外观精美的博客系统。无论你是刚接触 Web 开发&#xff0c;还是经验丰富的程序员&#xff0c;这个教程都将带你step by…

Linux网络编程 --- Socket编程

前言 首先看看TCP/IP网络协议和在我们计算机系统层次中的对应关系。 socket的位置 网络通信的本质就是贯穿网络协议层的过程。 局域网数据的封装和解包过程 逻辑上我们认为同层协议之间通信 几乎任何层的协议都会提供一种解包和分用的功能。 几乎任何层的协议&#xff…

FPGA实现SDI视频H265压缩网络推流输出,基于VCU架构,支持12G-SDI 4K60帧,提供工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我这里已有的视频图像编解码方案本博已有的 SDI 编解码方案 3、详细设计方案设计框图FPGA开发板视频输入SDI硬件均衡器LMH1219UHD-SDI GT SDI视频解串SMPTE UHD-SDI RX SUBSYSTEM SDI视频解码Video Frame Buffer WriteZynq UltraS…

Apollo Planning模块中的Hybird A*算法

文章目录 流程图OpenSpacePlanner算法与周边模块关系OpenSpacePlanner与PublicRoadPlanner关系Hybird A*流程Hybird A*外部调用入口Hybird A*内部流程 Hybird A*代码逻辑主函数Plan碰撞检测ReedsShepp曲线加速搜索扩展相邻的节点计算节点的代价路径后处理路径分割轨迹平滑&…

android AccessibilityService合法合规增加小红书曝光阅读量(2024-09-02)

免责任声明: 任何可操作性的内容与本人无关,文章内容仅供参考学习&#xff0c;如有侵权损害贵公司利益&#xff0c;请联系作者&#xff0c;会立刻马上进行删除。 一、分析 目前可增加曝光阅读流量渠道入口&#xff08;完成&#xff09; 1. 发现页 打开小红书app选择顶部发现页&…

【网络世界】网络层

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 网络层 &#x1f4c1; IPV4 &#x1f4c2; 什么是IP地址 &#x1f4c2; 网段划分 &#x1f4c2; 特殊IP &#x1f4c2; 内网和公网 &#x1f4c2; IPV4的危机 &#x1f4c1; IP协议格式 &#x1f4c1; 路由 &#x1f…

VSCode+Keil协同开发之Keil Assistant

VSCodeKeil协同开发之Keil Assistant 目录 VSCodeKeil协同开发之Keil Assistant1. 效果展示2. Keil Assistant简介3. Keil Assistant功能特性4. 部署步骤4.1. 部署准备4.2. 安装Keil Assistant插件4.3. 配置Keil Assistant插件 5. Keil Assistant使用6. 总结 大家在单片机开发时…