如何从对象数组中提取属性数组?

How to extract an array of properties out of an array of objects?

本文关键字:数组 提取 属性 对象      更新时间:2023-10-16

想象一下我有一个对象数组,如下所示:

class Segment {
public:
float x1, x2, y1, y2;
}
Segment* SegmentList[100];

基于这个段数组,我想快速提取它的属性并创建包含所有 x1、x2、y1 和 y2 的向量,就像这样;

float x1List[100];
for(int=0; i<100; i++) {
x1List[i] = SegmentList[i]->x1;
}

我想知道是否有一种更快的方法将所有"x1"属性读取到数组中。

更新 1:

由于我将使用此数组加载到 AVX 寄存器中,因此我可以将我的问题改写为:

"有没有更快的方法将对象数组的属性加载到 AVX 寄存器中?">

我只想提出一个不同的观点。我的贡献实际上只是在您的原始帖子下方扩展了一条评论,@PeterCordes,但它太长了,无法作为对该评论的回复发布。

我最近刚刚优化了我的一个旧模拟。我有一个和你类似的问题。我正在模拟粒子的运动,我的程序依赖于大致如下的结构:

struct Particle
{
double x, y, z; // x,y,z positions
double vx, vy, vz; // x,y,z velocities
};

我知道单个粒子的仿真是相互独立的,因此我决定使用 SIMD 并行性来加快仿真速度。 如果我继续依赖粒子结构,我将不得不像这样将速度和位置的每个分量加载到 AVX 寄存器中。为了简单起见,我假装我的数组只由四个粒子组成,但实际上我正在处理一个包含数千个粒子的堆数组

void make_one_step(std::array<Particle, 4>& p, double time_step)
{
__m256d pos_x = _mm256_set_pd(p[3].x, p[2].x, p[1].x, p[0].x);
// do similar for y and z component of position and for all velocities
// compute stuff (bottleneck)
// __m256d new_pos_x = ...
// do this for every component of velocity and position
double vals[4];
_mm256_store_pd(vals, new_pos_x);
for(int i = 0; i < 4; ++i) p[i].x = vals[i]; 
}
void simulate_movement(std::array<Particle, 4>& p)
{
for( ... lots of steps ...)
{
make_one_step(p, time_step); // bottleneck
// check values of some components and do some cheap operations
}
}

说实话,我必须在模拟中计算如此多的东西(一些相对先进的物理学),以至于加载和存储根本不是瓶颈。但是,在程序的每一步中重新包装的丑陋给了我额外的动力来解决问题。我没有更改算法的输入(我仍然使用粒子对象),但在算法本身中,我重新组合了来自四个粒子的数据,并将其存储在这样的结构中:

struct Quadruple
{
double pos_x[4]; 
// and similar for other position/velocity components
}

在这些更改之后,模拟看起来像这样。长话短说,我只是修改了算法和接口之间的层。高效装载?检查。输入数据不变?检查。

void make_one_step(Quadruple& p, double time_step)
{
__m256d pos_x = _mm256_load_pd(p.pos_x); // for every component
// compute stuff in same way as before
_mm256_store_pd(p.pos_x, new_pos_x); // for every component
}
void simulate_movement(std::Array<Particle, 4> &particles, double time_step)
{
//Quadruple q = ... // store data in Quadruple
for( ... a lot of time steps ... )
{
make_one_step(q, time_step); //bottleneck
// check values of some components and do some cheap operations
}
// get data from quadruple and store it in an array of particles
}

不幸的是,我无法判断这是否对你有帮助;这取决于你做什么。如果您在开始计算之前需要数组中的所有数据,我的建议将无济于事,如果重新组合数据本身被证明是一个瓶颈,它将同样无用。:)祝你好运。