在 Nvidia Docker 容器编译构建显存优化加速组件 xFormers

news2024/11/17 15:43:40

本篇文章,聊聊如何在新版本 PyTorch 和 CUDA 容器环境中完成 xFormers 的编译构建。

让你的模型应用能够跑的更快。

写在前面

xFormers 是 FaceBook Research (Meta)开源的使用率非常高的 Transformers 加速选型,当我们使用大模型的时候,如果启用 xFormers 组件,能够获得非常明显的性能提升。

FaceBook Research (Meta)- xFormers

因为 xFormers 对于 Pytorch 和 CUDA 新版本支持一般会晚很久。所以,时不时的我们能够看到社区提出不能在新版本 CUDA 中构建的问题(#935或 #958),以及各种各样的编译失败的问题。

另外,xFormers 的安装还有一个问题,会在安装的时候调整当前环境已经安装好的 PyTorch 和 Numpy 版本,比如我们使用的是已经被验证过的环境,比如 Nvidia 的月度发布的容器环境,这显然是我们不乐见的事情。

方便的 Nvidia 高性能 Docker 镜像环境

下面,我们就来解决这两个问题,让 xFormers 能够在新的 CUDA 环境中完成编译,以及让 xFormers 的安装不需要变动我们已经安装好的 Pytorch 或者 Numpy。

环境准备

环境的准备一共有两步,下载容器和 xFormers 源代码。

Nvidia 容器环境

在之前的许多文章中,我提过很多次为了高效运行模型,我推荐使用 Nvidia 官方的容器镜像(nvcr.io/nvidia/pytorch:23.12-py3)。

下载镜像很简单,一条命令就行:

docker pull nvcr.io/nvidia/pytorch:23.12-py3

完成镜像下载后,准备工作就完成了一半。

准备好镜像后,我们可以检查下镜像中的具体组件环境,使用 docker run 启动镜像:

docker run --rm -it --gpus all --ipc=host --ulimit memlock=-1 -v `pwd`:/app nvcr.io/nvidia/pytorch:23.12-py3 bash

然后,使用 python -m torch.utils.collect_env 来获取当前环境的信息,方便后续完成安装后确认原始环境稳定:

# python -m torch.utils.collect_env

Collecting environment information...
PyTorch version: 2.2.0a0+81ea7a4
Is debug build: False
CUDA used to build PyTorch: 12.3
ROCM used to build PyTorch: N/A

OS: Ubuntu 22.04.3 LTS (x86_64)
GCC version: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Clang version: Could not collect
CMake version: version 3.27.9
Libc version: glibc-2.35

Python version: 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (64-bit runtime)
Python platform: Linux-6.5.0-14-generic-x86_64-with-glibc2.35
Is CUDA available: True
CUDA runtime version: 12.3.107
CUDA_MODULE_LOADING set to: LAZY
GPU models and configuration: GPU 0: NVIDIA GeForce RTX 4090
Nvidia driver version: 525.147.05
cuDNN version: Probably one of the following:
/usr/lib/x86_64-linux-gnu/libcudnn.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_adv_infer.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_adv_train.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_cnn_infer.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_cnn_train.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_ops_infer.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_ops_train.so.8.9.7
HIP runtime version: N/A
MIOpen runtime version: N/A
Is XNNPACK available: True

CPU:
Architecture:                       x86_64
CPU op-mode(s):                     32-bit, 64-bit
Address sizes:                      39 bits physical, 48 bits virtual
Byte Order:                         Little Endian
CPU(s):                             32
On-line CPU(s) list:                0-31
Vendor ID:                          GenuineIntel
Model name:                         13th Gen Intel(R) Core(TM) i9-13900KF
CPU family:                         6
Model:                              183
Thread(s) per core:                 2
Core(s) per socket:                 24
Socket(s):                          1
Stepping:                           1
CPU max MHz:                        5800.0000
CPU min MHz:                        800.0000
BogoMIPS:                           5990.40
Flags:                              fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi vnmi umip pku ospke waitpkg gfni vaes vpclmulqdq rdpid movdiri movdir64b fsrm md_clear serialize arch_lbr ibt flush_l1d arch_capabilities
Virtualization:                     VT-x
L1d cache:                          896 KiB (24 instances)
L1i cache:                          1.3 MiB (24 instances)
L2 cache:                           32 MiB (12 instances)
L3 cache:                           36 MiB (1 instance)
NUMA node(s):                       1
NUMA node0 CPU(s):                  0-31
Vulnerability Gather data sampling: Not affected
Vulnerability Itlb multihit:        Not affected
Vulnerability L1tf:                 Not affected
Vulnerability Mds:                  Not affected
Vulnerability Meltdown:             Not affected
Vulnerability Mmio stale data:      Not affected
Vulnerability Retbleed:             Not affected
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass:    Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:           Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:           Mitigation; Enhanced / Automatic IBRS, IBPB conditional, RSB filling, PBRSB-eIBRS SW sequence
Vulnerability Srbds:                Not affected
Vulnerability Tsx async abort:      Not affected

Versions of relevant libraries:
[pip3] numpy==1.24.4
[pip3] onnx==1.15.0rc2
[pip3] optree==0.10.0
[pip3] pytorch-quantization==2.1.2
[pip3] torch==2.2.0a0+81ea7a4
[pip3] torch-tensorrt==2.2.0a0
[pip3] torchdata==0.7.0a0
[pip3] torchtext==0.17.0a0
[pip3] torchvision==0.17.0a0
[pip3] triton==2.1.0+6e4932c

获取 xFormers

下载 xFormers 的源代码,并且记得使用 --recursive 确保所有依赖都下载完毕:

git clone --recursive https://github.com/facebookresearch/xformers.git --depth 1

xFormers 的源码包含三个核心组件 cutlassflash-attentionsputnik,除去最后一个开源软件在 xFormers 项目 sputnik 因为 Google 不再更新,被固定了代码版本,其他两个组件的版本分别为:cutlass@3.2flash-attention@2.3.6

Dao-AILab - flash-attention

Dao-AILab/flash-attention目前最新的版本是 v2.4.2,不过更新的主干版本包含了更多错误的修复,推荐直接升级到最新版本。在 v2.4.2 版本中,它依赖的 cutlass 版本为 3.3.0,所以我们需要升级 cutlass 到合适的版本。

cd xformers/third_party/flash-attention
git pull origin main

Nvidia/cutlass 在 3.1+ 的版本对性能提升明显。

NVIDIA  - cutlass Perf

不过如果直接更新 3.2 到目前最新的 3.4 flash-attention 找不到合适的版本,会发生编译不通过的问题,所以我们将版本切换到 v3.3.0 即可。

cd xformers/third_party/cutlass
git pull origin main
git checkout v3.3.0

另外,在前文中提到了在安装 xFormers 的时候,会连带更新本地已经安装好的依赖。想要保护本地已经安装好的环境不被覆盖,尤其是 Nvidia 容器中的依赖不被影响,我们需要将 xformers/requirements.txt 内容清空。

echo '' > xformers/requirements.txt

好了,到这里准备工作就结束了。

完成容器中的 xFormers 的安装

想要顺利完成 xFormers 的构建,还有一些小细节需要注意。为了让我们能够从源码进行构建,我们需要关闭我们下载 xFormers 路径的 Git 安全路径检查:

git config --global --add safe.directory /app/xformers
git config --global --add safe.directory /app/xformers/third_party/flash-attention
git config --global --add safe.directory /app/xformers/third_party/cutlass

为了让构建速度有所提升,我们需要安装一个能够让我们加速完成构建的工具 ninja

pip install ninja

当上面的工具都完成后,我们就可以执行命令,开始构建安装了:

pip install -v -e .

需要注意的是,默认情况下安装程序会根据你的 CPU 核心数来设置构建进程数,不过过高的工作进程,会消耗非常多的内存。如果你的 CPU 核心数非常多,那么默认情况下直接执行上面的命令,会得到非常多的 Killed 的编译错误。

想要解决这个问题,我们需要设置合理的 MAX_JOBS 参数。如果你的硬件资源有限,可以设置 MAX_JOBS=1,如果你资源较多,可以适当增加数值。我的构建设备有 64G 内存,我一般会选择设置 MAX_JOBS=3 来使用大概最多 50GB 的内存,来完成构建过程,MAX_JOBS 的构建内存消耗并不是完全严格按照线性增加的,当我们设置为 1 的时候,16GB 的设备就能够完成构建、当我们设置为 2 的时候,使用 32GB 的设备构建会比较稳妥,当设置到 4 的时候,构建需要的内存就需要 60GB 以上了。

MAX_JOBS=按照你的情况来 python setup.py develop

构建的过程非常漫长,过程中我们可以去干点别的事情。

当然,为了我们后续使用镜像方便,最好的方案是编写一个 Dockerfile,然后将构建的产物保存在镜像中,以方便后续各种场景使用:

FROM nvcr.io/nvidia/pytorch:23.12-py3
LABEL maintainer="soulteary@gmail.com"

# according to your situation, use pypi mirrors
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
WORKDIR /app

# xformers
RUN git clone --recursive https://github.com/facebookresearch/xformers.git --depth 1
RUN git config --global --add safe.directory /app/xformers && \
    git config --global --add safe.directory /app/xformers/third_party/flash-attention && \
    git config --global --add safe.directory /app/xformers/third_party/cutlass
RUN cd /app/xformers/third_party/flash-attention && git pull origin main && \
    cd /app/xformers/third_party/cutlass && git pull origin main && git checkout v3.3.0
WORKDIR /app/xformers
RUN echo '' > requirements.txt
RUN pip install ninja
ARG MAX_JOBS=1
RUN pip install -v -e .

在构建的时候,我们可以使用类似下面的命令,来搞定既使用了最新的 Nvidia 镜像,包含最新的 Pytorch 和 CUDA 版本,又包含 xFormers 加速组件的容器环境。

docker build -t soulteary/common-runtime --build-arg MAX_JOBS=3 .

如果你是在本机上进行构建,没有使用 Docker,那么构建成功,你将看到类似下面的日志:

...
    Creating /usr/local/lib/python3.10/dist-packages/xformers.egg-link (link to .)
    Adding xformers 0.0.24+6600003.d20240112 to easy-install.pth file

    Installed /app/docker/xformers
Successfully installed xformers-0.0.24+6600003.d20240112

等待漫长的构建结束,我们可以使用下面的命令,来启动一个包含构建产物的容器,来测试下构建是否成功:

docker run --rm -it --gpus all --ipc=host --ulimit memlock=-1 -v `pwd`:/app soulteary/common-runtime bash

当我们进入容器的交互式命令行之后,我们可以执行 python -m xformers.info,来验证 xFromers 是否构建正常:

xFormers 0.0.24+6600003.d20240112
memory_efficient_attention.cutlassF:               available
memory_efficient_attention.cutlassB:               available
memory_efficient_attention.decoderF:               available
memory_efficient_attention.flshattF@v2.3.6:        available
memory_efficient_attention.flshattB@v2.3.6:        available
memory_efficient_attention.smallkF:                available
memory_efficient_attention.smallkB:                available
memory_efficient_attention.tritonflashattF:        unavailable
memory_efficient_attention.tritonflashattB:        unavailable
memory_efficient_attention.triton_splitKF:         available
indexing.scaled_index_addF:                        available
indexing.scaled_index_addB:                        available
indexing.index_select:                             available
swiglu.dual_gemm_silu:                             available
swiglu.gemm_fused_operand_sum:                     available
swiglu.fused.p.cpp:                                available
is_triton_available:                               True
pytorch.version:                                   2.2.0a0+81ea7a4
pytorch.cuda:                                      available
gpu.compute_capability:                            8.9
gpu.name:                                          NVIDIA GeForce RTX 4090
dcgm_profiler:                                     unavailable
build.info:                                        available
build.cuda_version:                                1230
build.python_version:                              3.10.12
build.torch_version:                               2.2.0a0+81ea7a4
build.env.TORCH_CUDA_ARCH_LIST:                    5.2 6.0 6.1 7.0 7.2 7.5 8.0 8.6 8.7 9.0+PTX
build.env.XFORMERS_BUILD_TYPE:                     None
build.env.XFORMERS_ENABLE_DEBUG_ASSERTIONS:        None
build.env.NVCC_FLAGS:                              None
build.env.XFORMERS_PACKAGE_FROM:                   None
build.nvcc_version:                                12.3.107
source.privacy:                                    open source

以及,使用 python -m torch.utils.collect_env 再次确认下环境是否一致:

# python -m torch.utils.collect_env
PyTorch version: 2.2.0a0+81ea7a4
Is debug build: False
CUDA used to build PyTorch: 12.3
ROCM used to build PyTorch: N/A

OS: Ubuntu 22.04.3 LTS (x86_64)
GCC version: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Clang version: Could not collect
CMake version: version 3.27.9
Libc version: glibc-2.35

Python version: 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (64-bit runtime)
Python platform: Linux-6.5.0-14-generic-x86_64-with-glibc2.35
Is CUDA available: True
CUDA runtime version: 12.3.107
CUDA_MODULE_LOADING set to: LAZY
GPU models and configuration: GPU 0: NVIDIA GeForce RTX 4090
Nvidia driver version: 525.147.05
cuDNN version: Probably one of the following:
/usr/lib/x86_64-linux-gnu/libcudnn.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_adv_infer.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_adv_train.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_cnn_infer.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_cnn_train.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_ops_infer.so.8.9.7
/usr/lib/x86_64-linux-gnu/libcudnn_ops_train.so.8.9.7
HIP runtime version: N/A
MIOpen runtime version: N/A
Is XNNPACK available: True

...

Versions of relevant libraries:
[pip3] numpy==1.24.4
[pip3] onnx==1.15.0rc2
[pip3] optree==0.10.0
[pip3] pytorch-quantization==2.1.2
[pip3] torch==2.2.0a0+81ea7a4
[pip3] torch-tensorrt==2.2.0a0
[pip3] torchdata==0.7.0a0
[pip3] torchtext==0.17.0a0
[pip3] torchvision==0.17.0a0
[pip3] triton==2.1.0+6e4932c

最后

好了,这篇文章就先写到这里啦。

–EOF


我们有一个小小的折腾群,里面聚集了一些喜欢折腾、彼此坦诚相待的小伙伴。

我们在里面会一起聊聊软硬件、HomeLab、编程上、生活里以及职场中的一些问题,偶尔也在群里不定期的分享一些技术资料。

关于交友的标准,请参考下面的文章:

致新朋友:为生活投票,不断寻找更好的朋友

当然,通过下面这篇文章添加好友时,请备注实名和公司或学校、注明来源和目的,珍惜彼此的时间 😄

关于折腾群入群的那些事


本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

本文作者: 苏洋

创建时间: 2024年01月12日
统计字数: 10731字
阅读时间: 22分钟阅读
本文链接: https://soulteary.com/2024/01/12/xformers-source-code-compilation-with-nvidia-docker.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1377357.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

可以打印试卷的软件有哪些?推荐这几款

可以打印试卷的软件有哪些?随着科技的飞速发展,越来越多的学习工具如雨后春笋般涌现,其中,能够打印试卷的软件尤其受到广大学生和家长的青睐。这些软件不仅方便快捷,而且内容丰富,可以满足不同学科、不同年…

从零学Java Set集合

Java Set集合 文章目录 Java Set集合1 Set 集合2 Set实现类2.1 HashSet【重点】2.2 LinkedHashSet2.3 TreeSet 3 Comparator 自定义比较器 1 Set 集合 特点:无序无下标、元素不可重复。 方法:全部继承自Collection中的方法。 常用方法: publ…

windos exe 以服务的形式运行(开机运行)

windos 品台编写的 小工具 exe 或者 批处理 .bat 经常需要开机自启动,可以直接把它 加在开启启动项,或者做成 windos服务,这样既可以开机自动启动而且还可以 防止误触关闭掉; windos 以服务启动 exe/bat 的通用方式&#xff1…

js逆向第18例:猿人学第15题备周则意怠-常见则不疑

文章目录 一、前言二、定位关键参数三、代码实现四、参考文献一、前言 任务十五:抓取这5页的数字,计算加和并提交结果 二、定位关键参数 先找到数据接口 可以看到接口的url地址中存在变量m如下 进入堆栈,定位m值 如下图逻辑很清晰,可以看到window.

ChatGPT到底能做什么呢?

1、熟练掌握ChatGPT提示词技巧及各种应用方法,并成为工作中的助手。 2、通过案例掌握ChatGPT撰写、修改论文及工作报告,提供写作能力及优化工作 3、熟练掌握ChatGPT融合相关插件的应用,完成数据分析、编程以及深度学习等相关科研项目。 4、…

【AI视野·今日Sound 声学论文速览 第四十三期】Mon, 8 Jan 2024

AI视野今日CS.Sound 声学论文速览 Mon, 8 Jan 2024 Totally 6 papers 👉上期速览✈更多精彩请移步主页 Daily Sound Papers MusicAOG: an Energy-Based Model for Learning and Sampling a Hierarchical Representation of Symbolic Music Authors Yikai Qian, Tia…

实现秒杀功能设计

页面 登录页面 登录成功后,跳转商品列表 商品列表页 加载商品信息 商品详情页 根据商品id查出商品信息返回VO(包括rmiaoshaStatus、emainSeconds)前端根据数据展示秒杀按钮,点击开始秒杀 订单详情页 秒杀页面设置 后端返回秒杀…

在线陪玩软件开发系统(APP小程序H5、平台、搭建)游戏陪玩系统APP开发 源码搭建,源码交付,支持二开!

一、游戏陪玩系统APP的核心功能 1. 匹配系统:通过智能匹配算法,将寻找陪玩的玩家与愿意提供陪玩服务的玩家进行匹配,确保双方的需求能够得到满足。 2. 实时通讯:提供实时语音和文字聊天功能,让玩家和陪玩者可以在游戏…

Js - 函数(四)

1.函数简单介绍 什么是函数? 函数(function)是执行特定任务的一段代码块 为什么需要函数? 可以实现代码复用,提高开发效率 2.函数使用 函数的声明语法 函数名命名规范 函数的调用语法 函数体 函数体是函数的构…

【Scala】——流程控制

1 if-else 分支控制 让程序有选择的的执行,分支控制有三种:单分支、双分支、多分支 1.1单分支 if (条件表达式) {执行代码块 }1.2 双分支 if (条件表达式) {执行代码块 1 } else {执行代码块 2 }1.3 多分支 if (条件表达式1) {执行代码块 1 } else …

选中图层为什么不能建立3D模型---模大狮模型网

在Photoshop CC 2021(也就是PS6)中,要将选中的图层转换为3D模型,需要满足以下几个条件: 图层类型支持:只有特定类型的图层可以被转换为3D模型。通常,普通的像素图层、矢量图层和形状图层都可以进行转换。但是&#xff…

仲晶同志简历

女,汉族。1972年出生,国防大学科技与装备教研室教官。1992年,仲晶毕业于军事气象学院,1996年成为国防大学国防科技发展战略学硕士研究生,毕业后留校任教。曾出版过9部军事专著,先后发表学术论文100多万字。…

VUE element-ui实现表格动态展示、动态删减列、动态排序、动态搜索条件配置、表单组件化。

1、实现效果 1.1、文件目录 1.2、说明 1、本组件支持列表的表头自定义配置,checkbox实现 2、本组件支持列表列排序,vuedraggable是拖拽插件,上图中字段管理里的拖拽效果 ,需要的话请自行npm install 3、本组件支持查询条件动态…

代码随想录算法训练营第三十一天|理论基础、455.分发饼干、376. 摆动序列、53. 最大子序和

题目:理论基础 解释:贪心的本质是选择每一阶段的局部最优,从而达到全局最优 题目:455.分发饼干 文章链接:代码随想录 视频链接:LeetCode:455.分发饼干 题目链接:力扣题目链接 图释&#x…

【REST2SQL】07 GO 操作 Mysql 数据库

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 【REST2SQL】06 GO 跨包接口重构代码 MySQL是一个关系型数据库管理系统&#xf…

低代码与小程序开发:简化创新,加速应用开发

随着信息技术的迅速发展,应用程序的需求与日俱增。然而,传统的软件开发往往耗时、复杂,对于许多企业和开发者来说,开发应用程序的成本和难度成为了一道门槛。而近年来,低代码开发和小程序开发的兴起为解决这一难题带来…

专搞大厂?免费开源?这个小工具我相信很多人需要!

软件简介: 软件【下载地址】获取方式见文末。注:推荐使用,更贴合此安装方法! XHS-Downloader v1.6是一款功能齐全的免费开源工具,它使用Python Requests库开发而成,用于采集和下载X红S作品。该工具具备多…

青年人格测验

青年人格量表也叫加州人格量表(cpi),源于美国心理学家高夫的人格理论,共包含有18个维度,其中每个维度都是人格的基础元素,是人们在成长和外界交往中所形成的。 主要应用在人才测评领域,用来评估…

「 网络安全术语解读 」点击劫持Clickjacking详解

引言:要想深入理解点击劫持攻击,我们需要先清楚iframe的用途及优缺点。 1. 关于iframe iframe是HTML语言中的一部分,通常用于在网页中嵌入其他网页的内容,如图像、视频、音频、链接等。它允许在一个网页中插入另一个网页&#xf…

《豫鄂烽火燎原大小焕岭》:一部穿越时空的历史史诗

《豫鄂烽火燎原大小焕岭》:一部穿越时空的历史史诗 一部赓续红色血脉的生动教材 一部讴歌时代英雄和人民精神宝典 当历史的烽烟渐渐远去,留下的是一页页泛黄的记忆和无数英雄的壮丽诗篇。李传铭的力作《豫鄂烽火燎原大小焕岭》正是这样一部深情的回望&am…