2025年7月16日 星期三

系統性能探討

系統性能探討


曾慶潭 Ching-Tang Tseng
ilikeforth@gmail.com
Hamilton, New Zealand
16 July 2025


有許多規模比較龐大的程式,我沒有發表在這個網頁,純屬於我個人的應用程式者也不網貼。有些論題很適合用來檢討系統性能,因為它們的內容通常涉及一些比較特別的需求。這一次,我取用傅立葉轉換(Fourier transform)的技術來探討我設計之 ABC Forth 系統的一些性能。

網上已有很多傅立葉轉換技術方面的資源可供參考,我也不例外的大方採用,用到之處會說明來源,以尊重他人的創作。本文借用的貼圖來自不同的網頁,表示函數時的參數並不一致,這不是我所強調的重點,但很容易看懂。別人貼出的材料都是經過一番努力後的貢獻,所以不要太強求。

Twitter(X)社群媒體上,有一個名稱為歷史上的物理學(Physics in history)帳號,最近貼出過一份能夠精簡說明傅立葉轉換技術的照片,我轉貼於此處與大家分享。這方面的數學,要在大學二年級以後才學,它是專門用於信號處理的工具,也可以用來作為偏微分方程式(PDF)求解時的工具。它的完整數學表示式定義,照片中有。


以物理觀念更簡單的說明,就是傅立葉轉換,能把隨時間而變化的函數轉換成隨頻率而變化的函數,函數的本質不變。

我自己在工程實務上的應用,除了寫過大量信號處裡方面的相關程式外,就是曾將此技術應用於原子爐六台 600 匹馬力水泵兩公尺長轉軸各有四個軸承的長期監測上。當軸承安裝妥當後,以頻譜顯示儀獲得的頻譜,是只有很單純的一個尖峰。當軸承出現問題,例如是彈子盤保持器有微小破裂時,以頻譜顯示儀獲得的頻譜,是單一個的尖峰不見了,改以佔用頻率範圍很寬廣的許多低峰值圖譜出現。這個時候,運轉裝備必須停機更換軸承,否則直徑兩英吋的傳動軸就會被震斷,整套水泵連帶馬達都全毀,重裝新泵時,連地腳螺絲都得重新設計,損失非常大,我經歷過。量測元件獲得的訊號通常都是時變訊息,要想獲得對應的頻變訊息,就需要傅立葉轉換技術。貴重與安全要求較高的裝備,值得加裝這種監測系統,能防患於未然。

我大三時學過偏微方程專門課程,書中滿滿的傅立葉轉換應用,印象深刻。我從事過電腦信號處裡的研究工作,參與過台電核二廠雜波分析發展計畫,也參與過魚雷相控陣列聲納的電腦技術研發計畫,有過一些信號處裡方面的實作經驗。設計研發程式時,知道信號處裡軟體技術發展時講求的重點,但那時還沒有自己設計過系統。也因此在後來自己設計數學計算系統時,就會強行設計一些以前系統所沒有提供的性能。例如本文提到的複數運算系統,可以直接在複數體系觀念之下設計程式。

任何週期性的時變函數圖譜,都能由許多個不同週期的函數圖譜合成,這是一種線性關係(函數乘以常數後相加本質不變的函數關係),以簡圖表示就能看出,從時變轉換成頻變表示時,函數本質不變的道理。


我把細部強調式的傅立葉轉換數學式再貼一遍,此圖仔細說明了數學式中每個符號的意義。


電腦工程實務上,這樣的公式被改寫成離散傅立葉轉換(DFT)的數學表示式:


傅立葉轉換說明至此,不再深入,有興趣的讀者可以自行從網上學習。

接下來,我採用維基百科與 Rosetta code 網頁共同建議的快速傅立葉轉換(FFT)程序描訴虛碼來探討系統性能。資料來源網頁為:

維基百科自由百科全書(WikipediaThe Free Encyclopedia)

https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm


我們逐列探討能直接執行這套虛碼的系統規格。

