Ubuntu配置AlphaFold过程

文章目录

    • 安装Nvidia Docker
      • 注意
      • 安装对应的GPU驱动
      • 安装docker与NVIDIA Container Toolkit
    • 下载代码
    • 下载数据集
      • 注意
      • 数据集目录结构
      • 常规下载
      • 手动下载
      • 超常规手动下载
        • 额外处理
      • 配置环境
      • 运行Demo
      • 坑坑坑坑
        • 坑1. docker中的一些目录挂载出错。
        • 坑2. 运行时提示`ValueError: jaxlib is version 0.1.69, but this version of jax requires version 0.1.74.`
        • 坑3 运行时报错,提示FileNotFoundError或者是某些方法找不到

本文将根据 AlphaFold官方的步骤配置AlphaFold,并尝试解决配置过程中可能遇到的问题。

安装Nvidia Docker

按照NVIDIA文档中的过程安装NVIDIA Container Toolkit.

注意

  • 该步骤需要管理员权限,无法获取管理员权限的请直接放弃
  • 既然有了管理员权限,顺便安装一下aria2c(sudo apt install aria2),后续下载数据集时会用到。

安装对应的GPU驱动

如果不清楚怎么安装的可以按照Ubuntu 18.04 配置cuda中“GPU驱动的安装”一节进行安装。只要安装GPU驱动即可。

安装docker与NVIDIA Container Toolkit

  1. 如果服务器上已经有docker的可以跳过该步,否则可以执行

    curl https://get.docker.com | sh \
      && sudo systemctl --now enable docker
    
  2. 随后设置存储库

    distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
       && curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
       && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
    
  3. 接着就是更新并且安装

    sudo apt-get update
    sudo apt-get install -y nvidia-docker2
    sudo systemctl restart docker
    
  4. 最终,尝试输入docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi,如果能成功显示GPU的各类信息则说明安装成功,如下所示。

    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 450.51.06    Driver Version: 450.51.06    CUDA Version: 11.0     |
    |-------------------------------+----------------------+----------------------+
    | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
    |                               |                      |               MIG M. |
    |===============================+======================+======================|
    |   0  Tesla T4            On   | 00000000:00:1E.0 Off |                    0 |
    | N/A   34C    P8     9W /  70W |      0MiB / 15109MiB |      0%      Default |
    |                               |                      |                  N/A |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |  No running processes found                                                 |
    +-----------------------------------------------------------------------------+
    

注意:如果日后需要非root用户使用docker,请按照该链接所述方法进行设置。

下载代码

非常简单,直接在目标路径下执行git clone https://github.com/deepmind/alphafold.git即可

下载数据集

注意

  • AlphaFold需要非常巨大的数据集作为支撑,进行此步骤前请务必确认服务器磁盘空闲大小大于2.5TB以上

  • 此外,根据AlphaFold的要求,我们应该将数据集下载至AlphaFold工程目录外,以避免增加docker的大小。

数据集目录结构

如下所示,并不是水篇幅。下载完成后请务必按照如下文件结构一一对应,实际的文件体积可能会更大,但不会少。一定要尽可能一一对应!!!!!!!——血的教训

  • 查看当前文件夹大小的命令为du -sh
$DOWNLOAD_DIR/                             # Total: ~ 2.2 TB (download: 438 GB)
    bfd/                                   # ~ 1.7 TB (download: 271.6 GB)
        # 6 files.
    mgnify/                                # ~ 64 GB (download: 32.9 GB)
        mgy_clusters_2018_12.fa
    params/                                # ~ 3.5 GB (download: 3.5 GB)
        # 5 CASP14 models,
        # 5 pTM models,
        # 5 AlphaFold-Multimer models,
        # LICENSE,
        # = 16 files.
    pdb70/                                 # ~ 56 GB (download: 19.5 GB)
        # 9 files.
    pdb_mmcif/                             # ~ 206 GB (download: 46 GB)
        mmcif_files/
            # About 180,000 .cif files.
        obsolete.dat
    pdb_seqres/                            # ~ 0.2 GB (download: 0.2 GB)
        pdb_seqres.txt
    small_bfd/                             # ~ 17 GB (download: 9.6 GB)
        bfd-first_non_consensus_sequences.fasta
    uniclust30/                            # ~ 86 GB (download: 24.9 GB)
        uniclust30_2018_08/
            # 13 files.
    uniprot/                               # ~ 98.3 GB (download: 49 GB)
        uniprot.fasta
    uniref90/                              # ~ 58 GB (download: 29.7 GB)
        uniref90.fasta

