因爲OpenCL在異構系統上進行計算,須要管理並調度多個設備,就須要在設備之間內部或外部進行數據交互以及同步。
<!-- more -->程序員
根據同步的類型,同步分爲兩部分:宿主機端同步和設備端同步。安全
設備端同步主要指同一個內核內不一樣線程以前的同步,主要用於保證數據的一致性。根據工做組的劃分,能夠細分爲組內同步和全局同步。網絡
OpenCL採用寬鬆的同步模型和內存一致性模型。一般來講,採用硬件實現可以最好的實現同步,可是做爲一個跨平臺的API,並不能徹底實現這些特性。因此OpenCL的解決方案是讓程序員明確的知道當前系統的狀態,添加同步點,從而能夠依據這些信息獲取預期行爲。異步
在x86(CPU)平臺上,咱們使用同步機制若是條件還未知足,咱們可使系統進入休眠等待條件知足。可是GPU上的線程與系統層級的線程不是一個概念,GPU的線程所佔用的資源是固定的,不能釋放的,這也就致使了若是不一樣的不一樣work group不能爲同一個資源作同步,由於沒有釋放的概念,因此必然存在死鎖的狀態。因此只能組內同步。函數
組內同步的機制是barrier
,即屏障,在組內全部的item沒有到達這個barrier以前,全部的item是不想下執行的。ui
item1 | item2 | | item3 | | | | 5s |4s | 3s | | | ------------------------------ 全部達到 barrier以後,同時出發 | | | | | |
目前OpenCL不支持與組內同步相似的全局同步方式(緣由上方已經介紹)。能夠經過global fence
以及原子操做來達到目的。spa
OpenCL是基於任務並行,主機控制的模型,其中每一項任務都是數據並行的,具體經過使用和設備關聯的線程安全的命令隊列來實現。固然,內核、數據以及其餘操做並非簡單調用來進行的,而是經過異步加入指定的隊列中。線程
從宿主機角度來看,保證宿主機同步的要點有一下三條:code
固然,根據所須要同步的計算設備的個數,能夠分爲單設備同步
和多設備同步
。隊列
clFinish能夠阻塞程序的執行直到命令隊列中的全部命令都執行完成。可是這只是至關於在末尾加上了一個barrier。在中間加入barrier須要調用以下函數:
cl_int clEnqueueBarrier( cl_command_queue command_queue )
等待事件,即將一個等待事件加入命令隊列,只有這個等待事件知足之後,才能執行以後加入的命令,使用的命令以下:
cl_int clEnqueueWaitForEvents( cl_command_queue command_queue, cl_uint num_events, const cl_event* event_list )
從變量定義上很好理解,再也不贅述。
咱們在進行網絡訪問或者進行IO讀取的時候是如何進行阻塞與非阻塞的區分的呢,沒錯,每每是傳入一個標誌。對於OpenCL也是同樣的,如:
clEnqueReadBuffer(que, CL_TRUEm....)
上面這個示例的第二個參數就是指定這個函數是不是同步操做,若是爲TRUE,那麼就會阻塞直至拷貝完成,若是爲FALSE,在設置完後不等拷貝完成,就會返回。
在以前咱們已經瞭解到,使用事件只能在同一個上下文中實現同步。那麼在不一樣的設備不一樣的上下文中如何實現同步呢,只剩下了一種方法,cFinish,等待另外一個命令隊列執行完成,以後的命令才能繼續執行。如一個CPU一個GPU,二者須要互相訪問彼此的數據,那麼如何實現同步呢,若是CPU要訪問CPU的數據,必須等待CPU當前的命令隊列執行完成,再也不佔用內存,GPU才能進行訪問。
版權聲明:本文爲博主原創文章,轉載需聲明爲轉載內容並添加原文地址。
原文地址:http://coderdock.com