如果我想std::vector用SSE 处理数据,我需要16字节对齐.我怎样才能做到这一点?我需要编写自己的分配器吗?或者默认分配器是否已经与16字节边界对齐?
我__m256用作模板类的参数(参见下面的代码).在Ubuntu 16.10(Yakkety Yak)上使用g ++ 6.2进行编译时,它会警告我在模板参数上忽略了属性:
警告:忽略模板参数'__m256上的属性{aka __vector(8)float}'[-Wignored-attributes] typedef vec_array <__ m256> vec256
这种__m256类型似乎有一些关于对齐的属性(也许还有其他一些?).(其产生警告和)下面示出该原语容器类的唯一目的是处理在堆上这些特殊英特尔变量(存储器对准__m256,__m128等等).
当我在整个程序中使用此容器类时,它似乎工作正常.但是,我的问题是当GCC忽略这些属性时会产生什么影响(我已经阅读了GCC手册对该问题的看法).
作为参考,下面的代码会产生此警告.
///////////////////////////////////////////////////////////////////////////////
// System includes:
#include <x86intrin.h>
#include <cstdint>
static const size_t AVX_alignment = 32;
template<typename VecT>
class vec_array
{
protected:
VecT* m_pdata;
size_t m_num_vector_elements;
public:
vec_array();
vec_array(size_t num_vector_elements);
virtual ~vec_array();
void allocate(size_t num_vector_elements);
void free();
};
template<typename VecT>
vec_array<VecT>::vec_array() : m_pdata(nullptr), m_num_vector_elements(0)
{}
template<typename VecT>
vec_array<VecT>::vec_array(size_t num_vector_elements) : m_pdata(nullptr),
m_num_vector_elements(num_vector_elements)
{
allocate(num_vector_elements); …Run Code Online (Sandbox Code Playgroud) 在以下问题是相关的,但答案是旧的,并且从用户评论马克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++ 有更好的方法?
我想询问是否有更快的方法来进行音频转换,而不是逐个迭代所有值并将它们除以32768.
void CAudioDataItem::Convert(const vector<int>&uIntegers, vector<double> &uDoubles)
{
for ( int i = 0; i <=uIntegers.size()-1;i++)
{
uDoubles[i] = uIntegers[i] / 32768.0;
}
}
Run Code Online (Sandbox Code Playgroud)
我的方法很好,但它可以更快.但是我没有找到任何方法来加快速度.
感谢您的帮助!
我在使用时遇到对齐问题 ymm寄存器,一些代码片段对我来说似乎很好.这是一个最小的工作示例:
#include <iostream>
#include <immintrin.h>
inline void ones(float *a)
{
__m256 out_aligned = _mm256_set1_ps(1.0f);
_mm256_store_ps(a,out_aligned);
}
int main()
{
size_t ss = 8;
float *a = new float[ss];
ones(a);
delete [] a;
std::cout << "All Good!" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然,sizeof(float)是4在我的架构(英特尔(R)至强(R)CPU E5-2650 V2 @ 2.60GHz),我与编译gcc使用-O3 -march=native标志.当然,错误会随着未对齐的内存访问而消失,即指定_mm256_storeu_ps.我在xmm寄存器上也没有这个问题,即
inline void ones_sse(float *a)
{
__m128 out_aligned = _mm_set1_ps(1.0f);
_mm_store_ps(a,out_aligned);
}
Run Code Online (Sandbox Code Playgroud)
我做了什么愚蠢的事吗?解决这个问题的方法是什么?
我正在尝试将一个向量加载到SSE寄存器中,我的代码编译没有错误,但是当我尝试运行它时,我有分段错误.这是我的代码:
inline int SSEJaccard::calcSSEJaccardDist(unsigned int id1, unsigned int id2) {
int result;
__m128i v, v1;
std::vector<uint32_t> &fv1 = fvs[id1];
std::vector<uint32_t> &fv2 = fvs[id2];
v = _mm_load_si128((__m128i const*) (&fv1));
v1 = _mm_load_si128((__m128i const*) (&fv2));
v = _mm_and_si128(v,v1);
result =_mm_extract_epi16(v, 0) + _mm_extract_epi16(v, 4);
return result;
}
Run Code Online (Sandbox Code Playgroud)
fsv是一个全局变量,定义如下:
std::vector<std::vector<uint32_t> > fvs;
Run Code Online (Sandbox Code Playgroud)
我正在使用英特尔编译器(ICC).谢谢