• 計算化學研究者應當了解的文件壓縮的常識

    計算化學研究者應當了解的文件壓縮的常識

    文/Sobereva@北京科音

    First release: 2023-Jun-10    Last update: 2023-Jun-11


    0 前言

    筆者每天在網上回答各種計算化學問題時,經常看到有計算化學研究者對文件壓縮真是毫無概念。比如分享好幾百兆甚至1GB以上的fch、cub文件時居然都不壓縮!又浪費自己上傳文件的時間,又浪費他人下載文件的時間,還浪費自己硬盤上的儲存空間。而且在論壇里直接上傳很大的文本型文件還造成寶貴的論壇服務器空間的嚴重浪費。今天答疑時又看到這種情況,忍不住寫一個科普文章,強調一下文件壓縮的重要性。


    1 文件壓縮的基本概念

    文件壓縮的目的是為了減小原文件的尺寸,原文件尺寸除以壓縮后的尺寸稱為壓縮率。根據壓縮的目的,分為兩類:
    (1)特定目的的壓縮:比如視頻壓縮、音頻壓縮、圖像壓縮
    (2)通用目的的壓縮:可用于所有文件
    文件壓縮又分為有損和無損壓縮,前者會降低原文件承載的信息的質量,無法復原;后者完整保持原文件里的信息,在解壓后可以復原。

    壓縮算法學問很深,但最簡單的一些壓縮思想也很好理解。比如視頻壓縮,原視頻需要記錄每一幀圖像的完整信息,而在壓縮時可以只記錄每一幀相對于上一幀有顯著變化部分的信息,自然能節約大量儲存空間,特別是當視頻里沒有大量大幅色彩變化的情況。再比如無損壓縮文本文件,假設原文件有個部分內容是222222222,壓縮時可記錄為9*2,自然也節約了巨大空間。有損壓縮由于允許信息的犧牲,因而在壓縮后的質量能保證滿足實際要求的情況下,原理上能夠比無損壓縮達到更高的壓縮率。針對特定目的壓縮算法由于能考慮原數據信息的特征并加以利用,也能做到比通用目的的壓縮更高的壓縮率。

    一些壓縮文件格式例子:
    針對圖像的有損壓縮:jpg、gif
    針對圖像的無損壓縮:png、tif
    針對音頻的有損壓縮:mp3、ogg
    針對音頻的無損壓縮:flac
    針對軌跡的有損壓縮:GROMACS的xtc格式(相對于全精度的trr而言)
    針對cube文件的無損壓縮:bqb(TRAVIS支持)
    通用的無損壓縮:zip、rar、bz2、gz、zst、xz、7z

    格式和壓縮算法不總是同一個概念,比如7z格式支持LZMA、LZMA2、bzip2等算法,zip格式支持Deflate、LZMA、bzip2等算法。也有的格式就只對應一種算法,比如rar格式(rar算法)、bz2格式(全稱bzip2,特有算法)、gz格式(全稱gzip,基于Deflate算法)、xz格式(基于LZMA2算法)、zst格式(Zstandard算法)。由于某些壓縮格式允許用不同的算法,因此不能簡單說這種格式的壓縮率如何,必須具體到壓縮算法。而且對于同一種壓縮算法,壓縮率還取決于一些參數,比如字典越大可能得到越高的壓縮率,但壓縮和解壓時的耗時和耗內存也越高。

    不同壓縮算法的壓縮率、壓縮/解壓過程的運算量和內存消耗、流行程度、能實現的程序都有所不同。對于支持同一種算法的不同的容器格式,其提供的特性也各有不同。

    計算機文件分為文本型和二進制型兩種:
    (1)文本型文件:通過文本編輯器打開后看到的都是人能閱讀的信息。在計算化學領域里包括Gaussian的fch文件、通用的記錄波函數信息的mwfn/wfn/wfx/molden文件、記錄格點數據的cube文件、記錄化學體系坐標的pdb/xyz/mol/mol2文件、GROMACS的gro/mdp/top文件、AMBER的mdcrd/prmtop文件、CP2K的restart文件等等,以及各種程序的輸入和輸出文件(如Gaussian的gjf和out文件)
    (2)二進制文件:用文本編輯器打開后會看到許多亂碼。在計算化學領域里包括Gaussian的chk文件、GROMACS的trr/xtc/tpr/cpt文件、dcd軌跡文件、AMBER的binpos文件等等。
    用二進制方式記錄數值為主的信息,比如動力學軌跡、軌道展開系數等,會比文本型文件尺寸小得多。所有前述的壓縮文件格式也都是二進制文件。

    對于同一種算法來說,比如rar,對于不同文件的壓縮率是不同的,往往相差極其懸殊,這和被壓縮的文件里記錄的信息特征有關,可以稱為“油水”。文本型文件一般總是有巨大的油水,像是好幾百MB甚至上GB的fch、cube文件,你通過網絡傳給別人時如果不壓縮,會顯得是非常沒常識的行為。如果你是通過慢如龜速的百毒網盤(對免費用戶來說)分享這樣的文件,不壓縮更是不可理喻的行為,倘若下載文件的對方稍微有一點文件壓縮的常識都會在心里吐槽你。至于二進制文件有多少壓縮的油水那不一定,比如說壓縮一個H.264編碼的mp4視頻文件、mp3音頻文件、png文件,無論你用哪種壓縮算法,如bzip2、rar、LZMA2等,肯定尺寸都沒有明顯減小,因為這樣的文件根本就沒什么油水,因為那些文件內容本身就已經是被壓縮過的,因此給別人發這些文件時還刻意去壓縮也是顯得很沒常識,別人還得再解壓一次,完全多此一舉。不要以為用一種算法壓縮后再換一種算法壓縮就能再次減小很多,因為大量壓縮思想在不同算法之間都是共通的,油水在初榨的時候已經被利用掉了。如果二進制文件是“生”的,那可能有壓縮的價值,使具體文件而定。比如Gaussian計算直接產生的chk經過壓縮后普遍能減小非常多尺寸。GROMACS的trr軌跡的油水一般,壓成比如rar后往往能減小幾分之一。而GROMACS的xtc軌跡的話本身就已經是有損壓縮了,再壓縮就沒有什么油水了。如果不清楚某種文件的油水的話,找個典型文件壓縮試試便知,以后就有經驗了。


    2 Linux下壓縮/解壓文件的方法

    Windows下文件壓縮和解壓沒什么好說的,Winrar(收費)、7zip(免費)都是主流的文件壓縮/解壓程序,有圖形界面,小學生都會用。做計算化學的人總和Linux打交道,這里對Linux下的壓縮做一個快速的掃盲,給出一些很簡單的例子,更多的用法自行看help或google。其中tar命令是Linux系統自帶的(太老的系統里的版本不支持zst格式)

    2.1 基本用法

    ? 解壓文件(程序自動根據后綴判斷怎么解壓)
    tar -xf [壓縮文件名]

    ? 把指定的文件或整個目錄壓縮成new.tbz(tbz是tar.bz2的簡寫)
    tar -caf new.tbz [文件名或目錄名]

    ? 把指定的文件或整個目錄壓縮成new.tgz(tgz是tar.gz的簡寫)
    tar -caf new.tgz [文件名或目錄名]

    ? 把指定的文件或整個目錄壓縮成new.tar.xz
    tar -caf new.tar.xz [文件名或目錄名]

    ? 把指定的文件或整個目錄壓縮成new.tar.zst
    tar -caf new.tar.zst [文件名或目錄名]

    以上-caf選項等同于同時寫-c -a -f。-c代表壓縮,-a代表根據后綴自動判斷以什么方法壓縮,-f代表指定文件名。以上寫文件名的地方可以一次寫多個文件名,以空格分隔,也可以用通配符,比如*.chk *.fch代表把當前目錄下所有.chk和.fch文件都打包并壓縮。

    7z、zip、rar格式能夠包含多個被壓縮的文件,而bz2、gz、xz、zst這些格式本身只能記錄單個文件。tar是一種可以由tar程序產生的打包格式,多個文件(或目錄)可以合并成一個.tar文件,這個過程不改變文件的總尺寸。上面提到的諸如.tar.xz是先把被壓縮的文件用tar打包然后再壓縮成xz格式的產物。因此,如果被壓縮的文件只有一個,上面的.tar.xz可以簡化為.xz,而如果涉及多個文件就必須寫成.tar.xz。


    2.2 并行壓縮

    文件很大時,而且用的又是復雜度較高的壓縮算法,在壓縮時耗時會很高。以上方式壓縮都是只用單線程壓縮,下面也說一下怎么并行壓縮以顯著節約時間。

    以上面方式用tar命令在壓縮時,對bz2、gz、xz、zst實際上是分別調用bzip2、gzip、xz、zst程序進行的壓縮。這些程序也有相應的并行版,分別為pbzip2、pigz、pxz、pzst,自動會用盡量多的核來多線程處理。可以手動直接運行它們,也可以在用tar命令的時候通過-I明確指定用這些程序來做壓縮。這些并行版壓縮程序不一定在安裝系統時就自動裝了,如果運行時提示找不到命令的話可以手動裝。例如在Rocky Linux 9上,首先用dnf install epel-release,然后再運行dnf install pxz,就把pxz裝好了。下面是使用例子

    ? 并行壓縮成tar.xz格式
    tar -I pxz -cf new.tar.xz [文件名或目錄名]
    如果發現壓縮過程中CPU占用率太低而沒法充分靠并行節約時間,可以帶上-D 1,如下所示(-D 1是傳遞給pxz程序的參數,代表把每個線程壓縮上下文尺寸設為字典的1倍而非默認的3倍大小。此時并行效率可能提升很多而大幅節約時間,但壓縮率有時會有一定下降)
    tar -I 'pxz -D 1' -cf new.tar.xz [文件名或目錄名]

    ? 并行壓縮成tar.zst格式
    tar -I pzstd -cf new.tar.zst [文件名或目錄名]

    ? 并行壓縮成tbz格式
    tar -I pbzip2 -cf new.tbz [文件名或目錄名]

    ? 并行壓縮成tgz格式
    tar -I pigz -cf new.tgz [文件名或目錄名]


    2.3 壓縮質量的設置

    有的壓縮程序可以接上控制壓縮質量的選項,在相應命令后面加上--help即可查看,并且用tar明確調用這些程序時在-I中可以加上相應的選項。不管什么算法,選最低壓縮質量的話總是速度非常快。

    ? 壓成.tgz情況的選項:-1是最快,-9是最好,默認是-6。例如以最好質量并行壓縮
    tar -I 'pigz -9' -cf new.tgz [文件名或目錄名]

    ? 壓成.tar.xz情況的選項:-0是最快,-9是最好。一般用默認的-6就足夠好了,用更高質量時耗時會提升非常多,壓縮率也沒什么顯著的提升。例如以-5質量并行壓縮
    tar -I 'pxz -5 -D 1' -cf new.tar.xz [文件名或目錄名]

    ? 壓成.tar.zst情況的選項:-1是最快,-19是最好。默認的-3時的壓縮率比較爛。例如以質量和耗時權衡較好的-16質量并行壓縮:
    tar -I 'pzstd -16' -cf new.tar.zst [文件名或目錄名]

    我比較推薦并行壓縮成默認質量的tar.xz格式,壓縮率夠高,耗時也不高,常用的winrar也能解壓。如果你是為了輸入命令時盡量省事,也懶得裝pxz程序,可以壓縮成tbz,winrar也能解壓。


    2.4 關于zip和unzip命令

    主流Linux系統也自帶了zip命令和unzip命令用于壓縮成zip文件和解壓zip文件。前面說了,zip格式的一個好處是能直接包含多個文件而不需要tar。此外,不是很老的Windows系統還可以直接訪問zip里的內容。

    壓縮一個或多個文件成為sob.zip:
    zip  sob [一個或多個文件名]
    如果其中包含目錄名,需要加上-r,這樣才能把目錄里所有內容都包含進去。
    在壓縮過程中默認會顯示所有被壓縮的文件名,加上-q可以避免顯示。
    zip命令默認使用原始且壓縮率較低的deflate算法,如果用壓縮率更高但也更貴的bzip2算法需要再加上-Z bzip2選項。

    解壓zip文件:unzip sob.zip


    3 幾種計算化學領域的大文件的壓縮效果對比

    為了體現不同壓縮方式對于計算化學研究者的實際意義,以及不同壓縮方式的壓縮率和耗時差異,筆者選了4個有代表性的測試文件:
    (1) fch文件(343 MB):筆者在Phys. Chem. Chem. Phys. (2023) DOI: 10.1039/D3CP01896B里研究了OPP和兩個18碳環構成的主-客體復合物,共260原子。此文件是這個體系opt freq任務產生的chk文件轉成的fch文件
    (2) cube文件(215 MB):是基于上面這個fch文件,通過Multiwfn(http://www.shanxitv.org/multiwfn)計算的電子密度格點數據文件
    (3) molden文件(464 MB):這是北京科音CP2K第一性原理計算培訓班(http://www.keinsci.com/workshop/KFP_content.html)里我講授用Multiwfn對WO3晶體計算態密度所使用的CP2K導出的molden文件
    (4) xyz文件(149 MB):這是北京科音CP2K第一性原理計算培訓班里我講使用CP2K做蛋白質+水體系分子力場幾何優化任務產生的記錄優化過程每一幀的xyz文件,有8047個原子,292幀

    測試的方法包括利用tar命令將各個文件壓縮成gz、bz2、xz、zst格式的情況,用的是Rocky Linux 9所對應的程序版本,這些測試在雙路EPYC 7R32機子上完成,96個物理核心,512GB內存,PM9A1固態硬盤,此機子介紹見《淘寶上購買的雙路EPYC 7R32 96核服務器的使用感受和雜談》(http://www.shanxitv.org/653)。另外還測試了Winrar 6.22 beta 1 64bit(壓縮成rar格式)和7zip 23.0 64bit(LZMA2算法壓縮成7z格式)的情況,都是默認的并行方式,此部分測試是在Intel i9-13980HX(24個物理核心)CPU的筆記本上跑的,64GB內存,PM9A1固態硬盤,Windows 11操作系統。由于解壓的耗時遠遠低于壓縮的耗時,因此解壓速度就不做對比測試了。

    下表是壓縮后的文件尺寸對比


    下表是文件壓縮耗時的對比


    由上可見
    (1)Winrar壓縮成rar的速度很快,但壓縮率很平庸。用rar格式的“最好”壓縮質量會令耗時比默認時增加至少一倍,而并沒有令壓縮率有多少提升,極個別情況壓縮率反倒還輕微下降。用rar4格式的“最好”壓縮質量相對于默認不怎么影響耗時,但壓縮率也沒提升。所以rar只推薦用于Windows下快速壓縮目的。
    (2)7zip程序用LZMA2算法在默認設置下壓縮成7z格式的速度遠不如rar,但壓縮率高得多,因此很適合看重壓縮率的人。用“極限壓縮”設置時耗時提升甚巨,而壓縮率提升極為有限,所以用默認設置足矣。如果用“快速壓縮”,耗時比winrar默認壓縮時還更低,而壓縮率至少不輸于之。“極速壓縮”的耗時非常低,而壓縮率依然說得過去,因此非常推薦追求速度的時候用。PS:7zip壓縮的時候如果選擇xz格式,在相同的算法和設定下,耗時和壓縮率和用7z格式是相同的,用xz的好處是在Linux下能直接用tar -xf解壓,但缺點是只支持單文件。
    (3)tar在默認設置下壓縮成bz2和gz文件的耗時相仿佛,而bz2的壓縮率明顯高一些,因此相對來說更推薦bz2。二者用并行版本程序壓縮時耗時極低,對所有的測試文件在一秒左右就能壓縮完。壓縮gz時用最高質量的-9沒必要,耗時增加很多但對壓縮率改進甚微。
    (4)xz格式用的是LZMA2算法,和7zip壓縮成7z默認用的算法相同,因此xz的壓縮率也與之差不多,都是當前測試里表現得最好的。由于這種算法壓縮耗時相當高,因此強烈建議用pxz并行壓縮并且結合-D 1選項。雖然此時比并行壓縮成bz2和gz的耗時還是高得多,但對于大文件已經完全是立等可取的范疇了。壓縮xz時用最高質量的-9沒必要(除非你癡迷于壓縮率),耗時增加幾分之一而對壓縮率改進甚微。
    (5)默認設置下zst的壓縮耗時極低,但壓縮率也倒數第一,如果你很看重壓縮速度而對壓縮率要求很低的話這是適合使用的。zstd結合-16的時候壓縮率不錯,已經比bz2明顯更好了,但耗時也比之高很多。-19的時候耗時極高,快趕上默認設置的xz了,但壓縮率則明顯不如之,而且相對于pxz結合-D 1的時候pzstd在速度上也沒優勢。所以zst格式基本主要就是低質量壓縮時在效率方面有獨特長處,對壓縮率但凡有些要求的時候就不如用pzstd -D1。

    總結一下,有下面的關系,讀者可根據對速度和壓縮率的要求擇情選用壓縮方法。gz沒用處。
    ? Windows下
    速度:7z(LZMA2,極速) > 7z(LZMA2,快速) > rar(標準) > 7z(LZMA2,標準)
    壓縮率:7z(LZMA2,標準) > 7z(LZMA2,快速) >= rar(標準) ≈ 7z(LZMA2,極速)
    ? Linux下
    速度:zst(默認) > bz2 >= gz > xz(默認)
    壓縮率:xz(默認)> bz2 > gz > zst(默認)

    以上的測試也充分體現了,哪怕用耗時很低的很廉價的壓縮方式,如zst(默認)和7z(LZMA2,極速),對于計算化學領域常見的文本型文件也能干掉一多半體積。所以再次強調,該壓縮的時候一定要想著壓縮!如果你是要分享一個要被很多人下載的大文件,或者要把文件放到一個硬盤空間很緊張的地方,那么建議使用壓縮率較高的方式壓縮,比如基于LZMA2算法在默認設置下的xz或7z格式。如果文件只是用于臨時性的一對一傳輸,想通過壓縮節約傳輸時間,那只需要用很快速的方法壓縮一下就夠了,若把過多的CPU運算時間花在對壓縮率的追求上就得不償失了。

    久久精品国产99久久香蕉