首先,第一列的說明強調要用到以 2 為基底的對數函數。
我在設計系統時,連浮點數的對數函數也全為採用以 2 為基底的根本函數來推導出其他所有的對數函數。但是以數學體系的觀念來設計系統時,整數與浮點數是不能混著出現在同一列運算表達式之程式中的,因為系統中兩者的資料格式完全不同。所以,在整數環境中,必須專為整數體系建立它自己的以 2 為基底的對數函數。我設計的系統中有此函數,名稱就叫做 nlb ( n1 -- n2 ),以對應於以 10 為基底的整數之對數函數 nlog ( n1 -- n2 ) 。

程式設計方法一開始就強調時變輸入信號 A 數列的點數必須為 2 的整數方次,例如:2 的 10 次方就是 1024 點,且輸入信號必須為複數的格式。我設計的系統中可以直接宣告產生陣列,所使用的指令是 [ARRAY] 。指標可以從 0 開始,這一條件,也是這套虛碼程序設計方法中的要求條件之一。

描述方法中有一列在計算複數的 exp 函數,它的參數必須是複數,結果也必須是複數。我設計的系統中建立了這樣的函數,在純粹 Forth 的環境中,我仍沿用 Forth 愛用者的習慣使用 zexp 的函數名稱。但在 BASIC 環境中,我直接就採用 exp 的設計,這樣設計不會搞混系統,因為浮點術與複數的資料格式不同,在同一列運算程式中只能有一種數字格式,所以複數環境仍可以照樣採用 exp 為該函數的名稱。

描述方法中只有指標需要運算之處是我設計系統時沒有實現的設計。這裡有兩個數列的指標 (k+j+m/2) 與 (k+j) 需要進行整數運算。在正整數運算之計算落定後,資料格式必須是正整數,這在整數環境內,不經設計就能直接執行得出來。但是在浮點數、複數等的非整數環境內就不能直接執行出來。要設計出這樣的規格時,必須在運算列內增加改變運算規格的暫態處裡,待指標之整數運算結束後,還得改變回來。我嫌這樣設計起來雜亂無章,只在 Win32Forth 系統中實現過設計後,便放棄了這樣的設計。解決辦法很簡單,凡是遇到指標有運算的地方,就必須在前一列直接增設一列程式。例如上述情況就寫成:


   
10 let k+j+m/2 = k + j + ( m / 2 )
10 let k+j = k + j


此處討論的陣列指標之運算,是快速傅立葉轉換(FFT)技術的關鍵部份。能這樣運算後調整陣列輸出數據指標,將計算所得放置到指標指定的位置,是快速傅立葉轉換能快的主因。研究 FFT 技術的主要工作,就是在探討如何處裡指標才能減少運算次數,以便加速獲得數位訊號整體的轉換結果。每種方式的技術細節,當初都曾被寫成博士論文而發表。這種技術就適合拿來檢驗系統的性能。

沒有其他限制了。換句話說,我設計的系統能夠直接書寫複數運算式子,設計好的程式跟虛碼所描述的步驟會很接近,系統有此特點。

輸入與輸出數據上了千點以上,很難再單憑人工輸入每一點數據的方式來完成工作了。我設計的系統因此而安排了可以簡易執行開關檔案、自動進行數據存取工作的能力。這一點很重要,遇到產生結果需要藉由別的軟體實現複雜工作時特別有用,過去的貼文中已有很多這樣的使用範例。

在套用這種功能時,有一點必須注意,如果數列只是單一個變數的數列,容易處裡。數列每列具有兩個以上的變數數列時必須注意 ! 按照 Forth 處裡輸出輸入數據的方式,一次只做一列,遇到跳列(LF或CR)時可以暫停。但輸入的數據在堆疊上是先進後出,輸出的數據是後進的先出。我在 Win32Forth 增建 ABC Forth 性能時,解決過這方面的問題,後來再增建的系統就簡化了設計,不再理會這種問題,特此聲明。

2025年7月1日 星期二

弦外之音

弦外之音


曾慶潭 Ching-Tang Tseng
ilikeforth@gmail.com
Hamilton, New Zealand
2 July 2025