常规下载

AlphaFold很贴心的提供了数据集的下载脚本,正常情况下进入AlphaFold的根目录下直接执行如下代码(二选一)即可:

# 完整数据集
scripts/download_all_data.sh <DOWNLOAD_DIR>
# 精简数据集
scripts/download_all_data.sh <DOWNLOAD_DIR> reduced_dbs

其中,请替换成数据集的保存目录。
众所周知,这个脚本没有什么用,如果能通过该脚本快速的下载完所有数据那就皆大欢喜;但由于下载速度一般会非常缓慢,所以需要单独手动下载,才能更有效率的下载完所有的数据。

手动下载

我们可以通过手动执行scripts目录下的各脚本(除download_all_data.sh)从而手动下载各数据集。方法就是将“常规下载”内的对应文件名替换成你希望运行的脚本名即可。

超常规手动下载

分析脚本内容我们可以知道,作者主要是通过aria2c进行下载的。我们随便打开一个脚本可以发现类似的内容:

DOWNLOAD_DIR="$1"
ROOT_DIR="${DOWNLOAD_DIR}/bfd"
# Mirror of:
# https://bfd.mmseqs.com/bfd_metaclust_clu_complete_id30_c90_final_seq.sorted_opt.tar.gz.
SOURCE_URL="https://storage.googleapis.com/alphafold-databases/casp14_versions/bfd_metaclust_clu_complete_id30_c90_final_seq.sorted_opt.tar.gz"
BASENAME=$(basename "${SOURCE_URL}")

mkdir --parents "${ROOT_DIR}"
aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}"
tar --extract --verbose --file="${ROOT_DIR}/${BASENAME}" \
  --directory="${ROOT_DIR}"
rm "${ROOT_DIR}/${BASENAME}"

其中的ROOT_DIR给出了该数据集压缩包的下载目录,例如本例中"${DOWNLOAD_DIR}/bfd"为你给出的数据集的下载目录/bfd下;SOURCE_URL给出了数据集的下载地址,有了下载地址我们就可以通过各种方法搞到这个数据集了(例如各种网盘的离线下载之类的功能)。

当文件下载成功后,我们将压缩包挪动至对应的ROOT_DIR(如果不存在可以手动创建或者先运行一下各数据集的下载脚本)后再注释掉aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}"这一行代码,如下所示:

DOWNLOAD_DIR="$1"
ROOT_DIR="${DOWNLOAD_DIR}/bfd"
# Mirror of:
# https://bfd.mmseqs.com/bfd_metaclust_clu_complete_id30_c90_final_seq.sorted_opt.tar.gz.
SOURCE_URL="https://storage.googleapis.com/alphafold-databases/casp14_versions/bfd_metaclust_clu_complete_id30_c90_final_seq.sorted_opt.tar.gz"
BASENAME=$(basename "${SOURCE_URL}")

mkdir --parents "${ROOT_DIR}"
# aria2c "${SOURCE_URL}" --dir="${ROOT_DIR}"
tar --extract --verbose --file="${ROOT_DIR}/${BASENAME}" \
  --directory="${ROOT_DIR}"
rm "${ROOT_DIR}/${BASENAME}"

如此就能跳过从国外服务器下载文件的步骤了。

额外处理

