色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何在CUDA中使用驅(qū)動程序API

星星科技指導(dǎo)員 ? 來源:NVIDIA ? 作者:Ken He ? 2022-05-07 15:07 ? 次閱讀

驅(qū)動程序 API 在 cuda 動態(tài)庫(cuda.dll或cuda.so)中實現(xiàn),該庫在安裝設(shè)備驅(qū)動程序期間復(fù)制到系統(tǒng)上。 它的所有入口點都以 cu 為前綴。

它是一個基于句柄的命令式 API:大多數(shù)對象都由不透明的句柄引用,這些句柄可以指定給函數(shù)來操作對象。

驅(qū)動程序 API 中可用的對象匯總在下表中。Table 16. Objects Available in the CUDA Driver API

pYYBAGJ2GteAcMJDAABKIgowDRk296.png

在調(diào)用驅(qū)動程序 API 的任何函數(shù)之前,必須使用cuInit()初始化驅(qū)動程序 API。 然后必須創(chuàng)建一個附加到特定設(shè)備的 CUDA 上下文,并使其成為當(dāng)前調(diào)用主機(jī)線程,如上下文中所述。

在 CUDA 上下文中,內(nèi)核作為 PTX 或二進(jìn)制對象由主機(jī)代碼顯式加載,如模塊中所述。 因此,用 C++ 編寫的內(nèi)核必須單獨編譯成 PTX 或二進(jìn)制對象。 內(nèi)核使用 API 入口點啟動,如內(nèi)核執(zhí)行中所述。

任何想要在未來設(shè)備架構(gòu)上運行的應(yīng)用程序都必須加載 PTX,而不是二進(jìn)制代碼。 這是因為二進(jìn)制代碼是特定于體系結(jié)構(gòu)的,因此與未來的體系結(jié)構(gòu)不兼容,而 PTX 代碼在加載時由設(shè)備驅(qū)動程序編譯為二進(jìn)制代碼。

以下是使用驅(qū)動程序 API 編寫的內(nèi)核示例的主機(jī)代碼:

int main()
{
    int N = ...;
    size_t size = N * sizeof(float);

    // Allocate input vectors h_A and h_B in host memory
    float* h_A = (float*)malloc(size);
    float* h_B = (float*)malloc(size);

    // Initialize input vectors
    ...

    // Initialize
    cuInit(0);

    // Get number of devices supporting CUDA
    int deviceCount = 0;
    cuDeviceGetCount(&deviceCount);
    if (deviceCount == 0) {
        printf("There is no device supporting CUDA.\n");
        exit (0);
    }

    // Get handle for device 0
    CUdevice cuDevice;
    cuDeviceGet(&cuDevice, 0);

    // Create context
    CUcontext cuContext;
    cuCtxCreate(&cuContext, 0, cuDevice);

    // Create module from binary file
    CUmodule cuModule;
    cuModuleLoad(&cuModule, "VecAdd.ptx");

    // Allocate vectors in device memory
    CUdeviceptr d_A;
    cuMemAlloc(&d_A, size);
    CUdeviceptr d_B;
    cuMemAlloc(&d_B, size);
    CUdeviceptr d_C;
    cuMemAlloc(&d_C, size);

    // Copy vectors from host memory to device memory
    cuMemcpyHtoD(d_A, h_A, size);
    cuMemcpyHtoD(d_B, h_B, size);

    // Get function handle from module
    CUfunction vecAdd;
    cuModuleGetFunction(&vecAdd, cuModule, "VecAdd");

    // Invoke kernel
    int threadsPerBlock = 256;
    int blocksPerGrid =
            (N + threadsPerBlock - 1) / threadsPerBlock;
    void* args[] = { &d_A, &d_B, &d_C, &N };
    cuLaunchKernel(vecAdd,
                   blocksPerGrid, 1, 1, threadsPerBlock, 1, 1,
                   0, 0, args, 0);

    ...
}

完整的代碼可以在 vectorAddDrv CUDA 示例中找到。

L.1. Context

CUDA 上下文類似于 CPU 進(jìn)程。驅(qū)動 API 中執(zhí)行的所有資源和操作都封裝在 CUDA 上下文中,當(dāng)上下文被銷毀時,系統(tǒng)會自動清理這些資源。除了模塊和紋理或表面引用等對象外,每個上下文都有自己獨特的地址空間。因此,來自不同上下文的 CUdeviceptr 值引用不同的內(nèi)存位置。

主機(jī)線程一次可能只有一個設(shè)備上下文當(dāng)前。當(dāng)使用 cuCtxCreate() 創(chuàng)建上下文時,它對調(diào)用主機(jī)線程是當(dāng)前的。如果有效上下文不是線程當(dāng)前的,則在上下文中操作的 CUDA 函數(shù)(大多數(shù)不涉及設(shè)備枚舉或上下文管理的函數(shù))將返回 CUDA_ERROR_INVALID_CONTEXT。

