【发布时间】:2015-11-06 15:45:41
【问题描述】:
我正在尝试用 c 编程围绕 SOA [数组结构]。
我有一些简单的数学函数,我编写了我认为相当不错的标量实现。
这里是一个简单的向量3数据结构
struct vector3_scalar {
float p[3];
};
以及我编写的一个典型函数,用于添加其中两个向量 3 数据结构。
struct vector3_scalar* vec3_add(struct vector3_scalar* out,
const struct vector3_scalar* a,
const struct vector3_scalar* b) {
out->p[0] = a->p[0] + b->p[0];
out->p[1] = a->p[1] + b->p[1];
out->p[2] = a->p[2] + b->p[2];
return out;
}
我知道这个简单的数据结构没有正确填充,但对于标量,我只是想在开始实现其他功能之前先得到一些有效的东西。
现在我的问题是,“无填充问题”结构是设置数据结构的好方法吗?
这些呢?
struct vector3_scalar {
float p[3];
};
struct vector3_scalar {
float px;
float py;
float pz;
};
或任何其他我可以布置数据的方式。我个人不介意翻转数据结构,因为一旦编写和优化了这个数学的用户不应该把它弄得这么低,只需要更高级的函数就可以了;
vec3 *a = vec3_create(0, 1, 0);
vec3 *b = vec3_create(1, 0, 0);
vec3 *c = vec3_zero(void);
vec3* vec3_add(vec3* out, const vec3* in_a, const vec3* in_b);
c = vec3_add(c, a, b); // c == 1, 1, 0
以便您可以内联或单独使用该函数。
vec3 *d = vec3_create(10, 10, 10);
vec3 *e = vec3_create(1, 1, 1);
vec3 *f = vec3_zero();
/* c + d = 11, 11, 10 */ /* c + e = 2, 2, 1 */
vec3_add(f, vec3_add(c, d), vec3_add(c, e));
vec3_free(a);
...
vec3_free(f);
正如您从公共 api 中看到的那样,除了实现者之外,底层结构应该并不重要。
我想使用如下数据布局编写我已经编写的基本标量版本:
struct vector3_scalar {
float p[3];
}
但我愿意改变它,因为它可以工作并且看起来足够稳定以符合我的口味。
【问题讨论】:
-
根据您显示的内容,没有任何其他上下文,如果您使用离散值
px、py、pz或数组p[3]并不重要.我不确定您所说的“填充问题”是什么意思。我认为这两种方法都没有任何问题。你有具体的问题吗?如果不是,那么这个问题很大程度上是基于意见的,或者应该在 codereview.stackexchange.com 区域中。 -
这些假设的“填充问题”是什么?不要为他们担心;编译器以最佳方式布置事物。对填充感到不安的人要么在设计结构时粗心,要么试图强制文件或有线格式的内存表示与文件或有线格式中的字节完全匹配。没有证据表明这里有问题。在您的两种数据结构中,都没有填充(或者您不太可能有一个引入任何填充的编译器,尽管编译器理论上可以,但实际上不会)。
-
填充是在处理 SIMD 设备等并行数据操作时,通常为缓存一致性的 16、32、64 或 128 位对齐数据。
-
我怀疑您误解了 AOS 和 SOA 之间的区别。如果您使用 3 个值的“数组”来表示,例如三维空间中的坐标,您不是在使用数组结构,而是在使用结构数组。
-
@EOF 我确定我误解了 AOS 和 SOA,这就是问题的根源。我进行了很多搜索并听到了它的提及,但没有太多可靠的文档。你有什么可以参考的吗?
标签: c arrays data-structures parallel-processing structure