C+中的快速内存访问+;? 当我在C++中开发了一个快速内存访问游戏时,我应该考虑什么?

C+中的快速内存访问+;? 当我在C++中开发了一个快速内存访问游戏时,我应该考虑什么?,c++,memory,memory-management,C++,Memory,Memory Management,我加载的内存是静态的,所以我应该放在一个连续的内存块中,对吗 另外,我应该如何组织结构内部的变量以提高性能 你不在乎。这些事情很可能是最小性质的微观优化。首先让它工作,如果它太慢,那么找出哪些部分慢,并对它们进行优化(提示:这可能是您调用库等的方式,而不是内存访问)。在出现问题之前找到解决方案是没有效率的 最好将精力集中在设计上,将这些细节留待以后处理,谁知道呢,由于良好的总体设计,最终可能永远不会出现任何性能问题。内存使用不必是连续的。如果你能将所使用的内存减半,这可能会有所帮助 在结构组织方

我加载的内存是静态的,所以我应该放在一个连续的内存块中,对吗


另外,我应该如何组织结构内部的变量以提高性能

你不在乎。这些事情很可能是最小性质的微观优化。首先让它工作,如果它太慢,那么找出哪些部分慢,并对它们进行优化(提示:这可能是您调用库等的方式,而不是内存访问)。

在出现问题之前找到解决方案是没有效率的


最好将精力集中在设计上,将这些细节留待以后处理,谁知道呢,由于良好的总体设计,最终可能永远不会出现任何性能问题。

内存使用不必是连续的。如果你能将所使用的内存减半,这可能会有所帮助

在结构组织方面,您应该将字节保持在一起,然后将字节缩短在一起,以此类推。否则,编译器将浪费内存来对齐较小的字节并缩短到双字位置

另一个提示。如果您使用的是一个类,那么您可以将它放在堆栈上,而不是用new来分配它

我是说

CmyClass x;

instead of 

Cmyclass px = new CmyClass;
...
delete px;
**编辑
当你调用NeW()或Maloc时,你会调用C++堆,有时堆会在几个周期中返回一个新的内存块,有时它不会。当您在堆栈上声明一个类时,您仍然会占用相同的内存量(可能更复杂),但该类只是在堆栈上“推送”的,不需要函数调用。曾经当函数退出时,堆栈被清除,堆栈收缩。

从缓存读取的地址比从主存读取的地址快得多。所以,试着让你们读到的任何地址尽可能靠近彼此

例如,在构建一个链表时,为所有节点创建一个大的块(可以按顺序排列)可能比为每个节点创建一个malloc(这可能会使数据结构产生碎片)更好。

内存性能非常模糊

我认为您需要的是处理CPU缓存,因为缓存中的访问和主内存中的访问之间有一个大约为10的因子

要获得有关缓存背后机制的完整参考,您可能希望阅读以下优秀系列文章

简言之:

瞄准地方

您不应该在内存中跳转,所以请尝试(如果可能)将要一起使用的项目分组

以可预测性为目标

如果您的内存访问是可预测的,那么CPU可能会为下一个工作块预取内存,以便在完成当前块后立即或很快可用

典型示例是阵列上的
for
循环:

for (int i = 0; i != MAX; ++i)
  for (int j = 0; j != MAX; ++j)
    array[i][j] += 1;
改变
数组[i][j]+=1
数组[j][i]+=1和性能变化。。。处于较低的优化级别;)

编译器应该捕获那些明显的情况,但有些情况更隐蔽。例如,使用基于节点的容器(链表、二进制搜索树)而不是基于数组的容器(向量、一些哈希表)可能会降低应用程序的速度

不要浪费空间。。。谨防虚假分享

尝试打包你的结构。这与对齐有关,您可能会因为结构中的对齐问题而浪费空间,这会人为地增大结构大小并浪费缓存空间

一个典型的经验法则是通过减小大小对结构中的项目进行排序(使用
sizeof
)。这是愚蠢的,但效果很好。如果您对尺寸和对齐更了解,只需避免孔:)注意:仅适用于具有大量实例的结构

然而,要小心虚假的分享。在多线程程序中,并发访问两个足够接近以共享同一缓存线的变量的成本很高,因为这涉及大量缓存失效和CPU争夺缓存线所有权

个人资料

不幸的是,这很难理解

如果您碰巧在Unix上编程,
Callgrind
(Valgrind套件的一部分)可以使用缓存模拟运行,并识别触发缓存未命中的代码部分


我想还有其他工具,我只是从来没有使用过。

我同意前面的说法。你应该写你的游戏,然后找出花在哪里的时间,并尝试在那里改进

然而,本着提供一些可能有用[并可能分散对实际问题的注意力:-)的精神,您可能会发现一些常见的陷阱:

  • 函数指针和虚拟方法提供了很大的设计灵活性,但是如果经常使用它们,您会发现它们比可以内联的东西要慢。这主要是因为CPU更难通过函数指针对调用执行分支预测。C++中的一个很好的解决方法是使用模板,这可以在编译时给你类似的设计灵活性。
    BR/>这种方法的一个潜在缺点是内联会增加代码的大小。好消息是编译器决定是否内联,而且它可能比您做出更好的决定。在许多情况下,您的优化器知道您的特定CPU体系结构,并且可以对此做出一些正确的猜测

  • 在频繁访问的数据结构中避免间接寻址

例如:

struct Foo
{
   // [snip] other members here...

   Bar *barObject;  // pointer to another allocation owned by Foo structure
};
有时会创建效率低于此的内存布局:

struct Foo
{
   // [snip] other members here...

   Bar barObject;  // object is a part of Foo, with no indirection
};
这听起来可能很傻,在大多数情况下,你不会注意到任何区别。但总的想法是,避免“不必要的间接”是一件好事。不要走得太远