3. 實作方法
3.5 特殊的並行程式
}
SSet.add(Demo1Thread.saveState_0);
SSet.add(Demo1Thread.saveState_1);
MntrRG.saveState.add(SS1.Composite(SSet));
if (RaceVariant.saveState.getState() != null)
MntrRG.saveState.getState().setState_NO(
RaceVariant.saveState.getState().getState_NO());
return MntrRG;
} }
圖.23 Optimization code 裡 prefix‐based replay 程式碼
3.5 特殊的並行程式
法裡面,當我們省略某些 synchronization events 的時候,對於在這些忽略掉的 restore mode 的 synchronization events 中間可能穿插著區域變數,但是假如你沒 有對這些區域變數作處理的話,這樣將會出現區域變數的值並未更改到的狀況發 生,這樣可能會導致程式的錯誤。所以針對這樣的方式,我們也要將區域變數做 store 的方法,也要加入到 state 裡面去,像我之前設計的 state 內容一樣,我會用二維陣列的方式去儲存,之所以用二維主要是用來分辨他是哪個執行緒裡面的那 個區域變數之內容作儲存。一般來說我們會將這個區域變數的操作 hold 住在 synchronization event 之後,如下面的例子:
程式為兩個執行緒的並行程式,兩個共享變數a、b 初始值為 0,thread0 的區域 變數i 初始值為 0,當程式在跑的時候,我們對 line 2 的 synchronization event 作 store state 的方法,我們也會把這區域變數的操作加入到之後,如下圖 24。
圖.24 區域變數指令處理所放置的位置
store state 裡面會包含對區域變數裡的儲存,這樣也可以確保程式也對區域變數 store 到的狀況,在程式一開始的時候,在作 restore state 動作,也一併對區域變 數也作 restore,但是區域變數的 restore 並不是跟共享變數一樣的,它是屬於獨 立再一個執行緒裡面活動的變數,所以這裡要個別的去儲存,這樣子就可以確保 資料無誤了。
(2) 迴圈程式的處理方式
有了先前的區域變數的處理方式,我們對迴圈處理上就有了很大的幫助,程 式裡面迴圈的例子,我們大致上分為do while、while 和 for 的語法,因為三個語 言其實是可以互通的,所以我們針對whlie 迴圈來探討。
迴圈的程式裡面,我們主要是要處理當我們要跳到程式碼的某個迴圈裡面的
某個synchronization event 的時候,我們該怎麼去正確的找出省略的迴圈數,這 個就是重點之一。
在3.4 裡面,我們介紹了 prefix-based replay 的實作方式,其實在進行 replay 的時候,我們把mode 為 restore 的 synchronization events 抽出來是有意義的,再 搭配(1).所提的區域變數的處理,這樣我們再一開始載入區域變數(此時區域變 數是紀錄上次所儲存的迴圈數),因為我們再作 replay 的時候,已經沒有 mode 為restore 的 synchronization events,這兩步都作到了,該程式作 Prefix-base replay
的時候就會直接跳入該圈裡面去作執行了。
我們用以下的迴圈程式例子跑一次prefix-based replay 的處理,跟我們怎麼 處裡迴圈例子的形式:
大致上 thread0 會跑兩次 iteratives,當我們再處這樣迴圈的例子時,我們利用某 一次 race variant 來作 prefix-based replay 的方式來說明,可以看到我之前在 prefix-based replay 裡的設計,如圖 25。
圖.25 Prefix‐based replay 裡實作迴圈的例子
在圖25 裡我們可以解釋圖 22 裡面的抽象圖意,假設我們傳入某一個 race variant,
如圖中左邊那個race graph 的形式,他會包含一個 state0,在要送去 prefix-based replay 之時,他會將 restore synchronization events 抽出來,如圖中間那四個 synchronization events,之後我們就實際開始跑 prefix-based replay 的動作,如圖 右所示,我們是從i:=2 那個 iterative 開始執行的,所以只要再一開始的地方有載 入state 的內容,就可以對上修改過後 prefix-based replay 這個部分,來達成我們 跳到迴圈裡面的某一個synchronization event 執行的目的了。最後在之前所移出 的restore synchronization events 作組合,即為完整的 SYN-sequence,如圖 25,
之後就會再送去 race analyzer 裡面分析他的 race variants,整個大框架就照著 reachability testing 裡的架構去跑,內部的修改並不會影響到大框架。
圖.25 Prefix‐based replay 作完後所形成的 SYN‐sequence