jjzjj

c++ - 紧密物理和碰撞循环中的缓存友好内存访问

coder 2024-02-05 原文

我正在编写一个物理引擎,并且很难找到设计数据存储的好方法。

我想要的功能:

  • 有一个代表 PhysicsBody 的类
  • 有一个代表碰撞体积的类(比方说一个盒子)
  • 每个物理体都可以附加一个碰撞体
  • 可能有没有碰撞体的物理体
  • 可选:没有物理体的 CollisionVolume。 (想想触发音量)

现在我基本上有两个循环。 一个更新模拟中的物理体。它更新它们的位置/速度/旋转。 第二个循环对所有碰撞体执行碰撞检测。它只是一个嵌套的 for 循环,用于检查每对碰撞体积之间的碰撞。 (我知道它可以做得更好,但这是一个单独的主题)

我知道理想的方式是将对象存储在连续的数组中。

std::vector<PhysicsBody> m_bodies;
std::vector<CollisionVolume> m_colliders;

我发现这种方法存在的问题:

  • 很难维护 PhysicsBody -> CollisionVolume 关系。例如,如果我想从我的 vector 中删除一个 CollisionVolume,我会将它与最后一个交换并弹出。数据被移动,如果我将索引存储到 PhysicsBody 中的 CollisionVolume,它就不再有效。
  • 每当我销毁一个 PhysicsBody 时,析构函数都会检查它是否附加了任何碰撞体,并适本地将其从物理系统中移除。问题是 vector 会制作内部拷贝并销毁它们,当这种情况发生时,它将通过删除不应该删除的碰撞体积而造成严重破坏。
  • CollisionVolume 实际上是一个基类(不一定是),其他类从它派生,例如盒子/球体等等。我可能不使用继承并提出一些其他复杂的设计,但要记住这一点。

我努力寻找解决方法,但最终还是存储了指针:

std::vector<PhysicsBody*> m_bodies;
std::vector<CollisionVolume*> m_colliders;

我想出的最小化缓存未命中的最佳解决方案是重载新建/删除并将这些对象存储在专用于物理系统的内存池中。

有没有其他更好的解决方案?显然性能是关键。

最佳答案

一个基本问题:在没有线程运行和修改来自不同内核 (CPU) 的数据的情况下,您在哪里看到需要关心缓存一致性成本?

缓存一致性协议(protocol)仅当一行在与读取器核心不同的核心上变脏时才会触发,反之亦然。

看来您实际上是指缓存局部性?是吗?

与一致性对比。地方不碍事,这是我的看法:

在你进入 vector 的那一刻,你就失去了对管理局部性的直接控制。您可以通过使用内存池来取回其中的一部分。不过,您将不得不应对与调整大小操作相关的重定位。

你预先知道元素的数量吗?如果是,您可以这样做。

vector<T> myVec;
myVec.reserve(NUM_ELEMS);

接着是来自连续内存区域的每个对象的就地新建。

myvec[i] = ...

vector 和元素的内存也可以完全来自一个池。这可以通过在实例化 std::vector 时传入自定义分配器来实现。请看以下内容:

关于c++ - 紧密物理和碰撞循环中的缓存友好内存访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29960446/

有关c++ - 紧密物理和碰撞循环中的缓存友好内存访问的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  6. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  7. ruby - 如何在 Ubuntu 中清除 Ruby Phusion Passenger 的缓存? - 2

    我试过重新启动apache,缓存的页面仍然出现,所以一定有一个文件夹在某个地方。我没有“公共(public)/缓存”,那么我还应该查看哪些其他地方?是否有一个URL标志也可以触发此效果? 最佳答案 您需要触摸一个文件才能清除phusion,例如:touch/webapps/mycook/tmp/restart.txt参见docs 关于ruby-如何在Ubuntu中清除RubyPhusionPassenger的缓存?,我们在StackOverflow上找到一个类似的问题:

  8. ruby-on-rails - Ruby on Rails 计数器缓存错误 - 2

    尝试在我的RoR应用程序中实现计数器缓存列时出现错误Unknownkey(s):counter_cache。我在这个问题中实现了模型关联:Modelassociationquestion这是我的迁移:classAddVideoVotesCountToVideos0Video.reset_column_informationVideo.find(:all).eachdo|p|p.update_attributes:videos_votes_count,p.video_votes.lengthendenddefself.downremove_column:videos,:video_vot

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

随机推荐