每個主機(jī)線程都有一堆當(dāng)前上下文。 cuCtxCreate() 將新上下文推送到堆棧頂部。可以調(diào)用 cuCtxPopCurrent() 將上下文與主機(jī)線程分離。然后上下文是“浮動的”,并且可以作為任何主機(jī)線程的當(dāng)前上下文推送。 cuCtxPopCurrent() 還會恢復(fù)先前的當(dāng)前上下文(如果有)。

還為每個上下文維護(hù)使用計數(shù)。 cuCtxCreate() 創(chuàng)建使用計數(shù)為 1 的上下文。cuCtxAttach() 增加使用計數(shù),而 cuCtxDetach() 減少使用計數(shù)。當(dāng)調(diào)用 cuCtxDetach() 或 cuCtxDestroy() 時使用計數(shù)變?yōu)?0,上下文將被銷毀。

驅(qū)動程序 API 可與運行時互操作,并且可以通過 cuDevicePrimaryCtxRetain() 從驅(qū)動程序 API 訪問由運行時管理的主上下文(參見初始化)。

使用計數(shù)有助于在相同上下文中運行的第三方編寫的代碼之間的互操作性。例如,如果加載三個庫以使用相同的上下文,則每個庫將調(diào)用 cuCtxAttach() 來增加使用計數(shù),并在庫使用上下文完成時調(diào)用 cuCtxDetach() 來減少使用計數(shù)。對于大多數(shù)庫,預(yù)計應(yīng)用程序會在加載或初始化庫之前創(chuàng)建上下文;這樣,應(yīng)用程序可以使用自己的啟發(fā)式方法創(chuàng)建上下文,并且?guī)熘恍鑼鬟f給它的上下文進(jìn)行操作。希望創(chuàng)建自己的上下文的庫(可能會或可能沒有創(chuàng)建自己的上下文的 API 客戶端不知道)將使用 cuCtxPushCurrent() 和 cuCtxPopCurrent(),如下圖所示。

L.2. Module

模塊是設(shè)備代碼和數(shù)據(jù)的動態(tài)可加載包,類似于 Windows 中的 DLL,由 nvcc 輸出(請參閱使用 NVCC 編譯)。 所有符號的名稱,包括函數(shù)、全局變量和紋理或表面引用,都在模塊范圍內(nèi)維護(hù),以便獨立第三方編寫的模塊可以在相同的 CUDA 上下文中互操作。

此代碼示例加載一個模塊并檢索某個內(nèi)核的句柄:

CUmodule cuModule;
cuModuleLoad(&cuModule, "myModule.ptx");
CUfunction myKernel;
cuModuleGetFunction(&myKernel, cuModule, "MyKernel");

此代碼示例從 PTX 代碼編譯和加載新模塊并解析編譯錯誤:

#define BUFFER_SIZE 8192
CUmodule cuModule;
CUjit_option options[3];
void* values[3];
char* PTXCode = "some PTX code";
char error_log[BUFFER_SIZE];
int err;
options[0] = CU_JIT_ERROR_LOG_BUFFER;
values[0]  = (void*)error_log;
options[1] = CU_JIT_ERROR_LOG_BUFFER_SIZE_BYTES;
values[1]  = (void*)BUFFER_SIZE;
options[2] = CU_JIT_TARGET_FROM_CUCONTEXT;
values[2]  = 0;
err = cuModuleLoadDataEx(&cuModule, PTXCode, 3, options, values);
if (err != CUDA_SUCCESS)
    printf("Link error:\n%s\n", error_log);

此代碼示例從多個 PTX 代碼編譯、鏈接和加載新模塊,并解析鏈接和編譯錯誤:

#define BUFFER_SIZE 8192
CUmodule cuModule;
CUjit_option options[6];
void* values[6];
float walltime;
char error_log[BUFFER_SIZE], info_log[BUFFER_SIZE];
char* PTXCode0 = "some PTX code";
char* PTXCode1 = "some other PTX code";
CUlinkState linkState;
int err;
void* cubin;
size_t cubinSize;
options[0] = CU_JIT_WALL_TIME;
values[0] = (void*)&walltime;
options[1] = CU_JIT_INFO_LOG_BUFFER;
values[1] = (void*)info_log;
options[2] = CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES;
values[2] = (void*)BUFFER_SIZE;
options[3] = CU_JIT_ERROR_LOG_BUFFER;
values[3] = (void*)error_log;
options[4] = CU_JIT_ERROR_LOG_BUFFER_SIZE_BYTES;
values[4] = (void*)BUFFER_SIZE;
options[5] = CU_JIT_LOG_VERBOSE;
values[5] = (void*)1;
cuLinkCreate(6, options, values, &linkState);
err = cuLinkAddData(linkState, CU_JIT_INPUT_PTX,
                    (void*)PTXCode0, strlen(PTXCode0) + 1, 0, 0, 0, 0);
