<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>MKL on 小葱的学术基站</title><link>https://xiaocong.site/tags/mkl/</link><description>Recent content in MKL on 小葱的学术基站</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Tue, 14 Apr 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://xiaocong.site/tags/mkl/index.xml" rel="self" type="application/rss+xml"/><item><title>记一次 QE 编译排障：从 FHC 收敛坑到 oneAPI/MKL 与 AOCL 优化</title><link>https://xiaocong.site/tricks/build_qe_with_oneapi/</link><pubDate>Tue, 14 Apr 2026 00:00:00 +0800</pubDate><guid>https://xiaocong.site/tricks/build_qe_with_oneapi/</guid><description>&lt;h1 id="记一次-qe-编译排障从-fhc-收敛坑到-oneapimkl-与-aocl-优化"&gt;&lt;a href="#%e8%ae%b0%e4%b8%80%e6%ac%a1-qe-%e7%bc%96%e8%af%91%e6%8e%92%e9%9a%9c%e4%bb%8e-fhc-%e6%94%b6%e6%95%9b%e5%9d%91%e5%88%b0-oneapimkl-%e4%b8%8e-aocl-%e4%bc%98%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;记一次 QE 编译排障：从 FHC 收敛坑到 oneAPI/MKL 与 AOCL 优化
&lt;/h1&gt;&lt;p&gt;作为一个刚开始认真折腾第一性原理计算的新人，我原本以为编译 &lt;code&gt;Quantum ESPRESSO&lt;/code&gt; 只是“把依赖装好，然后 &lt;code&gt;cmake &amp;amp;&amp;amp; make&lt;/code&gt;”这么简单。结果这一轮下来，我对 HPC 环境、数值库、编译器、运行时链接，以及“同样的版本号不代表同样的行为”这句话，有了非常痛的体会。&lt;/p&gt;
&lt;p&gt;这篇文章记录一次完整的踩坑过程：我为什么重新在 CPU 集群上编译 QE，为什么一度被“同一个构型、同样版本的 QE，却在不同环境下一个能收敛一个不收敛”这件事气到，以及最后是如何把问题逐渐收束到 &lt;strong&gt;Libxc 的 FHC 选项&lt;/strong&gt;、&lt;strong&gt;oneAPI + MKL&lt;/strong&gt; 的优化路径，以及 &lt;strong&gt;AOCC 并不等于 AOCL&lt;/strong&gt; 这几个关键点上的。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一起因29654-也不是万能的"&gt;&lt;a href="#%e4%b8%80%e8%b5%b7%e5%9b%a029654-%e4%b9%9f%e4%b8%8d%e6%98%af%e4%b8%87%e8%83%bd%e7%9a%84" class="header-anchor"&gt;&lt;/a&gt;一、起因：2×9654 也不是万能的
&lt;/h2&gt;&lt;p&gt;我最开始的想法其实很朴素：手里明明有 AMD EPYC 9654 这样的 CPU 节点，跑一些 QE 单点构型重标注，应该不会太慢吧？&lt;/p&gt;
&lt;p&gt;但实际测试下来，我发现我的 case 跑得并不理想。尤其是批量构型一多，单个 case 的耗时就很刺眼。于是我开始想：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;既然 CPU 集群上已经装好了 &lt;code&gt;Intel oneAPI&lt;/code&gt; 和 &lt;code&gt;MKL&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;而我这批计算本质上又是 CPU 密集型；&lt;/li&gt;
&lt;li&gt;那么是否应该在 Intel CPU 集群上重新编译一版 QE，走 &lt;code&gt;oneAPI + MKL&lt;/code&gt; 路线，看看能不能把性能和稳定性一起拉起来？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个想法后来证明完全正确。只是我没想到，真正先把我绊倒的，不是性能，而是&lt;strong&gt;收敛性&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="二最让我气愤的一幕同一个构型同版本-qe居然一个收敛一个不收敛"&gt;&lt;a href="#%e4%ba%8c%e6%9c%80%e8%ae%a9%e6%88%91%e6%b0%94%e6%84%a4%e7%9a%84%e4%b8%80%e5%b9%95%e5%90%8c%e4%b8%80%e4%b8%aa%e6%9e%84%e5%9e%8b%e5%90%8c%e7%89%88%e6%9c%ac-qe%e5%b1%85%e7%84%b6%e4%b8%80%e4%b8%aa%e6%94%b6%e6%95%9b%e4%b8%80%e4%b8%aa%e4%b8%8d%e6%94%b6%e6%95%9b" class="header-anchor"&gt;&lt;/a&gt;二、最让我气愤的一幕：同一个构型、同版本 QE，居然一个收敛一个不收敛
&lt;/h2&gt;&lt;p&gt;最开始我遇到的问题不是“算得慢”，而是“&lt;strong&gt;算不下来&lt;/strong&gt;”。&lt;/p&gt;
&lt;p&gt;症状很典型：某些构型在一个环境里可以继续往下跑，而在另一个环境里却报类似下面的错误：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error in routine c_bands (1):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;too many bands are not converged
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者更直接一点，在第一步、前几步就崩掉。&lt;/p&gt;
&lt;p&gt;最让我难受的是：&lt;strong&gt;QE 版本号明明一样。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我一度非常恼火。因为在一个 DFT 新手的直觉里，版本一样、输入一样、赝势一样，结果至少不应该差这么离谱。后来我才真正认识到，在 HPC 科学计算里，所谓“环境”从来都不只是一个版本号。它背后至少还包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;编译器；&lt;/li&gt;
&lt;li&gt;MPI 实现；&lt;/li&gt;
&lt;li&gt;BLAS/LAPACK/FFT 后端；&lt;/li&gt;
&lt;li&gt;外部库的版本与编译选项；&lt;/li&gt;
&lt;li&gt;动态库还是静态库；&lt;/li&gt;
&lt;li&gt;运行时究竟加载了哪一份库。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也正是在这一轮排查中，我第一次真正理解了：&lt;strong&gt;“软件版本相同”根本不等于“数值路径相同”。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="三第一轮排查怀疑-mpi怀疑脚本怀疑链接最后聚焦到-libxc"&gt;&lt;a href="#%e4%b8%89%e7%ac%ac%e4%b8%80%e8%bd%ae%e6%8e%92%e6%9f%a5%e6%80%80%e7%96%91-mpi%e6%80%80%e7%96%91%e8%84%9a%e6%9c%ac%e6%80%80%e7%96%91%e9%93%be%e6%8e%a5%e6%9c%80%e5%90%8e%e8%81%9a%e7%84%a6%e5%88%b0-libxc" class="header-anchor"&gt;&lt;/a&gt;三、第一轮排查：怀疑 MPI、怀疑脚本、怀疑链接，最后聚焦到 Libxc
&lt;/h2&gt;&lt;p&gt;起初我的排查路线比较朴素，主要看这些：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;srun&lt;/code&gt; 和 &lt;code&gt;mpirun&lt;/code&gt; 的差异；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pw.x&lt;/code&gt; 究竟链接的是哪一套 MPI；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; 是否正确；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;libxc&lt;/code&gt; 是否真的被启用；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MKL&lt;/code&gt; 是否被正确加载；&lt;/li&gt;
&lt;li&gt;运行时到底吃的是哪份 &lt;code&gt;libxc&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中一个重要发现是：&lt;strong&gt;不同节点上的 &lt;code&gt;pw.x&lt;/code&gt; 二进制其实根本不是同一个构建结果&lt;/strong&gt;。
虽然源码版本一致，但哈希值不同，依赖链也不同。换句话说，我之前以为自己在比较“同一程序在不同机器上的表现”，实际上是在比较“两套不同构建结果的 QE”。&lt;/p&gt;
&lt;p&gt;进一步查下去，我开始逐渐把怀疑集中到 &lt;code&gt;Libxc&lt;/code&gt; 上，尤其是对 &lt;code&gt;SCAN&lt;/code&gt; 这类泛函的支持。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="四关键转折fhc-才是那个真正影响能不能算的元凶之一"&gt;&lt;a href="#%e5%9b%9b%e5%85%b3%e9%94%ae%e8%bd%ac%e6%8a%98fhc-%e6%89%8d%e6%98%af%e9%82%a3%e4%b8%aa%e7%9c%9f%e6%ad%a3%e5%bd%b1%e5%93%8d%e8%83%bd%e4%b8%8d%e8%83%bd%e7%ae%97%e7%9a%84%e5%85%83%e5%87%b6%e4%b9%8b%e4%b8%80" class="header-anchor"&gt;&lt;/a&gt;四、关键转折：FHC 才是那个真正影响“能不能算”的元凶之一
&lt;/h2&gt;&lt;p&gt;后来最关键的线索出现了：
我发现自己之前的 &lt;code&gt;libxc&lt;/code&gt; 编译里，&lt;strong&gt;FHC 是开启的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;而在后续排查中，我注意到一个非常重要的事实：对于 &lt;code&gt;SCAN&lt;/code&gt; 这类 &lt;code&gt;meta-GGA&lt;/code&gt; 泛函，&lt;code&gt;libxc&lt;/code&gt; 的 &lt;strong&gt;Fermi hole curvature（FHC）&lt;/strong&gt; 选项可能直接影响数值稳定性。更具体地说，&lt;strong&gt;它不是“算得快不快”的问题，而是“同一个构型到底能不能稳定收敛”的问题。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这就解释了为什么我会遇到那么诡异的现象：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;输入文件一样；&lt;/li&gt;
&lt;li&gt;赝势一样；&lt;/li&gt;
&lt;li&gt;QE 版本号一样；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但某个构型在一套环境里会在前几步就报 &lt;code&gt;too many bands are not converged&lt;/code&gt;，而在另一套环境里却能正常收敛。&lt;/p&gt;
&lt;p&gt;后来当我重新编译一套 &lt;strong&gt;关闭 FHC 的 libxc&lt;/strong&gt; 后，原本不稳定的构型居然就能继续稳稳往下跑，并最终完成收敛。这一刻我真的有点震撼：
&lt;strong&gt;一个编译选项，足以决定“同一个构型到底是算得下来，还是算不下来”。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;也正因为这个经历，我现在对 &lt;code&gt;libxc&lt;/code&gt; 的态度已经完全变了。以前总觉得它只是“QE 的一个依赖”，现在我会把它视为：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;对某些泛函来说，&lt;code&gt;libxc&lt;/code&gt; 的版本与编译方式，本身就是数值模型的一部分。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="五第二个坑cmake-升太新也会出问题"&gt;&lt;a href="#%e4%ba%94%e7%ac%ac%e4%ba%8c%e4%b8%aa%e5%9d%91cmake-%e5%8d%87%e5%a4%aa%e6%96%b0%e4%b9%9f%e4%bc%9a%e5%87%ba%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;五、第二个坑：CMake 升太新，也会出问题
&lt;/h2&gt;&lt;p&gt;解决完 &lt;code&gt;libxc/FHC&lt;/code&gt; 这条主线后，我又踩到了另一个很典型、但一开始并不显眼的坑：&lt;strong&gt;CMake 版本太新。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为系统自带的 CMake 太旧，所以我当时一口气把 CMake 升到了 &lt;code&gt;4.3.1&lt;/code&gt;。按直觉看，这似乎是“升级工具链、拥抱新版本”的标准操作。但实际情况是，新版 CMake 对一些旧模块、旧写法更严格，结果导致 QE 构建中的某些模块开始报兼容性问题。&lt;/p&gt;
&lt;p&gt;最直接的影响包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内置 LAPACK 相关模块报错；&lt;/li&gt;
&lt;li&gt;MBD 相关模块出现兼容性问题；&lt;/li&gt;
&lt;li&gt;某些旧语法需要额外策略兼容。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后的处理思路不是回退一切，而是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;放弃 QE 内置数学库路线&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;直接切到 &lt;strong&gt;oneAPI + MKL&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;FFT 路线指定为 &lt;code&gt;Intel_DFTI&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;再通过追加&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-DCMAKE_POLICY_VERSION_MINIMUM=3.5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;让新版 CMake 对旧模块“网开一面”。&lt;/p&gt;
&lt;p&gt;这一段很有代表性。它说明一件事：
&lt;strong&gt;“新”不一定直接等于“更适合生产环境”。&lt;/strong&gt;
在科学计算软件生态里，一个过新的构建工具，反而可能把原本就不够现代化的上层项目折腾出额外兼容性问题。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="六我最后采用的生产路线oneapi--mkl--no-fhc-libxc"&gt;&lt;a href="#%e5%85%ad%e6%88%91%e6%9c%80%e5%90%8e%e9%87%87%e7%94%a8%e7%9a%84%e7%94%9f%e4%ba%a7%e8%b7%af%e7%ba%bfoneapi--mkl--no-fhc-libxc" class="header-anchor"&gt;&lt;/a&gt;六、我最后采用的生产路线：oneAPI + MKL + no-FHC libxc
&lt;/h2&gt;&lt;p&gt;在 Intel CPU 集群上，我最终确定下来的主线是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;编译器：&lt;code&gt;mpiicx / mpiifx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;MPI：Intel MPI&lt;/li&gt;
&lt;li&gt;BLAS/LAPACK：MKL&lt;/li&gt;
&lt;li&gt;FFT：&lt;code&gt;Intel_DFTI&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Libxc：单独编译，&lt;strong&gt;关闭 FHC&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;QE：CMake 构建&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我的环境变量大致是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Libxc 相关路径&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;LIBXC_SRC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/opt/libxc_src&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;LIBXC_BUILD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/opt/libxc_src/build&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;LIBXC_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/opt/libxc/6.2.2-nofhc-ifx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Quantum ESPRESSO (QE) 相关路径&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;QE_SRC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/opt/q-e-qe-7.3.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;QE_BUILD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/opt/q-e-qe-7.3.1/build&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="n"&gt;QE_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/opt/qe-7.3.1-ifx-cmake-nofhc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;最终使用的 QE 配置命令核心部分是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cmake &amp;#34;$QE_SRC&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_C_COMPILER=mpiicx \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_Fortran_COMPILER=mpiifx \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_BUILD_TYPE=Release \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_C_FLAGS=&amp;#34;-O2&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_Fortran_FLAGS=&amp;#34;-O2&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DQE_ENABLE_MPI=ON \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DQE_ENABLE_OPENMP=ON \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DQE_ENABLE_LIBXC=ON \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DQE_BLAS_INTERNAL=OFF \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DQE_LAPACK_INTERNAL=OFF \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DQE_FFTW_VENDOR=Intel_DFTI \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_PREFIX_PATH=&amp;#34;$LIBXC_PREFIX&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DLibxc_ROOT=&amp;#34;$LIBXC_PREFIX&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_INSTALL_PREFIX=&amp;#34;$QE_PREFIX&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_INSTALL_RPATH=&amp;#34;$LIBXC_PREFIX/lib;/opt/intel/oneapi/mpi/2021.11/lib;/opt/intel/oneapi/compiler/2024.0/lib&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -DCMAKE_POLICY_VERSION_MINIMUM=3.5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;而 &lt;code&gt;libxc&lt;/code&gt; 这边，最关键的一条就是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-DDISABLE_FHC=ON
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这条看似不起眼，但在我的这批 &lt;code&gt;SCAN&lt;/code&gt; 构型上，几乎就是决定生死的选项。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="七一个很容易误判的点没报缺库不代表你真的理解了链接方式"&gt;&lt;a href="#%e4%b8%83%e4%b8%80%e4%b8%aa%e5%be%88%e5%ae%b9%e6%98%93%e8%af%af%e5%88%a4%e7%9a%84%e7%82%b9%e6%b2%a1%e6%8a%a5%e7%bc%ba%e5%ba%93%e4%b8%8d%e4%bb%a3%e8%a1%a8%e4%bd%a0%e7%9c%9f%e7%9a%84%e7%90%86%e8%a7%a3%e4%ba%86%e9%93%be%e6%8e%a5%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;七、一个很容易误判的点：没报缺库，不代表你真的理解了链接方式
&lt;/h2&gt;&lt;p&gt;中间我还遇到一个非常容易让人误判的问题：
有时候 &lt;code&gt;ldd pw.x&lt;/code&gt; 里看不到 &lt;code&gt;libxc.so&lt;/code&gt;，但程序并不报缺库，而且照样能跑。&lt;/p&gt;
&lt;p&gt;这让我一开始很困惑，以为是不是 &lt;code&gt;libxc&lt;/code&gt; 根本没连上。后来才意识到，这里还要区分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;动态链接&lt;/strong&gt;：&lt;code&gt;ldd&lt;/code&gt; 能直接看到 &lt;code&gt;libxc.so&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;静态链接&lt;/strong&gt;：&lt;code&gt;ldd&lt;/code&gt; 看不到，但构建和符号里实际上已经吃进去了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于我这种刚开始折腾 DFT 环境的人来说，这又是一个很有教育意义的坑：
&lt;strong&gt;“程序能跑”和“你知道它为什么能跑”是两件事。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;科学计算环境里，真正麻烦的从来不是出错，而是那种“看起来能跑，但你并没有完全搞清楚依赖链”的状态。因为那会让后续复现和迁移都变得非常危险。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="八另一个重要认知我其实只是用了-aocc-编译器并没有真正用到-aocl"&gt;&lt;a href="#%e5%85%ab%e5%8f%a6%e4%b8%80%e4%b8%aa%e9%87%8d%e8%a6%81%e8%ae%a4%e7%9f%a5%e6%88%91%e5%85%b6%e5%ae%9e%e5%8f%aa%e6%98%af%e7%94%a8%e4%ba%86-aocc-%e7%bc%96%e8%af%91%e5%99%a8%e5%b9%b6%e6%b2%a1%e6%9c%89%e7%9c%9f%e6%ad%a3%e7%94%a8%e5%88%b0-aocl" class="header-anchor"&gt;&lt;/a&gt;八、另一个重要认知：我其实只是用了 AOCC 编译器，并没有真正用到 AOCL
&lt;/h2&gt;&lt;p&gt;当 Intel 这套新环境跑顺之后，我又回头看了一眼自己之前在 AMD 9654 节点上的构建，结果发现了一个相当扎心的事实：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;我之前只是用了 &lt;strong&gt;AOCC 编译 QE&lt;/strong&gt;，但根本没有真正用 &lt;strong&gt;AOCL&lt;/strong&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;也就是说，我当时走的是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AOCC 编译器；&lt;/li&gt;
&lt;li&gt;但 BLAS/LAPACK 用的是 &lt;strong&gt;internal&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;FFT 用的也是 &lt;strong&gt;internal&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;难怪性能那么一般。&lt;/p&gt;
&lt;p&gt;这一点后来让我印象特别深。因为在很多人（包括之前的我）的直觉里，会下意识地把：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“用了 AMD 编译器”&lt;/li&gt;
&lt;li&gt;和“用了 AMD 优化数学库”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这两件事混为一谈。&lt;/p&gt;
&lt;p&gt;但实际上完全不是一回事。&lt;/p&gt;
&lt;h3 id="aocc-是编译器"&gt;&lt;a href="#aocc-%e6%98%af%e7%bc%96%e8%af%91%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;AOCC 是编译器
&lt;/h3&gt;&lt;h3 id="aocl-才是数学库加速栈"&gt;&lt;a href="#aocl-%e6%89%8d%e6%98%af%e6%95%b0%e5%ad%a6%e5%ba%93%e5%8a%a0%e9%80%9f%e6%a0%88" class="header-anchor"&gt;&lt;/a&gt;AOCL 才是数学库加速栈
&lt;/h3&gt;&lt;p&gt;如果你只是用了 AOCC，却仍然把：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;QE_BLAS_INTERNAL=ON&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QE_LAPACK_INTERNAL=ON&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QE_FFTW_VENDOR=Internal&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;写进 CMake 里，那本质上你并没有把 9654 这颗大 CPU 真正榨出来。&lt;/p&gt;
&lt;p&gt;这也是我后来特别想写下来的原因之一。因为它真的很容易让人产生一种错觉：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“我明明已经在高端节点上编译了，为什么还是不快？”&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;答案可能并不是 CPU 不够强，而是你根本没有把正确的后端接上去。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="九结果生产效率一下子进入了另一个量级"&gt;&lt;a href="#%e4%b9%9d%e7%bb%93%e6%9e%9c%e7%94%9f%e4%ba%a7%e6%95%88%e7%8e%87%e4%b8%80%e4%b8%8b%e5%ad%90%e8%bf%9b%e5%85%a5%e4%ba%86%e5%8f%a6%e4%b8%80%e4%b8%aa%e9%87%8f%e7%ba%a7" class="header-anchor"&gt;&lt;/a&gt;九、结果：生产效率一下子进入了另一个量级
&lt;/h2&gt;&lt;p&gt;当 oneAPI + MKL + no-FHC 的 Intel 版本跑通后，我再回头看自己的批量任务，心态已经完全不一样了。&lt;/p&gt;
&lt;p&gt;以前看着几千个构型，会本能地觉得：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这是不是又要跑很多天？&lt;/li&gt;
&lt;li&gt;哪个节点上挂了怎么办？&lt;/li&gt;
&lt;li&gt;收敛不稳会不会拖垮整批任务？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但当单个 24 原子构型在 4 核下不到两分钟就能算完时，量级立刻变了。
一旦批量并发开起来，原来觉得非常沉重的 DFT 重标注任务，突然就变成了一个可以认真规划、快速交付的工作流。&lt;/p&gt;
&lt;p&gt;这一刻我真正体会到：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;HPC 科学计算里的“调优”，从来不是锦上添花，而是决定你能不能把一件事从“理论可行”变成“工程上可执行”。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="十这次最大的收获不是把-qe-编译成功而是学会了如何看待环境"&gt;&lt;a href="#%e5%8d%81%e8%bf%99%e6%ac%a1%e6%9c%80%e5%a4%a7%e7%9a%84%e6%94%b6%e8%8e%b7%e4%b8%8d%e6%98%af%e6%8a%8a-qe-%e7%bc%96%e8%af%91%e6%88%90%e5%8a%9f%e8%80%8c%e6%98%af%e5%ad%a6%e4%bc%9a%e4%ba%86%e5%a6%82%e4%bd%95%e7%9c%8b%e5%be%85%e7%8e%af%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;十、这次最大的收获，不是把 QE 编译成功，而是学会了如何看待“环境”
&lt;/h2&gt;&lt;p&gt;如果只是把结论写成一句话，那就是：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;科学计算里，版本号只是入口，环境才是本体。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;这次折腾之后，我对下面几件事的理解都比以前深得多：&lt;/p&gt;
&lt;h3 id="1-libxc-不是无脑依赖"&gt;&lt;a href="#1-libxc-%e4%b8%8d%e6%98%af%e6%97%a0%e8%84%91%e4%be%9d%e8%b5%96" class="header-anchor"&gt;&lt;/a&gt;1. &lt;code&gt;libxc&lt;/code&gt; 不是无脑依赖
&lt;/h3&gt;&lt;p&gt;它的版本、编译方式，尤其是像 &lt;code&gt;FHC&lt;/code&gt; 这样的选项，可能直接改变收敛行为。&lt;/p&gt;
&lt;h3 id="2-编译器不等于数学库"&gt;&lt;a href="#2-%e7%bc%96%e8%af%91%e5%99%a8%e4%b8%8d%e7%ad%89%e4%ba%8e%e6%95%b0%e5%ad%a6%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;2. 编译器不等于数学库
&lt;/h3&gt;&lt;p&gt;AOCC 不等于 AOCL；oneAPI 也不只是编译器，还包含了一整套数值后端生态。&lt;/p&gt;
&lt;h3 id="3-能跑不够"&gt;&lt;a href="#3-%e8%83%bd%e8%b7%91%e4%b8%8d%e5%a4%9f" class="header-anchor"&gt;&lt;/a&gt;3. “能跑”不够
&lt;/h3&gt;&lt;p&gt;真正的生产环境应该满足三件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;能跑；&lt;/li&gt;
&lt;li&gt;稳定；&lt;/li&gt;
&lt;li&gt;快。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;少任何一项，后面都要付出代价。&lt;/p&gt;
&lt;h3 id="4-hpc-调优是科研生产力的一部分"&gt;&lt;a href="#4-hpc-%e8%b0%83%e4%bc%98%e6%98%af%e7%a7%91%e7%a0%94%e7%94%9f%e4%ba%a7%e5%8a%9b%e7%9a%84%e4%b8%80%e9%83%a8%e5%88%86" class="header-anchor"&gt;&lt;/a&gt;4. HPC 调优是科研生产力的一部分
&lt;/h3&gt;&lt;p&gt;有时候，手握 9654 这样的硬件“利器”，但没有把库链、FFT、BLAS、LAPACK、MPI、外部依赖配对好，那你其实并没有真正拥有它的性能。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="结语新手也能折腾但最好别只靠运气"&gt;&lt;a href="#%e7%bb%93%e8%af%ad%e6%96%b0%e6%89%8b%e4%b9%9f%e8%83%bd%e6%8a%98%e8%85%be%e4%bd%86%e6%9c%80%e5%a5%bd%e5%88%ab%e5%8f%aa%e9%9d%a0%e8%bf%90%e6%b0%94" class="header-anchor"&gt;&lt;/a&gt;结语：新手也能折腾，但最好别只靠运气
&lt;/h2&gt;&lt;p&gt;回头看，这整个过程其实非常像我刚接触第一性原理计算时的状态：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对软件栈的认识是碎片化的；&lt;/li&gt;
&lt;li&gt;遇到错误时容易把问题归结为“玄学不收敛”；&lt;/li&gt;
&lt;li&gt;对 HPC 环境里“编译方式”和“运行结果”之间的关系缺乏真正的直觉。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但也正是因为这一轮完整踩坑，我第一次认真意识到：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;编译不是安装，部署不是复制，调优也不是可有可无的附加项。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;尤其是在科学计算里，很多时候“为什么同样的 case 这个环境能算、那个环境不能算”，背后未必是什么高深的理论问题，而可能就是一个你之前根本不会在意的库选项。&lt;/p&gt;
&lt;p&gt;所以如果你也在新环境里折腾 QE、CP2K、LAMMPS 这类软件，我想说的一点经验是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要只记“命令怎么敲”；&lt;/li&gt;
&lt;li&gt;一定要顺手把&lt;strong&gt;构建参数、依赖版本、路径和踩过的坑写下来&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因为等你真的踩过一次之后就会发现，
&lt;strong&gt;最可怕的不是报错，而是你明明修好了，却不知道自己到底修好了什么。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;而这，恐怕才是从“会运行程序”到“能掌控计算环境”之间，最重要的一步。&lt;/p&gt;</description></item></channel></rss>