相关疑难解决方法(0)

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

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

optimization x86 memory-management cpu-architecture micro-optimization

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

malloc是否懒惰地为Linux(和其他平台)上的分配创建支持页面?

在Linux上,如果我去的话malloc(1024 * 1024 * 1024),malloc实际上做了什么?

我确定它为分配分配了一个虚拟地址(通过遍历空闲列表并在必要时创建新映射),但它实际上是否创建了1 GiB的交换页面?或者它mprotect是地址范围并在您实际触摸它们时创建页面mmap吗?

(我正在指定Linux,因为标准对这些细节没有提及,但我有兴趣知道其他平台也会这样做.)

linux malloc

71
推荐指数
5
解决办法
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万
查看次数

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

英特尔Skylake上的商店循环出乎意料的糟糕和奇怪的双峰性能

我看到一个简单的存储循环出乎意料地表现不佳,这个存储循环有两个存储:一个具有16字节的正向步长,另一个总是位于同一位置1,如下所示:

volatile uint32_t value;

void weirdo_cpp(size_t iters, uint32_t* output) {

    uint32_t x = value;
    uint32_t          *rdx = output;
    volatile uint32_t *rsi = output;
    do {
        *rdx    = x;
        *rsi = x;

        rdx += 4;  // 16 byte stride
    } while (--iters > 0);
}
Run Code Online (Sandbox Code Playgroud)

在汇编这个循环可能3看起来像:

weirdo_cpp:

...

align 16
.top:
    mov    [rdx], eax  ; stride 16
    mov    [rsi], eax  ; never changes

    add    rdx, 16

    dec    rdi
    jne    .top

    ret
Run Code Online (Sandbox Code Playgroud)

当访问的存储区域在L2中时,我希望每次迭代运行少于3个周期.第二个商店只是一直在同一个位置,应该添加一个周期.第一个商店意味着从L2引入一条线,因此每4次迭代也会驱逐一条线.我不确定你如何评估L2成本,但即使你保守估计L1只能在每个周期中执行以下操作之一:(a)提交商店或(b)从L2接收一行或(c)将一条线驱逐到L2,对于stride-16商店流,你会得到1 + 0.25 + …

optimization performance x86 assembly x86-64

25
推荐指数
2
解决办法
1629
查看次数

intel core i7处理器使用哪种缓存映射技术?

我已经了解了不同的缓存映射技术,如直接映射,关联映射和集合关联映射技术,还学习了权衡.但我很好奇现在在intel core i7或AMD处理器中使用了什么.以及这些技术是如何演变的.还有哪些事情需要改进?

x86 amd intel cpu-architecture cpu-cache

8
推荐指数
1
解决办法
2255
查看次数

英特尔硬件上的商店缓冲区大小?什么是商店缓冲区?

英特尔优化手册似乎对存储缓冲区的数量存在于处理器的许多地方,但谈判没有谈存储缓冲区的大小.这是公共信息还是商店缓冲区的大小保留为微架构细节?

我正在研究的处理器主要是Broadwell和Skylake,但其他人的信息也不错.

另外,存储缓冲区究竟做了什么?

performance x86 assembly intel cpu-architecture

8
推荐指数
1
解决办法
717
查看次数

在最近的英特尔上拆分行/页存储是否需要两个存储缓冲区条目?

一般理解为每个store分配一个store buffer entry,这个store buffer entry保存了store数据和物理地址1

在存储跨越 4096 字节页面边界的情况下,可能需要两个不同的转换,每个页面一个,因此可能需要存储两个不同的物理地址。这是否意味着跨页存储需要 2 个存储缓冲区条目?如果是这样,它是否也适用于跨线商店?


1 ...也许还有一些/全部虚拟地址来帮助存储转发。

x86 intel cpu-architecture micro-optimization micro-architecture

8
推荐指数
0
解决办法
110
查看次数

Write-Combining Buffer位于何处?86

Write-Combine缓冲区是如何物理连接的?我已经看到了说明许多变体的方框图:

  • 在L1和内存控制器之间
  • 在CPU的存储缓冲区和内存控制器之间
  • 在CPU的AGU和/或存储单元之间

它是依赖于微架构的吗?

x86 intel cpu-architecture cpu-cache amd-processor

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

为什么对这个数组结构体的成员求和比对结构体数组求和要快得多?

我一直在使用https://github.com/google/benchmark和g++ 9.4.0来检查不同场景下数据访问的性能(用“ -O3”编译)。结果令我惊讶。

我的基线是访问std::array(“减少数据”)中的长数。我想添加一个额外的字节数据。一次我创建一个额外的容器(“拆分数据”),一次我在数组中存储一个结构(“组合数据”)。

