CUDA學習(十二)

2021-09-21 17:13:30 字數 1893 閱讀 7620

流:

應用程式通過流管理上述併發操作。 流是按順序執行的一系列命令(可能由不同的主機執行緒發出)。 另一方面,不同的流可以相對於彼此或同時地不按順序執行它們的命令; 這種行為是不能保證的,因此不應該依賴於正確性(例如,核心間通訊是未定義的)

流的創造和銷毀:

通過建立流物件並將其指定為核心啟動序列和主機< - >裝置記憶體副本的流引數來定義流。 以下**示例建立兩個流,並在pagelocked記憶體中分配乙個浮點陣列hostptr:

cudastream_t stream[2];

for (int i = 0; i < 2; ++i)

cudastreamcreate(&stream[i]);

float* hostptr;

cudamallochost(&hostptr, 2 * size);

這些流中的每乙個都由以下**示例定義為從主機到裝置的乙個記憶體副本,乙個核心啟動以及乙個從裝置到主機的記憶體副本的序列:

for (int i = 0; i < 2; ++i)
每個流將其輸入陣列hostptr的部分複製到裝置記憶體中的陣列inputdevptr,通過呼叫mykernel()來處理裝置上的inputdevptr,並將結果outputdevptr複製回hostptr的同一部分。 重疊行為根據裝置的能力描述在這個示例中流如何重疊。 請注意,hostptr必須指向頁面鎖定的主機記憶體,以便發生任何重疊。

流通過呼叫cudastreamdestroy()來釋放:

for (int i = 0; i < 2; ++i)

cudastreamdestroy(stream[i]);

如果裝置在呼叫cudastreamdestroy()時仍然在流中工作,則函式將立即返回,一旦裝置完成了流中的所有工作,與流關聯的資源將自動釋放。

預設流:

核心啟動和主機< - >裝置記憶體副本,不指定任何流引數,或者等同於將流引數設定為零,傳送到預設流。 因此他們是按順序執行的。

對於使用--default-stream per-thread編譯標誌(或者在包含cuda標頭檔案(cuda.h和cuda_runtime.h)之前定義了cuda_api_per_thread_default_stream巨集)的**,預設流是常規流,每個主機執行緒 有它自己的預設流

對於使用--default-stream傳統編譯標誌編譯的**,預設流是乙個稱為null流的特殊流,每個裝置都有乙個用於所有主機執行緒的null流。 null流是特殊的,因為它會導致隱式同步,如隱式同步中所述。

對於編譯時未指定--default-stream編譯標誌的**, - default-stream legacy被認為是預設值

顯式同步:

有多種方法可以明確地使流彼此同步:

cudadevicesynchronize()等待,直到所有主機執行緒的所有流中的所有前面的命令都完成;

cudastreamsynchronize()將流作為引數,並等待,直到給定流中的所有前面的命令都完成為止。 它可用於將主機與特定的流同步,從而允許其他流在裝置上繼續執行。

cudastreamwaitevent()將乙個流和乙個事件作為引數(請參閱events來描述事件),並在呼叫cudastreamwaitevent()之後,將所有新增到給定流的命令延遲執行直到給定事件完成。 流可以為0,在這種情況下,在呼叫cudastreamwaitevent()等待事件之後,所有命令新增到任何流;

cudastreamquery()為應用程式提供了一種方法來知道流中的所有前面的命令是否完成;

為避免不必要的減速,所有這些同步功能通常最適合用於計時目的,或隔離發生故障的啟動或記憶體拷貝。

CUDA學習(五十二)

例子 每個執行緒的分配 include include global void malloctest int main 結果 thread 0 got pointer 00057020 thread 1 got pointer 0005708c thread 2 got pointer 000570...

CUDA學習(三十二)

本地記憶體 本地記憶體訪問只對一些自動變數發生,如可變記憶體空間說明符中所述。編譯器可能在本地記憶體中放置的自動變數是 檢查ptx彙編 通過使用 ptx orkeep選項編譯獲得 將會告訴在第乙個編譯階段變數是否被放置在本地記憶體中,因為它將使用.local助記符進行宣告,並使用ld.local進行...

CUDA學習(六十二)

流 裝置執行時可以使用有名和無名 null 流。命名流可以被執行緒塊內的任何執行緒使用,但是流控制代碼可能不會被傳遞給其他塊或子 父核心。換句話說,乙個流應該被視為對它建立的塊是私有的。流控制代碼不保證在塊之間是唯一的,因此在未分配塊的塊中使用流控制代碼將導致未定義的行為。與主機端啟動類似,啟動到不...