這一次,我不談程式,改談 Forth 的哲理。哲理的範圍很廣,我縮小到只談 Forth 系統變數(user's variable)。我也不談各個系統變數的定義,只談整體的意義。

初學 Forth 的人在基礎教材中見不到這方面的論述,基礎教材通常只教標準指令的用法。也不談 Forth 的系統架構,因為各個 Forth 的系統架構大都不同,難談。

如果您想把 Forth 學得很好,將來想要大肆利用 Forth 發展出自己的抱負,Forth 哲理中的每個項目就都應該搞得清清楚楚。系統變數只是眾多哲理中的一個項目,它有必須存在之宏觀的理由,個別系統變數都有必須建立它的道理。這種哲理看似是在學習 Forth 時的弦外之音, 實則是使用者必需學會的基本觀念,碰到它時,不要逃避,不要排擠。

我們在 1984 年 4 月創辦的『FORTH期刊』p.19 中就有一篇諶其騮作者所寫的『FORTH系統變數簡介』,該文可以提供永久性的參考。即使後來其他系統的系統變數已有大量的變化,系統變數的使用觀念則沒有改變,是系統所需,也是使用者設計程式時經常非要用到不可的東西。

系統變數有幾項特色。

首先是通常被集中處裡,除了能讓系統結構整齊外,它另有幾方面隱含的性質。

古老的 Forth 強調多工(multi-task)性能,有少數幾個系統變數就是單工被執行時非得獨立起來使用不可的單套變數,例如:兩個堆疊指標 S0 及 R0 就是。它們都是能讓工多而不亂的變化根據。在 Forth 系統中,所謂的一工,可能只是一個程式,也可以是一位使用者(user),Forth 也因此把系統變數稱為使用者變數。

Forth 系統具有可以長出標的系統(target system)的固有性能,但不是每個系統的作者都能將這種性能設計得出來。所以,我在挑選可用系統時,會將這項要求列為首要考慮條件,以便自己長期努力發展出來的成果能被永久性的固定下來。Forth 系統無論是在初次以各種其他工具語言發展出來,或者是就憑祖代系統憑藉蛻變編譯(meta compile)能力產生新的子代系統,在系統長成的最後階段,都得對系統變數進行最後的調整修訂,如此,子代系統運行時,才能有正確的系統變數內容可用。

系統變數的放置方式有秩序性,不可前後隨便對調,這也是多工設計時的一項簡明要求。Forth 系統內的自有多功能力,在規劃出新的一工(task)時,第一個記憶體單元放的是此工是否要睡著(sleep down)不被執行時的跳躍指令,跳到下一工去。否則就該醒來(wake up)執行本工的第一件處置工作,那就是找到自己的回返堆疊指標,在那裡取得執行碼。因此,緊隨是否該跳躍的指令碼後,第一個系統變數就放此工總系統變數的指標,叫 U0 ,然後,緊隨著的就是 S0 和 R0 ,這種秩序絕不能變。

系統變數通常有幾十個,以現行的 ciForth 為例,Fig-Forth 是它的前身,系統變數大約有四十個。這些系統變數又可化分成兩大類,一類是多工狀況執行時要求至少必須獨立分出來的系統變數,在 ciForth 中選出了十一個。另一類系統變數則是分工程式被執行時還必須與它工共用的系統變數,成立新工時,就可以不必另外宣告出記憶體空間來放置此類系統變數。因此,成立新工的宣告過程,必定包含了需要宣告出多少個單元來存放該工之系統變數的用量。

傳統的 Forth 多工,是根據一種被稱為知更鳥輪唱(round Robin)法設計出來的多工方式,跟現行作業系統固有的多工運作方式不同,現行作業系統採用一種所謂的先佔式(temptative)多工來運作,那一工先被喚醒就先執行那一工,多 CPU 的時代,不再熱衷於傳統 Forth 的多工設計,逐漸地,大家也不設計傳統的多工程式了。

我們在 32 位元的 Win32Forth 系統中還能見得到純用 Forth 設計出來的多工範例,在 64 位元的 ciForth 中沒有這方面的需求。我需要時,也改採 Linux OS 中的多工方式,直接讓 Forth 去叫用另一套 Forth ,執行出另一個工。這在本網頁的貼文中可以看到好幾個使用範例, 凡是有程式執行的展示影片,同時出現有背景音樂的短片內,都依靠用 Forth 叫用另一套 Forth 執行音樂播放之先佔式多工而完成設計。

ciForth 是一個可以自行長出標的系統的好用 Forth,它在處裡出長成的標的系統時,有一段處裡系統變數的工作必須要做,這樣,整個系統的可執行碼檔案中才能固定出新的系統變數規格,這是一個很有效率的作法,卻不是其他 Forth 系統能辦得到的設計,是作者熟悉 Linux OS 使用環境後的創意設計。也請注意 ciForth 在各種作業系統中的版本,並非全部都具有此項功能,微軟的 Wina64 就不具有,沒有此項功能的系統我就不用。

能讀通系統源程式碼是件痛快的事情,看似弦外之音的系統變數之形成哲理大有意義存在,講述如何研究它? 則超出了貼出一個範例程式的範疇,只能專文討論。我在設計 ciForth 的 ABC Forth 數學計算系統時,動用到它,修改過執行 >NUMBER 時必須隱性影響 DPL (第 20 個系統變數)的方式,特貼此文說明。

黃河

中國所有的兒童都聽過『大禹治水十三年,三過家門而不入』的故事,也曉得故事的意義在強調工作時要用對方法,要堅忍不拔的完成工作,這是四千多年前流傳下來的故事。

大禹是夏朝的第一個皇帝(在位七年,時間為西元前 2205~2198 年,另有在位 27 年之說)。這個故事從此告訴了後人,黃河經常氾濫成災。古人形容邪惡帝王的惡劣統治就像洪水與猛獸,所指的洪水,就有如黃河的氾濫。

中國歷史上,黃河在過去的三千多年內共有高達 1,593 次的氾濫記錄,氾濫使其主幹道改變了 18 次;每次的泛濫也都造成大量傷亡及經濟損失。

近代的四次記錄則為 1410 年黃河氾濫, 1887 年黄河决口, 1921 年宫家决口, 1958 年黄河洪水。

1900 年以後的兩次災情記錄為:

宮家決口也稱宮家壩決口,是民國時期 1921 年 7 月 19 日發生在中國山東利津宮家的一次黃河決口。決口後水災影響到利津、霑化、濱縣、無棣四縣,災民 18.4 萬餘人,受災面積 5400 平方里。

1958 年黃河洪水指的是 1958 年 7 月發生在中華人民共和國黃河中下游地區的水災。此次水災淹沒村莊 1708 個,淹沒耕地 304 萬畝,房屋倒塌 30 萬間,京廣鐵路中斷 14 天,受災人口達 74.08 萬人。據中國政府官方資料顯示,河南、山東兩省出動約 200 萬人進行防汛,確保了黃河下游的防洪安全。

黃河氾濫的起因係上游大量沖積下來的黃沙,沉積在下游出海前的河床上,長久下來,河槽萎縮,造成河床高於地面的懸河現象,直到河堤受不了而潰堤,於是發生規模宏大之河水氾濫的洪災,這是定性的說法。最近我看到中國黃河教育電視台的科普教育新聞報導中,提供了一些近代的定量數據,可以讓大家更深刻的了解黃河。

根據科普新聞報導,現代的黃河,平均每年有 4 億噸泥沙堆積在下游河道裡。下游「地上懸河」現象長達 800 公里,最大懸差 10 公尺。

大禹治水能夠成功,用對的方法是疏導而非築堤圍堵,今人治理黃河,當然也只宜疏導。問題是年產 4 億噸的泥沙可不是個小量的數字, 800 公里的 10 公尺高度是個驚人的河床,就算動用南海吹沙填海的工程機器來幹此活,可能都不是一件輕鬆的工程,因此,最好的疏導方法,仍是讓沙流入海。

中國科普報導則介紹了一種借力使力的方式調沙,利用上下游水庫間歇性的突然大量放水,便可借大量的挾沙水流沖洗河床,這種調水調沙的方式可以清除河床積沙入海。今年一年進行了 26 次,可以沖掉 21 億立方公尺的沙,讓河床平均下切了 3.1 公尺。

文末附貼一部陝西電視台製作的壺口大瀑布記錄短片顯示了大量的黃泥水,另附黃河下游廣闊的河道照片與幾張三門峽水庫與小浪底水庫調水調沙時的壯觀景象。在來沙的源頭執行沙漠造林有利於水土保持,中國做得到,最後展示一張在這一方面成就明顯的照片。