日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何加速 LaTeX 编译

發布時間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何加速 LaTeX 编译 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

十秒鐘速覽

  • 換用 Linux 系統
  • 使用批處理模式,即編譯時加上?-interaction=batchmode?參數
  • 使用預編譯技術,涉及到一個宏包(mylatexformat)和兩條命令:
  • etex -initialize -jobname="hello" "&pdflatex" "mylatexformat.ltx" "hello.tex"
  • pdflatex -shell-escape "&hello" hello.tex
  • 一些其他(作用較小的或者適用范圍狹窄的)技巧

  • 前言

    “We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.”

    “我們應該忽略小的開銷,比方說97%的時間:過早優化是萬惡之源。然而我們不應放棄那重要的3%的機會。”

    ——Donald E. Knuth.?"Structured Programming with Goto Statements".?Computing Surveys 6:4 (December 1974), pp. 268, §1.


    不只一個人跟我抱怨過,“LaTeX 的編譯實在是太慢了”。尤其是在入門階段,用戶需要不斷重復編譯和預覽的過程,來驗證代碼的功能。

    實際上,考慮到 TeX 系統在底層要做的大量工作,它的速度已經很快了。然而貪婪的用戶只會懷念 Word 這樣的文字處理軟件,并且由衷地感嘆,“為什么 TeX 不能像 Word 那樣即改即得呢”。

    我這里不會向你介紹 TeX 底層是多么辛苦,做了多少繁瑣的工作,兼顧了多少復雜的情況。因為大部分用戶并不在乎。

    我也不必解釋 TeX 的使用方式和 Word 相比是怎樣的不同。因為你不應說服一個掄錘子砸墻的人去使用電鉆。

    這篇文章面向有一定基礎并且面臨同樣問題的 TeX 用戶,當然對于新手來說也并不難懂。如果你覺得用不上或者不會用,不必感到煩惱,等你真正需要用的時候自然就能理解了。


    性能瓶頸分析

    正如開篇所言,僅憑模糊猜測和反復試驗去做優化是非常低效的,這是企圖用戰術上的勤奮(不斷調試)來掩蓋戰略上的懶惰(不去探究背后的原理和機制)。

    關于 TeX 程序的性能瓶頸,其實在 @李阿玲 的?這個回答?中已經說得很好了。

    我這里摘抄核心部分如下:

    任何TeX,影響它速度主要還是文件I/O,尤其是Windows下面的影響,非常顯著。同等的硬件,換成Linux+ext4的話,效果會很不一樣。

    其次是解析上的操作,從源文件到token這一級別,中間有可能做編碼轉換之類。但是這一部分不會耗時太長。之所以能夠影響速度是因為調用的包的子文件比較多,尤其是tikz之類的大包。

    插圖其實并不會怎么影響TeX的速度,之所以讓人感覺插圖會比較耗時,那是因為XeTeX調用了dvipdfmx插圖的時候會讀文件,會有壓縮運算,這速度自然會慢一些。

    總結起來就是 TeX 的性能瓶頸在于:文件 I/O

    而文件 I/O 速度主要取決于操作系統和硬件。

    這是因為在不同的操作系統下,TeX 系統的實現是有區別的,這也就造成了文件 I/O 速度上的差異。

    經過粗略且不準確的測試,在相同硬件性能的情況下,同樣的 TeX 代碼,在 Ubuntu 18.04 虛擬機下的運行時間大概是 Windows 10 物理機的 40% ~ 70%。(@李阿玲 說如果采用 Linux 物理機性能提升會更加明顯。由于手頭沒有配 Linux 的物理機,所以暫時無法驗證。)

    此外,一個值得注意的說法是,將機械硬盤換成固態硬盤效果更佳。然而我在測試當中,發現在 Windows 下,TeX 系統裝在不同類型的硬盤中并沒有明顯的速度差別(甚至將 TeX 裝到 RAMDisk 中也沒有明顯提升)。希望有大佬給出相關的測試數據,驗證或否定我的測試結果(最好能否定),要是能說明原因就更好了。這也是我感到十分不解的一個地方。

    除了存儲設備,CPU 也有一定的影響,不過提升 CPU 性能獲得的收益,并不如提升文件 I/O 速度。

    當然,確實有人問過 LaTeX 編譯性能最佳的硬件配置:

    • Tips for choosing hardware for best LaTeX compile performance

    結論是:起決定性因素的是 CPU 的單線程計算能力。

    這個貼子下的回答,也提到了和我上面的測試一致的結果:磁盤 I/O 速度對于 TeX 的文件 I/O 并沒有太大影響。

    所以我覺得這里所說的“文件 I/O 速度”,可能并不是單純指將 .tex/.sty/.cfg/.def 這些文件導入到內存的速度,而是包括了 TeX 解析各種宏包再導入子文件時的速度,而不同操作系統下的差異就體現在這一步。

    你問我能不能用 GPU 加速 LaTeX 編譯?沒錯,也有人問過了:

    • Is it possible to use GPU acceleration on compiling large LaTeX documents?

    結論是:幾乎不可行。除非你能將 TeX 的 CPU 指令轉換為 GPU 指令,并且讓操作系統支持這些操作。

    不同的引擎(pdfTeX、XeTeX、LuaTeX)的速度也會有些許差異。比如一般情況下 pdfTeX 速度要快于其他引擎,不過也有?ptex-ng?這種性能更高的引擎(是基于 C 語言的 TeX82 實現),我有幸嘗試過一個私人版本,速度快得飛起。大家有興趣可以邀請它的作者 @李阿玲 多科普科普這個引擎。

    不同的編譯模式也有細微的影響。經過測試,使用批處理模式(batchmode)速度要優于默認的模式(不加參數)和其他一些模式(比如?nonstopmode?和?scrollmode), 這是因為批處理模式在編譯和執行階段是靜默的,不輸出任何信息,因此要快上一些。


    性能提升方法

    上面扯了那么多瓶頸,那么下面談一談怎么改善這些瓶頸。

    其實主要有三個辦法:換用 Linux 、使用批處理模式和預編譯。

    TeX 在 Linux 下的表現確實是大大優于 Windows 的。不過這個方法對大多數人來說并不現實,畢竟大多數人習慣用的系統是 Windows。

    使用批處理模式,就是編譯時加上?-interaction=batchmode?參數,即?pdflatex -interaction=batchmode hello.tex。需要注意的是,批處理模式不會報錯(雖然我用 Sublime Build System 時會提示返回 exit code 1)。因此如果需要檢查代碼的錯誤,那么不建議使用批處理模式。

    預編譯就是生成 .fmt 文件,把 .tex 文件序言區那些諸如 newcommand 和 usepackage 的東西打包起來。

    大家都有經驗,復制很多小文件花費的時間,要遠大于復制單個大文件的時間。TeX 的預編譯把各種小文件打包成一個大文件,那么之后的編譯,只需要導入和解析這個大文件就可以,就不用挨個再索引和導入各種零碎的小文件了。它在 I/O 速度上的提升正源于此。

    有一個?mylatexformat?宏包,可以幫助用戶預編譯文件序言區。在?mylatexformat?之前其實有另外一個同樣功能的宏包,叫?mylatex?。不過我還是推薦使用?mylatexformat。

    當然還有人會提到一些其他的技巧,比如:

  • 將 TikZ 繪圖的代碼提前編譯好,直接 include 生成的 pdf 文件
  • 避免使用?ctex?和?tikz?這樣的龐大而零碎的宏包
  • 對于 pdfTeX 引擎,可以加上?-draftmode?參數
  • 對于 XeTeX 引擎,可以加上?-output-driver='xdvipdfmx -z0'?參數調整壓縮級別,用文件大小換取編譯速度
  • 這些技巧的改善作用其實并不大,而且也有明顯的適用范圍限制。大家可以酌情嘗試和選用。

    雖然上面提到不同的引擎(pdfTeX、XeTeX、LuaTeX)有速度差異,不過并不明顯,所以不必糾結。

    下面著重介紹如何預編譯?.tex?文件。


    預編譯流程

    假設你有這樣一個?hello.tex?文件:

    \documentclass[border=5pt, tikz]{standalone} \usepackage{tikz} \usepackage[UTF8]{ctex} \newcommand{\hello}{Hello 你好}\begin{document} \begin{tikzpicture} \node [draw, thick, minimum width=10em, minimum height=10em] {English 中文 \hello}; \end{tikzpicture} \end{document}

    那么預編譯只需要在命令行中運行這條指令:

    etex -initialize -jobname="hello" "&pdflatex" "mylatexformat.ltx" "hello.tex"

    就能在文件夾中看到?hello.fmt?文件,這個文件里包含了你在?hello.tex?序言區定義的宏和導入的宏包。

    • etex?是原生 TeX 的一個擴展版本,源于 NTS (New Typesetting System)項目,是開發 LaTeX2e 時用的引擎,后續的引擎比如 pdfTeX 和 XeTeX 都以它為基礎或者參照。

    • -initialize?參數就是表明要將文件轉儲(dump)到一個中間文件,這里也就是生成?.fmt?文件

    • -jobname="hello"?是指定生成的?.fmt?文件名為?hello.fmt

    • &pdflatex?指定生成的?.fmt?文件對應的引擎是 pdfLaTeX

    • "mylatexformat.ltx"?則是我們上面提到的宏包,用于對序言區進行處理,方便?.fmt?文件的轉儲

    • hello.tex?自然就是源文件了,寫在序言區的語句會被預編譯(更高級地,可以用?\endofdump?這樣的語句指定哪些部分要預編譯,哪些不要預編譯)

    預編譯時輸出的信息是這樣的:

    This is pdfTeX, Version 3.14159265-2.6-1.40.19 (MiKTeX 2.9.6930 64-bit) (INITEX) entering extended mode% 各種導入的文件信息(C:\Users\xxx\AppData\Roaming\MiKTeX\2.9\tex/latex/mylatexformat\mylatexforma t.ltx LaTeX2e <2018-12-01> ) (hello.tex (C:\Users\xxx\AppData\Roaming\MiKTeX\2.9\tex/latex/standalone\standalone.cls Document Class: standalone 2018/03/26 v1.3a Class to compile TeX sub-files stan dalone (D:\MiKTeX\tex/latex/tools\shellesc.sty) (D:\MiKTeX\tex/generic/oberdiek\ifluatex.sty) (D:\MiKTeX\tex/generic/oberdiek\ifpdf.sty) (D:\MiKTeX\tex/generic/ifxetex\ifxetex.sty) ... (C:\Users\xxx\AppData\Roaming\MiKTeX\2.9\tex/generic/ctex\zhwindowsfonts.tex{ C:/Users/xxx/AppData/Local/MiKTeX/2.9/pdftex/config/pdftex.map}{UGBK.sfd}{Uni code.sfd})))) (C:\Users\xxx\AppData\Roaming\MiKTeX\2.9\tex/latex/ctex/config\ctex.cfg) )% 接下來就是將上面導入的子文件和字體 dump 到 hello.fileBeginning to dump on file hello.fmt(preloaded format=hello 2019.1.16) 30612 strings of total length 571285 464867 memory locations dumped; current usage is 329&459222 26854 multiletter control sequences% 一些字體相關的配置\font\nullfont=nullfont \font\OMX/cmex/m/n/5=cmex10 \font\tenln=line10 \font\tenlnw=linew10 \font\tencirc=lcircle10 ... \font\OT1/cmr/bx/it/9.03374=cmbxti10 at 9.03374pt \font\OT1/cmr/bx/it/7.52812=cmbxti10 at 7.52812pt \font\OT1/cmr/bx/it/5.52061=cmbxti10 at 5.52061pt 537653 words of font info for 41 preloaded fonts% 字符連接的信息1141 hyphenation exceptions Hyphenation trie of length 362741 has 8547 ops out of 35111143 for language 74377 for language 73110 for language 72 ...97 for language 2137 for language 1181 for language 0% 告訴你它完事了0 words of pdfTeX memory 3 indirect objects No pages of output. Transcript written on hello.log.

    然后編譯原文件。在命令行運行:

    pdflatex -shell-escape "&hello" hello.tex

    或者:

    latex -shell-escape --output-format pdf "&hello" hello.tex

    • 此時我們加上?&hello?參數,也就是用上了?hello.fmt?文件
    • 不要忘記?-shell-escape?參數

    更多?mylatexformat?宏包使用相關的細節可以參考它的文檔:CTAN: Package mylatexformat。

    這里有幾點說明:

    • 預編譯對 pdfTeX 的支持是比較好的,也支持大多數宏包。
    • 一旦涉及到某些字體相關的事情,預編譯就會出現問題。這是因為 .fmt 格式本身就是上古時期的產物,沒有兼顧到很多字體方面的事情。比如雖然文檔中給出了 XeTeX 編譯時的用法(使用?xetex?引擎和?&xelatex?參數),然而實際運行時總是會出現?! Can't \dump a format with native fonts or font-mappings.?的錯誤。所以不建議在預編譯時使用 XeTeX 引擎。
    • 雖然?ctex?這樣處理 CJK 字符的宏包還能用,也可以使用?\kaishu?和?\lishu?這樣的宏,但是相關的 CJK 字體并不是無級縮放的,也就是放大到一定程度之后會出現鋸齒。此外,\setCJKmainfont?這類更加復雜的宏也是無法使用的。
    • 如果需要頻繁修改序言區,那么可以先不預編譯,以節省時間(雖然預編譯也沒有多花多少時間)。等到序言區的內容基本固定,只需要一次預編譯,之后就可以只運行?pdflatex -shell-escape "&hello" hello.tex?這一條編譯命令了。
    • 輸出最后的成品時,還是建議直接使用?pdflatex hello.tex?或者?xelatex hello.tex,以消除預編譯導致的一些格式和字體上的差異。

    如果你用的編輯器是 Sublime,還可以自己寫一個 Build System 的腳本,將預編譯這個選項加進去,這樣就不用每次都切到命令行界面運行了。

    我自己用的配置如下,供有需要的人參考:

    mylatex.sublime-build:

    {"selector": "text.tex","variants":[{ "name": "pdflatex - precompile + batchmode + .fmt","shell_cmd": "etex -initialize -jobname=\"$file_base_name\" \"&pdflatex\" \"mylatexformat.ltx\" $file_base_name.tex & pdflatex -shell-escape -interaction=batchmode -aux-directory=latex-temp \"&$file_base_name\" $file_base_name.tex",},{ "name": "pdflatex - batch mode + .fmt","shell_cmd": "pdflatex -shell-escape -interaction=batchmode -aux-directory=latex-temp \"&$file_base_name\" $file_base_name.tex",},{ "name": "pdflatex - precompile","shell_cmd": "etex -initialize -jobname=\"$file_base_name\" \"&pdflatex\" \"mylatexformat.ltx\" $file_base_name.tex",},{ "name": "pdflatex - batch mode","shell_cmd": "pdflatex -shell-escape -interaction=batchmode -aux-directory=latex-temp $file_base_name.tex",},{ "name": "pdflatex - normal mode + .fmt","shell_cmd": "pdflatex -shell-escape -aux-directory=latex-temp \"&$file_base_name\" $file_base_name.tex",},{ "name": "pdflatex - normal mode","shell_cmd": "pdflatex -shell-escape -aux-directory=latex-temp $file_base_name.tex",},{ "name": "xelatex - normal mode","shell_cmd": "xelatex -aux-directory=latex-temp $file_base_name.tex",},{ "name": "xelatex - batch mode","shell_cmd": "xelatex -aux-directory=latex-temp -interaction=batchmode $file_base_name.tex",},{ "name": "lualatex - normal mode","shell_cmd": "lualatex -aux-directory=latex-temp $file_base_name.tex",},{ "name": "lualatex - batch mode","shell_cmd": "lualatex -aux-directory=latex-temp -interaction=batchmode $file_base_name.tex",},] }

    相關資料

    我在 TeX.SE 的?這個問題?下已經羅列了大部分加速 TeX 編譯的相關問題鏈接:

    • Speeding up LaTeX compilation
    • How to speed up LaTeX compilation with several TikZ pictures?
    • Ultrafast PDFLaTeX with precompiling
    • Externalizing tikz with precompiled preamble
    • Precompile header with xelatex
    • How to speed up pdflatex for a very large document on MacOS X?
    • Speeding up compilation using precompiled preamble with LuaTeX

    以及:

    • Precompiled Preamble for LaTeX
    • LaTeX: Speed up Latex compilation by precompiling the preamble part
    • Precompileing parts of a document other than the header
    • Example of Using a Pre-Compiled LateX Preamble
    • LaTeXDaemon
    • How to create a new format file

    總結

    以上是生活随笔為你收集整理的如何加速 LaTeX 编译的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。