相关疑难解决方法(0)

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

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

optimization x86 memory-management cpu-architecture micro-optimization

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

使std :: vector分配对齐的内存

是否可以使用std::vector自定义结构分配对齐的内存以便使用SIMD指令进行进一步处理?如果有可能,有Allocator没有人碰巧有这样的分配器,他可以分享?

c++ memory-management memory-alignment allocator

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

获得对齐内存的最佳跨平台方法

这是我通常用于通过Visual Studio和GCC获得对齐内存的代码

inline void* aligned_malloc(size_t size, size_t align) {
    void *result;
    #ifdef _MSC_VER 
    result = _aligned_malloc(size, align);
    #else 
     if(posix_memalign(&result, align, size)) result = 0;
    #endif
    return result;
}

inline void aligned_free(void *ptr) {
    #ifdef _MSC_VER 
        _aligned_free(ptr);
    #else 
      free(ptr);
    #endif

}
Run Code Online (Sandbox Code Playgroud)

这个代码一般是好的吗?我也见过人们用_mm_malloc,_mm_free.在大多数情况下,我想要对齐内存,使用SSE/AVX.我可以一般使用这些功能吗?它会使我的代码更简单.

最后,创建我自己的函数来对齐内存很容易(见下文).为什么会有这么多不同的常用函数来获得对齐的内存(其中许多只能在一个平台上运行)?

此代码执行16字节对齐.

float* array = (float*)malloc(SIZE*sizeof(float)+15);

// find the aligned position
// and use this pointer to read or write data into array
float* alignedArray = (float*)(((unsigned long)array + 15) & (~0x0F));

// dellocate memory …
Run Code Online (Sandbox Code Playgroud)

c c++ performance sse memory-alignment

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

为什么gcc不将_mm256_loadu_pd解析为单个vmovupd?

我正在编写一些AVX代码,我需要从可能未对齐的内存中加载.我目前正在加载4个双打,因此我将使用内部指令_mm256_loadu_pd ; 我写的代码是:

__m256d d1 = _mm256_loadu_pd(vInOut + i*4);
Run Code Online (Sandbox Code Playgroud)

然后,我使用选项进行编译,-O3 -mavx -g然后使用objdump获取汇编代码以及带注释的代码和line(objdump -S -M intel -l avx.obj).
当我查看底层汇编程序代码时,我发现以下内容:

vmovupd xmm0,XMMWORD PTR [rsi+rax*1]
vinsertf128 ymm0,ymm0,XMMWORD PTR [rsi+rax*1+0x10],0x1
Run Code Online (Sandbox Code Playgroud)

我期待看到这个:

vmovupd ymm0,XMMWORD PTR [rsi+rax*1]
Run Code Online (Sandbox Code Playgroud)

并充分利用256位寄存器(YMM0),而不是它看起来像海湾合作委员会已决定在128位部分(填写XMM0),然后再次加载另一半vinsertf128.

有人能够解释这个吗?在MSVC VS 2012中
使用单个vmovupd编译等效代码.

我运行gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0Ubuntu的18.04 X86-64.

assembly gcc simd vectorization avx

13
推荐指数
2
解决办法
464
查看次数

编译器找不到"aligned_alloc"函数

尝试使用对齐功能在堆上分配可移植函数.

找到"aligned_alloc",我认为这是在stdlib.h中,但gcc似乎不这么认为

错误:未在此范围内声明'aligned_alloc'

使用带有标志的gcc -std = c ++ 11 -m64

尝试导入

#include <stdlib.h>
#include <cstdlib>
Run Code Online (Sandbox Code Playgroud)

c c++

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

使用SSE内在函数编译简单的c ++程序

我是SSE指令的新手,我试图从这个网站上学习它们:http: //www.codeproject.com/Articles/4522/Introduction-to-SSE-Programming

我在Ubuntu 10.10上使用GCC编译器和Intel Core i7 960 CPU

这是基于我尝试的文章的代码:

对于两个长度为ARRAY_SIZE的数组,它会计算出来

fResult[i] = sqrt( fSource1[i]*fSource1[i] + fSource2[i]*fSource2[i] ) + 0.5

这是代码

