美文网首页
avx2 _mm256_store_ps()多行调用时出问题

avx2 _mm256_store_ps()多行调用时出问题

作者: 寽虎非虫003 | 来源:发表于2022-04-19 17:10 被阅读0次

    问题描述

    我有两个函数从__m256拷贝数据到float *再转到unsigned char,其中一个是单通道的,一个是三通道的,代码如下

    typedef __m256 __m256f;
    // 单通道版本
    void _mm256_store_ps_to8(__m256f &_f256, unsigned char *p8, int &index, int &nMax)
    {
        float *p = new float[8];
        _mm256_store_ps(p, _f256);
        for (size_t i = 0; i < 8; i++)
        {
            p8[MIN(nMax, index + i)] = static_cast<unsigned char>(p[i]);
        }
        delete[] p;
    }
    
    //3通道版本
    void _mm256_store_ps_to8x3(__m256f &_f256_R, __m256f &_f256_G, __m256f &_f256_B,
                               unsigned char *p8, int &index, int &nMax)
    {
        int nm = nMax * 3;
        int ni = index * 3;
        float *pR = new float[8];
        float *pG = new float[8];
        float *pB = new float[8];
    
        _mm256_store_ps(pR, _f256_R);
        _mm256_store_ps(pG, _f256_G);
        _mm256_store_ps(pB, _f256_B);
        for (size_t i = 0; i < 8; i++)
        {
            p8[MIN(nm, ni + i * 3 + 2)] = static_cast<unsigned char>(pR[i]);
            p8[MIN(nm, ni + i * 3 + 1)] = static_cast<unsigned char>(pG[i]);
            p8[MIN(nm, ni + i * 3)] = static_cast<unsigned char>(pB[i]);
        }
        delete[] pR;
        delete[] pG;
        delete[] pB;
    }
    

    其中单通道的方法能够正常工作,但是3通道就不行。会在_mm256_store_ps(pG, _f256_G);这一行报出Segmentation fault (core dumped)

    有效的解决方案

    将原本的new的行改成如下即可

        size_t alignment = alignof(__m256f);
        float * pR = (float *) aligned_alloc(alignment, sizeof(float) * 8);
        float * pG = (float *) aligned_alloc(alignment, sizeof(float) * 8);
        float * pB = (float *) aligned_alloc(alignment, sizeof(float) * 8);
    

    补充关于aligned_alloc

    以下内容来源于aligned_alloc()函数-C/C++

    函数签名

    void *aligned_alloc(size_t alignment, size_t size);
    

    函数定义在stdlib.h
    第一个参数alignment规定了分配空间的起始地址对齐的位置,由于地址是二进制的因此alignment也必须是2的整数次方.
    比如alignedment= 2^{8} = 256时,分配地址的低8位为00000000.alignedment= 2^{10} = 1024时,分配地址的低10位为0000000000.
    第二个参数size为分配的具体空间大小.规定size必须为alignment的整数倍.

    使用方法
    一般来讲分配的空间会大于实际需要的空间.由于不知道要分配数据类型在系统中的大小所以会将size = alignment * sizeof(数据类型).这就导致了分配空间大于实际需要的空间.
    aligned_alloc()一般使用在intel的AVX指令集中,从内存中初始化向量.下面举两个例子说明如何使用该函数.

    1. 分配int数组空间
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int *p1 = (int *)malloc(10 * sizeof(int));
        printf("default-aligned addr:   %p\n", (void*)p1);
        free(p1);
    
        int *p2 = (int *)aligned_alloc(1024, 1024 * sizeof(int));
        printf("1024-byte aligned addr: %p\n", (void*)p2);
        free(p2);
    }
    

    第一个例子给int数组分配了一段空间,可以从结果看到aligned_alloc()分配的空间起始地址对齐了0x7fffcbf35800,运行结果见下:

    default-aligned addr:   0x7fffdd5c6260
    1024-byte aligned addr: 0x7fffdd5c7400
    
    1. 用aligned_alloc()分配的空间初始化向量
    #include <immintrin.h>
    #include "print.h"
    
    int main()
    {
        // 用float指针初始化向量
        int i;
        // 这个地方实际上多申请的很多空间
        float *aligned_float = (float *)aligned_alloc(32, 8 * 8 * sizeof(float));
        // 给申请的空间赋值
        for (i = 0; i < 8; ++i) aligned_float[i] = (float)(i) + 1;
        // 使用对齐的内存空间初始化AVX中的向量
        __m256 float_vec = _mm256_load_ps(aligned_float);
    
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:avx2 _mm256_store_ps()多行调用时出问题

          本文链接:https://www.haomeiwen.com/subject/mlhlertx.html