if (err != CUDA_SUCCESS)
    printf("Link error:\n%s\n", error_log);
err = cuLinkAddData(linkState, CU_JIT_INPUT_PTX,
                    (void*)PTXCode1, strlen(PTXCode1) + 1, 0, 0, 0, 0);
if (err != CUDA_SUCCESS)
    printf("Link error:\n%s\n", error_log);
cuLinkComplete(linkState, &cubin, &cubinSize);
printf("Link completed in %fms. Linker Output:\n%s\n", walltime, info_log);
cuModuleLoadData(cuModule, cubin);
cuLinkDestroy(linkState);

完整的代碼可以在 ptxjit CUDA 示例中找到。

L.3. Kernel Execution

cuLaunchKernel() 啟動具有給定執(zhí)行配置的內(nèi)核。

參數(shù)可以作為指針數(shù)組(在 cuLaunchKernel() 的最后一個參數(shù)旁邊)傳遞,其中第 n 個指針對應(yīng)于第 n 個參數(shù)并指向從中復(fù)制參數(shù)的內(nèi)存區(qū)域,或者作為額外選項之一( cuLaunchKernel()) 的最后一個參數(shù)。

當(dāng)參數(shù)作為額外選項(CU_LAUNCH_PARAM_BUFFER_POINTER 選項)傳遞時,它們作為指向單個緩沖區(qū)的指針傳遞,在該緩沖區(qū)中,通過匹配設(shè)備代碼中每個參數(shù)類型的對齊要求,參數(shù)被假定為彼此正確偏移。

表 4 列出了內(nèi)置向量類型的設(shè)備代碼中的對齊要求。對于所有其他基本類型,設(shè)備代碼中的對齊要求與主機(jī)代碼中的對齊要求相匹配,因此可以使用 __alignof() 獲得。唯一的例外是當(dāng)宿主編譯器在一個字邊界而不是兩個字邊界上對齊 double 和 long long(在 64 位系統(tǒng)上為 long)(例如,使用 gcc 的編譯標(biāo)志 -mno-align-double ) 因為在設(shè)備代碼中,這些類型總是在兩個字的邊界上對齊。

CUdeviceptr是一個整數(shù),但是代表一個指針,所以它的對齊要求是__alignof(void*)。

以下代碼示例使用宏 (ALIGN_UP()) 調(diào)整每個參數(shù)的偏移量以滿足其對齊要求,并使用另一個宏 (ADD_TO_PARAM_BUFFER()) 將每個參數(shù)添加到傳遞給 CU_LAUNCH_PARAM_BUFFER_POINTER 選項的參數(shù)緩沖區(qū)。

#define ALIGN_UP(offset, alignment) \
      (offset) = ((offset) + (alignment) - 1) & ~((alignment) - 1)

char paramBuffer[1024];
size_t paramBufferSize = 0;

#define ADD_TO_PARAM_BUFFER(value, alignment)                   \
    do {                                                        \
        paramBufferSize = ALIGN_UP(paramBufferSize, alignment); \
        memcpy(paramBuffer + paramBufferSize,                   \
               &(value), sizeof(value));                        \
        paramBufferSize += sizeof(value);                       \
    } while (0)

int i;
ADD_TO_PARAM_BUFFER(i, __alignof(i));
float4 f4;
ADD_TO_PARAM_BUFFER(f4, 16); // float4's alignment is 16
char c;
ADD_TO_PARAM_BUFFER(c, __alignof(c));
float f;
ADD_TO_PARAM_BUFFER(f, __alignof(f));
CUdeviceptr devPtr;
ADD_TO_PARAM_BUFFER(devPtr, __alignof(devPtr));
float2 f2;
ADD_TO_PARAM_BUFFER(f2, 8); // float2's alignment is 8

void* extra[] = {
    CU_LAUNCH_PARAM_BUFFER_POINTER, paramBuffer,
    CU_LAUNCH_PARAM_BUFFER_SIZE,    ¶mBufferSize,
    CU_LAUNCH_PARAM_END
};
cuLaunchKernel(cuFunction,
               blockWidth, blockHeight, blockDepth,
               gridWidth, gridHeight, gridDepth,
               0, 0, 0, extra);

