修复伪共享问题
简要示范全流程使用动态源码优化工具对源码文件进行采集分析,以falsesharing_demo.cpp源码文件为例,发现伪共享问题,根据优化建议进行修复并验证修复成功。整体流程如图1所示。
工具基于采集的数据输出热点问题,无法保证扫描出程序中所有的伪共享问题。
前提条件
以动态源码分析工具安装路径“/home/DevKit-Optimizer-CLI-x.x.x-Linux-Kunpeng”为例。
操作步骤
- 定位伪共享问题发生的位置。
- 编译源码文件,生成可执行二进制文件。以源码文件存放路径“/home/test/falsesharing_demo.cpp”为例,请根据实际情况进行修改。
g++ /home/test/falsesharing_demo.cpp -o falsesharing_demo -g -lpthread
falsesharing_demo.cpp文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
#include <sched.h> #include <cstring> #include <pthread.h> #include <stdio.h> #define EXE_TIME 999999990 #define NUM_THREADS 2 int arr[32]; void *sum_a(void*) { int cpu_num = 0; cpu_set_t mask; cpu_set_t get; CPU_ZERO(&mask); CPU_SET(cpu_num, &mask); if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { perror("warning: could not set CPU affinity\n"); } CPU_ZERO(&get); if (sched_getaffinity(0, sizeof(get), &get) == -1) { perror("warning: could not get CPU affinity\n"); } if (CPU_ISSET(cpu_num, &get)) { printf("sum_a affinity cpu_id: %d, current cpu: %d\n", cpu_num, sched_getcpu()); } int s = 0; for (int i = 0; i < EXE_TIME; i++) { s = arr[0]; arr[0] += 1; } } void *inc_b(void*) { int cpu_num = 1; cpu_set_t mask; cpu_set_t get; CPU_ZERO(&mask); CPU_SET(cpu_num, &mask); if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { perror("warning: could not set CPU affinity\n"); } CPU_ZERO(&get); if (sched_getaffinity(0, sizeof(get), &get) == -1) { perror("warning: could not get CPU affinity\n"); } if (CPU_ISSET(cpu_num, &get)) { printf("inc_b affinity cpu_id: %d, current cpu: %d\n", cpu_num, sched_getcpu()); } int s = 0; for (int i = 0; i < EXE_TIME; i++) { s = arr[1]; arr[1] += 1; } } int main() { int ret; pthread_t tids[NUM_THREADS]; ret = pthread_create(&tids[0], NULL, sum_a, NULL); if (ret != 0) { printf("pthread_create error: error code %d\n", ret); return -1; } ret = pthread_create(&tids[1], NULL, inc_b, NULL); if (ret != 0) { printf("pthread_create error: error code %d\n", ret); return -1; } pthread_join(tids[0], NULL); pthread_join(tids[1], NULL); return 0; }
- 在“/home/test”目录执行二进制文件。
1./falsesharing_demo
返回信息如下:inc_b affinity cpu_id: 1, current cpu: 1 sum_a affinity cpu_id: 0, current cpu: 0
- 保持程序运行,进入源码优化工具目录,指定falsesharing_demo进程的
PID ,采集基础性能数据,生成数据文件。cd /home/DevKit-Optimizer-CLI-x.x.x-Linux-Kunpeng ./devopt.sh record -p 3315674 -d 5 -o /home/test
进程PID为3315674,采集时间指定为5s,在“/home/test”下生成数据文件。
返回信息如下:
Saved the record data to /home/test/devopt_3315674_20260513155321.rawdata
- 启用精细化内存采集模式,基于数据文件进行精细化内存分析。
./devopt.sh record -p 3315674 -d 5 -m -i /home/test/devopt_3315674_20260513155321.rawdata
执行上述命令会读取数据文件中的基础性能数据,启动伪共享检测工具进行精细化内存采集,分析检测伪共享问题,将检测结果追加到原始数据文件中。
返回信息如下:
Possible false sharing detected
- 选择以下两种方式之一,查看分析结果。
- 使用script命令查看分析结果。
./devopt.sh script -i /home/test/devopt_3315674_20260513155321.rawdata -t memory
返回信息如下:
FS 1: 0x4009bc <-> 0x400bcc Type:SL CacheLineAddr:0x420040 Access Info: adjacent;+0x20/+0x24;4B/4B A: sum_a(void*)@/home/test/falsesharing_demo:32 B: inc_b(void*)@/home/test/falsesharing_demo:59表1 字段说明 字段
字段说明
FS
FS(False Sharing)表示该事件属于伪共享类型。
1
表示伪共享事件的排序序号,表示伪共享对的分析优先级。
0x4009bc、0x400bcc
访问缓存行的程序计数器地址。
Type
表示内存访问的类型。
- SS(Store-Store)表示两次访问都是写操作。
- SL(Store-Load)表示一次访问是写操作,一次访问是读操作。
CacheLineAddr
缓存行中发生伪共享问题的起始地址。
示例中的“0x420040”为发生伪共享问题的缓存行起始地址。
Access Info
内存访问信息,包括访问的缓存行地址是否相邻,偏移量和访问宽度。
- “adjacent”表示两次访问缓存行的地址相邻。
- “same-line”表示两次访问缓存行的地址不相邻。
示例中的“adjacent”表示两次访问缓存行的地址相邻,“+0x20/+0x24”表示两次访问的偏移量为“+0x20”和“+0x24”,“4B/4B”表示两次访问的宽度都是4字节。
A、32
第一个程序计数器地址对应的函数名和源码行数。
示例中的“A”和“32”表示第一个程序计数器地址(0x4009bc)对应函数名和源码行数。
B、59
第二个程序计数器地址对应的函数名和源码行数。
示例中的“B”和“59”表示第二个程序计数器地址(0x400bcc)对应函数名和源码行数。
- 使用report命令查看分析结果。
./devopt.sh report -i /home/test/devopt_3315674_20260513155321.rawdata
返回信息如下:

