相关疑难解决方法(0)

在现代(流水线/超标量)处理器上执行x86 rep指令

我最近一直在写x86程序集(为了好玩),并且想知道rep前缀字符串指令是否实际上在现代处理器上具有性能优势,或者它们是否刚刚实现了后向兼容性.

我理解为什么当处理器一次只运行一条指令时,英特尔最初会实现代表指令,但现在使用它们有什么好处?

通过循环可以编译更多指令,还有更多要填充管道和/或无序发布.现代处理器是为优化这些重复前缀指令而构建的,还是在现代代码中很少使用的rep指令,它们对制造商来说并不重要?

performance x86 assembly pipeline

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

优化的memcpy

在C++中有没有更快的memcpy()替代品?

c++ optimization memcpy

17
推荐指数
5
解决办法
1万
查看次数

英特尔内存模型是否使SFENCE和LFENCE冗余?

英特尔内存模型保证:

  • 商店不会与其他商店重新订购
  • 载荷不会与其他载荷重新订购

http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/

我已经看到声称由于Intel内存模型,SFENCE在x86-64上是多余的,但从来没有LFENCE.上述内存模型规则是否使指令冗余?

optimization x86 assembly atomic memory-barriers

15
推荐指数
1
解决办法
1355
查看次数

什么是_mm_prefetch()位置提示?

内部函数导说,只有这么多关于void _mm_prefetch (char const* p, int i):

从包含地址p的内存中获取数据行到由locality hint i指定的缓存层次结构中的位置.

你能列出int i参数的可能值并解释它们的含义吗?

我发现_MM_HINT_T0,_MM_HINT_T1,_MM_HINT_T2,_MM_HINT_NTA_MM_HINT_ENTA,但我不知道这是否是一个详尽的列表和它们的含义.

如果特定于处理器,我想知道他们在Ryzen和最新的英特尔酷睿处理器上做了什么.

c++ x86-64 prefetch intrinsics cpu-cache

15
推荐指数
1
解决办法
7077
查看次数

我什么时候应该使用_mm_sfence _mm_lfence和_mm_mfence

我阅读了"英特尔架构的英特尔优化指南指南".

但是,我仍然不知道何时应该使用

_mm_sfence()
_mm_lfence()
_mm_mfence()
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释在编写多线程代码时何时应该使用它们?

c++ x86 multithreading intrinsics memory-barriers

14
推荐指数
3
解决办法
6488
查看次数

rep stosb指令如何比等效循环执行得更快?

指令如何rep stosb比这段代码执行得更快?

    Clear: mov byte [edi],AL       ; Write the value in AL to memory
           inc edi                 ; Bump EDI to next byte in the buffer
           dec ecx                 ; Decrement ECX by one position
           jnz Clear               ; And loop again until ECX is 0
Run Code Online (Sandbox Code Playgroud)

在所有现代CPU上都能保证这一点吗?我是否应该总是喜欢使用rep stosb而不是手动编写循环?

optimization performance x86 assembly micro-optimization

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

REP做什么设置?

引用英特尔 ®64 和IA-32架构优化参考手册,§2.4.6"REP String Enhancement":

使用REP字符串的性能特征可归因于两个组件: 启动开销和数据传输吞吐量.

[...]

对于较大粒度数据传输的REP字符串,随着ECX值的增加,REP String的启动开销呈逐步增加:

  • 短串(ECX <= 12):REP MOVSW/MOVSD/MOVSQ的延迟约为20个周期,
  • 快速字符串(ECX> = 76:不包括REP MOVSB):处理器实现通过移动尽可能多的16字节数据来提供硬件优化.如果其中一个16字节数据传输跨越缓存行边界,则REP字符串延迟的延迟会有所不同:

    • 无拆分:延迟包括大约40个周期启动成本,每个64字节的数据增加4个周期,
    • 高速缓存拆分:延迟包括大约35个周期启动成本,每64个字节的数据增加6个周期.
  • 中间字符串长度:REP MOVSW/MOVSD/MOVSQ的延迟具有大约15个周期启动成本加上word/dword/qword中数据移动的每次迭代的一个周期.

(强调我的)

没有进一步提及这种启动成本.它是什么?它做了什么,为什么总是需要更多的时间?

optimization performance x86 assembly

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

关于x86字符串指令性能的可靠信息?

