【发布时间】:2019-06-12 11:38:49
【问题描述】:
我试图从实际意义上理解 AoS 和 SoA 之间的区别。
我已经在 C# 中尝试过,但没有产生任何结果,所以现在我在 C++ 中尝试。
#include <stdlib.h>
#include <chrono>
#include <iostream>
#include <math.h>
const int iterations = 40000000;
class Entity {
public:
float a, b, c;
};
struct Entities {
public:
float a[iterations];
float b[iterations];
float c[iterations];
};
void AoSTest(int iterations, Entity enArr[]);
void SoATest(int iterations, Entities* entities);
int main()
{
Entity* enArr = new Entity[iterations];
Entities* entities = new Entities;
int A = rand() - 50;
int B = rand() - 50;
int C = rand() - 50;
for (int i = 0; i < iterations; i++)
{
enArr[i].a = A;
enArr[i].b = B;
enArr[i].c = C;
entities->a[i] = A;
entities->b[i] = B;
entities->c[i] = C;
}
auto start = std::chrono::high_resolution_clock::now();
AoSTest(iterations, enArr);
//SoATest(iterations, entities);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
//std::cout << std::to_string(elapsed.count()) + "time";
std::cout << std::to_string(std::chrono::duration_cast<std::chrono::seconds>(finish - start).count()) + "s";
}
void AoSTest(int iterations, Entity enArr[]) {
for (int i = 0; i < iterations; i++)
{
enArr[i].a = sqrt(enArr[i].a * enArr[i].c);
enArr[i].c = sqrt(enArr[i].c * enArr[i].a);
//std::cout << std::to_string(sqrt(enArr[i].a) + sqrt(enArr[i].b)) + "\n";
}
}
void SoATest(int iterations, Entities* entities) {
for (int i = 0; i < iterations; i++)
{
entities->a[i] = sqrt(entities->a[i] * entities->c[i]);
entities->c[i] = sqrt(entities->c[i] * entities->a[i]);
//std::cout << std::to_string(sqrt(entities->a[i]) + sqrt(entities->b[i])) + "\n";
}
}
我的想法是,由于理论上数据布局应该不同,因此应该有性能差异......
我不明白为什么有人说如果它对上下文如此敏感,到目前为止我认为它有很多好处。
它完全依赖于 SIMD 还是某些特定的优化选项?
我在 Visual Studio 中运行它。
【问题讨论】:
-
你是如何构建它的?东西被优化了吗? godbolt.org 会发生什么?
-
您是否构建了它并启用了优化?输出是什么?
-
似乎不会有性能差异。它更多地是关于你如何为你的记忆建模——这对你来说更容易理解。
标签: c++ performance