相关疑难解决方法(0)

rdtscp,rdtsc:memory和cpuid/rdtsc之间的区别?

假设我们正在尝试使用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)

c c++ performance assembly rdtsc

61
推荐指数
2
解决办法
3万
查看次数

获取CPU周期数?

我在SO上看到这篇文章,其中包含C代码以获取最新的CPU周期数:

基于CPU周期计算的C/C++ Linux x86_64中的分析

有没有办法在C++中使用这个代码(欢迎使用windows和linux解决方案)?虽然用C语言编写(而C是C++的一个子集)但我不太确定这段代码是否适用于C++项目,如果没有,如何翻译呢?

我使用的是x86-64

EDIT2:

找到此功能但无法让VS2010识别汇编程序.我需要包含任何内容吗?(我相信我必须换uint64_tlong 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:'操作码'中的内联汇编语法错误;找到'数据类型'"

有人可以帮忙吗?

c c++ performance x86 rdtsc

26
推荐指数
5
解决办法
4万
查看次数

加载和存储是否只有重新排序的指令?

我已经阅读了很多关于内存排序的文章,并且所有这些文章都只说CPU重新加载和存储.

CPU(我对x86 CPU特别感兴趣)是否仅重新排序加载和存储,并且不重新排序它具有的其余指令?

x86 cpu-architecture memory-barriers

6
推荐指数
2
解决办法
915
查看次数

clflush通过C函数使缓存行无效

我试图用来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)

c performance x86 intrinsics cpu-cache

6
推荐指数
2
解决办法
1088
查看次数

LFENCE是否在AMD处理器上进行序列化?

在最近的英特尔ISA文档中,该lfence指令被定义为序列化指令流(防止指令流无序执行).特别是,该指令的描述包括以下行:

具体来说,LFENCE不会执行,直到所有先前的指令在本地完成,并且在LFENCE完成之前没有后续指令开始执行.

请注意,这适用于所有的指令,不只是内存加载指令,使得lfence 更多的不仅仅是一个存储排序防护.

虽然这现在出现在ISA文档中,但不清楚它是否是"架构",即所有x86实现都遵守,或者它是否特定于Intel.特别是AMD处理器是否也将lfence序列化为指令流?

x86 amd intel cpu-architecture memory-barriers

5
推荐指数
2
解决办法
723
查看次数

NASM中的RDTSCP始终返回相同的值

我正在NASM中使用RDTSC和RDTSCP测量各种汇编语言指令的机器周期,以帮助优化。

我读了Intel的Gabriele Paoloni撰写的“如何在Intel IA-32和IA-64指令集体系结构上对代码执行时间进行基准测试”(2010年9月)和其他Web资源(其中大多数是C语言中的示例)。

使用下面的代码(从C转换),我测试了各种指令,但RDTSCP在RDX中始终返回零,在RAX中始终返回7。我首先认为7是周期数,但显然并非所有指令都需要7个周期。

rdtsc
cpuid
addsd xmm14,xmm1 ; Instruction to time
rdtscp
cpuid
Run Code Online (Sandbox Code Playgroud)

返回7,这并不奇怪,因为在某些体系结构上,添加了7个周期(包括延迟)。前两个指令(根据某些情况)可以颠倒,先是cpuid,然后是rdtsc,但这在这里没有什么区别。

当我将指令更改为2周期指令时:

rdtsc
cpuid
add rcx,rdx ; Instruction to time
rdtscp
cpuid
Run Code Online (Sandbox Code Playgroud)

这还会在rax中返回7,在rdx中返回零。

所以我的问题是:

  1. 如何访问和解释RDX:RAX中返回的值?

  2. 为什么RDX总是返回零,应该返回什么?

更新:

如果我将代码更改为此:

cpuid
rdtsc
mov [start_time],rax
addsd xmm14,xmm1 ; INSTRUCTION
rdtscp
mov [end_time],rax
cpuid
mov rax,[end_time]
mov rdx,[start_time]
sub rax,rdx
Run Code Online (Sandbox Code Playgroud)

我的rax达到了64,但这听起来像是周期太多。

optimization x86-64 nasm rdtsc windows64

3
推荐指数
1
解决办法
186
查看次数

是否有比cpuid更便宜的序列化指令?

我已经看到了相关的问题,包括这里这里,但似乎有关序列化的唯一指令rdtsccpuid.

不幸的是,cpuid我的系统需要大约1000个周期,所以我想知道是否有人知道更便宜(更少的周期和没有读或写内存)序列化指令?

我看着iret,但这似乎改变了控制流程,这也是不可取的.

我实际上看过亚历克斯的答案中关联的白纸rstscp,但它说:

在读取计数器之前,RDTSCP指令等待直到执行了所有先前的指令.然而,后续指令可以在执行读取操作之前开始执行.

第二点似乎是让它不理想.

intel rdtsc cpu-cache

2
推荐指数
2
解决办法
1317
查看次数