这是代码:

#include <benchmark/benchmark.h>

#include <array>
#include <random>

constexpr int width  = 640;
constexpr int height = 480;

std::array<std::uint64_t, width * height> containerWithReducedData;

std::array<std::uint64_t, width * height> container1WithSplitData;
std::array<std::uint8_t, width * height>  container2WithSplitData;

struct CombinedData
{
    std::uint64_t first;
    std::uint8_t  second;
};

std::array<CombinedData, width * height> containerWithCombinedData;

void fillReducedData(const benchmark::State& state)
{
    // Variable is intentionally unused
    static_cast<void>(state);

    // Generate pseudo-random numbers (no seed, therefore always the same numbers)
    // NOLINTNEXTLINE
    auto engine …
Run Code Online (Sandbox Code Playgroud)

c++ arrays caching compiler-optimization data-oriented-design

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

优化累积总和

我需要一些帮助来了解我尝试的优化是如何工作的。

cumsum函数获取一个向量,并用累加和写入一个向量。

我尝试了以下方法来优化它:我没有在整个向量上执行一次循环,而是编写了一个循环,该循环在每四分之一的向量上同时运行。然后调整每个部分以考虑前面部分的总和。结果略有不同,但这不是问题。

这是程序:

module cumsum_mod
    implicit none
    integer, parameter, private :: dp = kind(1d0)
contains
    ! cumsum in one straight loop
    subroutine cumsum1(n, a, b)
        integer :: n, i
        real(dp) :: a(n), b(n)
        
        b(1) = a(1)
        do i = 2, n
            b(i) = a(i) + b(i-1)
        end do
    end subroutine
    
    subroutine cumsum2(n, a, b)
        integer :: n, i, m
        real(dp) :: a(n), b(n)
        
        m = n/4
        
        ! Loop over the four parts
        b(1) = a(1)
        b(1+m) = …
Run Code Online (Sandbox Code Playgroud)

optimization x86 assembly fortran x86-64

5
推荐指数
0
解决办法
81
查看次数

x86 内在:2 个复数浮点向量的乘法

我的输入是 2 个复数浮点向量。两个向量交错:

VecAReal = Are0, Are1, Are2,...Are[N-1]
VecAImag = Aim0, Aim1, Aim2,...Aim[N-1]

VecBReal = Bre0, Bre1, Bre2,...Bre[N-1]
VecBImag = Bim0, Bim1, Bim2,...Bim[N-1]
Run Code Online (Sandbox Code Playgroud)

我必须运行标量乘法:

VecCReal = Cre0, Cre1, Cre2,...Cre[N-1]
VecCImag = Cim0, Cim1, Cim2,...Cim[N-1]


Cre[i] = Are[i]*Bre[i] - Aim[i]-Bim[i]
Cim[i] = Are[i]*Bim[i] + Aim[i]+Bre[i]
Run Code Online (Sandbox Code Playgroud)

在每次迭代中,我必须_mm_load_ps在 4 个不同的指针上运行。

在 sum、add 之后,在每次迭代中我必须_mm_store_ps在 2 个不同的指针上运行。

由于大量加载/存储,它看起来效率很低。你能建议一个更好的方法吗?

c x86 sse intrinsics complex-numbers

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

并行嵌套循环中的数据竞争

我有一个三重嵌套循环,我想并行化,但是,我遇到了数据争用问题。我很确定我需要以某种方式使用缩减,但我不太知道如何使用。

这是有问题的循环:

#pragma omp parallel for simd collapse(3)
    for (uint64 u = 0; u < nu; ++u) {
        for (uint64 e = 0; e < ne; ++e) {
            for (uint64 v = 0; v < nv; ++v) {
                uAT[u][e] += _uT[u][e][v] * wA[e][v];
            }
        }
    }

Run Code Online (Sandbox Code Playgroud)

有人可以向我解释一下,为什么这会导致数据竞争?我真的很想了解这一点,这样我将来就不会遇到这些问题。另外,这个循环可以并行吗?如果是这样,怎么办?

编辑:我怎么知道存在数据竞争?

这个循环应该完成的任务(并且它是串行完成的)是计算不连续伽辽金框架中函数的元素平均值。当我多次运行代码时,有时会得到不同的结果,尽管它应该总是产生相同的结果。产生的错误值总是小于应有的值,这就是为什么我假设某些值没有被添加。也许这张图可以更好地解释它:第三个单元格中的平均值显然是错误的(太小)。 第三个单元格中的平均值显然是错误的(太小)。

c simd openmp data-race

0
推荐指数
1
解决办法
239
查看次数