結(jié)構(gòu)的對齊要求等于其字段的對齊要求的最大值。 因此,包含內(nèi)置向量類型 CUdeviceptr 或未對齊的 double 和 long long 的結(jié)構(gòu)的對齊要求可能在設(shè)備代碼和主機(jī)代碼之間有所不同。 這種結(jié)構(gòu)也可以用不同的方式填充。 例如,以下結(jié)構(gòu)在主機(jī)代碼中根本不填充,但在設(shè)備代碼中填充了字段 f 之后的 12 個字節(jié),因為字段 f4 的對齊要求是 16。

typedef struct {
    float  f;
    float4 f4;
} myStruct;

L.4. Interoperability between Runtime and Driver APIs

應(yīng)用程序可以將運行時 API 代碼與驅(qū)動程序 API 代碼混合。

如果通過驅(qū)動程序 API 創(chuàng)建上下文并使其成為當(dāng)前上下文,則后續(xù)運行時調(diào)用將獲取此上下文,而不是創(chuàng)建新上下文。

如果運行時已初始化(如 CUDA 運行時中提到的那樣),cuCtxGetCurrent() 可用于檢索在初始化期間創(chuàng)建的上下文。 后續(xù)驅(qū)動程序 API 調(diào)用可以使用此上下文。

從運行時隱式創(chuàng)建的上下文稱為主上下文(請參閱初始化)。 它可以通過具有主要上下文管理功能的驅(qū)動程序 API 進(jìn)行管理。

可以使用任一 API 分配和釋放設(shè)備內(nèi)存。 CUdeviceptr 可以轉(zhuǎn)換為常規(guī)指針,反之亦然:

CUdeviceptr devPtr;
float* d_data;

// Allocation using driver API
cuMemAlloc(&devPtr, size);
d_data = (float*)devPtr;

// Allocation using runtime API
cudaMalloc(&d_data, size);
devPtr = (CUdeviceptr)d_data;

特別是,這意味著使用驅(qū)動程序 API 編寫的應(yīng)用程序可以調(diào)用使用運行時 API 編寫的庫(例如 cuFFT、cuBLAS…)。

參考手冊的設(shè)備和版本管理部分的所有功能都可以互換使用。

L.5. Driver Entry Point Access

L.5.1. Introduction

驅(qū)動程序入口點訪問 API 提供了一種檢索 CUDA 驅(qū)動程序函數(shù)地址的方法。 從 CUDA 11.3 開始,用戶可以使用從這些 API 獲得的函數(shù)指針調(diào)用可用的 CUDA 驅(qū)動程序 API。

這些 API 提供的功能類似于它們的對應(yīng)物,POSIX 平臺上的 dlsym 和 Windows 上的 GetProcAddress。 提供的 API 將允許用戶:

使用 CUDA 驅(qū)動程序 API 檢索驅(qū)動程序函數(shù)的地址。

使用 CUDA 運行時 API 檢索驅(qū)動程序函數(shù)的地址。

請求 CUDA 驅(qū)動程序函數(shù)的每線程默認(rèn)流版本。 有關(guān)更多詳細(xì)信息,請參閱檢索每個線程的默認(rèn)流版本

使用較新的驅(qū)動程序訪問舊工具包上的新 CUDA 功能。

L.5.2. Driver Function Typedefs

為了幫助檢索 CUDA 驅(qū)動程序 API 入口點,CUDA 工具包提供對包含所有 CUDA 驅(qū)動程序 API 的函數(shù)指針定義的頭文件的訪問。 這些頭文件與 CUDA Toolkit 一起安裝,并且在工具包的 include/ 目錄中可用。 下表總結(jié)了包含每個 CUDA API 頭文件的 typedef 的頭文件。Table 17. Typedefs header files for CUDA driver APIs

上面的頭文件本身并沒有定義實際的函數(shù)指針; 他們?yōu)楹瘮?shù)指針定義了typedef。 例如,cudaTypedefs.h具有驅(qū)動 APIcuMemAlloc的以下typedef

    typedef CUresult (CUDAAPI *PFN_cuMemAlloc_v3020)(CUdeviceptr_v2 *dptr, size_t bytesize);
    typedef CUresult (CUDAAPI *PFN_cuMemAlloc_v2000)(CUdeviceptr_v1 *dptr, unsigned int bytesize);

CUDA 驅(qū)動程序符號具有基于版本的命名方案,其名稱中帶有_v*擴(kuò)展名,但第一個版本除外。 當(dāng)特定 CUDA 驅(qū)動程序 API 的簽名或語義發(fā)生變化時,我們會增加相應(yīng)驅(qū)動程序符號的版本號。 對于cuMemAlloc驅(qū)動程序 API,第一個驅(qū)動程序符號名稱是cuMemAlloc,下一個符號名稱是cuMemAlloc_v2。 CUDA 2.0 (2000) 中引入的第一個版本的typedefPFN_cuMemAlloc_v2000。 CUDA 3.2 (3020) 中引入的下一個版本的typedefPFN_cuMemAlloc_v3020

