0

我试图使用面向数据的设计来定位我的代码以尽可能有效地使用缓存,这是我第一次考虑这样的事情。我想出了一种方法来循环在屏幕上绘制精灵的相同指令,发送到函数的向量包括所有游戏实体的位置和精灵。

我的问题是条件语句是否摆脱了指令缓存中的绘图函数并因此破坏了我的计划?或者我在做什么通常是疯了?

struct position
{
    position(int x_, int y_):x(x_), y(Y_)
    int x,y;
};

vector<position> thePositions;
vector<sprite> theSprites;
vector<int> theNoOfEntities; //eg 3 things, 4 thingies, 36 dodahs
int noOfEntitesTotal;

//invoking the draw function
draw(&thePositions[0], &theSprites[0], &theNoOfEntities[0], noOfEntitesTotal)

void draw(position* thepos, sprite* thesp, int* theints, int totalsize)
{
    for(int j=0;int i=0;i<totalsize;i++)
    {
        j+=i%size[j]?1:0;
        thesp[j].draw(thepos[i]);
    }
}
4

2 回答 2

1

您是否验证了条件在汇编中仍然是条件?通常使用上面介绍的简单条件,表达式可以优化为无分支序列(在机器级别使用机器特定指令,或在 IR 级别使用一些花哨的位数学)。

在您的情况下,您有条件地在 x86 上很好地折叠成一个平面序列(并且 AFAIK,这也将发生在大多数非 x86 平台上,因为它是一种数学优化,而不是特定于机器的优化):

IDIV DWORD PTR SS:[ARG.1]
MOV EAX,EDX
NEG EAX                                  ; Converts EAX to boolean
SBB EAX,EAX
NEG EAX

因此,这意味着除了遵循模式的外部循环之外,没有任何要预测的分支,这意味着它不会导致任何错误预测(它可能会在退出时错误预测,具体取决于生成的程序集,但它的退出,所以没关系)。

这提出了第二点,永远不要假设,总是分析和测试(汇编知识有很大帮助的情况之一),这样您就可以花时间优化真正重要的地方(并且您可以了解您的内部和内部工作原理)目标平台上的代码也更好)。

如果您真的担心分支错误预测和所招致的惩罚,请使用您的目标架构制造商提供的资源(不同的架构对分支错误预测的行为非常不同),例如英特尔的thisthis。AMD 的 CodeAnalyst 是检查分支错误预测及其可能造成的惩罚的绝佳工具。

于 2012-07-04T12:21:39.290 回答
-1

哇,伙计!没有冒犯,但看起来你在没有完全理解它的方式和原因的情况下阅读了有关 DOD 的内容。现在,您只需遵循有关 DOD 的文章中设置的指南,就像它们很重要一样。他们不是,在 DOD 中重要的是理解数据、理解计算机架构以及理解你的代码如何使用你对架构的知识尽可能高效地操作数据。国防部文章中列出的指导方针只是提醒人们要考虑的常见问题。

想知道何时以及为何需要使用 DOD?了解您正在使用的架构。你知道一次缓存未命中的代价吗?真的真的真的真的很低。算一算。我是认真的,你自己算一下,我可能会给你一些数字,但那样你就不会学到很多东西。因此,找出有关体系结构、处理器如何工作、内存和缓存如何工作、汇编语言如何工作以及编译器生成的汇编是什么样子的信息。一旦你了解并理解了所有这些,DOD 只不过是陈述一些几乎显而易见的指导方针来编写真正有效的代码。

于 2012-07-04T11:25:07.280 回答