对于许多问题,答案似乎可以在"标准"中找到.但是,我们在哪里找到它?最好是在线.
谷歌搜索有时会觉得徒劳,尤其是对于C标准,因为他们在编程论坛的大量讨论中被淹没.
要开始这个,因为这些是我现在正在搜索的,那里有很好的在线资源:
是否可以使用std::vector自定义结构分配对齐的内存以便使用SIMD指令进行进一步处理?如果有可能,有Allocator没有人碰巧有这样的分配器,他可以分享?
有没有办法使用属性((对齐))强制STL容器对齐到特定字节?目标编译器不是Microsoft Visual C++.
哪些库(如果有的话)提供具有特定显式向量化的STL算法的专用模板,例如SSE.我感兴趣的编译器是g ++,Intel和IBM XL.
在以下问题是相关的,但答案是旧的,并且从用户评论马克Glisse表明有因为C ++ 17的新方法这个问题可能没有得到充分讨论。
我试图让对齐的内存为 SIMD 正常工作,同时仍然可以访问所有数据。
在 Intel 上,如果我创建一个类型为 的浮点向量__m256,并将我的大小减小 8 倍,它会给我对齐的内存。
例如 std::vector<__m256> mvec_a((N*M)/8);
以一种稍微有点麻烦的方式,我可以将指向向量元素的指针转换为浮点,这允许我访问单个浮点值。
相反,我更喜欢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));
Run Code Online (Sandbox Code Playgroud)
但是我不确定如何为std::vector<float>. 授予的std::vector<float>所有权marr_a 似乎是不可能的。
我已经看到一些建议我应该编写自定义分配器,但这似乎需要做很多工作,也许现代 C++ 有更好的方法?
有以下代码段错误的明显原因吗?
#include <vector>
#include <emmintrin.h>
struct point {
__m128i v;
point() {
v = _mm_setr_epi32(0, 0, 0, 0);
}
};
int main(int argc, char *argv[])
{
std::vector<point> a(3);
}
Run Code Online (Sandbox Code Playgroud)
谢谢
编辑:我在linux/i686上使用g ++ 4.5.0,我可能不知道我在做什么,但是因为甚至以下的段错误
int main(int argc, char *argv[])
{
point *p = new point();
}
Run Code Online (Sandbox Code Playgroud)
我真的认为它必须和对齐问题.
如果我定义一个具有特定对齐要求的简单类型,那么std::vector<t>所述类型的a是否应该遵循每个元素的对齐?
请考虑以下示例
typedef std::array<double,3> alignas(32) avx_point;
std::vector<avx_point> x(10);
assert(!(std::ptrdiff_t(&(x[0]))&31) && // assert that x[0] is 32-byte aligned
!(std::ptrdiff_t(&(x[1]))&31)); // assert that x[1] is 32-byte aligned
Run Code Online (Sandbox Code Playgroud)
我发现对齐要求是默认(没有任何警告)被clang 3.2(有或没有)违反-stdlib=libc++,而gcc 4.8.0发出一个警告,它忽略了模板参数的属性std::vector(intel编译器太愚蠢了解alignas,但如果我使用__declspec(align(32))它,它的行为就像clang).两者都创建触发断言的代码.
那么,这是正确的行为还是clang(和icpc)的错误以及gcc的问题?
编辑 以回答评论中提出的问题:如果我定义
typedef typename std::aligned_storage<sizeof (avx_point),
alignof(avx_point)>::type avx_storage;
Run Code Online (Sandbox Code Playgroud)
我明白了
sizeof (avx_storage) == 32;
alignof(avx_storage) == 32;
Run Code Online (Sandbox Code Playgroud)
但是std::vector<avx_storage>仍然无法对齐clang和gcc的第一个元素(因此也是所有其他元素)(这次没有警告).因此,实现显然存在两个问题:首先,std::allocator<type>即使对于第一个元素(非法?),也忽略了任何对齐要求;其次,没有应用填充来确保后续元素的对齐.
我有一个算法,其中一个目标是填充向量.出于性能考虑,算法的迭代遍布OpenMP线程.我想知道哪种方式可以提供更好/更安全的填充向量的方法.
注意,向量的排序必须是一致的(即vec1的值n必须来自与vec2的值n相同的迭代.)
假设1:
std::vector<BasicType> vec1;
std::vector<BasicType> vec2;
#pragma opm parallel for
for(...)
{
// Do some intensive stuff to compute val1 and val2
// ...
#pragma omp critical
{
vec1.push_back(val1);
vec2.push_back(val2);
}
}
// Then go on to work with vec1 and vec2...
Run Code Online (Sandbox Code Playgroud)
假设2:
std::vector<BasicType> vec1;
std::vector<BasicType> vec2;
#pragma opm parallel
{
std::vector<BasicType> vec1local;
std::vector<BasicType> vec2local;
#pragma omp for
for(...)
{
// Do some intensive stuff to compute val1 and val2
// ...
vec1local.push_back(val1);
vec2local.push_back(val2);
}
#pragma omp critical
{ …Run Code Online (Sandbox Code Playgroud) 对于我当前的项目,我需要创建一个 256 位 AVX 向量的向量。我用了
myVector = vector<__m256d>(nrVars(), _mm256_set1_pd(1.0));
Run Code Online (Sandbox Code Playgroud)
一次工作正常,但在执行该行两次后,它给了我一个分段错误。我能够想出以下代码
vector<__m256d> temp;
__m256d entry = _mm256_set1_pd(1.0);
temp = vector<__m256d>(10, entry);
temp = vector<__m256d>(10, entry);
Run Code Online (Sandbox Code Playgroud)
总是会产生分段错误。您能否向我解释为什么会这样,以及我将来如何避免这个问题?
非常感谢!
PS即使这样也行不通:
myVector.clear();
myVector.reserve(nrVars());
for (size_t i=0; i<nrVars(); ++i) {
myVector[i] = _mm256_set1_pd(1.0);
}
Run Code Online (Sandbox Code Playgroud)
并回答评论。这是一个产生段错误的完整示例:
#include <vector>
#include "immintrin.h"
using namespace std;
int main(int argc, char **argv) {
vector<__m256d> temp;
__m256d entry = _mm256_set1_pd(1.0);
temp = vector<__m256d>(10, entry);
temp = vector<__m256d>(10, entry);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
要阅读 m256d 和我正在使用的功能,请查看英特尔内部网站(https://software.intel.com/sites/landingpage/IntrinsicsGuide/)