如下两个数据集需要额外处理,

  1. download_uniprot.sh

    DOWNLOAD_DIR="$1"
    ROOT_DIR="${DOWNLOAD_DIR}/uniprot"
    
    TREMBL_SOURCE_URL="ftp://ftp.ebi.ac.uk/pub/databases/uniprot/current_release/knowledgebase/complete/uniprot_trembl.fasta.gz"
    TREMBL_BASENAME=$(basename "${TREMBL_SOURCE_URL}")
    TREMBL_UNZIPPED_BASENAME="${TREMBL_BASENAME%.gz}"
    
    SPROT_SOURCE_URL="ftp://ftp.ebi.ac.uk/pub/databases/uniprot/current_release/knowledgebase/complete/uniprot_sprot.fasta.gz"
    SPROT_BASENAME=$(basename "${SPROT_SOURCE_URL}")
    SPROT_UNZIPPED_BASENAME="${SPROT_BASENAME%.gz}"
    
    mkdir --parents "${ROOT_DIR}"
    aria2c "${TREMBL_SOURCE_URL}" --dir="${ROOT_DIR}"
    aria2c "${SPROT_SOURCE_URL}" --dir="${ROOT_DIR}"
    pushd "${ROOT_DIR}"
    gunzip "${ROOT_DIR}/${TREMBL_BASENAME}"
    gunzip "${ROOT_DIR}/${SPROT_BASENAME}"
    
    # Concatenate TrEMBL and SwissProt, rename to uniprot and clean up.
    cat "${ROOT_DIR}/${SPROT_UNZIPPED_BASENAME}" >> "${ROOT_DIR}/${TREMBL_UNZIPPED_BASENAME}"
    mv "${ROOT_DIR}/${TREMBL_UNZIPPED_BASENAME}" "${ROOT_DIR}/uniprot.fasta"
    rm "${ROOT_DIR}/${SPROT_UNZIPPED_BASENAME}"
    popd
    

    如上所示,uniprot的路径为"${DOWNLOAD_DIR}/uniprot",然而它分别由两个文件组成,地址分别为TREMBL_SOURCE_URL与SPROT_SOURCE_URL。我们需要分别下载这两个文件后再执行屏蔽下载操作后的脚本。该脚本大意就是说uniprot.fasta这个文件分别由uniprot_sprot.fasta.gz与uniprot_trembl.fasta.gz合并而成。

  2. download_pdb_mmcif.sh
    这个数据集是个非常麻烦的数据集,作者并未直接给出具体的文件地址,而是使用了同步(rsync)的方式进行下载。并且下载下来并不是压缩包,而是非常多的文件夹,里边又是一系列压缩包。各压缩包解压时并不会因为下载不完全报错,因此很容易因为下载不完全导致后续代码运行报错。脚本如下所示:

    DOWNLOAD_DIR="$1"
    ROOT_DIR="${DOWNLOAD_DIR}/pdb_mmcif"
    RAW_DIR="${ROOT_DIR}/raw"
    MMCIF_DIR="${ROOT_DIR}/mmcif_files"
    
    echo "Running rsync to fetch all mmCIF files (note that the rsync progress estimate might be inaccurate)..."
    mkdir --parents "${RAW_DIR}"
    rsync --recursive --links --perms --times --compress --info=progress2 --delete --port=33444 \
      rsync.rcsb.org::ftp_data/structures/divided/mmCIF/ \
      "${RAW_DIR}"
    
    echo "Unzipping all mmCIF files..."
    find "${RAW_DIR}/" -type f -iname "*.gz" -exec gunzip {} +
    
    echo "Flattening all mmCIF files..."
    mkdir --parents "${MMCIF_DIR}"
    find "${RAW_DIR}" -type d -empty -delete  # Delete empty directories.
    for subdir in "${RAW_DIR}"/*; do
      mv "${subdir}/"*.cif "${MMCIF_DIR}"
    done
    
    # Delete empty download directory structure.
    find "${RAW_DIR}" -type d -empty -delete
    
    aria2c "ftp://ftp.wwpdb.org/pub/pdb/data/status/obsolete.dat" --dir="${ROOT_DIR}"
    

    最终只能根据https://www.rehiy.com/post/134的方法进行多线程同步,代码如下:

    #!/bin/sh
    
    src='rsync.rcsb.org::ftp_data/structures/divided/mmCIF' #源路径,结尾不带斜线
    dst='./pdb_mmcif/raw' #目标路径,结尾不带斜线
    opt="--recursive --links --perms --times --compress --info=progress2 --delete --port=33444" #同步选项
    num=10 #并发进程数
    depth='5 4 3 2 1' #归递目录深度
    task=/tmp/`echo $src$ | md5sum | head -c 16`
    [ -f $task-next ] && cp $task-next $task-skip
    [ -f $task-skip ] || touch $task-skip
    
    # 创建目标目录结构
    rsync $opt --include "*/" --exclude "*" $src/ $dst
    
    # 从深到浅同步目录
    for l in $depth ;do
        # 启动rsync进程
        for i in `find $dst -maxdepth $l -mindepth $l -type d`; do
            i=`echo $i | sed "s#$dst/##"`
            if `grep -q "$i$" $task-skip`; then
                echo "skip $i"
                continue
            fi
            while true; do
                now_num=`ps axw | grep rsync | grep $dst | grep -v '\-\-daemon' | wc -l`
                if [ $now_num -lt $num ]; then
                    echo "rsync $opt $src/$i/ $dst/$i" >>$task-log
                    rsync $opt $src/$i/ $dst/$i &
                    echo $i >>$task-next
                    sleep 1
                    break
                else
                    sleep 5
                fi
            done
        done
    done
    

    请将以上代码保存至DOWNLOAD_DIR目录下再运行。使用时并发进程数num请勿设置的过大否则容易被服务器拉黑。

