简体   繁体   English

XNA优化-循环展开?

[英]XNA optimizations - Loop Unrolling?

I'm making a XNA game and I wonder if there is a way of optimizing some loops. 我正在制作XNA游戏,我想知道是否有一种优化某些循环的方法。 For example: 例如:

I have a Map class, that contains a collection of tiles, so, in the Map Update() I just call every tiles Update() 我有一个Map类,其中包含图块的集合,因此,在Map Update()中,我只调用每个图块Update()

    // Update method in Map Class
    public void Update()
    {
        for (int index = 0; index < tiles.Count; index++)
        {
            tiles[index].Update();
        }
    }

This works fine but, it can get worst with some larger populated objects, like the Particle class where, every particle is managed with a ParticleManager class (that contains a collection of particles) so: 这可以很好地工作,但是对于一些较大的填充对象(例如Particle类),可能会变得更糟,其中每个粒子都由一个粒子管理器类(包含粒子集合)来管理,因此:

    // Update method in ParticleManager class
    public void Update()
    {
        for (int index = 0; index < particle.Count; index++)
        {
            particle[index].Update();
        }
    }

    //Update Method in Particle class
    public void Update()
    {
        for (int index = 0; index < Map.tiles.Count; index++)
        {
             CheckCollitions(Map.tile[index], this);
        }
    }

The ParticleManager loops for every particle and, each particle checks collitions for every Tile. ParticleManager为每个粒子循环,并且每个粒子检查每个Tile的归类。 So, if you got 20 particles and 100 Tiles, it will do lots of computation: 因此,如果您有20个粒子和100个Tiles,它将进行大量计算:

20 loops cycles * 100 loops cycles

That's why I was thinking of some optimizations, like loop unrolling but, I don't know if it works (I think not) with undefined length loops (cause the compiler doesn't know those loops lengths in compile time) 这就是为什么我在考虑一些优化,例如循环展开,但是,我不知道它是否可以在未定义的长度循环中使用(我认为不行)(因为编译器在编译时不知道这些循环的长度)

To sum up: 总结一下:

  1. It is possible to optimize those loops using loop unrolling? 是否可以使用循环展开来优化这些循环?
  2. Can you advice me with any other type of optimization? 您可以提出其他任何类型的优化建议吗?

Thanks 谢谢

First of all, loop unrolling is a micro-optimization and won't get to a lot of benefit. 首先,循环展开是一个微优化,不会带来很多好处。 Don't bother until it's absolutely needed. 在绝对需要之前不要打扰。

More importantly, the way to optimize code is more about the data structures and algorithms used, not how fast you can iterate through a collection. 更重要的是,优化代码的方式更多地与所使用的数据结构和算法有关,而不是您可以快速遍历一个集合。

In your particular example, you are effectively doing this.. 在您的特定示例中,您正在有效地执行此操作。

    for (int p = 0; p < particle.Count; p++)
    {
        for (int t = 0; t < Map.tiles.Count; t++)
        {
                 CheckCollitions(Map.tile[t], particle[p]);
        }
    }

Nested loops like this indicate an O(n^2) complexity and are a sure sign of potential performance issues. 这样的嵌套循环表示O(n ^ 2)复杂度,并且是潜在性能问题的肯定标志。

Typically when you are working with collision detection you can optimize the code by reducing the number of objects that could collide based on things you already know. 通常,当您使用碰撞检测时,可以通过减少可能会基于已知情况发生碰撞的对象的数量来优化代码。

For example, I assume tiles don't move around and are laid out in a uniform grid. 例如,我假设瓷砖不会四处走动,而是以统一的网格布局。 I can also assume particles are very small. 我还可以假设粒子非常小。

Let's say you store tile data in a 2 dimensional array. 假设您将图块数据存储在二维数组中。

var tiles = new int[32,32];

A value of 0 means no tile, and a value of 1 (or > 0) means the tile is solid. 值为0表示无图块,值为1(或> 0)表示图块为实心。 You also know that when tiles are rendered on the screen they are 64x64 pixels. 您还知道,在屏幕上渲染图块时,它们为64x64像素。

This means, you can do a basic collision test with any tile very quickly using simple math.. 这意味着,您可以使用简单的数学运算对任何图块进行基本的碰撞测试。

    for (int p = 0; p < particle.Count; p++)
    {
        var tileWidth = 64;
        var tileHeight = 64;
        var particlePosition = particle[p].Position;
        var tx = particlePosition.X / tileWidth; 
        var ty = particlePosition.Y / tileHeight;

        var tile = tiles[tx, ty];

        if(tile == 0)
        {
            // no collision
        }
        else
        {
            // collision detected
        }
    }

At this point, you know exactly which tile in the array the particle position falls into and removed the inner loop (effectively reducing it to an O(n) complexity). 在这一点上,您确切地知道粒子位置属于数组中的哪个图块并删除了内部循环(有效地将其降低为O(n)复杂度)。 Obviously, you'll also need to be careful not to check outside the bounds of the array and there may be some other details to deal with if your particles are larger than a single pixel, but you get the idea. 显然,您还需要注意不要检查数组的边界之外,并且如果您的粒子大于单个像素,可能还需要处理其他一些细节,但是您可以理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM