相关疑难解决方法(0)

为什么memcpy()和memmove()比指针增量更快?

我复制从N个字节pSrcpDest.这可以在一个循环中完成:

for (int i = 0; i < N; i++)
    *pDest++ = *pSrc++
Run Code Online (Sandbox Code Playgroud)

为什么这比memcpy或慢memmove?他们用什么技巧加快速度?

c c++ loops

90
推荐指数
6
解决办法
3万
查看次数

为什么循环指令慢?英特尔无法有效实施吗?

LOOP(英特尔参考手动输入)递减ecx/rcx,然后如果非零则跳转.这很慢,但是英特尔不能廉价地把它变得很快吗? dec/jnz已经将宏观融合成 Sandybridge家族的一个 uop; 唯一的区别是设置标志.

loop关于各种微体系结构,来自Agner Fog的说明表:

  • K8/K10:7 m-ops
  • Bulldozer-family/Ryzen:1 m-op(与宏观融合测试和分支相同,或者jecxz)

  • P4:4次(相同jecxz)

  • P6(PII/PIII):8次
  • Pentium M,Core2:11 uops
  • Nehalem:6个uops.(11为loope/ loopne).吞吐量= 4c(loop)或7c(loope/ne).
  • SnB家族:7个uops.(11为loope/ loopne). 吞吐量=每5个循环一个,这是将循环计数器保留在内存中的瓶颈!jecxz只有2 uops,吞吐量与普通吞吐量相同jcc
  • Silvermont:7次
  • AMD Jaguar(低功耗):8 uops,5c吞吐量
  • 通过Nano3000:2 uops

难道解码器不能像lea rcx, [rcx-1]/ 那样解码jrcxz吗?这将是3 uops.至少那是没有地址大小前缀的情况,否则它必须使用ecx和截断RIP,EIP如果跳转; 也许奇怪的地址大小选择控制减量的宽度解释了许多uops?

或者更好,只需将其解码为不设置标志的融合分支和分支? dec ecx …

performance x86 assembly intel cpu-architecture

53
推荐指数
3
解决办法
6096
查看次数

为什么复杂的memcpy/memset优越?

在调试时,我经常进入memcpy和memset的手写汇编实现.这些通常使用流指令(如果可用),循环展开,对齐优化等实现...我最近也遇到了由于glibc中的memcpy优化而导致的"错误".

问题是:为什么硬件制造商(英特尔,AMD)不能优化具体情况

rep stos
Run Code Online (Sandbox Code Playgroud)

rep movs
Run Code Online (Sandbox Code Playgroud)

被认可,并尽可能快地填写和复制他们自己的架构?

c optimization 64-bit x86 assembly

22
推荐指数
3
解决办法
9127
查看次数

SSE-copy,AVX-copy和std :: copy性能

我试图通过SSE和AVX提高复制操作的性能:

    #include <immintrin.h>

    const int sz = 1024;
    float *mas = (float *)_mm_malloc(sz*sizeof(float), 16);
    float *tar = (float *)_mm_malloc(sz*sizeof(float), 16);
    float a=0;
    std::generate(mas, mas+sz, [&](){return ++a;});

    const int nn = 1000;//Number of iteration in tester loops    
    std::chrono::time_point<std::chrono::system_clock> start1, end1, start2, end2, start3, end3; 

    //std::copy testing
    start1 = std::chrono::system_clock::now();
    for(int i=0; i<nn; ++i)
        std::copy(mas, mas+sz, tar);
    end1 = std::chrono::system_clock::now();
    float elapsed1 = std::chrono::duration_cast<std::chrono::microseconds>(end1-start1).count();

    //SSE-copy testing
    start2 = std::chrono::system_clock::now();
    for(int i=0; i<nn; ++i)
    {
        auto _mas = mas;
        auto _tar = tar; …
Run Code Online (Sandbox Code Playgroud)

c++ performance sse simd avx

19
推荐指数
2
解决办法
1万
查看次数

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

标签 统计

assembly ×3

performance ×3

x86 ×3

c ×2

c++ ×2

optimization ×2

64-bit ×1

avx ×1

cpu-architecture ×1

intel ×1

loops ×1

simd ×1

sse ×1