用pthreads对Box2D进行线程处理
所以我基本上是试图实现一个AIR本地扩展,它通过Actionscript通过接口在C中进行物理模拟。用pthreads对Box2D进行线程处理
我已经经历了很多次迭代,我会在下面列出这些迭代,因为我感兴趣的是我认为这可能是我最终尝试以更高效的方式获得此工作的最终尝试。
最终,我正在寻找如何设置线程环境来运行Box2D在单独线程上的仿真,然后在AS3中查询状态的帮助。
方法:
- 蛮力:
在这种方法中,我只是从AS3叫成C,并告诉它创造一个世界,并将它传递一些箱子添加到这个世界。在AS3中的每一帧,我调用C来告诉世界Step,然后循环遍历世界中所有的物体,获得它们的位置和旋转,将它们转换为动作对象并将它们放入动作数组中,然后将它们发送回AS3。一旦那里我循环通过返回的数组,并将这些位置和旋转值分配给我的精灵,以便它们在视觉上更新。
结果实际上相当不错,在帧率下降之前添加了大约116个盒子。这与纯粹的AS3实施中的30个盒子相比较。请注意,这些统计信息处于调试模式。在发布模式下,它们都达到约120个盒子。 AS3实现和本地扩展实现之间几乎没有区别。
- 的ByteArray共享
- 直接对象设置在C
- 线程
为了提高性能我决定这将是一个好主意,试图限制数据量C两端和AS3被编组。 ANE的支持共享一个字节数组的内存空间,所以我会将在AS3中创建的ByteArray发送给C,并让C只更新ByteArray。这使我们不必在C中构造AS3对象并将它们传回。每一帧,AS3只需要遍历它的ByteArray并查看C写入的内容,然后将这些值分配给精灵来设置视觉状态。
这里的结果可悲的是大约相同。改进只是微不足道的。
另一件事ANE的是能够被设定,生活在AS3对象的属性。从这个意义上说,我的目标是消除将数据传回AS3的开销,循环通过主体来收集C中的数据,并在AS3中循环以分配值。我直接修改了Box2D代码,这样当它的值发生改变时,它会直接在相应的Sprite上写入新的x,y旋转值。
由于设置这些属性的调用时间短于毫秒,因此结果令人惊讶。问题是这个线性缩放和大约90个左右的对象,开销太大,事情开始放缓。
在这一点上我是有点难倒。编组数据的开销很大,C语言中需要花费一定的代价来迭代和构造要返回的数据,并且在AS3中需要花费一些代价才能将值分配给精灵。
很明显,需要权衡一下,所以我现在的解决方案是最好的。
在AS3方面,你调用C来创建你的世界,打电话给这个世界添加一个盒子,然后打电话告诉C你想刷新你的数据。当在AS3中创建盒子时,它们将获得一个唯一的ID,并将它们存储在字典中,其中的键为ID。
在C方面,世界被创建并且产生一个新的pthread来完成该步骤。基本上在另一个线程上模拟世界。在它步骤之后,它汇编所有数据并将其写入双数组中。然后它一次又一次地这样做。它只是基本上模拟自己的线程。
当我们打电话给C添加一个新盒子时,我需要创建一个新盒子并将其添加到该世界。由于世界正在步进,这可能会导致问题,这意味着我非常确定需要使用互斥体。
同样的事情,当我们调用获取在AIR中刷新的值时,我想从双精度数组中执行一个memcpy到我的AS3 bytearray中,然后通过bytearray循环来设置视觉上的值。
互斥是给我找麻烦,所以我基本上实现我自己的,你可以看到下面......在:)
但是它的工作笑,只是没有那么快,我想这一点。大约在90后我们再次减速。
任何人有任何想法或指针?这将不胜感激!
C代码
解析器是在演戏,所以我在这里贴吧: http://pastebin.com/eBQGuGJX
AS3代码
与分析器进行同样的事情。我只包含了处理AS3中每一帧的相关方法。 http://pastebin.com/R1Qs2Tyt
我忘记了我有这个问题。幸运的是我已经知道了。
使用互斥锁等的想法首先是过度设计和不必要的。
由于我们在Flash中运行,所有内容都在主线程中运行。这意味着每个“帧”闪光将本机处理任何媒体,然后处理我们写的客户代码,然后实际渲染到屏幕上,最后在必要时进行垃圾收集。
我实际上并不需要物理sim模拟永远,我只需要让它比我的客户端代码提前一步。
所以现在发生的事情是,当客户端调用ANE来建立世界时,它会创建一个模拟世界并立即返回到Flash的新线程。 Flash将继续执行其余的客户端代码,然后渲染,然后GC。
然后在Flash的每一帧中,我们可以简单地调用ANE来检索结果。在仿真线程未完成的情况下,我们通过联接等待,提取值并将它们返回给Flash。确保在返回课程之前为下一步创建另一个线程。
通过这种方式,我们可以最大限度地提高效率,因为在Flash忙于执行其他我们无法控制的事情时(如渲染和GC),模拟正在发生。
好消息是,这种方法的性能几乎翻倍。从同步纯AS3实现中的约90个盒子到采用线程ANE方法的约170个盒子。
瓶颈最终成为通过从ANE返回的数据的迭代并将这些值分配给显示对象。
我希望这可以帮助别人寻找类似的东西。我将在4月底在多伦多FITC上发表演讲,以便我可以发布更多信息和材料。
http://www.fitc.ca/events/presentations/presentation.cfm?event=124&presentation_id=1973
我有一种感觉,这是流血的边缘,以至于你不会找到很多帮助的任何地方:)我也疑惑,为什么线程会有所帮助。由于每个世界步骤都需要来自最后一步的信息,因此它们不能并行运行,并且如果将信息传输到AS3,则在自己的线程中运行C部分无助于此。在世界范围内,可以同时进行小部分过程,但是性能增益非常小,普遍的共识似乎是使用额外内核进行渲染或其他方面更有优势。 – iforce2d 2012-03-03 10:55:17
谢谢iforce2d。是的,我不确定我是否能够得到答案,但我希望能够进一步讨论这种方法,或者链接到相关材料以获得更深入的解释。 我的希望是模拟可以在它自己的线程上运行,并且渲染将会弹出并拉取对象位置的最新“快照”并使用它来渲染。 – Jon 2012-03-30 12:58:32
+1非常有趣的问题/文章 – Ryan 2012-04-17 15:20:04