相关疑难解决方法(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?

我在C中进行图像处理,需要在内存周围复制大块数据 - 源和目标永远不会重叠.

使用GCC(其中SSE,SSE2但不是SSE3可用)在x86平台上执行此操作的绝对最快方法是什么?

我希望解决方案可以是汇编还是使用GCC内在函数?

我发现下面的链接,但不知道它是否去了解它的最佳方式(笔者也表示有一些错误):http://coding.derkeiler.com/Archive/Assembler/comp.lang.asm. 86/2006-02/msg00123.html

编辑:请注意,副本是必要的,我无法复制数据(我可以解释为什么,但我会饶你解释:))

c optimization assembly image-processing memcpy

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

我可以在Linux上进行写时复制memcpy吗?

我有一些代码,我经常复制一大块内存,通常只需要对它进行非常小的更改.

我已经实现了一个跟踪更改的系统,但我认为如果可能的话,可以告诉操作系统对内存进行"写时复制",并让它只处理那些部分的副本哪个改变了.然而,虽然Linux执行copy-on-write,例如fork()时,我找不到一种控制它并自己动手的方法.

c linux memory-management

24
推荐指数
1
解决办法
7896
查看次数

128位到512位寄存器用于什么?

在查看x86/x64架构中的寄存器表之后,我注意到有128,256和512位寄存器的整个部分,我从未见过它们用于汇编或反编译的C/C++代码: XMM(0-15)表示128,YMM(0-15)表示256,ZMM(0-31)512.

做了一些挖后我所收集的是,你必须使用2个64位操作,以一个128位的数字进行的,而不是使用通用的数学,add,sub,mul,div操作.如果是这种情况,那么具有这些扩展寄存器集的用途究竟是什么,是否有任何汇编操作可以用来操作它们?

assembly sse x86-64 simd cpu-registers

7
推荐指数
1
解决办法
645
查看次数

使用SIMD double-&gt; float转换将2个double数组快速交织到具有2个float和1个int(循环不变)成员的结构体数组中?

我有一段代码是在x86处理器上运行的C ++应用程序的瓶颈,其中我们从两个数组中获取双精度值,强制转换为float并存储在结构数组中。这是瓶颈的原因是它被称为具有非常大的循环或数千次。

是否有使用SIMD Intrinsics进行复制和转换操作的更快方法?我已经在更快的memcpy上看到了这个答案,但没有解决演员表问题。

简单的C ++循环情况如下所示

        int _iNum;
        const unsigned int _uiDefaultOffset; // a constant 

        double * pInputValues1; // array of double values, count = _iNum;
        double * pInputValues2; 

        MyStruct * pOutput;    // array of outputs defined as
        // struct MyStruct 
        // { 
        //    float O1;
        //    float O2;
        //    unsigned int Offset;
        // };

        for (int i = 0; i < _iNum; ++i)
        {
            _pPoints[i].O1 = static_cast<float>(pInputValues1[i]);
            _pPoints[i].O2 = static_cast<float>(pInputValues2[i]);
            _pPoints[i].Offset = _uiDefaultOffset;
        }
Run Code Online (Sandbox Code Playgroud)

注意: …

c++ x86 simd intrinsics avx

7
推荐指数
3
解决办法
277
查看次数

通过输入参数多次传递完美转发

考虑以下函数accept,该函数采用类型的"通用引用" T并将其转发给具有parse<T>()lvalues重载和rvalues重载的函数对象:

template<class T>
void accept(T&& arg)
{
    parse<T>()(std::forward<T>(arg), 0); // copy or move, depending on rvaluedness of arg
}

template<class T>
class parse
{
    // parse will modify a local copy or move of its input parameter
    void operator()(T const& arg, int n) const { /* optimized for lvalues */ }
    void operator()(T&& arg)    , int n) const { /* optimized for rvalues */ }
};
Run Code Online (Sandbox Code Playgroud)

由于完美转发使源对象处于有效但未定义的状态,因此无法在同一范围内再次完美转发.下面我尝试在一个假设的split()函数中尽可能少地复制一个int代表必须对输入数据进行的数字传递:

template<class T>
void …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue-reference move-semantics perfect-forwarding c++11

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