gpt4 book ai didi

c - 数组结构和内存访问模式

转载 作者:太空狗 更新时间:2023-10-29 15:02:09 25 4
gpt4 key购买 nike

这是对这个原始问题的跟进,添加了一些新信息。如果您有兴趣,请在此处查看第一部分:Struct of arrays, arrays of structs and memory usage pattern

我第一次尝试为一个简单的类设置数组结构时,似乎出现了很多问题。主要是为指针分配过多的内存,以及在上一个问题中从 vec3_b 分配这些指针可能导致内存泄漏。

我考虑过如何在不使用指针的情况下重新排列数据,这需要我首先为我的数据桶的大小设置一些常量变量,这样就没有像指针这样的无限值,但也会减少内存量固定。

    const size_t batch_size = 100;
struct vec3_c
{
size_t x[batch_size];
size_t y[batch_size];
size_t z[batch_size];
};

struct vec3_c vec3_c(size_t x, size_t y, size_t z, size_t index)
{
struct vec3_c v;
v.x[index] = x;
v.y[index] = y;
v.z[index] = z;
return v;
}

struct vec3_c vc3;
for(int i = 0; i < batch_size; i++)
{
vc3 = vec3_c(i+1, i*i, i*10, i);
//printf("vec3c x:%zu, y:%zu, z:%zu\n",vc3.x[i], vc3.y[i], vc3.z[i]);
printf("vec3c x:%p, y:%p, z:%p\n",(void*)&vc3.x[i], (void*)&vc3.y[i], (void*)&vc3.z[i]);
}

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

0| 0x7fff57489f40 : 140734657765184 | 0x7fff5748a260 : 140734657765984 | 0x7fff5748a580 : 140734657766784
1| 0x7fff57489f48 : 140734657765192 | 0x7fff5748a268 : 140734657765992 | 0x7fff5748a588 : 140734657766792
2| 0x7fff57489f50 : 140734657765200 | 0x7fff5748a270 : 140734657766000 | 0x7fff5748a590 : 140734657766800

使用这个更新的代码,我必须有一个固定的桶大小,所以我将它设置为 100 的 batch_size 只是为了简单的数字。用一些数据填充 vec3c 并做了类似的测试,这次似乎每个值都以 8 字节 block 对齐。

例如:

size of vec3      : 24 bytes
size of vec3a : 24 bytes
size of vec3b : 24 bytes
size of vec3c : 2400 bytes
size of size_t : 8 bytes
size of int : 4 bytes
size of 16 int : 64 bytes
vec3c x:0x7fff592d2f40, y:0x7fff592d3260, z:0x7fff592d3580
vec3c x:0x7fff592d2f48, y:0x7fff592d3268, z:0x7fff592d3588
vec3c x:0x7fff592d2f50, y:0x7fff592d3270, z:0x7fff592d3590
vec3c x:0x7fff592d2f58, y:0x7fff592d3278, z:0x7fff592d3598
vec3c x:0x7fff592d2f60, y:0x7fff592d3280, z:0x7fff592d35a0
vec3c x:0x7fff592d2f68, y:0x7fff592d3288, z:0x7fff592d35a8
vec3c x:0x7fff592d2f70, y:0x7fff592d3290, z:0x7fff592d35b0
vec3c x:0x7fff592d2f78, y:0x7fff592d3298, z:0x7fff592d35b8
vec3c x:0x7fff592d2f80, y:0x7fff592d32a0, z:0x7fff592d35c0
vec3c x:0x7fff592d2f88, y:0x7fff592d32a8, z:0x7fff592d35c8

均以8字节分隔。

这应该可以解决内存泄漏和指针所需的额外内存问题。

这是新的布局,比如 sizeof(vc3[0].x) 会返回 8 个字节。

回到最初的问题:

  1. 我的 struct vec3_c 实现是设置数组结构的正确方法吗?

  2. vec_3c 批处理大小为 100,它显示 2400 字节大,但每个单独的元素只有 8 个字节并且正确对齐,所以我现在实际上可以在 1 个现代 cpu 缓存行上容纳 8 个元素?

  3. 将传递给我的数据转换成结构数组的典型格式是否会超过处于缓存友好状态并且能够在每个指令调用上对多个数据点进行操作的性能优势?需要注意的是,第 1 点和第 2 点都是正确的。

ex 计算两个 vector 的点积:这意味着我可以在每个指令周期得到 2 个 vec3_c 的点积?

编辑还有一个问题,添加额外的 8 字节数据以使该结构成为 32 字节的倍数并且可能将额外的 8 字节用作暂存空间或将其留空会更好吗?

编辑有人向我指出,我的初始初始化函数只是把事情搞得一团糟。我将其更新为这种形式:

struct vec3_c* vec3_c()
{
struct vec3_c *v = (struct vec3_c*)malloc(sizeof(struct vec3_c));
v->index = 0;
return v;
}

struct vec3_c* v3 = vec3_c();
for(size_t i = 0; i < batch_size; i++)
{
v3->x[i] = i + 1;
v3->y[i] = i * i;
v3->z[i] = i * 10;
printf("index:%d\tvec3c x:%zu, y:%zu, z:%zu\n",i,v3->x[i], v3->y[i], v3->z[i]);
printf("index:%zu\tvec3c x:%p, y:%p, z:%p\n",i,(void*)&v3->x[i], (void*)&v3->y[i], (void*)&v3->z[i]);
}

最佳答案

如果您将拥有 很多 这些 xyz 点,并且您希望能够同时对所有 x 执行操作,那么将所有 x 放在一起更有意义:

struct PointBatch {
size_t x[batchsize];
size_t y[batchsize];
size_t z[batchsize];
}

// More efficient for things like
// - find the point with the largest X
// - find the sum of all the points as [xsum, ysum, zsum]

如果您通常对单个数据点的 x、y 和 z 进行操作,那么将每个点放在一起作为一个结构更有意义。

struct Point {
size_t x;
size_t y;
size_t z;
}

struct Point pointBatch[batchsize];

// Better for things like
// - plot all the points on a graph
// - determine which points satisfy the equation: x^2 + y^2 < z^2

注意
请注意,在性能不是问题的情况下,您可能会发现 Point/pointBatch 方法使您的代码更易于编写且更具可读性,因为struct PointBatch 没有提供方便的方法来引用或传递单个点。

关于c - 数组结构和内存访问模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31422631/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com