備份自:http://blog.rainy.im/2015/05/01/psychtoolbox-3-accurate-timing-1/
Psychtoolbox 3 中一些基本概念與基本原理的介紹,重點總結精確到幀的呈現時間的控制與精確的鍵盤(鼠標)輸入時間的控制。
1. Textures, Windows, Screens 等基本概念
PTB 中 screen 指代顯示器,Screen 0 代表默認顯示器,Screen 1 代表雙屏系統中第二個顯示器,以此類推。Screen('Screens')
返回可用顯示器的列表。
PTB 中 (onscreen) window 是用來展示實驗刺激的,一個顯示器(screen)最多只能有一個全屏顯示的 window。所有的繪制操作都在 window 中執行。window 都是雙緩沖的,也就是包含了后緩沖區(backbuffer)和前緩沖區(frontbuffer)兩部分。如果把顯示器看作是一個舞臺,后緩沖區相當于舞臺的后臺,將要繪制的圖形在這里完成準備工作;而前緩沖區相當于看得見的舞臺部分,也就是顯示器呈現刺激的部分,如一般實驗室采用的 CRT 顯示器,在前緩沖區中陰極射線管通過掃描完成一次成像。當我們通過一些繪制指令(如Screen('DrawTexture',...)
)完成繪制的準備工作后,需要通過調用Screen('Flip',...)
指令,完成前后緩沖區的切換,同時保證這一切換過程(一般1ms之內即可完成)發生在兩次(幀)掃描的間隔(也就是電子槍回溯到屏幕左上角的時間段),避免造成成像斷裂等現象。Flip
指令最重要的功能是將圖像繪制過程與實際呈現過程分離。
(offscreen) window 就是之前版本中的 Texture,唯一的不同是指令名稱和執行效率。細微的差別就不再贅述。
2. Flip 指令
Screen('Flip?') % 可以通過 Screen('Func?')進行查詢該指令的說明文檔
Usage:
[VBLTimestamp StimulusOnsetTime FlipTimestamp Missed Beampos]
= Screen('Flip', windowPtr [, when] [, dontclear] [, dontsync] [, multiflip]);
Flip 指令返回的第一個值 VBLTimestamp
是指上一幀掃描結束的時間點,接下來陰極射線管的電子槍需要回到屏幕左上角進行下一幀的掃描,這一間隔稱為垂直空白間隙(vertical blank interval, VBL)。同時前后緩沖區的切換也從這一時間點開始。此時 PTB 會進入休眠狀態,一直等到切換過程結束才會重新請求 CPU 資源,在這期間 CPU 可以保證系統其它部分的正常運行。等到切換完成之后,PTB 立即執行下面兩件事:
- 查詢電子槍(beam)當前的位置,并返回給變量
Beampos
; - 通過
GetSecs()
查詢當前精確的時間戳。
一般的多任務操作系統(OS X & Windows),在具體事件的時間點上都可能存在非常細微的隨機誤差,例如 VBL 開始的時間(VBLTimestamp
)、PTB 重新占用 CPU 的時間,一般這一時間差不會超過 1ms,但偶爾也有可能出現幾毫秒的誤差。為了補償這一誤差,PTB 利用電子槍回溯的位置作為另外一個高分辨率的時鐘進行精確時間的控制,其計算的原理如下圖所示:

