1

我本来打算写一篇长篇大论的文章,​​但我会在这里总结一下:

我正在尝试通过 XNA 模仿 NES 的图形老式风格。但是,我的 FPS 很慢,试图修改每帧 65K 像素。如果我只是循环遍历所有 65K 像素并将它们设置为任意颜色,我会得到 64FPS。我为查找应该将哪些颜色放置在哪里而编写的代码,我得到了 1FPS。

我认为这是因为我的面向对象代码。

现在,我将事物分为大约六个类,包括 getter/setter。我猜我至少每帧调用 360K getter,我认为这是很多开销。每个类都包含包含自定义枚举、int、Color 或 Vector2D 字节的非/和-或一维或二维数组。

如果我将所有类组合成一个类,并直接访问每个数组的内容会怎样?代码看起来很乱,并抛弃了面向对象编码的概念,但速度可能会快得多。

我也不担心访问冲突,因为任何获取/设置数组中数据的尝试都将在块中完成。例如,所有对数组的写入都将发生在从它们访问任何数据之前。


至于强制转换,我说我使用的是自定义枚举、int、Color 和 Vector2D、字节。 在 .net Framework、XNA、XBox、C# 中使用和访问哪些数据类型最快?我认为不断铸造可能是这里放缓的原因。

此外,我没有使用数学来确定应该放置哪些索引数据,而是使用预先计算的查找表,因此我不必使用常数乘法、加法、减法、除法每帧。:)

4

4 回答 4

4

您是否分析了您的代码以确定减速的位置?在你重写你的应用程序之前,你至少应该知道哪些部分需要重写。

我强烈怀疑访问器和数据转换的开销是微不足道的。您的算法更有可能在做不必要的工作,重新计算它们可以缓存的值,以及其他可以在不破坏对象设计的情况下解决的事情。

于 2010-06-10T21:13:56.873 回答
4

如果您是 XNA 开发人员,那么 GDC 2008 上有一个很棒的演示文稿值得一读。它被称为了解 XNA 框架性能

对于您当前的体系结构-您还没有真正描述得足够好,无法给出明确的答案-您可能在一个紧密的循环中做了太多不必要的“东西”。如果我不得不猜测,我建议您当前的方法是破坏缓存 - 您需要修复您的数据布局。

在理想情况下,您应该有一个很好的大数组,包含尽可能小的值类型(结构而不是类),以及一个将数据线性推入其中的大量内联循环。

旁白:关于什么是快速的:整数和浮点数学非常快 - 通常,您不应该使用查找表。函数调用非常快 - 以至于在传递大型结构时复制它们会更重要。 JIT 将内联简单的 getter 和 setter - 尽管您不应该依赖它在非常紧密的循环中内联任何其他内容 - 例如您的 blitter。)

但是- 即使优化了 - 您当前的架构也很糟糕。面对现代 GPU 的工作方式,您正在做的事情大相径庭。您应该将精灵加载到 GPU 上并让它合成您的场景。

如果您想在像素级别操作精灵(例如:您提到的托盘交换),那么您应该使用像素着色器。360(和 PC)上的 CPU 速度很快,但是当你做这样的事情时,GPU 会快得多!

Sprite Effects XNA 示例是一个很好的起点。

于 2010-06-11T02:49:09.330 回答
1

您是否为每个像素或其他东西指定颜色等?如果是这种情况,我认为您应该更多地考虑架构。开始使用可以加快速度的精灵。

编辑

好的,我认为您的解决方案可能是加载几个具有不同颜色的精灵(几个像素的精灵)并重用它们。指向同一个精灵比为每个像素分配不同的颜色更快,因为精灵已经加载到内存中

于 2010-06-10T21:12:54.160 回答
0

与任何性能问题一样,您应该分析应用程序以识别瓶颈,而不是试图猜测。我严重怀疑 getter 和 setter 是你问题的根源。编译器几乎总是内联这些类型的函数。我也很好奇你对数学有什么看法。例如,将两个整数相乘是计算机可以做的最快的事情之一。

于 2010-06-10T21:14:56.083 回答