考虑:
#include <time.h>
#include <unistd.h>
#include <iostream>
using namespace std;
const int times = 1000;
const int N = 100000;
void run() {
for (int j = 0; j < N; j++) {
}
}
int main() {
clock_t main_start = clock();
for (int i = 0; i < times; i++) {
clock_t start = clock();
run();
cout << "cost: " << (clock() - start) / 1000.0 << " ms." << endl;
//usleep(1000);
}
cout << "total cost: " << …
Run Code Online (Sandbox Code Playgroud) 假设我们正在尝试使用tsc进行性能监控,我们希望防止指令重新排序.
这些是我们的选择:
1: rdtscp
是序列化调用.它可以防止对rdtscp的调用进行重新排序.
__asm__ __volatile__("rdtscp; " // serializing read of tsc
"shl $32,%%rdx; " // shift higher 32 bits stored in rdx up
"or %%rdx,%%rax" // and or onto rax
: "=a"(tsc) // output to tsc variable
:
: "%rcx", "%rdx"); // rcx and rdx are clobbered
Run Code Online (Sandbox Code Playgroud)
但是,rdtscp
仅适用于较新的CPU.所以在这种情况下我们必须使用rdtsc
.但是rdtsc
非序列化,因此单独使用它不会阻止CPU重新排序.
所以我们可以使用这两个选项中的任何一个来防止重新排序:
2:这是一个电话cpuid
然后rdtsc
.cpuid
是一个序列化的电话.
volatile int dont_remove __attribute__((unused)); // volatile to stop optimizing
unsigned tmp;
__cpuid(0, tmp, tmp, tmp, …
Run Code Online (Sandbox Code Playgroud) 我在SO上看到这篇文章,其中包含C代码以获取最新的CPU周期数:
基于CPU周期计算的C/C++ Linux x86_64中的分析
有没有办法在C++中使用这个代码(欢迎使用windows和linux解决方案)?虽然用C语言编写(而C是C++的一个子集)但我不太确定这段代码是否适用于C++项目,如果没有,如何翻译呢?
我使用的是x86-64
EDIT2:
找到此功能但无法让VS2010识别汇编程序.我需要包含任何内容吗?(我相信我必须换uint64_t
到long long
窗户......?)
static inline uint64_t get_cycles()
{
uint64_t t;
__asm volatile ("rdtsc" : "=A"(t));
return t;
}
Run Code Online (Sandbox Code Playgroud)
EDIT3:
从上面的代码我得到错误:
"错误C2400:'操作码'中的内联汇编语法错误;找到'数据类型'"
有人可以帮忙吗?
我希望能够%rbp
在内联asm中使用基指针寄存器().这样的玩具示例是这样的:
void Foo(int &x)
{
asm volatile ("pushq %%rbp;" // 'prologue'
"movq %%rsp, %%rbp;" // 'prologue'
"subq $12, %%rsp;" // make room
"movl $5, -12(%%rbp);" // some asm instruction
"movq %%rbp, %%rsp;" // 'epilogue'
"popq %%rbp;" // 'epilogue'
: : : );
x = 5;
}
int main()
{
int x;
Foo(x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望,因为我使用通常的序幕/结尾函数调用方法来推送和弹出旧的%rbp
,这样就可以了.但是,当我尝试在内x
联asm之后访问时,它会出现故障.
GCC生成的汇编代码(略微剥离)是:
_Foo:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
# INLINEASM
pushq %rbp; // prologue
movq %rsp, …
Run Code Online (Sandbox Code Playgroud) 我已经阅读了很多关于内存排序的文章,并且所有这些文章都只说CPU重新加载和存储.
CPU(我对x86 CPU特别感兴趣)是否仅重新排序加载和存储,并且不重新排序它具有的其余指令?
我试图用来clflush
手动驱逐缓存行,以确定缓存和行大小.我没有找到任何关于如何使用该指令的指南.我所看到的,是一些使用更高级别功能的代码.
有一个内核函数void clflush_cache_range(void *vaddr, unsigned int size)
,但我仍然不知道在我的代码中包含什么以及如何使用它.我不知道size
该功能是什么.
更重要的是,我怎样才能确定该行被驱逐以验证我的代码的正确性?
更新:
这是我想要做的初始代码.
#include <immintrin.h>
#include <stdint.h>
#include <x86intrin.h>
#include <stdio.h>
int main()
{
int array[ 100 ];
/* will bring array in the cache */
for ( int i = 0; i < 100; i++ )
array[ i ] = i;
/* FLUSH A LINE */
/* each element is 4 bytes */
/* assuming that cache line size is 64 bytes */
/* array[0] till …
Run Code Online (Sandbox Code Playgroud) 在最近的英特尔ISA文档中,该lfence
指令被定义为序列化指令流(防止指令流无序执行).特别是,该指令的描述包括以下行:
具体来说,LFENCE不会执行,直到所有先前的指令在本地完成,并且在LFENCE完成之前没有后续指令开始执行.
请注意,这适用于所有的指令,不只是内存加载指令,使得lfence
更多的不仅仅是一个存储排序防护.
虽然这现在出现在ISA文档中,但不清楚它是否是"架构",即所有x86实现都遵守,或者它是否特定于Intel.特别是AMD处理器是否也将lfence
序列化为指令流?
x86 ×5
c++ ×4
performance ×4
c ×3
assembly ×2
rdtsc ×2
amd ×1
benchmarking ×1
cpu-cache ×1
intel ×1
intrinsics ×1
linux ×1
red-zone ×1