是否可以使用std::vector自定义结构分配对齐的内存以便使用SIMD指令进行进一步处理?如果有可能,有Allocator没有人碰巧有这样的分配器,他可以分享?
这是我通常用于通过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) 我正在编写一些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.0在Ubuntu的18.04 X86-64.
尝试使用对齐功能在堆上分配可移植函数.
找到"aligned_alloc",我认为这是在stdlib.h中,但gcc似乎不这么认为
错误:未在此范围内声明'aligned_alloc'
使用带有标志的gcc -std = c ++ 11 -m64
尝试导入
#include <stdlib.h>
#include <cstdlib>
Run Code Online (Sandbox Code Playgroud) 我是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) 我正在编写一个代码,创建32个线程,并将它们的亲和性设置为我的多核多处理器系统中的32个核心中的每一个.
线程只是执行RDTSCP指令,并且值存储在非重叠位置的共享数组中,这是共享数组:
uint64_t rdtscp_values[32];
Run Code Online (Sandbox Code Playgroud)
因此,每个线程都将根据其核心编号写入特定的阵列位置.
最重要的是,一切都正常工作,除了我知道我可能没有使用正确的数据结构来避免缓存行反弹.
PS: 我已经检查过我的处理器缓存行是64字节宽.
因为我使用的是一个简单的uint64_t数组,所以它意味着由于预读,单个缓存行将存储该数组的8个位置.
由于这个简单的数组,虽然线程写入不同的索引,但我的理解是,每次写入此数组都会导致所有其他线程的缓存失效?
我怎样才能创建一个与缓存行对齐的结构?
我的系统是: 2x Intel Xeon E5-2670 2.30GHz(8核,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) GNU文档指出,它malloc在 64 位系统上与 16 字节倍数对齐。为什么是这样?
如果我的理解是正确的,寄存器和所有指令都对最大 8 字节宽的值进行操作。因此,似乎需要 8 字节对齐。
笔记:
x86_64当我在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) 我正在尝试重新实现 malloc 并且我需要了解对齐的目的。据我了解,如果内存对齐,代码将执行得更快,因为处理器不必采取额外的步骤来恢复被切割的内存位。我想我明白 64 位处理器读取 64 位 x 64 位内存。现在,让我们假设我有一个按顺序排列的结构(没有填充):一个字符、一个短字符、一个字符和一个整数。为什么短路会错位?我们拥有区块中的所有数据!为什么它必须在一个 2 的倍数的地址上。对于整数和其他类型,同样的问题?
我还有第二个问题:使用我之前提到的结构,处理器如何知道当它读取它的 64 位时前 8 位对应于一个字符,然后接下来的 16 位对应于一个短等等......?
我有一个代码片段。该代码段仅加载 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) 问题: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) c++ ×6
c ×5
simd ×4
sse ×4
avx ×3
x86 ×3
x86-64 ×3
assembly ×2
allocator ×1
c++11 ×1
caching ×1
codeblocks ×1
cpu ×1
gcc ×1
intrinsics ×1
low-level ×1
memory ×1
nasm ×1
optimization ×1
performance ×1