Jetson是Nvidia推出的一款嵌入式AI计算平台,相比笔记本电脑和服务器,Jetson具有更小的体积和更低的功耗,适合部署在边缘设备上。Oxford Nanopore Technology也曾基于Jetson平台发布了MinION Mk1C,用于实时测序数据的分析。本文介绍了如何在Jetson上安装并运行Bonito Basecaller,以便在边缘设备上进行实时测序数据的分析和模型训练。

本文基于运行Jetson Linux 35.2.1Jetson Xavier NX开发板,其他Jetson设备可能需要稍作调整。

$ uname -r
5.10.216-tegra

$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2022 NVIDIA Corporation
Built on Sun_Oct_23_22:16:07_PDT_2022
Cuda compilation tools, release 11.4, V11.4.315
Build cuda_11.4.r11.4/compiler.31964100_0

确保CUDA依赖

Bonito Basecaller是基于CUDA的深度学习模型,因此需要确保CUDA的依赖已经安装。在使用sdkmanager安装Jetson Linux的过程中,需要选择安装CUDA Toolkit,确保CUDA的依赖已经安装。进入系统后,可以通过以下命令检查CUDA的版本:

$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2022 NVIDIA Corporation
Built on Sun_Oct_23_22:16:07_PDT_2022
Cuda compilation tools, release 11.4, V11.4.315
Build cuda_11.4.r11.4/compiler.31964100_0

安装Conda

为了避免与系统的Python环境冲突,我们可以使用Conda来创建一个独立的Python环境。首先,我们先创建Conda环境:

conda create -n bonito-py38-081
conda activate bonito-py38-081

并在该环境中安装Python 3.8:

conda install python=3.8

安装Bonito

观察Bonito的requirements.txt文件,我们可以看到Bonito依赖于以下Python库:

# general requirements
edlib
fast-ctc-decode
mappy
networkx     # required for py3.8 torch compatability
numpy<2      # numpy~=2 is currently unreleased, it may have breaking changes
pandas<3     # pandas~=3 is currently unreleased, it may have breaking changes
parasail
pod5
pysam
python-dateutil
requests
toml
tqdm
wheel
# specific requirements
torch==2.1.2
# ont requirements
ont-fast5-api
ont-koi
ont-remora

经过笔者的测试,在arm64架构上会出现兼容性问题的包主要集中于torchont-koi这两个包。其中PyTorch是需要安装nvidia提供的torch包,而ont-koi则需要移植dorado的koi库。

PyTorch

根据Nvidia的文档和兼容性矩阵表格,我们可以安装距离Pytorch 2.1.2最接近的版本2.1.0a(请根据实际的Jetpack Linux版本选择合适的PyTorch版本):

# Download the PyTorch wheel file
wget https://developer.download.nvidia.com/compute/redist/jp/v512/pytorch/torch-2.1.0a0+41361538.nv23.06-cp38-cp38-linux_aarch64.whl
# Install numpy and pandas
pip install "numpy<2" "pandas<3"
# Install PyTorch
pip install torch-2.1.0a0+41361538.nv23.06-cp38-cp38-linux_aarch64.whl

安装完成后,可以通过以下命令确定pytorch读到了Jetson的GPU:

python3

>>> import torch
torch.cuda.get_device_name(0)
>>> torch.cuda.get_device_name(0)
'Xavier'

ont-koi

编译so文件

由于ONT只提供了适用于x86_64架构的koi库,我们需要自行移植koi库到arm64架构。笔者经过观察,在Dorado的Koi.cmake里发现了预编译好的koi包,我们可以直接下载并编译出so文件。我们首先从ONT下载koi包:

# Download the koi package
wget https://cdn.oxfordnanoportal.com/software/analysis/libkoi-0.4.3-Linux-aarch64-cuda-11.4.tar.gz
tar -zxvf libkoi-0.4.3-Linux-aarch64-cuda-11.4.tar.gz

随后,在文件夹里新建一个setup.py:

import os
from cffi import FFI

ffi = FFI()

def build_koi():
    with open("include/koi.h", 'r') as f:
        header_content = f.read()
    
    ffi.cdef(header_content)
    
    ffi.set_source(
        'koi._runtime',
        '#include <koi.h>',
        include_dirs=['./include'],  # include
        library_dirs=['./lib'],      # lib
        libraries=['koi'],           # link libkoi.a
        extra_link_args=['-Wl,-rpath,$ORIGIN/lib'] 
    )
    
    ffi.compile()

if __name__ == '__main__':
    build_koi()

并运行该脚本。编译完成后,我们可以在当前目录下找到_runtime.cpython-38-aarch64-linux-gnu.so文件。

安装ont-koi

由于koi的架构不同,我们需要手动安装ont-koi:

# 我们先下载x86_64架构的whl包
wget https://files.pythonhosted.org/packages/fe/68/4bb9241c65d6c0c51b6ae366b5dedda2e8a41ba17d2559079ee8811808ef/ont_koi-0.4.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

# 解压 wheel 文件(wheel 本质上是一个 zip 文件)
unzip ont_koi-0.4.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -d ont_koi_temp

# 找到 Python 的 site-packages 目录
SITE_PACKAGES=$(python -c "import site; print(site.getsitepackages()[0])")

# 直接复制文件到 site-packages(但注意备份)
cp -r ont_koi_temp/koi $SITE_PACKAGES/
cp -r ont_koi_temp/ont_koi.libs $SITE_PACKAGES/
cp -r ont_koi_temp/ont_koi-0.4.4.dist-info $SITE_PACKAGES/

# 替换 so 文件
cp /path/to/your/new/_runtime.cpython-38-aarch64-linux-gnu.so $SITE_PACKAGES/koi/_runtime.abi3.so

安装Bonito

我们先下载Bonito的源码:

git clone https://github.com/nanoporetech/bonito
cd bonito

注释掉requirements.txt里torchont-koi的依赖,然后安装Bonito:

pip install .

运行Bonito

bonito basecaller [email protected] --reference reference.mmi /data/reads > basecalls.bam