#include <iostream>
#include <iomanip>
#include <ctime>
#include <stdlib.h>
#include <xmmintrin.h> // Contain the SSE compiler intrinsics
#include <malloc.h>
void myssefunction(
          float* pArray1,                   // [in] first source array
          float* pArray2,                   // [in] second source array
          float* pResult,                   // [out] result array
          int nSize)                        // [in] size of all arrays
{
    int nLoop = nSize/ 4;

    __m128 m1, m2, m3, …
Run Code Online (Sandbox Code Playgroud)

c++ x86 sse simd

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

如何避免多个线程写入共享数组的缓存行失效?

问题的背景:

我正在编写一个代码,创建32个线程,并将它们的亲和性设置为我的多核多处理器系统中的32个核心中的每一个.

线程只是执行RDTSCP指令,并且值存储在非重叠位置的共享数组中,这是共享数组:

uint64_t rdtscp_values[32];
Run Code Online (Sandbox Code Playgroud)

因此,每个线程都将根据其核心编号写入特定的阵列位置.

最重要的是,一切都正常工作,除了我知道我可能没有使用正确的数据结构来避免缓存行反弹.

PS: 我已经检查过我的处理器缓存行是64字节宽.

因为我使用的是一个简单的uint64_t数组,所以它意味着由于预读,单个缓存行将存储该数组的8个位置.

题:

由于这个简单的数组,虽然线程写入不同的索引,但我的理解是,每次写入此数组都会导致所有其他线程的缓存失效?

我怎样才能创建一个与缓存行对齐的结构?

编辑1

我的系统是: 2x Intel Xeon E5-2670 2.30GHz(8核,16线程)

c multithreading caching x86-64

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

_declspec(align(16))没有将指针对齐到16个字节

所以我正在尝试使用SSE功能__mm_load_128,如果我在某处犯了一些愚蠢的错误,我对SSE很新,请原谅我.

这是代码

void one(__m128i *arr, char *temp)
{
    // SSE needs 16 byte alignment.
    _declspec (align(16)) __m128i *tmp = (__m128i*) temp;

    if (((uintptr_t)tmp & 15) == 0)
        printf("Aligned pointer");
    else 
        printf("%d", ((uintptr_t)tmp & 15)); // This prints as 12

    arr[0] = _mm_load_si128(tmp);
}
Run Code Online (Sandbox Code Playgroud)

我在visual studio上收到错误 0xC0000005: Access violation reading location 0xFFFFFFFF.

0xFFFFFFFF 看起来不对,我做错了什么.

arr 参数初始化为 _m128i arr[5] = { 0 }

替代方案是使用_mm_loadu_128哪个工作正常,但据我了解,它应该产生movdqu指令,但这是生成的程序集

    arr[0] = _mm_loadu_si128(tmp);
00D347F1  mov         eax,dword ptr [tmp]  
00D347F4  movups      xmm0,xmmword ptr …
Run Code Online (Sandbox Code Playgroud)

c++ sse

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

为什么malloc是16字节对齐的?

GNU文档指出,它malloc在 64 位系统上与 16 字节倍数对齐。为什么是这样?

如果我的理解是正确的,寄存器和所有指令都对最大 8 字节宽的值进行操作。因此,似乎需要 8 字节对齐。

笔记:

c memory x86-64 memory-alignment

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

在分配了new []的阵列上使用avx时出现分段错误(核心转储)

当我在Visual Studio 2015中运行此代码时,代码可以正常运行,但是代码在代码块中生成以下错误:分段错误(核心已转储)。我也用同样的错误在ubuntu中运行了代码。

#include <iostream>
#include <immintrin.h>

struct INFO
{
    unsigned int id = 0;
    __m256i temp[8];
};

int main()
{
    std::cout<<"Start AVX..."<<std::endl;
    int _size = 100;
    INFO  *info = new INFO[_size];
    for (int i = 0; i<_size; i++)
    {
        for (int k = 0; k < 8; k++)
        {
            info[i].temp[k] = _mm256_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
                20, 21, 22, 23, 24, 25, 26, 27, …
Run Code Online (Sandbox Code Playgroud)

codeblocks intrinsics avx c++11

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

处理器如何读取内存?

我正在尝试重新实现 malloc 并且我需要了解对齐的目的。据我了解,如果内存对齐,代码将执行得更快,因为处理器不必采取额外的步骤来恢复被切割的内存位。我想我明白 64 位处理器读取 64 位 x 64 位内存。现在,让我们假设我有一个按顺序排列的结构(没有填充):一个字符、一个短字符、一个字符和一个整数。为什么短路会错位?我们拥有区块中的所有数据!为什么它必须在一个 2 的倍数的地址上。对于整数和其他类型,同样的问题?

我还有第二个问题:使用我之前提到的结构,处理器如何知道当它读取它的 64 位时前 8 位对应于一个字符,然后接下来的 16 位对应于一个短等等......?

c cpu cpu-architecture memory-alignment low-level

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

_mm_load_ps 导致段错误

我有一个代码片段。该代码段仅加载 2 个数组并使用 SSE 计算它们之间的点积。

代码在这里:

using namespace std;

long long size = 3200000;

float* _random()
{
    unsigned int seed = 123;
    //    float *t = malloc(size*sizeof(float));
    float *t = new float[size];
    int i;
    float num = 0.0;
    for(i=0; i < size; i++) {
        num = rand()/(RAND_MAX+1.0);
        t[i] = num;
    }
    return t;
}

float _dotProductVectorSSE(float *s1, float *s2)
{
    float prod;
    int i;
    __m128 X, Y, Z;

    for(i=0; i<size; i+=4)
    {
        X = _mm_load_ps(&s1[i]);
        Y = _mm_load_ps(&s2[i]);
        X = …
Run Code Online (Sandbox Code Playgroud)

c++ x86 sse simd memory-alignment

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

YASM:vmovaps指令导致分段错误

问题:movaps给我一个分段错误.

上下文:x86-64指令vmovaps设计用于Core i系列处理器(我运行此系统)上的AVX寄存器.AVX寄存器的宽度是SSE寄存器的两倍(分别为256和128位).指令vmovaps应将对齐的浮点值(32位)的向量移动到指定的ymm寄存器中.

可能的原因:源数据的对齐特别重要,因为错误对齐的数据是分段错误的来源.但是,即使我对齐了数据,我自己也遇到了分段错误.

    segment .data

align 16
xs:
    dd  0.0
    dd  1.1
    dd  2.2
    dd  3.3
    dd  4.4
    dd  5.5
    dd  6.6
    dd  7.7

align 16
ys:
    dd  8.8
    dd  7.7
    dd  6.6
    dd  5.5
    dd  4.4
    dd  3.3
    dd  2.2
    dd  1.1

    segment .text
    global main

main:
    push rbp
    mov rbp, rsp

    ; Move eight 32-bit floats from "xs" into ymm0
    vmovaps ymm0, [xs]

    ; Move …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 simd nasm avx

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