我正在尝试搞一个物理引擎,计划先用常规的技术实现,将来弄到GPU上以获得更高的性能。那么,虽然现在只是在本机上面运行,最好能够做一些往CUDA上面移植的准备,以减少将来的工作量。
GPGPU计算有个显著的特点:它是异构的,相当于同时操纵两台电脑。这两个东西各自有一套内存,通过几个cuda函数进行内存交互。于是就产生了地址的问题。考虑下面的代码:
class Foo {};
class Bar
{
Foo* member;
};
如果我把一个Bar实例传到显卡上,那么里面的member成员所指向的地址很可能是无效的,因为显卡相当于另一台电脑:在另一台电脑上仍然指向原地址,那个地址存什么东西可就没谱了。
但如果换一种思路,我们存一个索引:
class Foo {};
Foo* foo_pool;
class Bar
{
int member_i;
};
在调用GPU之前,把foo_pool的内容整个传过去;在GPU端通过数组索引获得Foo对象,就没有什么问题了。
但现在出现了新的问题:直接使用一个列表的pool是不方便的。我们应当把它构建成一个内存池类型,设立一系列的机制来自动管理对分配的请求。基本的想法是这样的:用两个映射结构,分别记录空余和已分配的内存块。分配的时候从一块足够大的空余内存中掐一块出来,如果没有足够大的块,就扩充pool的尺寸。回收的时候看看所回收的块是否和已有的空块相邻,如果相邻,就融合成一个大的空块。
// 用C++标准库