配置环境

当数据集下载完毕后,就可以准备配置环境了。直接在AlphaFold根目录下执行docker build -f docker/Dockerfile -t alphafold .创建docker环境即可。注意,此处也是有坑的,但是先按照默认设置进行配置,下一步运行时会说到这个。
随后通过pip3 install -r docker/requirements.txt安装依赖项。

运行Demo

当上述步骤全部完成后,就可以尝试运行代码了:

python3 docker/run_docker.py \
  --fasta_paths=T1050.fasta \
  --max_template_date=2020-05-14 \
  --data_dir=$DOWNLOAD_DIR

其中测试数据T1050.fasta官方貌似没有提供,可以直接在AlphaFold根目录执行wget -o /dev/null -O T1050.fasta 'https://www.predictioncenter.org/casp14/target.cgi?target=T1050&view=sequence'下载;并且$DOWNLOAD_DIR需要替换成上述设置的数据集下载目录。

如果一切顺利,你就成功配置好了AlphaFold。如果碰到坑,请参考如下解决办法尝试处理:

坑坑坑坑

坑1. docker中的一些目录挂载出错。

如果提示docker.errors.APIError: 400 Client Error for http+docker://localhost/v1.41/containers/create: Bad Request ("invalid mount config for type "bind": bind source path does not exist: /tmp/alphafold")。出现这个问题应该是因为官方示例里并没有给出程序的输出目录,而默认的输出目录是有问题的。可以在运行时增加--output_dir=你自己的输出目录字段;或者直接修改docker/run_docker.py中的flags.DEFINE_string('output_dir', '你自己的输出目录', 'Path to a directory that will store the results.'),可以顺便把下边的flags.DEFINE_string('data_dir', '你自己的数据集下载目录','Path to directory with supporting data: AlphaFold parameters and genetic and template databases. Set to the target of download_all_databases.sh.'),这样以后运行代码时就不用再手动给出data_dir了。

坑2. 运行时提示ValueError: jaxlib is version 0.1.69, but this version of jax requires version 0.1.74.

这是一个让人非常无语的错误。当时因为这个折腾了很久怎么都修复不了。解决办法非常简单:将docker/Dockerfile中的&& pip3 install --upgrade jax jaxlib==0.1.69+cuda${CUDA/./} -f \修改成&& pip3 install --upgrade jax jaxlib>=0.1.69+cuda${CUDA/./} -f \,随后重新执行docker build -f docker/Dockerfile -t alphafold .即可。

如果还报错,请将docker/Dockerfile中的ARG CUDA=11.0修改为ARG CUDA=11.1,再重新执行docker build -f docker/Dockerfile -t alphafold .即可。

坑3 运行时报错,提示FileNotFoundError或者是某些方法找不到

出现这种错误首先看具体提示的是什么错误:

  • 如果是数据集相关的文件找不到,或者query的时候失败。回去重新下载对应的数据集,务必对照目录结构确保数据集下载完整了,特别是两个需要额外处理的数据集。
  • 如果是代码相关的文件,或者是import失败,又或者是一些莫名其妙的文件(路径不在数据集目录下),那么有非常大的可能你在创建docker的时候没下完整,请换个好点的网络,并且疯狂无脑反复执行docker build -f docker/Dockerfile -t alphafold .,并确保输出日志中的每一项都确实下载、安装完毕了。

你可能感兴趣的:(Ubuntu,#,Cuda,开发环境,ubuntu,docker,容器,AlphaFold)