前人指路#
有一个项目叫做 LocalColabFold,但是在国内服务器上安装各种依赖和解决依赖冲突实在是灾难,项目在这里:GitHub - YoshitakaMo/localcolabfold: ColabFold on your local PC ↗
一个很好的解决办法是使用 Docker/Singularity 来运行 ColabFold:Running ColabFold in Docker · sokrypton/ColabFold Wiki · GitHub ↗
拉取镜像#
将 ghcr.io 替换为 ghcr.nju.edu.cn 即可,用南大的镜像站
singularity pull docker://ghcr.nju.edu.cn/sokrypton/colabfold:1.5.5-cuda12.2.2bash权重文件下载#
singularity run -B ./cache:/cache \
colabfold_1.5.5-cuda12.2.2.sif \
python -m colabfold.downloadbash这个会在当前目录下创建一个 cache ,里面会下载权重文件,速度忽好忽慢
运行预测#
我写了俩脚本,一个用于快速预测,另外一个用来精细化预测,而且因为实验室的卡有两张 A100,所以我还尝试做了并行优化
这个优化的逻辑其实很简单,就是在一个文件夹下面放多个蛋白的 fasta 文件,然后脚本去取两个蛋白,分别丢到两个 GPU 上,这个过程并不涉及交火,所以其实性能损耗很小
但是似乎效果不太好
运行脚本大概是:
bash run_parallel_colabfold.sh --input liueic/protein_data --out liueic/output_dir --cache liueic/colabfold_cache --work-bind liueic/protein_data --sif liueic/colabfold_1.5.5-cuda12.2.2.sif --gpus 1 --tasks-per-gpu 1 --colabfold-args "--num-models 5 --num-recycle 6 --max-seq 256 --max-extra-seq 512 --msa-mode mmseqs2_uniref_env --pair-mode unpaired_paired --model-type auto --stop-at-score 90 --zip"bash刚开始预测的时候速度比较慢,但是我能看到显存已经被占用了,打开日志可以看到,是因为请求 MSA 服务:
[00:23:21] [GPU 0] [] WARNING: You are welcome to use the default MSA server, however keep in mind that it's a
[00:23:21] [GPU 0] [] limited shared resource only capable of processing a few thousand MSAs per day. Please
[00:23:21] [GPU 0] [] submit jobs only from a single IP address. We reserve the right to limit access to the
[00:23:21] [GPU 0] [] server case-by-case when usage exceeds fair use. If you require more MSAs: You can
[00:23:21] [GPU 0] [] precompute all MSAs with `colabfold_search` or host your own API and pass it to `--host-url`bash如果是要做高通量并行这样是不行的,比较好的方法是自部署一个 MSA 服务,可以参考:GitHub - sokrypton/ColabFold: Making Protein folding accessible to all! ↗
但是这个磁盘需求比较大,应该需要一台专门的服务器来做这个:
First create a directory for the databases on a disk with sufficient storage (940 GB (!)). Depending on where you are, this will take a couple of hours
目前即使不自己部署 MSA,其实也是能接受的,大不了晚上睡一觉起来又好了,因为也就几百个蛋白(?可能)
自部署MSA服务#
安装 MMseqs 2 (带 AVX 2 支持)#
需要安装最新版的 MMseqs 2,建议使用静态编译版本以获得最佳性能
# 下载静态编译版本 (Linux AVX2)
wget https://mmseqs.com/latest/mmseqs-linux-avx2.tar.gz
tar xvf mmseqs-linux-avx2.tar.gz
export PATH=$(pwd)/mmseqs/bin/:$PATH
# 验证安装
mmseqs -hbash下载并构建数据库#
可以前往这个网站进行下载:Steinegger Lab Dataset ↗
需要下载的数据库有:uniref30_2302.db.tar.gz、colabfold_envdb_2023.tar.gz
数据库非常大
解压,创建索引#
创建对应的目录:
mkdir MMSeqs # 创建目录
cd MMSeqs
tar -I pigz -xvf /48T/software/colabfold_envdb_2023.tar.gz -C .
tar -I pigz -xvf /48T/software/uniref30_2302.db.tar.gz -C .bash然后等待,这一步等待时间非常长,建议使用 tmux 或者其他的东西挂起终端,怕意外中断
做 padding,(对 colabfold_envdb_2023 同理):
# 语法: mmseqs makepaddedseqdb <输入数据库> <输出数据库名称>
mmseqs makepaddedseqdb uniref30_2302_db uniref30_2302_db_paddedbash这一步发生了什么? 它会生成一个新的数据库(uniref 30_2302_db_padded),里面的序列长度会被补齐(Pad)到特定的倍数,这会占用额外的磁盘空间,但对于 A 100 这种大卡来说,能极大地减少显存访问的碎片化,速度至关重要
这一步无法使用 GPU 进行加速,只能使用 CPU
开始推理#
可以直接参考我写的这个脚本,你可能需要根据自己的需求来更改,MMseqs 本身应该是支持多序列单文件的输入的:
#!/bin/bash
# =====================================================================
# MMseqs2 多物种批量 MSA 生成脚本
# =====================================================================
set -u
set -e
# --- 1. 核心路径配置 (请核对) ---
# 输入数据的文件夹 (当前目录)
INPUT_ROOT="./Gene_Family"
# 输出结果的总目录
OUTPUT_ROOT="./MSA_Results"
# MMseqs 程序和数据库路径 (根据你之前的记录填写)
MMSEQS_BIN="/mnt/liueic/MMSeqs/mmseqs/bin/mmseqs"
DB_UNIREF="/mnt/liueic/MMSeqs/uniref30_2302_db"
DB_ENV="/mnt/liueic/MMSeqs/colabfold_envdb_2023"
# --- 2. 参数设置 ---
THREADS=16
GPU_ID=1
export CUDA_VISIBLE_DEVICES="$GPU_ID"
# 创建总输出目录
mkdir -p "$OUTPUT_ROOT"
echo "=========================================================="
echo "开始批量处理 MSA"
echo "扫描目录: $INPUT_ROOT"
echo "结果输出: $OUTPUT_ROOT"
echo "=========================================================="
# 遍历所有 .faa 文件
for fasta_file in "${INPUT_ROOT}"/*.faa; do
# 检查文件是否存在 (防止目录为空)
[ -e "$fasta_file" ] || continue
# --- A. 提取物种名,创建独立文件夹 ---
filename=$(basename "$fasta_file")
# 提取物种名 (去掉后缀 blast.pep.faa,让文件夹名更短更干净)
species_name="${filename%.pep.faa}"
# 或者如果你想要完整文件名做文件夹,用这个: species_name="${filename%.*}"
# 定义该物种的专属输出目录
JOB_DIR="${OUTPUT_ROOT}/${species_name}"
TMP_DIR="${JOB_DIR}/tmp"
FINAL_DIR="${JOB_DIR}/final_a3m"
mkdir -p "$JOB_DIR" "$TMP_DIR" "$FINAL_DIR"
echo ""
echo "----------------------------------------------------------"
echo "正在处理物种: $species_name"
echo "输入文件: $filename"
echo "专属目录: $JOB_DIR"
echo "----------------------------------------------------------"
# --- B. 运行 MMseqs2 流程 ---
# 1. CreateDB
"$MMSEQS_BIN" createdb "$fasta_file" "$JOB_DIR/query_db" --shuffle 0 > /dev/null
# 2. Search UniRef30 (A100 加速)
echo " Running Search UniRef30..."
"$MMSEQS_BIN" search "$JOB_DIR/query_db" "$DB_UNIREF" \
"$JOB_DIR/res_uniref" "$TMP_DIR" \
--threads "$THREADS" -s 8 --gpu 1 --max-seqs 2000 --num-iterations 3 > /dev/null
# 3. Search EnvDB
echo " Running Search EnvDB..."
"$MMSEQS_BIN" search "$JOB_DIR/query_db" "$DB_ENV" \
"$JOB_DIR/res_env" "$TMP_DIR" \
--threads "$THREADS" -s 8 --gpu 1 --max-seqs 2000 --num-iterations 3 > /dev/null
# 4. Result2MSA
echo " Converting to MSA..."
"$MMSEQS_BIN" result2msa "$JOB_DIR/query_db" "$DB_UNIREF" \
"$JOB_DIR/res_uniref" "$JOB_DIR/msa_uniref" \
--msa-format-mode 2 --threads "$THREADS" > /dev/null
"$MMSEQS_BIN" result2msa "$JOB_DIR/query_db" "$DB_ENV" \
"$JOB_DIR/res_env" "$JOB_DIR/msa_env" \
--msa-format-mode 2 --threads "$THREADS" > /dev/null
# 5. Unpack (解包)
# 先解包到一个临时 merged 目录方便合并
RAW_A3M_DIR="$JOB_DIR/raw_a3m"
mkdir -p "$RAW_A3M_DIR"
"$MMSEQS_BIN" unpackdb "$JOB_DIR/msa_uniref" "$RAW_A3M_DIR" --unpack-name-mode 0 --unpack-suffix ".uniref" > /dev/null
"$MMSEQS_BIN" unpackdb "$JOB_DIR/msa_env" "$RAW_A3M_DIR" --unpack-name-mode 0 --unpack-suffix ".env" > /dev/null
# --- C. 合并 & 重命名 (自动化修正文件名) ---
echo " Merging and Renaming..."
# 读取 ID 映射表 (MMseqs 自动生成的 query_db.lookup)
LOOKUP_FILE="$JOB_DIR/query_db.lookup"
while read -r id original_header; do
# 1. 解析文件名
# original_header 可能是 ">SeqID description...",我们要取第一个词作为文件名
clean_name=$(echo "$original_header" | awk '{print $1}' | tr -d '>' | tr '|/ ' '___')
# 定义输入输出
uni_file="${RAW_A3M_DIR}/${id}.uniref"
env_file="${RAW_A3M_DIR}/${id}.env"
final_file="${FINAL_DIR}/${clean_name}.a3m"
# 2. 合并操作
if [ -f "$uni_file" ]; then
cat "$uni_file" > "$final_file"
# 如果有环境序列,去掉第一行后追加
if [ -f "$env_file" ]; then
tail -n +2 "$env_file" >> "$final_file"
fi
fi
done < "$LOOKUP_FILE"
# --- D. 清理 ---
echo " Cleaning up tmp files for $species_name..."
rm -rf "$TMP_DIR" "$RAW_A3M_DIR" "$JOB_DIR/res_uniref*" "$JOB_DIR/res_env*" "$JOB_DIR/msa_*"
echo "$species_name 完成!"
done
echo "=========================================================="
echo "所有物种处理完毕!"
echo "请查看结果目录: $OUTPUT_ROOT"
echo "=========================================================="bash查看是否运行成功,查看显卡调用 nvidia-smi:

运行结束后的目录结构:
MSA_Results_P450/
├── Manduca_sexta/ <-- 自动根据文件名创建的文件夹
│ ├── query_db <-- 保留了 DB 以备不时之需
│ └── final_a3m/ <-- 这里是可以直接喂给 ColabFold 的!
│ ├── SeqA.a3m
│ ├── SeqB.a3m
│ └── SeqC.a3m
├── Papilio_xuthus/
│ └── final_a3m/
│ ├── ...
└── ...plaintextMMseqs 2 的工作流是: FASTA -> Createdb -> Search (生成 ResultDB) -> Result 2 MSA (转换) -> UnpackDB (解压出文件)
后话#
MSA Search#
ColabFold 里面允许我们自定义 host-url,于是我就病急乱投医,我真的去找了 MSA Search 的容器镜像,在英伟达的官网这里可以找到:Overview — NVIDIA NIM for MSA Search ↗
然后非常令人哭笑不得的是,如果你直接使用中国大陆的 IP 去拉这个容器,他会告诉你说让你去找大陆的代理商


但是据我测试这个代理商国内如果你要使用的话,需要以机构/企业的身份去申请,就很离谱,因为英伟达上面下载只需要个人开发者申请一个 key 就可以了
所以我整了个花活,我用了 Azure 东京地区的服务器,去拉这个容器,然后再把容器中转到阿里云的容器仓库,再用集群从阿里云容器仓库拉这个容器
虽然我最后没有跑起来,因为我用的是 singularity,这个东西有各种奇奇怪怪的文件系统写入的问题,很无语
gpuserver#
因为这个 MMseqs 每次都需要重新读取数据,导致速度非常慢!需要启动一个守护进程,把数据写入到显存/内存中,以一个服务端的形式提供服务
#!/bin/bash
# ===============================================================
# MMseqs2 GPU 驻留服务启动脚本 (修正版)
# ===============================================================
set -u
# === 1. 配置路径 ===
MMSEQS_BIN="mmseqs/bin/mmseqs"
WORKDIR=$(pwd)
# 数据库路径 (确保这些路径是正确的)
DB_UNIREF="uniref30_2302_db"
DB_ENV="colabfold_envdb_2023"
# 日志文件
LOG_UNIREF="server_uniref.log"
LOG_ENV="server_env.log"
# === 2. GPU 环境设置 ===
# 指定卡,这里简化处理,默认使用 GPU 0 或 1
# 如果你有特定 GPU 编号,请修改这里
export CUDA_VISIBLE_DEVICES=0
echo "------------------------------------------------"
echo "正在启动 MMSeqs2 GPU Resource Managers..."
echo "注意:gpuserver 不是网络服务器,它不监听端口。"
echo "它将数据库锁定在 GPU/内存中以加速本地搜索。"
echo "------------------------------------------------"
# 检查可执行文件
if [ ! -f "$MMSEQS_BIN" ]; then
echo "错误: 找不到 mmseqs 可执行文件: $MMSEQS_BIN"
exit 1
fi
# --- 启动 UniRef30 Server ---
echo "启动 UniRef30 GPU Resident Process..."
# 去掉了 --port, --gpu-mode, --gpu-mem, --db-load-mode, --threads
# gpuserver 只需要数据库路径。其他参数通常是在 'search' 时指定的,
# 或者它会默认加载。
nohup "$MMSEQS_BIN" gpuserver "$DB_UNIREF" \
> "$LOG_UNIREF" 2>&1 &
PID_UNIREF=$!
echo " PID: $PID_UNIREF | Log: $LOG_UNIREF"
# --- 启动 ColabFold EnvDB Server ---
echo "启动 EnvDB GPU Resident Process..."
nohup "$MMSEQS_BIN" gpuserver "$DB_ENV" \
> "$LOG_ENV" 2>&1 &
PID_ENV=$!
echo " PID: $PID_ENV | Log: $LOG_ENV"
echo "------------------------------------------------"
echo " GPU 服务已启动。"
echo "------------------------------------------------"bash然后这个坑点在于,新版本的 MMseqs 的参数已经改了,不能使用启动 http 服务器这种方式处理任务了,我也没想好要怎么处理这个问题