结构和存储器使用模式的阵列的结构,数组(Struct of arrays, arrays of st

2019-10-23 20:44发布

我一直在阅读有关SOA和我想尝试的在我建立了一个系统,实现它。

我写了一些简单的C结构做了一些测试,但我有点糊涂了,现在我有一个3个不同的结构vec3 。 下面我会告诉他们,然后进入有关这一问题的进一步细节。

struct vec3
{
size_t x, y, z;
};

struct vec3_a
{
size_t pos[3];
};

struct vec3_b
{
size_t* x;
size_t* y;
size_t* z;
};

struct vec3 vec3(size_t x, size_t y, size_t z)
{
    struct vec3 v;
    v.x = x;
    v.y = y;
    v.z = z;
    return v;
}

struct vec3_a vec3_a(size_t x, size_t y, size_t z)
{
    struct vec3_a v;
    v.pos[0] = x;
    v.pos[1] = y;
    v.pos[2] = z;
    return v;
}

struct vec3_b vec3_b(size_t x, size_t y, size_t z)
{
    struct vec3_b v;
    v.x = (size_t*)malloc(sizeof(size_t));
    v.y = (size_t*)malloc(sizeof(size_t));
    v.z = (size_t*)malloc(sizeof(size_t));
    *(v.x) = x;
    *(v.y) = y;
    *(v.z) = z;
    return v;
}

这三种类型的VEC3的声明。

struct vec3 v = vec3(10, 20, 30);
struct vec3_a va = vec3_a(10, 20, 30);
struct vec3_b vb = vec3_b(10, 20, 30);

打印出来的printf与我得到的值这样的地址:

size of vec3      : 24 bytes
size of vec3a     : 24 bytes
size of vec3b     : 24 bytes
size of size_t    : 8 bytes
size of int       : 4 bytes
size of 16 int    : 64 bytes
vec3 x:10, y:20, z:30
vec3 x:0x7fff57f8e788, y:0x7fff57f8e790, z:0x7fff57f8e798
vec3a x:10, y:20, z:30
vec3a x:0x7fff57f8e768, y:0x7fff57f8e770, z:0x7fff57f8e778
vec3b x:10, y:20, z:30
vec3b x:0x7fbe514026a0, y:0x7fbe51402678, z:0x7fbe51402690

我做的最后一件事是创建10个结构数组vec3_b并打印出其返回这些值的地址。

    struct vec3_b vb3[10];
    for(int i = 0; i < 10; i++)
    {
        vb3[i] = vec3_b(i, i*2, i*4);
    }

index:0 vec3b x:0x7fbe514031f0, y:0x7fbe51403208, z:0x7fbe51403420
index:1 vec3b x:0x7fbe51403420, y:0x7fbe51403438, z:0x7fbe51403590
index:2 vec3b x:0x7fbe51403590, y:0x7fbe514035a8, z:0x7fbe514035c0
index:3 vec3b x:0x7fbe514035c0, y:0x7fbe514035d8, z:0x7fbe514035f0
index:4 vec3b x:0x7fbe514035f0, y:0x7fbe51403608, z:0x7fbe51403680
index:5 vec3b x:0x7fbe51403680, y:0x7fbe51403698, z:0x7fbe514036b0
index:6 vec3b x:0x7fbe514036b0, y:0x7fbe514036c8, z:0x7fbe514036e0
index:7 vec3b x:0x7fbe514036e0, y:0x7fbe514036f8, z:0x7fbe51403710
index:8 vec3b x:0x7fbe51403710, y:0x7fbe51403728, z:0x7fbe51403740
index:9 vec3b x:0x7fbe51403740, y:0x7fbe51403758, z:0x7fbe51403770

问题:

  1. 是我实现的struct vec3_b设置适当的方式排列的结构?

  2. 由于vec_3b结构为24个字节大,我能适应现代1个CPU的缓存行2个加12的额外字节?

  3. 如果我的vec3_b是做SOA的设置适当的方式,我有一些麻烦的处理,这里我把10 vec3_b在一起。

纵观十六进制值及其十进制表示我不能看到这使我相信,我的设置是不正确的任何图案。

      ---------------x-----------------|----------------y-----------------|----------------z-----------------|

0|    0x7fbe514031f0 : 140455383675376 | 0x7fbe51403208 : 140455383675400 | 0x7fbe51403420 : 140455383675936
1|    0x7fbe51403420 : 140455383675936 | 0x7fbe51403438 : 140455383675960 | 0x7fbe51403590 : 140455383676304
2|    0x7fbe51403590 : 140455383676304 | 0x7fbe514035a8 : 140455383676328 | 0x7fbe514035c0 : 140455383676352

Answer 1:

  1. 我想不出一个场合时vec_3b将是一个不错的主意。

  2. 请注意,您还必须找到空间的指针在指向24个字节的数据,它可能不会是连续的与结构本身,所以你可能只是相比2倍降低你的有效的缓存大小vec3vec_3a 。 每个malloc()具有最小尺寸; 在64位机器上,通常是至少16个字节。 因此,对于三个三个独立的分配在值指出在vec_3b结构需要至少48,用于支持数据(加上24本身的结构)的其它字节。 这并不适合单个高速缓存行; 它不能保证放置,使其适合2个高速缓存行。

  3. N / A - 这个问题的前提是一个错误的假设。



Answer 2:

1和3:不,你的vec3_b 不是结构-的阵列的设置。

你在做什么是具有多种结构,每一个64位的数据指针的64位。

随着结构-阵列的,你让ONE结构,它具有可变大小的几个阵列。

因此,第十x值将是mystruct.x[9]mystruct[9].x[0]

关键的一点是要有连续存储所有的x值,这样你就可以加载多个x与价值观movdqu / _mm_loadu_si128 。 如果你使用SIMD工作,选择将支持您需要的值的范围最小元素的宽度。 使用64位的元素将削减你的吞吐量的一半,与32位元素。 您的代码将同时处理128B,这是两倍多的元素,如果他们半宽。



文章来源: Struct of arrays, arrays of structs and memory usage pattern