- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试了解使用 CLFLUSH 对性能的影响。为此,我写了一个小指针追逐基准测试。我拿 std::vector<std::pair<size_t, size_t>>
其中第一个元素是下一个条目的偏移量,第二个元素是有效载荷。我从条目 0 转到下一个条目,依此类推,直到到达开头。在路上,我计算了所有有效载荷的总和。
另外,我有两个参数:If write==1
,我在读取后修改了有效负载(从而使缓存行无效)。如果clflush==1
, 我执行 CLFLUSH
在进入下一个元素之前。
vector 的大小等于 L1 缓存的大小 (32 KiB)。
这是我的结果:
write clflush runtime
0 0 5324060
0 1 298751237
1 0 4366570
1 1 180303091
我确实理解为什么使用 clflush 时运行速度比不使用时慢。但为什么读+写比写快,为什么它看起来比 CLFLUSH
快脏缓存行比干净缓存行?
作为引用,你可以找到我的基准here ,我使用 g++-4.8 -std=c++11 -lrt -O3
编译了它.
最佳答案
这可能不像一个答案,但我不认为您看到的效果是真实的。这是我在 Haswell i7-4770 上使用一些不同的编译器运行您的测试程序时看到的内容:
nate@haswell:~/stack$ chase-g481-orig
write clflush runtime
0 0 3238411
0 1 55916728
1 0 3220700
1 1 88299263
nate@haswell:~/stack$ chase-icpc-orig
write clflush runtime
0 0 3226673
0 1 53840185
1 0 4858013
1 1 88143220
nate@haswell:~/stack$ chase-clang-orig
write clflush runtime
0 0 13521595
0 1 54542441
1 0 3394006
1 1 88344640
它们之间有很多差异,但与您所看到的完全不符。我还在 Sandy Bridge E5-1620 上运行并发现了与这些相似的结果(与你的不匹配),尽管该机器上的旧版本的 clang++ 没有在 no-write no-flush 情况下爆炸。
首先,您的程序试图使用整个 L1 缓存有点尴尬。如果您可以完全控制系统(在启动时保留 CPU),这可能是合理的,但它似乎可能会引入混淆效果。如果您的目标是了解这种效果而不是查看缓存在满容量时的行为方式,我建议您将总大小更改为缓存大小的 1/2 或更少。
我认为最可能的解释是,不同的编译器将 clflush 提升到函数中的不同位置,其中一些并没有按照您的预期进行。当你在这个级别工作时,要真正说服编译器做你想做的事情是非常困难的。由于 clflush 内在函数实际上并没有改变结果,因此优化器规则通常会破坏您的意图。
我尝试查看生成的程序集 (objdump -d -C chase),但无法找到方向。一切都直接内联到 main 中,所以它不仅仅是查看 chase() 函数来查看发生了什么那么简单。使用 -g(用于调试)编译并向 objdump 命令添加 -S(用于源代码)有帮助,但仍然很复杂。我阻止编译器内联的尝试失败了。
如果是我,我会切换到 C 并使用 -fno-inline-functions 进行编译,然后检查是否仍能获得相同的效果。然后剖析 chase() 函数,直到您了解发生了什么。然后用gcc -S输出程序集,修改到顺序正确,看效果是否还在。
还值得注意的是,根据英特尔架构引用手册,clflush 不是序列化指令。即使汇编按照您认为应该的顺序进行,处理器执行之前和之后的指令也是公平的。考虑到你追逐的方式,我认为窗口不够宽,不能成为一个因素,但谁知道呢。您可以通过添加 mfence 来强制序列化。
另一种可能性是 clflush 在您的特定处理器上表现异常。您可以切换使用“wbinvd”的核选项以使所有缓存无效。这是一条很难执行的指令,因为它是“特权”指令,需要由内核执行。你必须写一个 ioctl 来做到这一点。
祝你好运!
关于c++ - 指针追逐基准 : Read+Write(+CLFLUSH) faster than Read(+CLFLUSH),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23429479/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
指针, C语言的精髓 莫队先咕几天, 容我先讲完树剖 (因为后面树上的东西好多都要用树剖求 LCA). 什么是指针 保存变量地址的变量叫做指针. 这是大概的定义, 但是Defad认为
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我是一名优秀的程序员,十分优秀!