相关疑难解决方法(0)

每个程序员应该了解的内存?

我想知道Ulrich Drepper 从2007年开始对每个程序员应该知道的内容有多少仍然有效.另外,我找不到比1.0更新的版本或勘误表.

optimization x86 memory-management cpu-architecture micro-optimization

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

为memcpy增强了REP MOVSB

我想使用增强的REP MOVSB(ERMSB)为自定义获得高带宽memcpy.

ERMSB引入了Ivy Bridge微体系结构.如果您不知道ERMSB是什么,请参阅英特尔优化手册中的"增强型REP MOVSB和STOSB操作(ERMSB)" 部分.

我知道直接执行此操作的唯一方法是使用内联汇编.我从https://groups.google.com/forum/#!topic/gnu.gcc.help/-Bmlm_EG_fE获得了以下功能

static inline void *__movsb(void *d, const void *s, size_t n) {
  asm volatile ("rep movsb"
                : "=D" (d),
                  "=S" (s),
                  "=c" (n)
                : "0" (d),
                  "1" (s),
                  "2" (n)
                : "memory");
  return d;
}
Run Code Online (Sandbox Code Playgroud)

然而,当我使用它时,带宽远小于memcpy. 使用我的i7-6700HQ(Skylake)系统,Ubuntu 16.10,DDR4 @ 2400 MHz双通道32 GB,GCC 6.2,__movsb获得15 GB/s并memcpy获得26 GB/s.

为什么带宽如此低REP MOVSB?我该怎么做才能改善它?

这是我用来测试它的代码.

//gcc -O3 -march=native -fopenmp foo.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly gcc memcpy

56
推荐指数
4
解决办法
1万
查看次数

为什么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
查看次数

非临时负载和硬件预取器,它们一起工作吗?

当从连续的内存位置执行一系列_mm_stream_load_si128()调用(MOVNTDQA)时,硬件预取器是否仍会启动,或者我应该使用显式软件预取(使用NTA提示)以获得预取的好处,同时仍然避免缓存污染?

我问这个的原因是因为他们的目标似乎与我相矛盾.流加载将获取绕过缓存的数据,而预取器尝试主动将数据提取到缓存中.

当顺序迭代一个大型数据结构(处理过的数据不会在很长一段时间内被修饰)时,我有必要避免污染chache层次结构,但我不想因频繁出现频繁的~100次循环处罚-fetcher闲置.

目标架构是Intel SandyBridge

performance x86 sse prefetch cpu-cache

9
推荐指数
3
解决办法
2512
查看次数

对于WB/WC标记的区域,MOVDQA和MOVNTDQA以及VMOVDQA和VMOVNTDQ有什么区别?

通过使用内存标记为WB指令之间的主要区别是什么(回写)和WC(写入合并):什么是之间的不同MOVDQAMOVNTDQA,什么是之间的不同VMOVDQAVMOVNTDQ

是不是对于内存标记为WC - 指令与[NT]通常没有区别(没有[NT]),并且内存标记为WB - 指令[NT]与它一起工作就好像它是一个内存WC?

x86 assembly sse simd avx

6
推荐指数
1
解决办法
2879
查看次数