定量药理学概述
定量药理学(Quantitative Pharmacology)是一种使用数学、计算机和统计学等工具来描述药物在体内吸收、分布、代谢和排泄等过程,以及药物与生物体系之间的相互作用的学科。定量药理学研究的目的是来客观描述和定量评价药物在生物体内的疗效及毒副作用,预测药物在不同人群中的药代动力学和药效动力学变异性,为开发新药和优化临床使用药物提供定量依据。Pharmacokinetics 药代动力学(PK)和 Pharmacodynamics 药效学(PD)被视为定量药理学的一个重要分支,它们分别描述了药物在体内的吸收、分布、代谢和排泄(PK)以及药物与生物体的相互作用和效应(PD),也是分子动力学的一个应用领域。
定量药理学离不开数学建模与模拟(Modeling and Simulation)技术,例如 PK/PD 模型是将 PK 和 PD 两个过程集成在一起的数学模型,用于描述药物在体内的动态过程和药效学效应。这些模型可以用于优化药物给药方案、预测药物响应、优化药物疗效,以及支持药物审批和监管等。这需要有专业的软件及充足的计算资源作为数据分析的支撑工具和平台。
本文以行业最常用的软件组合 NONMEM 和 PsN 作为 PK/PD 建模分析的核心,通过 Slurm 调度程序提交并分发作业至由 Amazon ParallelCluster 构建的计算集群之上,并借助并行计算框架 MPICH 提升计算效率。
本文解决方案及主要软件服务介绍
NONMEM(Nonlinear Mixed Effects Modeling)
定量药理学的研究以非线性混合效应模型法(Nonlinear Mixed Effects Modeling,NONMEM)为主,此概念最早于 1977 年由加利福尼亚大学旧金山分校正式提出,随后又用 Fortran 语言编制了与之同名的的非线性混合效应建模软件包,直至目前仍是应用最广泛的定量药理建模和模拟软件,也已成为 FDA 认证的群体药动学-药效学数据分析的“金标准”软件,作为 FDA 发布的《PK/PD 行业指南》的“Contains Nonbinding Recommendations”。
NONMEM 默认情况下是单线程(单核心)运行作业的。这意味着它只使用计算机中的一个 CPU 核心来执行模型拟合和参数估计。这种单线程模式在处理小型数据集时通常是足够的,但对于大型或复杂的数据集和模型,可能需要更多的计算资源并借助并行计算框架如 MPICH 来缩短模型拟合的时间。
PsN(Perl-speaks-NONMEM)
Perl-speaks-NONMEM(PsN)是一个由 Perl 模块和程序组成的开源工具集,可帮助开发使用 NONMEM 的非线性混合效应模型。其功能范围从解决简单任务(如数据准备、从输出文件中提取参数估计值、数据文件子集划分和重采样)到高级计算密集型统计方法(如对 NONMEM 的输出结果进行统计分析、图形展示、模型诊断和比较等操作),帮助用户对建立的 PK/PD 模型进行评估和优化。
Amazon ParallelCluster
Amazon ParallelCluster 是一个由 Amazon 支持的开源集群管理工具,可以帮助用户在亚马逊云中部署和管理高性能计算(HPC)集群。它会自动创建并设置所需的计算资源、调度程序和共享文件系统并且与 Slurm 调度程序一起使用,快速构建和部署概念验证和生产 HPC 计算环境。您还可以在 Amazon ParallelCluster 上构建和部署集成高级工作流,例如本次使用的 PsN 结合 Slurm 调度程序,可以实现优化计算资源利用率,提高 PK/PD 效率和可靠性,并简化作业管理和调度过程。
环境介绍
本次环境中各组件版本如下:
- NONMEM 7.5.1
- PsN 5.3.0
- Ubuntu 20.04
- MPICH 4.1.1
- ParallelCluster 3.5.1
架构图如下:
主要组件介绍:
Pcluster 管理节点:用于创建,删除,修改 ParallelCluster 集群
主节点:Slurm 主节点,用于集群调度和 NONMEM、PsN 作业提交
计算节点:Slurm 计算节点,用于由主节点通过 Slurm 提交的实际作业运算
EFS:共享存储,提供主节点和计算节点同时可访问的 NAS 文件存储
制作 ParallelCluster 自定义 AMI
基于 ParallelCluster 官方 AMI 启动 EC2
由于后续需要创建 Amazon ParallelCluster 集群,需要在 Amazon ParallelCluster 官方 AMI 上添加自定义软件如 NONMEM 和 PsN,再重新制作自定义 AMI 用于 ParallelCluster 集群创建。
要找到相对应区域的 AMI ID,需要在一台已经安装了 pcluster cli 的机器上,使用带有–region 参数的 pcluster list-official-images 命令来选择特定的 Amazon Web Services 区域和—os 及–architecture 架构参数,以筛选所需的 AMI 以及要使用的操作系统和架构。如下所示:
(pcluster3) [ec2-user@ip-172-16-0-97 ~]$ pcluster list-official-images --os ubuntu2004 --architecture x86_64
{
"images": [
{
"amiId": "ami-0c1c0f2403b85803e",
"os": "ubuntu2004",
"name": "aws-parallelcluster-3.5.1-ubuntu-2004-lts-hvm-x86_64-202303171149 2023-03-17T11-53-21.883Z",
"version": "3.5.1",
"architecture": "x86_64"
}
]
}
可以看到 x86_64 架构的 ubuntu 2004 的 ami id 为 ami-0c1c0f2403b85803e,选用这个作为 base image 进行 EC2 创建。
使用 Ubuntu 用户安装 NONMEM
创建 EC2 后登录进行必要的软件包安装,切记使用 ubuntu 用户进行软件的安装而非 root 用户安装。因为在 slurm 作业提交时使用 ubuntu 用户提交并在其他节点上使用 ubuntu 用户执行,如使用 root 安装软件则会出现执行权限问题。
sudo apt install gcc-9
sudo cp /usr/bin/gcc-9 /usr/bin/gcc
sudo apt install unzip
sudo apt install gfortran-9
sudo cp /usr/bin/gfortran-9 /usr/bin/gfortran
mkdir nonmem # nonmem 安装包解压放到此目录
mkdir nm751 # nonmem 7.5.1 的安装目录
下载 NONMEM 的安装包,下载 zip 文件,每年需要下载新版本。版本一年更新两次,每次安装新版本的时候不需要卸载老版本,一般用户每年续约的时更新一次。
解压安装包并进入 nm751CD 目录,进行 NONMEM 安装,使用以下命令:
ubuntu@ip-172-16-0-240:~/nonmem/nm751CD$ /bin/bash SETUP75 ~/nonmem/nm751CD/ ~/nm751 gfortran
安装完成后,将生产 license 文件 nonmem.lic 替换安装目录下的/nm751/license/nonmem.lic。
安装 PsN
PsN 相关文档参考 https://uupharmacometrics.github.io/PsN/docs.html。
安装系统依赖包
sudo apt install python3 python3-venv python3-dev
sudo apt install make
sudo apt install r-base pandoc libpq-dev libcairo2-dev libssl-dev libcurl4-openssl-dev libmariadb-dev libgmp-dev libmpfr-dev libxml2-dev libudunits2-dev libblas-dev liblapack-dev libmagick++-dev
修改 perl 源
国内安装 perl 包慢的问题可以通过修改 perl 源的清华源解决,操作如下:
root@ip-172-16-0-208:~# perl -MCPAN -e shell
Terminal does not support AddHistory.
To fix enter> install Term::ReadLine::Perl
cpan shell -- CPAN exploration and modules installation (v2.22)
Enter 'h' for help.
cpan[1]> o conf urllist http://mirrors.tuna.tsinghua.edu.cn/CPAN/
Please use 'o conf commit' to make the config permanent!
cpan[2]> o conf commit
commit: wrote '/root/.local/share/.cpan/CPAN/MyConfig.pm'
cpan[3]> exit
CPAN 安装 perl 包
sudo su
cpan Math::Random
cpan MouseX::Params::Validate
cpan Archive::Zip
安装 PsN
ubuntu@ip-172-16-0-240:~/PsN/PsN-Source$ sudo perl setup.pl
This is the PsN installer. I will install PsN version 5.3.0.
You need to answer a few questions. If a default value is presented
you may accept it by pressing ENTER.
PsN Utilities installation directory [/usr/local/bin]:
Path to perl binary used to run Utilities [/usr/bin/perl]:
PsN Core and Toolkit installation directory [/usr/local/share/perl/5.30.0]:
The next step is to check Perl module dependencies.
If a module is missing, you must install it, e.g. from CPAN,
http://www.cpan.org/modules/index.html
before PsN can be run.
Would you like this script to check Perl modules [y/n]?y
Testing required modules:
Module Math::Random ok
Module MouseX::Params::Validate ok
Done testing required modules.
Testing recommended but not required modules...
Module Archive::Zip ok
Tests done.
Searching for NM versions on your file system...
No NM versions have been found. You need to add at least one.
Enter the *complete* path of the NM-installation directory: /home/ubuntu/nm751
These are the loaded NM versions:
/home/ubuntu/nm751
Would you like to add another one [y/n] ?
n
Enter the name you want to use for the NM-version in
/home/ubuntu/nm751
with PsN option -nm_version,
or press ENTER to use the name nm751 :
A new configuration file has been created:
/usr/local/share/perl/5.30.0/PsN_5_3_0/psn.conf
If you want to add cluster options or personalized defaults or
NMqual settings you can do this manually by editing
/usr/local/share/perl/5.30.0/PsN_5_3_0/psn.conf
in a regular text editor.
Please note that if you have a psn.conf file in your home directory,
the settings in that file will override the settings in
/usr/local/share/perl/5.30.0/PsN_5_3_0/psn.conf
Installation complete.
Press ENTER to exit the installation program.
禁用 Open MPI
默认 ParallelCluster AMI 自带 Open MPI,而 NONMEM 需要使用 MPICH,两者的可执行命令均为 mpirun,与 MPICH 有冲突。因此需要禁用现有的 Open MPI。
ubuntu@ip-172-16-0-240:~$ sudo -s
root@ip-172-16-0-240:/home/ubuntu# cd /usr/bin/
root@ip-172-16-0-240:/usr/bin# mkdir default.mpi
root@ip-172-16-0-240:/usr/bin# mv mpi* default.mpi
root@ip-172-16-0-240:/usr/bin# exit
ubuntu@ip-172-16-0-240:~/run010$ which mpirun
/opt/amazon/openmpi/bin//mpirun
ubuntu@ip-172-16-0-240:~/run010$ cd /opt/amazon/openmpi/bin/
ubuntu@ip-172-16-0-240:/opt/amazon/openmpi/bin$ sudo su
root@ip-172-16-0-240:/opt/amazon/openmpi/bin# mkdir default.mpi
root@ip-172-16-0-240:/opt/amazon/openmpi/bin# mv mpi* default.mpi
root@ip-172-16-0-240:/opt/amazon/openmpi/bin# exit
下载 MPI 4.1.1 编译安装
下载地址:https://github.com/pmodels/mpich/releases/download/v4.1.1/mpich-4.1.1.tar.gz。
需要注意事项如下:
- MPI 安装运行目录需要所有 worker 节点均可以访问,因此可以使用默认头节点共享的/opt 目录,即安装目录为/opt/mpich-4.1.1
- 由于后续 NONMEM 并行计算需要使用 MPICH 的静态库文件`libmpich.a` (替换原有`/nm751/mpi/mpi_ling/libmpich.a` 文件),因此需要对 MPICH 进行静态编译生成静态库文件
- 因为 MPICH 编译时仅生成`libmpi.a`,需要使用`ln`添加 symlink 到`libmpich.a
sudo su
apt remove mpich
wget https://github.com/pmodels/mpich/releases/download/v4.1.1/mpich-4.1.1.tar.gz
tar xzf mpich-4.1.1.tar.gz
cd mpich-4.1.1
./configure --prefix=/opt/mpich-4.1.1 CFLAGS="-m64" FFLAGS="-m64" --enable-f90 --enable-timer-type=gettimeofday --enable-static=yes 2>&1 | tee c.txt #--enable-static 生成静态库文件.a
make -j64 2>&1 | tee m.txt #-j 根据当前机器的 cpu 数而定,数值越大编译越快,建议 64 核以上
make install 2>&1 | tee mi.txt
cd /home/ubuntu/nm751/mpi/mpi_ling/
mv libmpich.a libmpich.a.bk
ln -s /opt/mpich-4.1.1/lib/libmpi.a /home/ubuntu/nm751/mpi/mpi_ling/libmpich.a # 添加软连接到 nonmem 目录下的静态库
vim /etc/profile # 添加全局 mpich 环境变量
PATH=/opt/mpich-4.1.1/bin:$PATH; export PATH
source /etc/profile
NONMEM 单机 MPI 并行计算测试
使用 PsN execute 命令,2 个节点并行运行单个 nonmem 作业
ubuntu@ip-172-16-0-240:~/run010$ execute run010.ctl -nodes=2 -parafile=/home/ubuntu/nm751/run/mpilinux8.pnm
Starting 1 NONMEM executions. 1 in parallel.
S:1 ..
All executions started.
Starting NMTRAN
WARNINGS AND ERRORS (IF ANY) FOR PROBLEM 1
(WARNING 2) NM-TRAN INFERS THAT THE DATA ARE POPULATION.
Note: Analytical 2nd Derivatives are constructed in FSUBS but are never used.
You may insert $ABBR DERIV2=NO after the first $PROB to save FSUBS construction and compilation time
Recompiling certain components
USING PARALLEL PROFILE /home/ubuntu/nm751/run/mpilinux8.pnm
MPI TRANSFER TYPE SELECTED
Building NONMEM Executable
Starting MPI version of nonmem execution ...
Manager Location ip-172-16-0-240//home/ubuntu/run010/modelfit_dir6/NM_run1
License Registered to:
Expiration Date: 14 JUN 2023
Current Date: 17 MAY 2023
**** WARNING!!! Days until program expires : 27 ****
**** CONTACT idssoftware@iconplc.com FOR RENEWAL ****
First Order Conditional Estimation with Interaction
MONITORING OF SEARCH:
0ITERATION NO.: 0 OBJECTIVE VALUE: -5434.19246879288 NO. OF FUNC. EVALS.: 9
CUMULATIVE NO. OF FUNC. EVALS.: 9
NPARAMETR: 1.0143E+01 9.9945E+00 1.0358E+00 1.0924E+02 4.8085E+01 9.8599E+00 4.7377E-02 5.7569E-02 2.1213E-02 4.2273E-03
PARAMETER: 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01
GRADIENT: 1.6906E+02 1.2308E+02 3.6609E+01 1.2369E+01 1.1555E+01 3.2891E+00 1.5793E-02 -9.3163E-04 5.3890E-02 1.2228E+00
0ITERATION NO.: 2 OBJECTIVE VALUE: -5434.19246879288 NO. OF FUNC. EVALS.: 54
CUMULATIVE NO. OF FUNC. EVALS.: 63
NPARAMETR: 1.0143E+01 9.9945E+00 1.0358E+00 1.0924E+02 4.8085E+01 9.8599E+00 4.7377E-02 5.7569E-02 2.1213E-02 4.2273E-03
PARAMETER: 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01 1.0000E-01
GRADIENT: -1.0877E+00 2.4267E-01 -3.0004E+00 1.6597E+00 8.3079E-01 -2.4949E+00 1.5682E-02 -1.0777E-03 5.4210E-02 9.4077E-01
Elapsed estimation time in seconds: 3.47
Elapsed covariance time in seconds: 10.12
Elapsed postprocess time in seconds: 0.13
Elapsed finaloutput time in seconds: 0.06
Done with nonmem execution
F:1 ..
execute done
使用 PsN bootstarp 运行 30 次 samples
ubuntu@ip-172-16-0-240:~/run010$ bootstrap run010.ctl -samples=30 -threads=2 -nodes=2 -parafile=/home/ubuntu/nm751/run/mpilinux8.pnm
Resampling from /home/ubuntu/run010/RUN010_NM.csv
|..............................| ... done
Starting 30 NONMEM executions. 2 in parallel.
S:1 .. S:4 .. S:7 .. S:10 .. S:13 .. S:16 .. S:19 .. S:22 .. S:25 .. S:28 .. S:30 .. Waiting for all NONMEM runs to finish:
F:30 .. F:29 .. done
Bootstrap done.
正常完成即证明 NONMEM 并行计算运作正常,所有自定义组件安装完成。
使用 console 制作自定义镜像
开始制作 ParallelCluster 可用的自定义镜像
- 登录 EC2,运行以下命令,为实例做好创建 AMI 的准备。
sudo /usr/local/sbin/ami_cleanup.sh
- 在控制台中,选择实例状态和停止实例。
导航到实例,选择之前创建的实例,选择实例状态和停止实例。
- 使用 EC2 控制台从实例创建新
。
从 EC2 控制台
- 在导航窗格中选择 Instances(实例)。
- 选择您创建和修改的实例。
- 在操作中,选择 Image,然后选择创建 Image。
- 选择 Create Image。
- 待 AMI 状态为 Available 后,在创建集群的 yaml 配置的 CustomAmi 字段中输入此 AMI ID。
创建 ParallelCluster 集群
创建 pcluster 管理节点
参考 https://docs.amazonaws.cn/parallelcluster/latest/ug/install-v3-parallelcluster.html。
集群参考配置文件
样例 yaml 配置文件如下:
Region: cn-northwest-1
Image:
Os: ubuntu2004
CustomAmi: ami-0ec6815c1a911172b
SharedStorage:
- Name: efs
MountDir: /efs
StorageType: Efs
EfsSettings:
FileSystemId: fs-08b035afccad28cdb
HeadNode:
InstanceType: c6i.xlarge
Dcv:
Enabled: true
Networking:
SubnetId: subnet-005c6ee6d3fd9ec03
ElasticIp: true
Ssh:
KeyName: NONMEM
Scheduling:
Scheduler: slurm
SlurmQueues:
- Name: thinnode
ComputeResources:
- Name: c6i8xlarge
DisableSimultaneousMultithreading: false
Instances:
- InstanceType: c6i.8xlarge
MinCount: 0
MaxCount: 15
Networking:
SubnetIds:
- subnet-060134b58cca98d98
- Name: fatnode
ComputeResources:
- Name: c6imetal
Instances:
- InstanceType: c6i.metal
MinCount: 0
MaxCount: 3
Networking:
SubnetIds:
- subnet-060134b58cca98d98
Monitoring:
DetailedMonitoring: true
Logs:
CloudWatch:
Enabled: true
RetentionInDays: 30
DeletionPolicy: Delete
Dashboards:
CloudWatch:
Enabled: true
创建集群
pcluster create-cluster -n <cluster_name> -c <configfile> --dryrun true # 通过 dryrun 命令验证集群配置文件的正确性
pcluster create-cluster -n <cluster_name> -c <configfile> -nr # 去掉 dryrun 正式创建集群,添加-nr 参数防止失败回滚方便troubleshooting
提交集群作业测试
脚本命令编写注意事项
通过 EC2 console 查询并登录集群 Headnode,编写脚本后使用 sbatch 投递至集群计算。
使用 NONMEM nmfe
命令,需要在 sbatch
命令中指定所需的资源--cpus-per-task
与 nmfe 命令-node
数相同,例如脚本为:
#!/bin/bash
/home/ubuntu/nm751/run/nmfe75 run010.ctl run010.lst -parafile=/home/ubuntu/nm751/run/mpilinux8.pnm [nodes]=4
其中指定了[nodes]=4,因此需要在提交作业的时候指定--cpus-per-task=4
,即
sbatch --cpus-per-task=4 test1.sh
这种情况下,slurm 仅投递一个 job 进行运算。
而在使用 PsN 投递 execute 和 bootstrap 命令时,PsN 会先将命令作为一个 manager process job 投递到 slurm 集群上,再由此 job 投递单次拟合或重采样的作业,例如:
execute 作业投递后使用`squeue`查看,可以看到一个 manage process job 和一个 worker process job。
bootstrap 作业投递后 squeue,一个 manage process job 和-sample 数对应的 worker process jobs。
在 sbatch 提交中指定的–cpus-per-task 参数无法带入到子 worker process 任务中,如果不指定额外参数,每个子任务仅用 1 vcpu 执行。
如果需要多核 MPI 并行计算,需要通过 PsN common option 中的-run_on_slurm 和-slurm_prepend_flags 在投递任务中传递参数给子任务。
命令样例如下:
execute run010.ctl -nodes=4 -parafile=/home/ubuntu/nm751/run/mpilinux8.pnm -run_on_slurm -slurm_prepend_flags="--cpus-per-task=4"
bootstrap run010.ctl -samples=100 -threads=10 -nodes=4 -parafile=/home/ubuntu/nm751/run/mpilinux8.pnm -run_on_slurm -slurm_prepend_flags="--cpus-per-task=4"
作业调度的资源总 cpu 数为单个作业所需 node 数乘以并行作业数,即 nodes*threads。
作业性能对比
由于采用并行计算框架,突破原有单机工作站资源的限制,不仅在 Bootstrap 重采样场景下能大大缩短计算时间,在单模型拟合场景依托新一代的计算密集型实例也有相应的计算性能提升。
|
execute 单模型拟合 (16 核复杂模型) |
Bootstrap 2000 次重采样 |
On-prem 24 cores server |
30min |
2 weeks+ |
ParallelCluster 15 * c6i.8xlarge |
28min |
12 hours |
方案优势总结
- 使用 MPI 多线程多节点并行计算,并通过 PsN 结合 Slurm 进行 NONMEM PK/PD 模型单次拟合和重采样作业调度,计算效率显著提升,大大缩短药动学/药效学研究时间。
- 利用云计算弹性优势短时间能调用大量资源,及时快速完成计算任务。
- Amazon ParallelCluster 一键部署 HPC 集群,计算与存储资源按需使用,无需预制,使用后自动关闭,节省成本并简化运维。
参考资料
NONMEM:https://www.iconplc.com/solutions/technologies/nonmem/
PsN:https://uupharmacometrics.github.io/PsN/docs.html
ParallelCluster:https://docs.amazonaws.cn/en_us/parallelcluster/latest/ug/what-is-aws-parallelcluster.html
MPICH:https://github.com/pmodels/mpich/blob/main/README.vin
本篇作者