簡體   English   中英

AVX2:分配給__m256i類成員時出現分段錯誤

[英]AVX2: segmentation fault when assigning to __m256i class member

我目前正在重構一個命令式C ++程序,該程序將AVX2原語廣泛使用到結構良好的基於​​類的程序中。 不幸的是,在分配給具有AVX2數據類型的類成員時遇到了段錯誤。

我在WSL中使用:

gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)

用標志編譯:

g++ -mavx2 -g minimal.cpp

再現段錯誤的最小代碼示例是:

#include <immintrin.h>

class MyClass
{
    public:
        MyClass(int* arr);
        __m256i value;
};

MyClass::MyClass(int* arr){
    this->value = _mm256_set_epi32(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]);
}

int main(){
    int arr[8] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7};
    MyClass* m = new MyClass(arr);
}

GDB輸出:

Program received signal SIGSEGV, Segmentation fault.
0x00000000080007cf in MyClass::MyClass (this=0x8413e70, arr=0x7ffffffedd90) at minimal.cpp:11
11          this->value = _mm256_set_epi32(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]);

我已經嘗試在構造函數之后分配類成員,即相同的段錯誤。

更新: 是一個相關的問題,但是不是重復的。(在此:關注班級成員,與“新”的關系只有在最初的問題之后才變得明顯)

正如彼得·科德斯(Peter Cordes)在上面的評論中已經提到的那樣,這里的問題是new不尊重C ++ 17之前的擴展對齊。 (請參閱[P0035R4] (在C ++ 17中被采用,以使new的內存可用於比alignof(maxalign_t)對齊更多的內存alignof(maxalign_t) )。

GCC7和更高版本支持使用-std=gnu++17-std=c++17 (或僅-faligned-new )來-faligned-new 如果打開這些選項,您的代碼將為Just Work™並自動將所需的對齊方式傳遞給operator new


但舊的GCC,包括你的6.3, 沒有 ,所以你必須手動確保獲取已正確對齊的內存。 有幾種方法可以這樣做。

_mm_alloc已在注釋中提及。 在GCC上, _mm_alloc似乎基本上映射到posix_memalign ,因此您也可以直接使用它。 一個可移植的C ++ 11解決方案將分配一個足夠大的緩沖區,以容納您的類的對象,以及開始時需要進行填充以確保正確對齊的任何空間。 然后,您可以使用std::alignplacement new在適當對齊的地址處構造對象。

綜上所述,無論您選擇哪種分配適當對齊的內存的方法,我都強烈建議通過為您的類提供分配和釋放函數來封裝這些內容。 對齊要求是類型本身的屬性,由於實現細節(例如它具有__m256i類型的成員這樣的事實),所以不應該讓類的用戶知道該對齊要求,因為MyClass類型的任何對象都已擴展對齊要求,每當通過新表達式分配此類對象時,都必須考慮這些要求。 您應該禁止通過新表達式創建該類型的對象,或者提供必要的工具以使該類型與新表達式一起正常工作……

C ++ 11解決方案可能如下所示:

#include <cstddef>
#include <memory>

#include <immintrin.h>

class MyClass
{
    __m256i value;

public:
    MyClass(const int* arr)
    {
        this->value = _mm256_set_epi32(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]);
    }

    void* operator new(std::size_t size)
    {
        return _mm_malloc(size, alignof(MyClass));
    }

    void* operator new[](std::size_t size)
    {
        return _mm_malloc(size, alignof(MyClass));
    }

    void operator delete(void* ptr)
    {
        _mm_free(ptr);
    }

    void operator delete[](void* ptr)
    {
        _mm_free(ptr);
    }
};

int main()
{
    int arr[8] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7};
    auto m = std::unique_ptr<MyClass> { new MyClass(arr) };
}

這里的例子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM