Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 高效地迭代大量数据 介绍_C++_Loops_Data Structures_Iterator_Processing Efficiency - Fatal编程技术网

C++ 高效地迭代大量数据 介绍

C++ 高效地迭代大量数据 介绍,c++,loops,data-structures,iterator,processing-efficiency,C++,Loops,Data Structures,Iterator,Processing Efficiency,首先,我必须说这是为在线游戏服务器做的,它跟踪地图中的每个对象,无论是玩家还是AI(NPC或你想怎么称呼它) 它不仅要跟踪他们,还要在玩家之间通知他们的近邻。我已经解决了这个问题,目前我正在使用一种多线程的方法,这种方法非常有效。 我的问题 我将所有这些对象存储在一个哈希表中。我们可以认为哈希表是一个无序的映射,虽然实际上我使用了RD::Hash映射> /代码>,因为插入和获取(自测试)更快,虽然占用了更多的RAM(现在不是问题)。 问题是,该映射存储对象的唯一ID(64位),加上对象指针,

首先,我必须说这是为在线游戏服务器做的,它跟踪地图中的每个对象,无论是玩家还是AI(NPC或你想怎么称呼它)

它不仅要跟踪他们,还要在玩家之间通知他们的近邻。我已经解决了这个问题,目前我正在使用一种多线程的方法,这种方法非常有效。

我的问题 我将所有这些对象存储在一个哈希表中。我们可以认为哈希表是一个<代码>无序的映射,虽然实际上我使用了RD::Hash映射> /代码>,因为插入和获取(自测试)更快,虽然占用了更多的RAM(现在不是问题)。 问题是,该映射存储对象的唯一ID(64位),加上对象指针,类似于:
rde::hash\u映射

我的问题是:

我的应用程序(服务器)必须在一个循环中运行(线程内),必须每50毫秒调用一次循环,以保持运行平稳。循环代码如下所示:

void loop()
{
    UInt32 prev = clock();
    UInt32 prevSleep = 0;
    while (1)
    {
        UInt32 diff = clock() - prev;
        prev = clock();

        maps.update() // Suppose map is a class, which stores the objects map

        if (diff <= 50 + prevSleep)
        {
            prevSleep = 50 + prevSleep - diff;
            sleep(prevSleep);
        }
        else
            prevSleep = 0;
    }
}
稍后,必须调用每个对象的内部更新,我这样做是通过(再次使用伪代码):

如果这还不够,则必须将上述循环扩展为:

foreach objectsList as object:
    object->update()
    
    // Visit all the other objects
    // Called once every 1 sec for the object, not on every call
    foreach objectsList as other:
        if other != object:
            object->visit(other)

我尝试对此进行优化 将第一个循环(添加和通知)与更新循环合并,如下所示:

foreach objectsList as object:
    foreach objectsToBeAdded as joiner:
        object->notify(joiner)
        joiner->notify(object)

    object->update()

    // Called once every 1 sec for the object, not on every call
    foreach objectsList as other:
        if other != object
            object->visit(other)

这在对象数量不大的情况下起作用,当它增加循环数时,循环开始占用4秒的时间,这远远超过了我正在寻找的50毫秒。

我的问题 有没有其他方法可以进一步优化这一点?我曾经考虑过使用八叉树来跟踪对象在地图中的位置,但后来得出的结论是,这只会使问题更加严重

我还将每个地图划分为一个实体的35个单位(35是“视图范围”,LOS),因此给定的
rde::hash_地图
只包含彼此可以看到的单位,因此需要更新。只要对象计数较低,就可以工作

我还能做什么?谢谢大家!



注 所有这些
foreach
都是使用迭代器的循环,比如
rde::hash\u map::iterator
对象开始()
对象结束()


其他优化,如没有玩家(真正的用户,而不是NPC)时不更新、在给定地图上没有玩家时释放内存等,都已经被考虑在内。

除了空间分割之外,第一个想到的优化是只通知对象附近的变化(例如使用四叉树)是:是否每个对象都必须被告知每个更改?为什么不告诉每个对象,“每一帧,我将运行你的
update
方法。在你的
update
方法中,你可以查找你想查找的所有内容(例如,可能有一个缓冲区,包含该帧/最近帧中发生的所有更改)通过这种方式,您不必花费CPU周期通知对象他们实际上不需要知道或关心的事情

另外,您是否在程序上运行了CPU探查器,并验证了热点(占用CPU时间最多的地方)是否在您认为的位置

进一步讨论见评论:

 |
 |
\|/
 V

除了空间分割之外,我想到的第一个优化方法是只通知对象附近的变化(例如使用四叉树)is:是否每个对象都必须被告知每个更改?为什么不告诉每个对象,‘每一帧,我将运行您的
update
方法。在您的
update
方法中,您可以查找您想要查找的所有内容(例如,可能有一个缓冲区,包含此帧/最近帧中发生的所有更改)通过这种方式,您不必花费CPU周期通知对象他们实际上不需要知道或关心的事情

另外,您是否在程序上运行了CPU探查器,并验证了热点(占用CPU时间最多的地方)是否在您认为的位置

进一步讨论见评论:

 |
 |
\|/
 V

目前正在使用您的一些建议。每个
rde::hash_map
集合只包含彼此的可视范围(靠近它们)的对象,因此它们不会收到不必要对象的通知。
Object::update()
方法仅(目前)起作用计算对象的位置并将其相应地移动到不同的时间。
object::visit(who)
方法简单地告诉对象,
who
在附近,在内部什么都不做。时间花在连接(n=objects,m=tobeaded)通知的第一个O(n*m)循环上,以及进一步的O(n^2)上访问循环。我对其进行了分析。是的。这些是结果。作为补充说明,我还尝试将O(n*m)和O(n^2)循环统一为一个,使用外部类跟踪两个对象之间的“更新状态”,如:,从而使其成为一个O(n^2)通知连接事件或调用visit方法的循环。我也读过有关缓存命中/未命中的内容,并对其进行了研究,但我认为在使用哈希映射时无法减少未命中。由于哈希映射具有快速插入/查找和线程安全迭代器,因此必须使用哈希映射(意思是,在一个线程中删除一个对象不会使所有其他迭代器失效)。@ProStage让我举一个例子来说明我的意思——在一个有数千颗子弹的shmup中,比如在Touhou,你不需要通知每一颗子弹其他子弹的存在。为了确保游戏的正确性,尽可能做到最低限度(每个项目符号都是高级的,如果项目符号特别关心其他项目符号的状态,那么它在更新时会显式地处理它自己的状态,然后执行一些快速碰撞检测算法,也许可以利用这样一个事实,即只有非常接近玩家的项目符号才是重要的,项目符号的大小在项目符号的持续时间内是静态的,等等)@换句话说,如果你在做h
 |
 |
\|/
 V