第四章 系統實作
4.2 程序(P ROCEDUE )
在上一章我們說明了利用<proc>及<prog>兩種標籤來編輯程序的方法,接 下來我們用一個實例來說明。
由於為了讓使用者在編寫程序時,能夠更快速方便的處理一些基本的數學 運算,我們定義了一些基本矩陣的運算,以資料庫內部提供的內儲程式來實作,
讓使用者可以直接使用。這些運算包括了矩陣的相加(table_add)、矩陣相減 (table_sub)、矩陣相乘(table_mul)、以及取得矩陣內指定位置的值(getvalueat)。除 了這些矩陣數學運算之外,由於在某些演算法的計算過程中,會產生大量的計算 暫存資料。為了提高計算效率以及避免硬體空間的不足,我們將計算過程中所產
生需要儲存的暫存值,存放在暫時性表格中(temporary table)。
暫時性表格的特點為,能夠在使用者執行程式時,動態地配置表格空間,
且資料只有在使用者程式與資料庫的工作階段(session)仍保持連線時才會存在,
當使用者與資料庫的工作階段結束,暫時性表格中的資料也會自動地清除。如此 在計算過程中,使用者無需為了計算中暫時性資料的儲存與清除而去費心,亦能 減少硬碟空間的浪費。
接下來我們便利用上述所提出的方法來編輯程序,使用一些已經預先定義 好的運算,以及條件與迴圈的控制,來完成一個複雜的演算法運算。接續微陣列 矩陣的例子,在將資料建立實體與實體類型,並存入資料庫後,並利用前處理的 方法產生了矩陣類型的資料後,我們下一步便希望能夠對此矩陣作出有意義的分 析。因此我們以我們提出的程序的編輯方法,利用XML 的格式,來完成 k-means clustering 的分析。k-means 演算法的 pseudo-code 如表(10)。
表10 k-means pseudo-code
在k-means 的運算一開始,必須要先給定初始的群中心,接下來所有的資料點要 計算與各個群中心的距離,並將其指定到距離最近群中心所屬的那個群集。在每 個資料點都指定群集之後,重新計算每個群的群中心,並重複每點計算與群中心 距離的步驟,直至群中心不再改變為止。
Initialization
1. Set k cluster centers.
Main Loop
1. Calculate distances from all elements to all cluster centers 2. Assign every element to the nearest cluster
3. Recalculate every cluster center
4. Repeat main loop until no cluster center will move
<proc name=”kmeans”>
<arg tbl=”inputTable”/>
<table name=”temp1”>
<createTable name = “inputTable” />
</table>
<table name=”seed”>
<createRow>
<getValueAt tbl=” inputTable” row=”1” col=”1” />
</createRow>
<createRow>
<getValueAt tbl=” inputTable” row=”2” col=”2” />
</createRow>
</table>
<Loop>
<table name=”temp2”>
<call name=”table_sub”>
<arg name=”temp1”/>
<arg name=”seed”/>
</call>
</table>
<table name=”temp3”>
<call name=”table_mul”>
<arg name=”temp2”/>
<arg name=”temp2”/>
</call>
</table>
<table name=”temp4”>
<call name=”table_sqrt”>
<arg name=”temp3”/>
<arg name=”temp3”/>
</call>
</table>
<table name=”seed_new”>
<createRow>
<calMean tbl=”temp4” groupby=”clus” />
</createRow>
</table>
表11 k-means procedure example
在表(11)可以看到利用程序編輯 k-means clustering 的方法,利用了許多已事 先定義好的矩陣運算來完成。在我們的方法中,一開始便先將欲運算的資料存放
<call name=”table_sub”>
<arg name=”seednew”/>
<arg name=”seed”/>
</call>
</table>
<table name=”seed”>
<copy name = “seednew” />
</table>
<endLoop>
<if>
<check tbl="result" row="2" col="1" op="<" value="0"/>
</if>
</endLoop>
</Loop>
<return table = “temp4”/>
</proc>
運算結果的群中心傳回至主機。在得到各機器的運算結果後,主機器再計算新的 群中心,並重複之前的步驟,直到群中心不變為止。圖(11)為平行 k-means 程式 的示意圖。附錄(三)中包含了完整的程式。
表12 平行 k-means pseudo-code
圖 11 平行 k-means 示意圖
Master Process
1. Send each subset and cluster centers to each of the K slaves 2. Receive K resulting subsets from K slaves
Slave Process
1. Receive a subset data P and centers from master process 2. Compute cluster centers of the subset P
3. Send the calculating result to master
表13 平行 k-means 程式片段 1
在表(13)中是我們利用了符合附錄(二)定義的 DTD 所編輯的平行 k-means 程 式的片段。在這個片段內,我們讓使用者可以自輸入的表格中,指定位置來當作 k-means 程式開始執行時的初始群中心,將其以矩陣型態儲存,並可以指定這個 初始群中心的變數。
<table name="seed"> <!—- initial seed table -->
<createRow>
<getValueAt tblid="inputTable" row="1" col="1" />
</createRow>
<createRow>
<getValueAt tblid="inputTable" row="2" col="2" />
</createRow>
</table>
表14 平行 k-means 程式片段 2
<hidb name="poseidon" host="140.113.88.45"
port="1119" path="db"/>
<hidb name="poseidon" host="140.113.88.140"
port="1119" path="db"/>
</copy>
</assign>
</task>
</par>
表15 平行 k-means 程式片段 3
<Loop>
<par> <!-- partition jobs to remote clients -->
<task>
<copy tblid="seed" >
<hidb name="poseidon" host="140.113.88.45"
port="1119" path="db"/>
</copy>
</task>
<task>
<copy tblid="seed" >
<hidb name="poseidon" host="140.113.88.140"
port="1119" path="db"/>
<hidb name="poseidon" host="140.113.88.140"
port="1119" path="db"/>
</call>
</assign>
</task>
</par>
在完成對各機器的部分資料傳遞之後,程式便進入迴圈控制部分。表(15)的
<table name = "result2"> <!-- get client’s result -->
<get tblid= "id2">
<from>
<hidb name="poseidon" host="140.113.88.140"
port="1119" path="db" />
</from>
<to>
<hidb name="poseidon" host="140.113.88.45"
port="1119" path="db" />
</to>
</get>
</table>
<table name="new_seed"> <!—calculate new cluster center -->
<call name="calMean">
<tbl id="id1"/>
<tbl id="result2"/>
<hidb name="poseidon" host="140.113.88.140"
port="1119" path="db"/>
</call>
</table>
表17 平行 k-means 程式片段 5
在表(17)中,endLoop 這個標籤,則是定義了迴圈結束的條件。利用新計算 出的群中心與一開始的初始群中心的相減,來檢查群中心的位置是否不會改變。
如果群中心已不再移動,則會結束迴圈並結束程式,反之,則會將新的群中心的 值指定到seed 這個變數,並繼續執行迴圈,直到滿足結束條件。
由於微陣列矩陣資料分析完的結果,資料是以數值型態的方式儲存,無法直 接做判讀,所以我們將結果圖形化的呈現。
<endLoop> <!-- check end condition -->
<if>
<table name="result">
<call name="table_sub">
<arg name="new_seed"/>
<arg name="seed"/>
</call>
</table>
<check tbl="result" row="2" col="1" op="<" value="0"/>
</if>
</endLoop>
<table name = "seed">
<copy tblid="new_seed" >
<hidb name="poseidon" host="140.113.88.45"
port="1119" path="db"/>
</copy>
</table>
</Loop>
圖 12 K-means Analysis Result
4.3 分散式資料庫環境建置
在建立了分散式的資料庫系統之後,我們實做了 HiDB 的系統,讓使用者 能夠在同一個使用者介面中,瀏覽系統內所有的資料庫,而在程式的執行之前,
使用者必須建立一個 config 的初始設定檔案,讓程式知道欲連線的資料庫的名 稱、位置等資訊以建立連線。
表(18)是一個建立連線的 config 檔,讓系統知道在程式開始執行要去跟哪些 資料庫建立連線,在這個設定檔的範例當中,有兩個我們欲連接的資料庫,分別 以<hidb>的標籤定義,而各個資料庫在連線時所需的資訊,包括了主機名稱、位 置、使用者名稱、密碼以及資料庫的驅動程式,皆需要清楚完整的定義。在完成 連線後,便能夠在一個主介面上瀏覽所有資料庫內的資訊。圖(13)則是整個使用 者介面的概觀。
表18 Config 檔
圖 13 HiDB Console
<cfg>
<hidb name="poseidon"
user="system"
password="manager"
url="jdbc:oracle:thin:@140.113.88.45:1521:test1"
driver="oracle.jdbc.driver.OracleDriver"/>
<hidb name="bioserv"
user="system"
password="manager"
url="jdbc:oracle:thin:@140.113.88.140:1521:bioserv"
driver="oracle.jdbc.driver.OracleDriver"/>
</cfg>
第五章 實驗結果
為了瞭解我們系統的可行性,我們設計了一些實驗來檢驗我們系統的效 能。由於系統是建置在各資料庫之上,因此我們預期系統在處理大量資料時,能 夠維持一個穩定的執行狀態,在一般的運算上,也能夠有著可接受的效率。我們 實驗測試的環境為:
CPU:Intel Pentium4 2.0G Memory:256 Mb
Hard Disk:Maxtor 80Gb OS:Windows XP
Database:Oracle 9.1
5.1 矩陣加法的比較
圖 14 矩陣加法效能比較
圖(14)顯示的是利用 Java 程式執行矩陣加法 10 次,以及利用單一資料 庫的內儲程式來執行矩陣加法10 次,以及將資料分散至兩台資料庫利用內儲程 式各自執行矩陣加法5 次運算的結果比較。在資料量小於 50Mb 時,明顯的 Java
程式相較於資料庫內儲程式的運算有著較高的效能。但是在資料量增加成為 100Mb 後,由於矩陣加法在兩個矩陣相加後,需將結果存至第三個矩陣,所以 程式執行時會需要3 倍的計算空間,已超過了機器的實體記憶體,即使在執行之 前改變Java 執行環境(Java Runtime Environment)的旗標來增加 heap 和 stack 的大 小,但是 Java 程式在單一資料庫做完運算的時間內,仍無法結束運算。相較之 下,雖然資料庫的運算在資料量較小時,需要較多的時間來完成運算,但是在資 料量增加到一定大小後,還能穩定的完成運算。
5.2 矩陣乘法的比較
圖 15 矩陣乘法效能比較
除了矩陣加法之外,我們還測試了更耗費資源的矩陣乘法,其結果如圖(15) 所示。對一個N 維矩陣來說,矩陣乘法中矩陣的每一個位置的值需要經過 N 次 的乘法及N-1 次的加法所獲得,隨著資料量的增加,比起矩陣加法,計算的複雜 度更是可觀。以 1Mb 的資料量來說,Java 程式的實做,矩陣乘法所花費的時間 將近是矩陣加法的100 倍,且當資料量增加到為 50Mb 時,程式執行時會發生超 出記憶體的錯誤而無法執行。然而使用內儲程式執行的矩陣乘法,在執行上所花 的時間並沒有如同Java 程式那般暴增。
其間的差異,經過我們的分析,由於資料庫內儲程式能夠直接對儲存矩陣
的資料表格做存取,且矩陣存放在我們定義的 tbl 表格中,每個位置的值皆有 row_id 與 column_id 來作為資料表的鍵值,而這兩個欄與列的索引在矩陣的運算 上,提供了相當程度的便利,加速了矩陣乘法的運算。當資料量增大時,資料庫 的運算依然保持穩定的效能,並不像一般程式容易造成執行失敗的情形發生。因 此在面對大量的資料且在某些大量計算的情形下,以資料庫來完成運算,會較一 般使用程式來的更加的有效率及穩定。
5.3 資料傳輸的比較
我們建立的環境中,在服務與服務之間,底層訊息傳遞的機制是利用socket 來傳送XML 的訊息,由於各獨立的資料庫能夠將資料輸出成備份格式,並指定 傳入至特定的資料庫上,我們希望檢視我們所利用的資料傳輸的機制,與目前常 用的方法相較之下,是否會造成效能上的負擔。以格網環境為例,資料傳輸的服
我們建立的環境中,在服務與服務之間,底層訊息傳遞的機制是利用socket 來傳送XML 的訊息,由於各獨立的資料庫能夠將資料輸出成備份格式,並指定 傳入至特定的資料庫上,我們希望檢視我們所利用的資料傳輸的機制,與目前常 用的方法相較之下,是否會造成效能上的負擔。以格網環境為例,資料傳輸的服