使std :: vector分配内存的现代方法


11

以下问题是相关的,但答案是旧的,并且从用户评论马克Glisse表明有因为C ++ 17的新方法这个问题可能没有得到充分讨论。

我正在尝试使对齐的内存对于SIMD正常工作,同时仍然可以访问所有数据。

在Intel上,如果创建类型为float的向量__m256,并将大小减小8倍,则会使内存对齐。

例如 std::vector<__m256> mvec_a((N*M)/8);

以一种有点怪异的方式,我可以将指向矢量元素的指针强制转换为float,这使我可以访问各个float值。

取而代之的是,我希望具有一个std::vector<float>正确对齐的,因此可以在__m256不进行段错误的情况下加载到其他SIMD类型中。

我一直在研究aligned_alloc

这可以给我一个正确对齐的C样式数组:

auto align_sz = static_cast<std::size_t> (32);
float* marr_a = (float*)aligned_alloc(align_sz, N*M*sizeof(float));

但是我不确定如何执行此操作std::vector<float>。赋予std::vector<float>所有权marr_a 似乎是不可能的

我已经看到一些建议,我应该编写一个自定义分配器,但这似乎需要大量工作,也许对于现代C ++,有更好的方法吗?


1
不会出现segfaulting ...或使用时不会因高速缓存行拆分而导致速度下降_mm256_loadu_ps(&vec[i])。(但请注意使用默认的优化选项,GCC 分裂不保证对齐的256位加载/存储到vmovups XMM / vinsertf128。因此,有一个优势,使用_mm256_loadloadu,如果你关心如何在GCC您的代码编译,如果有人忘了使用-mtune=...-march=选项。)
Peter Cordes

Answers:


1

标准C ++库中的所有容器(包括向量)都具有一个可选的模板参数,用于指定容器的分配器,实现自己的分配器实际上不是很多工作:

class my_awesome_allocator {
};

std::vector<float, my_awesome_allocator> awesomely_allocated_vector;

您将不得不编写一些代码来实现您的分配器,但这不会比您已经编写的代码多得多。如果您不需要C ++ 17之前的支持,则只需要实现allocate()deallocate()方法即可。


他们还需要专门研究allocator_traits
NathanOliver

1
举个例子,人们可以复制/粘贴以跳过C ++的烦人的循环,这可能是一个规范答案的好地方。(如果有办法让std :: vector尝试就地重新分配,而不是通常的Braindead C ++总是alloc + copy,则奖励vector<float, MAA>是要指出的。)当然还要注意,这与类型不兼容vector<float>(并且不能因为任何.push_backstd::vector<float>没有此分配器的情况下进行普通编译的操作都可以进行新分配,并复制到最小对齐的内存中。并且new / delete与aligned_alloc / free不兼容)
Peter Cordes

1
我认为不能保证从分配器返回的指针可以直接用作std::vector数组的基地址。例如,我可以想象一个std::vector仅使用指向已分配内存的指针的实现,该指针在值范围之前将结束/容量/分配器存储在内存中。这很容易阻碍分配器完成的对齐。
DietmarKühl

1
除非std::vector保证。这就是它的用途。也许您应该查看C ++标准在这里指定的内容。
Sam Varshavchik

1
>他们还需要专业化allocator_traits-不,不是。所需要做的就是实现一个兼容的分配器。
Andrey Semashev
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.