【发布时间】:2021-03-15 12:57:11
【问题描述】:
我一直在 x86 上尝试一些实验 - 即 mfence 对存储/加载延迟等的影响。
这是我开始的:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define ARRAY_SIZE 10
#define DUMMY_LOOP_CNT 1000000
int main()
{
char array[ARRAY_SIZE];
for (int i =0; i< ARRAY_SIZE; i++)
array[i] = 'x'; //This is to force the OS to give allocate the array
asm volatile ("mfence\n");
for (int i=0;i<DUMMY_LOOP_CNT;i++); //A dummy loop to just warmup the processor
struct result_tuple{
uint64_t tsp_start;
uint64_t tsp_end;
int offset;
};
struct result_tuple* results = calloc(ARRAY_SIZE , sizeof (struct result_tuple));
for (int i = 0; i< ARRAY_SIZE; i++)
{
uint64_t *tsp_start,*tsp_end;
tsp_start = &results[i].tsp_start;
tsp_end = &results[i].tsp_end;
results[i].offset = i;
asm volatile (
"mfence\n"
"rdtscp\n"
"mov %%rdx,%[arg]\n"
"shl $32,%[arg]\n"
"or %%rax,%[arg]\n"
:[arg]"=&r"(*tsp_start)
::"rax","rdx","rcx","memory"
);
array[i] = 'y'; //A simple store
asm volatile (
"mfence\n"
"rdtscp\n"
"mov %%rdx,%[arg]\n"
"shl $32,%[arg]\n"
"or %%rax,%[arg]\n"
:[arg]"=&r"(*tsp_end)
::"rax","rdx","rcx","memory"
);
}
printf("Offset\tLatency\n");
for (int i=0;i<ARRAY_SIZE;i++)
{
printf("%d\t%lu\n",results[i].offset,results[i].tsp_end - results[i].tsp_start);
}
free (results);
}
我用gcc microbenchmark.c -o microbenchmark 编译很简单
我的系统配置如下:
CPU : Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
Operating system : GNU/Linux (Linux 5.4.80-2)
我的问题是这样的:
- 在一次运行中,所有延迟都相似
- 反复重复实验时,我没有得到与上一次类似的结果!
例如:
In run 1 I get:
Offset Latency
1 275
2 262
3 262
4 262
5 275
...
252 275
253 275
254 262
255 262
In another run I get:
Offset Latency
1 75
2 75
3 75
4 72
5 72
...
251 72
252 72
253 75
254 75
255 72
这非常令人惊讶(运行间变化非常高,而运行内变化可以忽略不计)!我不知道如何解释这一点。我的微基准有什么问题?
注意:我确实知道普通存储将是 write allocate 存储。从技术上讲,我的测量是负载(而不是存储)。此外,mfence 应该刷新存储缓冲区,从而确保没有存储被“延迟”。
【问题讨论】:
-
您的预热虚拟循环仅进行 100 万次迭代,在
-O0调试构建中约 6 百万个时钟周期 - 可能不足以让 CPU 在 CPU 上达到最大涡轮增压在 Skylake 的硬件 P 状态管理之前。 (Idiomatic way of performance evaluation?) RDTSCP 计算固定频率参考周期,而不是核心时钟周期。您的运行时间如此之短,以至于所有运行之间的变化都可能由 CPU 频率低或高来解释。见How to get the CPU cycle count in x86_64 from C++?
标签: c performance assembly x86 cpu-architecture