总览界面表格区域中各函数的issue列显示值为M,表示该函数检测出了伪共享问题,按Enter键进入明细页面后,建议区域(Code Suggestion)显示源码优化建议。如下图所示。

以sum_a(void*)函数为例,建议区域(Code Suggestion)显示内容如下:
Code Suggestions Memory: FS 1: self=0x4009bc L:32 <-> inc_b(void*) pc=0x400bcc L:59, kind=SL, cacheLine=0x420040, adjacent(+0x20/+0x24, 4B/4B) Suggestion: isolate hot data on separate cache lines using padding or alignas(64), and prefer thread-local or per-thread state with deferred merge or publish to reduce cache-line contention.
以inc_b(void*)函数为例,建议区域(Code Suggestion)显示内容如下:
Code Suggestions Memory: FS1: self=0x400bcc L:59 <-> sum_a(void*) pc=0x4009bc L:33, kind=SL, cacheLine=0x420040, adjacent(+0x20/+0x24, 4B/4B) Suggestion: isolate hot data on separate cache lines using padding or alignas(64), and prefer thread-local or per-thread state with deferred merge or publish to reduce cache-line contention.
字段说明请参见表1。
- 使用script命令查看分析结果。
- 得出结论。
- 源码优化工具检测结果表明:sum_a函数和inc_b函数访问了同一缓存行内两个相邻但不同的4B区域。
- 查看源码,sum_a函数绑定到cpu 0,inc_b函数绑定到cpu 1。 对应伪共享冲突代码行分别频繁读写arr[0]和arr[1],而arr是连续的int数组: int arr[32]。
- arr[0]和arr[1]共享了同一条缓存行,因此触发了典型的伪共享问题。
- 编译源码文件,生成可执行二进制文件。以源码文件存放路径“/home/test/falsesharing_demo.cpp”为例,请根据实际情况进行修改。
- 修改伪共享问题。
修改源码文件,使用padding或alignas(64)隔离。将源码文件中第9行的“int arr[32];”修改为以下内容:
struct alignas(64) Item { int value; char padding[60]; };将源码文件中第32行的“s = arr[0];”和第33行的“arr[0] += 1;”修改为以下内容:
s = arr[0].value; arr[0].value += 1;
将源码文件中第58行的“s = arr[1];”和第59行的“arr[1] += 1;”修改为以下内容:
s = arr[1].value; arr[1].value += 1;
- 验证是否解决伪共享问题。保存修改内容,重新编译运行源码文件,重新执行采集命令。
./devopt.sh record -p 3315674 -d 5 -o /home/test
返回信息如下:
Saved the record data to /home/test/devopt_3315674_20260513155321.rawdata
再次进行精细化内存分析。./devopt.sh record -p 3315674 -d 5 -m -i /home/test/devopt_3315674_20260513155321.rawdata
返回信息如下:
No false sharing detected
显示结果表明分析成功,未检测到伪共享问题。
使用report命令查看分析结果。./devopt.sh report -i /home/test/devopt_3315674_20260513155321.rawdata
返回的总览界面如下图所示。

总览界面的表格区域显示sum_a函数和inc_b函数的issue列未显示M,mem_bound数值下降,进入明细界面未显示源码优化建议,表明伪共享问题已解决。
