C/C++性能提升之cache分析

news/2025/2/12 0:48:45/

        在开发过程中,我们有时会碰到程序性能瓶颈,这时候需要我们查找热点代码,借用一些命令、工具去分析自己的程序,下面我就介绍一下如何使用perf工具分析程序的cache命中率。

        在编写代码前先介绍一下我们的硬件平台,我电脑的CPU 是酷睿i7-12700h (14个核20线程),系统ubuntu22.04, 内存16G,大概信息如下:

 

 接下来上我们的代码:

//
// Created by rookie on 23-6-4.
//
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/syscall.h>   /* For SYS_xxx definitions */#if  0
struct multi_var
{volatile int threadAVar;volatile int threadBVar;
}g_multi_var __attribute__((aligned(64)));
#else
struct multi_var
{volatile int threadAVar __attribute__((aligned(64)));volatile int threadBVar __attribute__((aligned(64)));
}g_multi_var;
#endifstatic const char *usage_str = "test cache\r\n";
static void usage()
{printf("%s", usage_str);
}void test_cpu_performance(unsigned  int cpu)
{float f1 = 1.2;double db1 = 2.3;int i;int count = 0;int n = 0, n1 = 0;double d = 1;struct timeval a1, a2;gettimeofday(&a1, NULL);if(cpu == 0){count = 0;while (count++ <= 100){for (n = 1; n < 1024*1024; ++n) {g_multi_var.threadAVar += n;}}} else if(cpu == 1){count = 0;while (count++ <= 100){for (n = 1; n < 1024*1024; ++n) {g_multi_var.threadBVar += n;}}}gettimeofday(&a2, NULL);long time = 1000000*(a2.tv_sec-a1.tv_sec)+a2.tv_usec-a1.tv_usec;printf("cpu = %d,time = %ld exit\r\n", cpu, time);
}static int set_cpu_affinity(unsigned int cpu)
{cpu_set_t cpuset;pid_t tid = syscall(SYS_gettid);CPU_ZERO(&cpuset);CPU_SET(cpu, &cpuset);printf("before sched setaffinity cpu=%d\r\n", cpu);if(sched_setaffinity(tid, sizeof(cpuset), &cpuset) < 0){perror("sched setaffinity");printf("cpu %d\r\n", cpu);return -1;}printf("pid = %d, after sched setaffinity cpu=%d\r\n", tid, cpu);return 0;
}
static void* wast_cpu_body(void* arg)
{int i = 2;unsigned  int cpu = *(unsigned int *)arg;printf("wast_cpu_body in cpu=%d\r\n", cpu);set_cpu_affinity(cpu);test_cpu_performance(cpu);return NULL;
}int main(int argc, char* argv[])
{pthread_t *thread;int cpunum = 4;int ret = 0;int j = 0;int *icpu = NULL;pthread_attr_t *attr = NULL;void *p_arg = NULL;if(argc > 2){usage();}else if(argc == 2){cpunum = atoi(argv[1]);thread = malloc(sizeof(*thread) * cpunum);attr = malloc(sizeof(*attr) * cpunum);icpu = malloc(sizeof(*icpu) * cpunum);for (j = 0; j < cpunum; ++j) {ret = pthread_attr_init(&attr[j]);
//        ret |= pthread_attr_setdetachstate(&attr[j], PTHREAD_CREATE_DETACHED);icpu[j] = j;ret |= pthread_create(&thread[j], &attr[j], (void*(*)(void*))wast_cpu_body, &icpu[j]);printf("cpu index = %d\r\n", j);}for (j = 0; j < cpunum; ++j) {pthread_join(thread[j], NULL);}for (j = 0; j < cpunum; ++j) {pthread_attr_destroy(&attr[j]);}free(icpu);free(thread);free(attr);}return ret;
}

这里说明一下,关于代码中的__attribute__((aligned(64)))  对齐字节数为什么选择64?

这是由于我电脑的CPU的CACHE_LINE就是64,具体可以使用getconf命令查看

接下来我们编译出来两个可执行文件,test_cache0test_cache1,与上述条件判断的对应关系如下: 

//test_cache1 !!!!
struct multi_var
{volatile int threadAVar;volatile int threadBVar;
}g_multi_var __attribute__((aligned(64)));//test_cache0 !!!!
struct multi_var
{volatile int threadAVar __attribute__((aligned(64)));volatile int threadBVar __attribute__((aligned(64)));
}g_multi_var;

 然后我们使用perf检测它们执行的情况

sudo perf stat -e L1-dcache-load-misses,L1-icache-load-misses,L1-dcache-load,L1-dcache-stores,branch-load-miss,branch-loads  ./test_cache0 10sudo perf stat -e L1-dcache-load-misses,L1-icache-load-misses,L1-dcache-load,L1-dcache-stores,branch-load-miss,branch-loads  ./test_cache1 10

通过上述信息我们发现0方式比 1方式运行的时间少了几乎50%

0方式的 cpu_core/L1-dcache-load-misses/  是36,246 , cpu_core/L1-dcache-load/ 是848,148,941,命中率为0.999957265

1方式的 cpu_core/L1-dcache-load-misses/  是38,540 , cpu_core/L1-dcache-load/ 是848,192,764,命中率为0.999954562

所以我们写代码时应该多注意对齐、以及cache这些问题,感兴趣的同学还可以多试试不以64对齐的情况

 


http://www.ppmy.cn/news/218191.html

相关文章

支持bt,种子,torrent的离线下载网页版工具!

曾几何时&#xff0c;迅雷离线&#xff0c;QQ离线&#xff0c;115离线&#xff0c;多么的风靡&#xff0c;现在基本上都用不成了。。 最近发现国外有一个非常好的离线下载工具&#xff0c;在线版的&#xff0c;非常给力。 重点&#xff1a; 点我进入 &#xff0c;当然&#x…

百度网盘如何下载下载ed2k链接

ed2k是电驴的链接&#xff0c;能下载的软件很多的 可以如下方法&#xff1a; 1、首先进入百度网盘首页&#xff1b; 2、找到“离线下载”功能&#xff1b; 3、然后点击一下&#xff0c;找到下拉菜单的“新建普通任务”&#xff1b; 4、然后弹出一个对话框&#xff1b; 5、找到…

ed2k链接文件,最快下载方式

今天要下载 ed2k://|file|ZRMPSEL_CN.iso|402690048|00D1BDA0F057EDB8DA0B29CF5E188788|/文件&#xff0c;搞了一圈&#xff0c;发现迅雷能下载&#xff0c;怎么做个备忘。 分享如下:

ED2K的资源链接如何进行下载?

ed2k是分布式的&#xff0c;下载它需要有一个链接&#xff0c;相信来看的一般都是已经找到链接的吧。 例如&#xff1a;ed2k://|file|xxxxxxx|xxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|/ 这种形式的。 复制你需要的一条链接&#xff0c;然后打开任意一个下载软件&#xff0c…

ed2k文件下载方法

之前可以用百度网盘的离线下载进行操作&#xff0c;但现在行不通了&#xff0c;听我的别乱尝试&#xff0c;直接下个迅雷&#xff0c;复制了ed2k链接之后就直接弹出窗口下载

ed2k如何下载

ed2k全称叫“eDonkey2000 network”&#xff0c;是一种文件共享网络&#xff0c;最初用于共享音乐、电影和软件。与多数文件共享网络一样&#xff0c;它是分布式的&#xff1b;文件基于P2P原理存放于用户的电脑上而不是存储于一个中枢服务器。而此类链接对我们的意义则是&#…

NDM下载器

NDM下载器 异次元介绍NDM下载器的文章&#xff1a;https://www.iplaysoft.com/ndm.html 官网软件下载地址&#xff1a; http://www.neatdownloadmanager.com/index.php/en/?utm_sourceiplaysoft.com&hmsriplaysoft.com 打开界面如下&#xff1a;

Internet Download Manager(最新版win/mac)最快下载器工具使用教程

IDM下载器全称Internet Download Manager&#xff0c;idm是一款超级好用的下载工具。几乎支持所有文件格式下载&#xff0c;可以完美替代迅雷&#xff0c;idm没有广告&#xff0c;也更加轻便&#xff0c;安装没有太大的体积&#xff0c;非常好用。目前来说最终要的功能要数idm可…