常见的widsom 在执行相同的操作时rep movsbrep movsd(或在64位上rep movsq)慢得多.但是,我已经在一些现代机器上进行了测试,并且在大量缓冲区大小(10字节到2兆)之间的运行时间相同(达到测量噪声).到目前为止,我刚刚在2台机器(32位Intel Atom D510和64位AMD FX 8120)上进行了测试.

  • 是否有rep movsbrep movsd(或rep movsq)更慢的现代x86(32位或64位)机器?

  • 如果没有,那么差异显着的最后一台机器是什么,它有多重要?

我想从这个问题的角度来看这个问题是为了避免货物过多的一系列测试将记忆分解成未对齐的头/尾和对齐中间以便使用rep movsd或者rep movsq如果这样做没有实际的好处......

optimization performance x86 assembly

12
推荐指数
1
解决办法
1337
查看次数

为什么Skylake比Broadwell-E在单线程内存吞吐量方面要好得多?

我们有一个简单的内存吞吐量基准.对于大块内存,它所做的只是重复记忆.

在几台不同的机器上查看结果(针对64位编译),Skylake机器的性能明显优于Broadwell-E,保持OS(Win10-64),处理器速度和RAM速度(DDR4-2133)不变.我们不是说几个百分点,而是大约2个因素.Skylake配置为双通道,Broadwell-E的结果不会因双/三/四通道而异.

任何想法为什么会这样?随后的代码在VS2015的Release中编译,并报告完成每个memcpy的平均时间:

64位:Skylake为2.2ms,Broadwell-E为4.5ms

32位:Skylake为2.2ms,Broadwell-E为3.5ms.

通过利用多个线程,我们可以在四通道Broadwell-E构建上获得更大的内存吞吐量,这很不错,但是看到单线程内存访问的这种巨大差异令人沮丧.为什么差异如此显着的任何想法?

我们还使用了各种基准测试软件,他们验证了这个简单示例所展示的内容 - 单线程内存吞吐量在Skylake上更好.

#include <memory>
#include <Windows.h>
#include <iostream>

//Prevent the memcpy from being optimized out of the for loop
_declspec(noinline) void MemoryCopy(void *destinationMemoryBlock, void *sourceMemoryBlock, size_t size)
{
    memcpy(destinationMemoryBlock, sourceMemoryBlock, size);
}

int main()
{
    const int SIZE_OF_BLOCKS = 25000000;
    const int NUMBER_ITERATIONS = 100;
    void* sourceMemoryBlock = malloc(SIZE_OF_BLOCKS);
    void* destinationMemoryBlock = malloc(SIZE_OF_BLOCKS);
    LARGE_INTEGER Frequency;
    QueryPerformanceFrequency(&Frequency);
    while (true)
    {
        LONGLONG total = 0;
        LONGLONG max = 0;
        LARGE_INTEGER StartingTime, …
Run Code Online (Sandbox Code Playgroud)

performance benchmarking x86 intel cpu-architecture

12
推荐指数
1
解决办法
1594
查看次数

为什么这个SIMD乘法不比非SIMD乘法快?

让我们假设我们有一个函数,每个函数乘以两个1000000双精度数组.在C/C++中,函数如下所示:

void mul_c(double* a, double* b)
{
    for (int i = 0; i != 1000000; ++i)
    {
        a[i] = a[i] * b[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器生成以下程序集-O2:

mul_c(double*, double*):
        xor     eax, eax
.L2:
        movsd   xmm0, QWORD PTR [rdi+rax]
        mulsd   xmm0, QWORD PTR [rsi+rax]
        movsd   QWORD PTR [rdi+rax], xmm0
        add     rax, 8
        cmp     rax, 8000000
        jne     .L2
        rep ret
Run Code Online (Sandbox Code Playgroud)

从上面的程序集看来,编译器似乎使用了SIMD指令,但每次迭代只会增加一倍.所以我决定在内联汇编中编写相同的函数,在那里我充分利用xmm0寄存器并一次乘以两个双精度:

void mul_asm(double* a, double* b)
{
    asm volatile
    (
        ".intel_syntax noprefix             \n\t"
        "xor    rax, rax                    \n\t"
        "0:                                 \n\t"
        "movupd …
Run Code Online (Sandbox Code Playgroud)

c++ performance assembly simd

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