Python大规模Beta细胞动力学数值模拟的性能优化求助
Beta细胞动力学模拟性能优化问题
我正基于Bertram等人2007年的研究开发Beta细胞动力学数值模拟模型,模型功能正常但运行效率不足:模拟步长设为0.1ms时,仅15个耦合Beta细胞的情况下,每1秒模拟时长需消耗约12秒真实时间。后续需要扩展至1000个细胞模拟完整胰岛,因此亟需实现10倍以上的性能提升。
现有代码结构
BetaCell类(已用Numba jitclass重构)
@jitclass(spec) class BetaCell: def __init__(self, cell_num: int, neighbours: list, G: float): ##设置初始条件(23个参数,包含浮点数和列表) def w_ijkl(self, ii, jj, kk, ll, f6p): ###计算并返回特定参数 def run_model_step(self, Ge: float): ###执行细胞的一个时间步长模拟(dt=0.1 ms) ###需计算/更新约55个参数
ModelParameters类
class ModelParameters: ###包含所有模型参数 ###时间步长、葡萄糖刺激强度、刺激起始时间等 ###同时定义何时保存时间步长用于后续可视化 @staticmethod def external_glucose(time): ###计算并返回当前外部葡萄糖水平 ###使用简单公式实现
CellParameters类
class CellParameters: ###包含模型运行所需的约70个浮点型参数 ###部分参数在初始化后(一次性)修改,以引入细胞异质性
模拟流程
- 导入包含细胞参数(位置、连接、连接权重)的数据
- 为每个细胞初始化编号、邻居及初始葡萄糖水平,存入名为
cells的列表 - 按需为细胞参数引入异质性
- 执行模拟步骤
模拟循环核心逻辑
def run_step(cell): cell.run_model_step(glc) if __name__ == '__main__': for step, current_time in enumerate(time): ###time数组根据设定的结束时间和模拟步长(dt)预计算得到 glc = ModelParameters.external_glucose(current_time) cells = calculate_gj_coupling(cells) #计算相连细胞间的间隙连接耦合 cells = list(map(run_step, cells))
当前该循环每模拟1秒时长(对应10000次0.1ms步长循环),需耗时10-12秒。
并行尝试及问题
我尝试用multiprocessing.Pool类提升性能,代码如下:
pool = Pool(processes=NUMBER_OF_WORKERS) . . . for step, current_time in enumerate(time): ###time数组根据设定的结束时间和模拟步长(dt)预计算得到 glc = ModelParameters.external_glucose(current_time) cells = calculate_gj_coupling(cells) #计算相连细胞间的间隙连接耦合 cells = pool.map(run_step, cells) pool.terminate()
但该方案反而导致性能下降,推测是体积较大的BetaCell类实例在进程间的内存传输开销过大。不过在小型DummyObject的并行测试中,该方案能大幅提速:
小型对象并行测试代码
def task_function(dummy_object): dummy_object.sum_ab() return dummy_object class DummyObject: def __init__(self, a, b): self.a = a self.b = b self.ab = 0.0 def sum_ab(self): time.sleep(2) #模拟耗时任务 self.ab += self.a + self.b if __name__ == '__main__': pool = Pool(processes=NUMBER_OF_WORKERS) cells = [DummyObject(i, randint(1,20), randint(1,20)) for i in range(NUMBER_OF_CELLS)] for i in range(NUMBER_OF_STEPS): pool.map(task_function, cells) pool.terminate()
测试中,200个细胞的单线程循环需400秒,而60进程并行仅需8秒。
当前核心需求
- 寻求适用于Beta细胞模拟的并行实现方案
- 后续发现
calculate_gj_coupling函数是性能瓶颈,以下是该函数代码,询问更高效的Python实现方式(该函数需在每个模拟步骤执行):
@jit(nopython=True) def calculate_gj_coupling(cells, cells_neighbours): for i, cell in enumerate(cells): ca_current = 0.0 voltage_current = 0.0 g6p_current = 0.0 adp_current = 0.0 for neighbour, weight in cells_neighbours[i]: voltage_current += (cell.Cgjv*weight)*(cells[neighbour].V-cell.V) ca_current += (cell.Cgjca*weight)*(cells[neighbour].C-cell.C) g6p_current += (cell.Cgjg6p*weight)*(0.3*cells[neighbour].G6P-0.3*cell.G6P) adp_current += (cell.Cgjadp*weight)*(cells[neighbour].ADPm - cell.ADPm) cell.couplingV = voltage_current cell.couplingCa = ca_current cell.couplingG6P = g6p_current cell.couplingADP = adp_current return cells
此外,我已重构BetaCell类:不再继承CellParameters,将所有细胞参数纳入类内,初始化时传入必要的模型参数(dt、save_step),从而成功使用Numba jitclass装饰器及Numba List替代Python内置列表。
内容的提问来源于stack exchange,提问作者Marko Šterk
相关产品推荐
相关产品推荐