typedef 可用于更輕松地在代碼中定義適當(dāng)類型的函數(shù)指針:

    PFN_cuMemAlloc_v3020 pfn_cuMemAlloc_v2;
    PFN_cuMemAlloc_v2000 pfn_cuMemAlloc_v1;

如果用戶對 API 的特定版本感興趣,則上述方法更可取。 此外,頭文件中包含所有驅(qū)動程序符號的最新版本的預(yù)定義宏,這些驅(qū)動程序符號在安裝的 CUDA 工具包發(fā)布時可用; 這些typedef沒有_v*后綴。 對于 CUDA 11.3 工具包,cuMemAlloc_v2最新版本,所以我們也可以定義它的函數(shù)指針如下:

  PFN_cuMemAlloc pfn_cuMemAlloc;

L.5.3. Driver Function Retrieval

使用驅(qū)動程序入口點訪問 API 和適當(dāng)?shù)?typedef,我們可以獲得指向任何 CUDA 驅(qū)動程序 API 的函數(shù)指針。

L.5.3.1. Using the driver API

驅(qū)動程序 API 需要 CUDA 版本作為參數(shù)來獲取請求的驅(qū)動程序符號的 ABI 兼容版本。 CUDA 驅(qū)動程序 API 有一個以 _v* 擴(kuò)展名表示的按功能 ABI。 例如,考慮 cudaTypedefs.h 中 cuStreamBeginCapture 的版本及其對應(yīng)的 typedef:

    // cuda.h
    CUresult CUDAAPI cuStreamBeginCapture(CUstream hStream);
    CUresult CUDAAPI cuStreamBeginCapture_v2(CUstream hStream, CUstreamCaptureMode mode);
            
    // cudaTypedefs.h
    typedef CUresult (CUDAAPI *PFN_cuStreamBeginCapture_v10000)(CUstream hStream);
    typedef CUresult (CUDAAPI *PFN_cuStreamBeginCapture_v10010)(CUstream hStream, CUstreamCaptureMode mode);

從上述代碼片段中的typedefs,版本后綴_v10000_v10010表示上述API分別在CUDA 10.0CUDA 10.1中引入。

    #include 
    
    // Declare the entry points for cuStreamBeginCapture
    PFN_cuStreamBeginCapture_v10000 pfn_cuStreamBeginCapture_v1;
    PFN_cuStreamBeginCapture_v10010 pfn_cuStreamBeginCapture_v2;
    
    // Get the function pointer to the cuStreamBeginCapture driver symbol
    cuGetProcAddress("cuStreamBeginCapture", &pfn_cuStreamBeginCapture_v1, 10000, CU_GET_PROC_ADDRESS_DEFAULT);
    // Get the function pointer to the cuStreamBeginCapture_v2 driver symbol
    cuGetProcAddress("cuStreamBeginCapture", &pfn_cuStreamBeginCapture_v2, 10010, CU_GET_PROC_ADDRESS_DEFAULT);

參考上面的代碼片段,要檢索到驅(qū)動程序 API cuStreamBeginCapture 的 _v1 版本的地址,CUDA 版本參數(shù)應(yīng)該正好是 10.0 (10000)。同樣,用于檢索 _v2 版本 API 的地址的 CUDA 版本應(yīng)該是 10.1 (10010)。為檢索特定版本的驅(qū)動程序 API 指定更高的 CUDA 版本可能并不總是可移植的。例如,在此處使用 11030 仍會返回 _v2 符號,但如果在 CUDA 11.3 中發(fā)布假設(shè)的 _v3 版本,則當(dāng)與 CUDA 11.3 驅(qū)動程序配對時,cuGetProcAddress API 將開始返回較新的 _v3 符號。由于 _v2 和 _v3 符號的 ABI 和函數(shù)簽名可能不同,使用用于 _v2 符號的 _v10010 typedef 調(diào)用 _v3 函數(shù)將表現(xiàn)出未定義的行為。

要檢索給定 CUDA 工具包的驅(qū)動程序 API 的最新版本,我們還可以指定 CUDA_VERSION 作為版本參數(shù),并使用未版本化的 typedef 來定義函數(shù)指針。由于 _v2 是 CUDA 11.3 中驅(qū)動程序 API cuStreamBeginCapture 的最新版本,因此下面的代碼片段顯示了檢索它的不同方法。

    // Assuming we are using CUDA 11.3 Toolkit

    #include 
    
    // Declare the entry point
    PFN_cuStreamBeginCapture pfn_cuStreamBeginCapture_latest;
    
    // Intialize the entry point. Specifying CUDA_VERSION will give the function pointer to the
    // cuStreamBeginCapture_v2 symbol since it is latest version on CUDA 11.3.
    cuGetProcAddress("cuStreamBeginCapture", &pfn_cuStreamBeginCapture_latest, CUDA_VERSION, CU_GET_PROC_ADDRESS_DEFAULT);
  

