In this slides (在幻灯片15之后)建议使用
void updateAims(float* aimDir, const AimingData* aim, vec3 target, uint count)
{
for(uint i = 0; i < count; i++)
{
aimDir[i] = dot3(aim->positions[i], target) * aim->mod[i];
}
}
因为它的缓存效率更高。
如果我有课
怎么办?class Bot
{
vec3 position;
float mod;
float aimDir;
void UpdateAim(vec3 target)
{
aimDir = dot3(position, target) * mod;
}
};
void updateBots(Bots* pBots, uint count, vec3 target)
{
for(uint i = 0; i < count; i++)
pBots[i]->UpdateAim(target);
}
我将该类的所有对象存储在一个线性数组中。
由于它们都在同一个数组中会有缓存未命中吗? 为什么第一种方法会更好?
答案 0 :(得分:10)
现代缓存架构通常被构造为数据的行,每个都足以容纳多个单词; 64字节是典型的行大小。当您尝试读取不在缓存中的数据时,将获取整行,而不仅仅是您需要的单词。写入时,缓存中的数据会更新(如果存在),但如果不存在则通常不需要获取。
在第一种情况下,对于每个获取的输入数据的高速缓存行,您将使用它的每个单词。在第二个,你只会使用一些结构字段;抓住其他人浪费了一些带宽。
具体来说,您每次都会获取aimDir
的旧值,这不是计算所需的。通常,“对象”可能包含更多字段,这些字段是您不希望进行此特定计算的,因为它们被提取到缓存中然后被忽略会浪费更多带宽。
答案 1 :(得分:0)
内存布局差异很大,如果使用Bots数组,第一种方法的好处将会被破坏。
在第一种方法中,所有aimDir
数据都存储在非碎片的内存块中。因此,如果您处理了第一个,您可以立即进入下一个项目,因为它存储在下一个内存单元中。
如果你有一个Bot
的数组,那么你有Bot
个对象存储在一个非碎片的内存块中。但是,两个机器人的不同aimDir
数据现在由机器人(position
和mod
)用其他数据分隔。
从图形上看,第一种方法(如果假设位置和mod的数组也是如此)看起来像
[R]表示与机器人无关的随机未知数据
[R][position_0][position_1]...[position_n][R][mod_0][mod_1]...[mod_n][R][aimDir_0][aimDir_1]...[aimDir_n][R]
第二种方法如下:
[R][[position_0],[mod_0],[aimDir_0]][[position_1][mod_1][aimDir_1]]...[[position_n][mod_n][aimDir_n]][R]