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

问题描述 投票:2回答:2

当我在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, 28, 29, 30, 31);

        }
    }
    std::cout<<"End AVX."<<std::endl;
    return 0;
}
c++11 codeblocks intrinsics avx
2个回答
5
投票

问题是在C ++ 17之前,newdelete不尊重待分配类型的对齐。如果从这个简单的函数中查看生成的程序集:

INFO* new_test() {
    int _size = 100;
    INFO  *info = new INFO[_size];
    return info;
}

您将看到,在使用C ++之前的任何内容编译时,将调用operator new[](unsigned long),而对于C ++ 17,将调用operator new[](unsigned long, std::align_val_t)(并且为第二个参数传递32)。 Play around with it at godbolt

如果你不能使用C ++ 17,你可以覆盖operator new[](和operator delete[] - 你也应该覆盖operator newoperator delete ......):

struct INFO {
    unsigned int id = 0;
    __m256i temp[8];
    void* operator new[](size_t size) {
        // part of C11:
        return aligned_alloc(alignof(INFO), size);
    }
    void operator delete[](void* addr) {
        free(addr); // aligned_alloc is compatible with free
    }
};

如果你用-DOVERWRITE_OPERATOR_NEW编译,这是前一个godbolt例子的一部分。

请注意,这不能解决使用std::vector(或任何其他std-container)时的对齐问题,因为您需要将对齐的分配器传递给容器(不是前一个示例的一部分)。


0
投票

我找到了解决这个问题的两种方法

第一个解决方案How to solve the 32-byte-alignment issue for AVX load/store operations?

struct INFO
{
    __m256i temp[8];
    unsigned int id = 0;
};
INFO  *info = static_cast<INFO*>(_mm_malloc(sizeof(INFO)*_size, 32));
_mm_free(info);

第二个解决方案

INFO  *info = new INFO[_size];
for (int i = 0; i < _size; i++)
{
    INFO new_info;
    for (int k = 0; k < 8; k++)
    {
        new_info.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, 28, 29, 30, 31);

    }
    info[i] = new_info;
}
© www.soinside.com 2019 - 2024. All rights reserved.