請注意,請求具有無效 CUDA 版本的驅(qū)動程序 API 將返回錯誤 CUDA_ERROR_NOT_FOUND。 在上面的代碼示例中,傳入小于 10000 (CUDA 10.0) 的版本將是無效的。

L.5.3.2. Using the runtime API

運行時 API 使用 CUDA 運行時版本來獲取請求的驅(qū)動程序符號的 ABI 兼容版本。 在下面的代碼片段中,所需的最低 CUDA 運行時版本將是 CUDA 11.2,因為當(dāng)時引入了 cuMemAllocAsync。

    #include 
    
    // Declare the entry point
    PFN_cuMemAllocAsync pfn_cuMemAllocAsync;
    
    // Intialize the entry point. Assuming CUDA runtime version >= 11.2
    cudaGetDriverEntryPoint("cuMemAllocAsync", &pfn_cuMemAllocAsync, cudaEnableDefault);
    
    // Call the entry point
    pfn_cuMemAllocAsync(...);

L.5.3.3. Retrieve per-thread default stream versions

一些 CUDA 驅(qū)動程序 API 可以配置為具有默認(rèn)流或每線程默認(rèn)流語義。具有每個線程默認(rèn)流語義的驅(qū)動程序 API 在其名稱中以 _ptsz 或 _ptds 為后綴。例如,cuLaunchKernel 有一個名為 cuLaunchKernel_ptsz 的每線程默認(rèn)流變體。使用驅(qū)動程序入口點訪問 API,用戶可以請求驅(qū)動程序 API cuLaunchKernel 的每線程默認(rèn)流版本,而不是默認(rèn)流版本。為默認(rèn)流或每線程默認(rèn)流語義配置 CUDA 驅(qū)動程序 API 會影響同步行為。更多詳細(xì)信息可以在這里找到。

驅(qū)動API的默認(rèn)流或每線程默認(rèn)流版本可以通過以下方式之一獲得:

使用編譯標(biāo)志 --default-stream per-thread 或定義宏 CUDA_API_PER_THREAD_DEFAULT_STREAM 以獲取每個線程的默認(rèn)流行為。

分別使用標(biāo)志 CU_GET_PROC_ADDRESS_LEGACY_STREAM/cudaEnableLegacyStream 或 CU_GET_PROC_ADDRESS_PER_THREAD_DEFAULT_STREAM/cudaEnablePerThreadDefaultStream 強(qiáng)制默認(rèn)流或每個線程的默認(rèn)流行為。

L.5.3.4. Access new CUDA features