Flip 返回的第二個值 StimulusOnsetTime
代表第二幀開始進行掃描的時間,即:StimulusOnsetTime = VBLTimestamp + VBL
。
Beamposition 的查詢必須依賴于顯卡硬件的支持,當無法通過硬件查詢準確的 Beamposition 時,也就無法獲取 VBL 時間。這時 PTB 一般會報錯:
----- ! PTB - ERROR: SYNCHRONIZATION FAILURE ! ----
One or more internal checks (see Warnings above) indicate that synchronization of Psychtoolbox to the vertical retrace (VBL) is not working on your setup.
如果對時間精確度的要求不是那么嚴格,或者程序還在調試階段,可以通過Screen('Preference', 'SkipSyncTests', 1)
跳過這一錯誤。此時,Flip 指令返回 StimulusOnsetTime = VBLTimestamp; beampos = -1;
。
3. Accurate Timing Demo
了解了以上原理,再來看精確時間控制的Demo:
首先是最簡單隨意的呈現方式,這樣無法保證精確控制時間,只是為了與后面的方法進行比較:
for frame = 1:numFrames
% Color the screen red
Screen('FillRect', window, [0.5 0.5 0.5]);
% Flip to the screen
Screen('Flip', window);
end
上一例子中沒有明確給出 Flip 執行的時間,這導致我們無法精確控制刺激呈現的時間。下面的例子中,首先在后緩沖區準備繪制之前讀取前一幀結束的時間vbl
,然后在連續呈現numFrames
幀刺激的過程中,明確指定每一次 Flip 的時間為上一幀掃描結束后的(waitframes - 0.5)*ifi
。當waitframes = 1;
時,前后兩次 Flip 之間的間隔一定為IFI,也就是連續呈現兩幀,從而確保刺激呈現的時間為兩幀。
waitframes = 1;
vbl = Screen('Flip', window);
for frame = 1:numFrames
% Color the screen red
Screen('FillRect', window, [0.5 0 0]);
% Flip to the screen
vbl = Screen('Flip', window, vbl + (waitframes - 0.5) * ifi);
end
上一例子中我們希望 PTB 可以在連續兩幀中呈現刺激,以保證刺激呈現時間。但現實并不一定如此,因為計算機操作系統需要同時維持所有軟硬件組成的正常運轉,如鍵盤、鼠標、網絡連接等等,這就可能導致 CPU 無法及時響應 PTB 的請求。為了讓 CPU 優先處理 PTB 的請求,我們需要提高 PTB 的優先等級;除此之外,還可以在繪制指令與 Flip 之間插入Screen('DrawingFinished', window);
來阻止其它繪制,保證更好的時間精確度:
topPriorityLevel = MaxPriority(window);
Priority(topPriorityLevel);
vbl = Screen('Flip', window);
for frame = 1:numFrames
% Color the screen red
Screen('FillRect', window, [0.5 0 0.5]);
% Tell PTB no more drawing commands will be issued until the next flip
Screen('DrawingFinished', window);
% Flip to the screen
vbl = Screen('Flip', window, vbl + (waitframes - 0.5) * ifi);
end
Priority(0);
4. 其它精確時間控制的設定及方法
對于現代計算機硬件來說,基本上可以通過代碼的控制做到精確的時間控制。如果實驗儀器是一些相對老舊的硬件設備(例如……),可能需要一些額外的系統配置來輔助精確時間的控制。
4.1 系統設置:
- 退出系統中無用的應用程序、后臺服務等,不要占用過多 CPU;
- 禁用殺毒軟件;
- 確保有足夠的內存,必要時利用虛擬內存;
- 確保節能選項不會減慢 CPU;
- 關閉藍牙、WIFI、網絡連接以及 CD/DVD 等外接設備;
- 不要盲目采用過高分辨率,這樣可能加重顯卡負擔,增加處理時間誤差。
4.2 Matlab設置:
-
matlab -nojvm
模式運行(如果沒有必要用到 Java 輔助工具,如GetChar
等); - 盡量減少 Matlab 圖形界面窗口;
- 閱讀 Matlab 文檔,優化代碼,充分利用內存加快執行速度;
-
help mlint
查看執行效率的瓶頸及代碼可能存在的問題。
4.3 程序編寫中需要注意的問題:
- PTB 輸出的 log 信息:
通過 Screen('Preference', 'Verbosity', level);
控制 PTB 執行過程中的輸出信息,在程序調試時可以選擇較高的 level
便于找到問題;正式實驗可以采用 Screen('Preference', 'Verbosity', 0);
禁用所有輸出信息,節省執行時間和資源。
- 函數的預加載:
Matlab 中的 .M & .MEX
源文件的加載需要一定的時間,如文件的定位、加載、執行等,這一初始化時間可能需要幾百毫秒,所以在實驗試次開始之前應該先執行一次需要的函數。
- 同一源文件內的
function
比通過文件加載的function
快:
Matlab 中的function
可以直接在當前腳本中定義,也可以通過單獨的腳本文件定義(函數名與文件名一致),調試過程中為方便可以將不同的function
切分成獨立的腳本文件,但在正式實驗時應該將必要的function
整合到同一個執行腳本。
- 優化代碼結構:
實驗程序的主體,trial loop 內的代碼應該以如下順序執行:
% 1. 繪制命令
Screen('DrawDots',...), Screen('DrawText',...),Screen('DrawTexture',...)...
% 2. 阻止多余繪制
Screen('DrawingFinished', win);
% 3. 其它與顯卡操作無關的代碼,如聲音、鍵盤、鼠標以及其它Matlab邏輯等
KbWait;
% 4. Flip 指令讓預備繪制刺激登臺
vbl = Screen('Flip', win, vbl+0.5*ifi);
5. 總結
上述內容主要針對 CRT 顯示器,CRT 與 液晶平板(LCD)的原理及優劣 Elze (2010)的文章中有詳細介紹,文章還總結了2003-2009三本心理學雜志中75篇實驗材料呈現時間低于50ms的研究,從各個研究中作者給出或推斷的實驗方法來看,許多研究者對顯示器上刺激呈現時間的基本概念與操作還存在一些誤解,導致實驗實際呈現的時間并非研究者所認為的時間。一直以來都有爭議而且最近比較熱鬧的心理學研究重復驗證,其實很大程度上與實驗條件控制有關,比如有些研究者文章中聲稱研究中刺激呈現時間為50ms,但是我們并不知道是如何做到的,實驗程序中是否存在不合適的操作等。所以說應該建議研究者投稿錄用后把實驗程序開源,放到 Github 上,供所有人查看,也大大節約了重復實驗的時間成本。哈哈,但是又有幾個人愿意這樣做呢~
到此為止基本介紹了 PTB 3 中對實驗刺激呈現時間進行精確控制的方法以及相關注意事項,在實驗過程中除了準確地呈現實驗刺激之外,還需要準確地記錄被試做出反應的時間,這主要涉及到鍵盤、鼠標或者特定的反應輸入設備的精確控制。PTB 3 中如何準確地處理響應輸入呢,下一節再說吧。
參考:
- FAQ: Textures, Windows, Screens
- FAQ: Performance Tuning
- Accurate Timing Demo
- Elze, T. (2010). Misspecifications of stimulus presentation durations in experimental psychology: A systematic review of the psychophysics literature. PloS one, 5(9), e12792.