相关疑难解决方法(0)

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

如何提高memcpy的性能

摘要:

memcpy似乎无法在真实或测试应用程序中在我的系统上传输超过2GB /秒.我该怎么做才能获得更快的内存到内存副本?

详细信息:

作为数据捕获应用程序的一部分(使用一些专用硬件),我需要将大约3 GB /秒的临时缓冲区复制到主内存中.为了获取数据,我为硬件驱动程序提供了一系列缓冲区(每个2MB).硬件将数据DMA数据到每个缓冲区,然后在每个缓冲区已满时通知我的程序.我的程序清空缓冲区(memcpy到另一个更大的RAM块),并将处理后的缓冲区重新发送到卡中再次填充.我遇到了memcpy足够快地移动数据的问题.似乎内存到内存的副本应该足够快,以便在我运行的硬件上支持3GB /秒.Lavalys EVEREST给了我一个9337MB /秒的内存复制基准测试结果,但即使在一个简单的测试程序中,我也无法通过memcpy获得接近这些速度的任何数据.

我通过在缓冲区处理代码中添加/删除memcpy调用来隔离性能问题.没有memcpy,我可以运行全数据速率 - 大约3GB /秒.启用memcpy后,我被限制在大约550Mb /秒(使用当前编译器).

为了在我的系统上对memcpy进行基准测试,我编写了一个单独的测试程序,它只是在某些数据块上调用memcpy.(我已经发布了下面的代码)我在我正在使用的编译器/ IDE(National Instruments CVI)以及Visual Studio 2010中都运行了这个.虽然我目前没有使用Visual Studio,但我愿意如果它将产生必要的性能,则进行切换.然而,在盲目地移动之前,我想确保它能解决我的memcpy性能问题.

Visual C++ 2010:1900 MB /秒

NI CVI 2009:550 MB /秒

虽然我并不感到惊讶,CVI比Visual Studio的显著慢,我很惊讶的是,memcpy的性能是这种低.虽然我不确定这是否可以直接比较,但这远低于EVEREST基准带宽.虽然我不需要那么高的性能水平,但至少需要3GB /秒.当然,标准库的实现不会比EVEREST使用的更糟糕!

在这种情况下,如果有的话,我可以做些什么来更快地使用memcpy?


硬件细节:AMD Magny Cours-4x八核128 GB DDR3 Windows Server 2003 Enterprise X64

测试程序:

#include <windows.h>
#include <stdio.h>

const size_t NUM_ELEMENTS = 2*1024 * 1024;
const size_t ITERATIONS = 10000;

int main (int argc, char *argv[])
{
    LARGE_INTEGER start, stop, frequency;

    QueryPerformanceFrequency(&frequency);

    unsigned short * src = …
Run Code Online (Sandbox Code Playgroud)

c cvi memcpy visual-studio memory-bandwidth

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

更快的替代memcpy?

我有一个正在执行memcpy的功能,但它占用了大量的周期.有没有比使用memcpy移动内存更快的替代/方法?

c performance memcpy

37
推荐指数
5
解决办法
6万
查看次数

如何在C#中实现Array.Copy?

我试着Array.Copy用ILSpy 查看C#中的实现,但它没有向我展示实现本身.

我写了一个简单的基准测试,Array.Copy与一个简单的for循环来复制数据.Array.Copy更快.

如何更快地实施?

谢谢,谢伊

c# arrays

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

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

memcpy在linux中移动128位

我正在linux中为PCIe设备编写设备驱动程序.此设备驱动程序执行多次读写操作以测试吞吐量.当我使用memcpy时,TLP的最大有效载荷是8个字节(在64位架构上).在我看来,获得16字节有效载荷的唯一方法是使用SSE指令集.我已经看到了这个,但代码没有编译(AT&T/Intel语法问题).

  • 有一种方法可以在linux中使用该代码吗?
  • 有谁知道我在哪里可以找到一个移动128位的memcpy的实现?

c linux assembly sse simd

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

C array =比memcpy()更快的数组

我有一段C代码,我正在尝试优化,其中包括设置数组a到b.我目前正在使用memcpy来实现这一点,并且它可以工作,但它不够快.即

double a[4] = {1.0, 2.0, 3.0, 4.0};
double b[4];
memcpy(b, a, sizeof(a));
Run Code Online (Sandbox Code Playgroud)

这是一个基本的例子,我的程序类似,但使用多达9000双打.我知道使用指针可以节省很多时间,但我不知道该怎么做.非常感谢您的帮助.

编辑:我不需要保留一个可以丢弃的数组.我只需要从a转移到b.

c optimization pointers memcpy

-1
推荐指数
1
解决办法
3113
查看次数