始終建議安裝最新的 CUDA 工具包以訪問新的 CUDA 驅(qū)動程序功能,但如果出于某種原因,用戶不想更新或無法訪問最新的工具包,則可以使用 API 來訪問新的 CUDA 功能 只有更新的 CUDA 驅(qū)動程序。 為了討論,讓我們假設(shè)用戶使用 CUDA 11.3,并希望使用 CUDA 12.0 驅(qū)動程序中提供的新驅(qū)動程序 API cuFoo。 下面的代碼片段說明了這個用例:

    int main()
    {
        // Assuming we have CUDA 12.0 driver installed.

        // Manually define the prototype as cudaTypedefs.h in CUDA 11.3 does not have the cuFoo typedef
        typedef CUresult (CUDAAPI *PFN_cuFoo)(...);
        PFN_cuFoo pfn_cuFoo = NULL;
        
        // Get the address for cuFoo API using cuGetProcAddress. Specify CUDA version as
        // 12000 since cuFoo was introduced then or get the driver version dynamically
        // using cuDriverGetVersion 
        int driverVersion;
        cuDriverGetVersion(&driverVersion);
        cuGetProcAddress("cuFoo", &pfn_cuFoo, driverVersion, CU_GET_PROC_ADDRESS_DEFAULT);
        
        if (pfn_cuFoo) {
            pfn_cuFoo(...);
        }
        else {
            printf("Cannot retrieve the address to cuFoo. Check if the latest driver for CUDA 12.0 is installed.\n");
            assert(0);
        }
        
        // rest of code here
        
    

關(guān)于作者

Ken He 是 NVIDIA 企業(yè)級開發(fā)者社區(qū)經(jīng)理 & 高級講師,擁有多年的 GPU人工智能開發(fā)經(jīng)驗。自 2017 年加入 NVIDIA 開發(fā)者社區(qū)以來,完成過上百場培訓(xùn),幫助上萬個開發(fā)者了解人工智能和 GPU 編程開發(fā)。在計算機(jī)視覺,高性能計算領(lǐng)域完成過多個獨立項目。并且,在機(jī)器人無人機(jī)領(lǐng)域,有過豐富的研發(fā)經(jīng)驗。對于圖像識別,目標(biāo)的檢測與跟蹤完成過多種解決方案。曾經(jīng)參與 GPU 版氣象模式GRAPES,是其主要研發(fā)者。

審核編輯:郭婷

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • API
    API
    +關(guān)注

    關(guān)注

    2

    文章

    1502

    瀏覽量

    62123
  • 應(yīng)用程序
    +關(guān)注

    關(guān)注

    37

    文章

    3277

    瀏覽量

    57738
  • CUDA
    +關(guān)注

    關(guān)注

    0

    文章

    121

    瀏覽量

    13641
收藏 人收藏

    評論

    相關(guān)推薦

    Linux驅(qū)動程序程序員指南

    電子發(fā)燒友網(wǎng)站提供《Linux驅(qū)動程序程序員指南.pdf》資料免費下載
    發(fā)表于 11-22 15:53 ?0次下載
    Linux<b class='flag-5'>驅(qū)動程序</b><b class='flag-5'>程序</b>員指南

    pcie設(shè)備驅(qū)動程序安裝步驟

    PCIe(Peripheral Component Interconnect Express)是一種高速串行計算機(jī)擴(kuò)展總線標(biāo)準(zhǔn),用于計算機(jī)內(nèi)部硬件組件之間的連接。安裝PCIe設(shè)備驅(qū)動程序是確保硬件
    的頭像 發(fā)表于 11-13 10:32 ?858次閱讀

    硬盤電機(jī)怎么驅(qū)動程序?它有什么典型特征?

    硬盤電機(jī)的驅(qū)動程序是硬盤中一個非常重要的組成部分,它負(fù)責(zé)控制硬盤電機(jī)的啟動、停止、轉(zhuǎn)速調(diào)節(jié)等操作。硬盤電機(jī)驅(qū)動程序的設(shè)計和實現(xiàn)涉及到電機(jī)控制理論、電子技術(shù)、計算機(jī)編程等多個領(lǐng)域的知識。 一、硬盤電機(jī)
    的頭像 發(fā)表于 10-22 11:10 ?378次閱讀

    何在TMS320DM643x器件上使用EDMA3驅(qū)動程序

    電子發(fā)燒友網(wǎng)站提供《如何在TMS320DM643x器件上使用EDMA3驅(qū)動程序.pdf》資料免費下載
    發(fā)表于 10-15 09:41 ?0次下載
    如<b class='flag-5'>何在</b>TMS320DM643x器件上使用EDMA3<b class='flag-5'>驅(qū)動程序</b>

    LSP 2.10 DaVinci Linux驅(qū)動程序

    電子發(fā)燒友網(wǎng)站提供《LSP 2.10 DaVinci Linux驅(qū)動程序.pdf》資料免費下載
    發(fā)表于 10-09 09:30 ?0次下載
    LSP 2.10 DaVinci Linux<b class='flag-5'>驅(qū)動程序</b>

    Linux設(shè)備驅(qū)動程序分類有哪些

    Linux設(shè)備驅(qū)動程序是操作系統(tǒng)與硬件設(shè)備之間的橋梁,負(fù)責(zé)實現(xiàn)硬件設(shè)備與操作系統(tǒng)之間的通信和控制。Linux設(shè)備驅(qū)動程序的分類繁多,可以根據(jù)不同的標(biāo)準(zhǔn)進(jìn)行分類。 按硬件類型分類 Linux設(shè)備
    的頭像 發(fā)表于 08-30 15:11 ?594次閱讀

    linux驅(qū)動程序如何加載進(jìn)內(nèi)核

    ,需要了解Linux內(nèi)核的基本概念和API。以下是一些關(guān)鍵概念: 1.1 內(nèi)核模塊:Linux內(nèi)核模塊是一種動態(tài)加載和卸載的代碼,可以在不重新啟動系統(tǒng)的情況下加載和卸載。驅(qū)動程序通常以內(nèi)核模塊的形式實現(xiàn)。 1.2 設(shè)備模型:Linux內(nèi)核使用設(shè)備模型來管理設(shè)
    的頭像 發(fā)表于 08-30 15:02 ?511次閱讀

    linux驅(qū)動程序主要有哪些功能

    Linux驅(qū)動程序是操作系統(tǒng)與硬件設(shè)備之間進(jìn)行通信的橋梁,負(fù)責(zé)實現(xiàn)硬件設(shè)備與操作系統(tǒng)之間的數(shù)據(jù)交換和控制。Linux驅(qū)動程序的主要功能包括以下幾個方面: 設(shè)備識別與初始化 Linux驅(qū)動程序需要
    的頭像 發(fā)表于 08-30 14:47 ?383次閱讀

    linux驅(qū)動程序的編譯方法是什么

    Linux驅(qū)動程序的編譯方法主要包括兩種: 與內(nèi)核一起編譯 和 編譯成獨立的內(nèi)核模塊 。以下是對這兩種方法的介紹: 一、與內(nèi)核一起編譯 與內(nèi)核一起編譯意味著將驅(qū)動程序的源代碼直接集成到Linux內(nèi)核
    的頭像 發(fā)表于 08-30 14:46 ?629次閱讀

    linux驅(qū)動程序運行在什么空間

    Linux 驅(qū)動程序是操作系統(tǒng)的一部分,負(fù)責(zé)管理硬件設(shè)備與操作系統(tǒng)之間的交互。驅(qū)動程序運行在內(nèi)核空間(Kernel Space),這是操作系統(tǒng)的核心部分,與用戶空間(User Space)相對。內(nèi)核
    的頭像 發(fā)表于 08-30 14:37 ?441次閱讀

    虹科技術(shù) Linux環(huán)境再升級:PLIN驅(qū)動程序正式發(fā)布

    Linux驅(qū)動程序領(lǐng)域再添新成員,PLIN驅(qū)動程序現(xiàn)已正式發(fā)布。
    的頭像 發(fā)表于 06-28 13:34 ?374次閱讀
    虹科技術(shù) Linux環(huán)境再升級:PLIN<b class='flag-5'>驅(qū)動程序</b>正式發(fā)布

    請問cmakelists中的變量如何在程序中使用?

    大家好, 我有個問題請教,cmakelists.txt中的變量如何在程序中使用?比如以下cmakelists.txt文件中的PROJECT_VER變量,我如何在c
    發(fā)表于 06-11 07:34

    實現(xiàn)機(jī)器人操作系統(tǒng)——ADI Trinamic電機(jī)控制器ROS1驅(qū)動程序簡介

    摘要 機(jī)器人操作系統(tǒng)(ROS)驅(qū)動程序基于ADI產(chǎn)品而開發(fā),因此可直接在ROS生態(tài)系統(tǒng)中使用這些產(chǎn)品。本文將概述如何在應(yīng)用、產(chǎn)品和系統(tǒng)(例如,自主導(dǎo)航、安全氣泡地圖和數(shù)據(jù)收 集機(jī)器人)中使
    的頭像 發(fā)表于 04-24 15:43 ?2225次閱讀
    實現(xiàn)機(jī)器人操作系統(tǒng)——ADI Trinamic電機(jī)控制器ROS1<b class='flag-5'>驅(qū)動程序</b>簡介

    怎么編寫Framebuffer驅(qū)動程序

    Framebuffer 驅(qū)動程序框架 分為上下兩層: fbmem.c:承上啟下 實現(xiàn)、注冊 file_operations 結(jié)構(gòu)體 把 APP 的調(diào)用向下轉(zhuǎn)發(fā)到具體的硬件驅(qū)動程序
    的頭像 發(fā)表于 03-22 09:13 ?570次閱讀
    怎么編寫Framebuffer<b class='flag-5'>驅(qū)動程序</b>

    何在測試中使用ChatGPT

    Dimitar Panayotov 在 2023 年 QA Challenge Accepted 大會 上分享了他如何在測試中使用 ChatGPT。
    的頭像 發(fā)表于 02-20 13:57 ?771次閱讀
    主站蜘蛛池模板: 国产精品人妻无码99999| 扒开粉嫩的小缝末成年小美女| 美国z0069| 韩国精品韩国专区久久| 国产精品av免费观看| 成人特级毛片| Zoofilivideo人馿交| 91原创在线| 91九色porny蝌蚪| 19十主播福利视频| 2018三级网站免费观看| 中国比基尼美女| 最近中文字幕高清中文| 中文无码字慕在线观看| 制服的微热| 8X拨牐拨牐X8免费视频8| 70岁妇女牲交色牲片| 97视频在线免费| jlzzzjizzzjlzzz亚洲| 成人国产在线观看| 高清撒尿hdtube撒尿| 国产精品99久久久久久AV下载 | 久久天堂网| 美女MM131爽爽爽| 牛牛免费视频| 日本动漫henta videos| 色戒西瓜视频| 香艳69xxxxx有声小说| 亚洲国产在线精品国自产拍五月| 亚洲精品久久午夜麻豆| 一个人在线观看免费高清视频在线观看 | 午夜福利理论片高清在线| 午夜福利试看120秒体验区| 亚洲精品国产国语| 伊人色综合久久天天| 91国在线产| 超碰在线视频人人AV| 国产精品VIDEOS麻豆TUBE| 国产无遮挡又黄又爽在线视频 | 久久久午夜精品福利内容| 免费看的一级毛片|