簡體   English   中英

cudaLaunchKernel如何知道“void ** args”的數組大小?

[英]How does cudaLaunchKernel know the array size of “void **args”?

我知道數組的大小可以通過以下代碼獲得:

int a = 12;
float b = 12.0f;
char c = 'c';
void *param[] = { (void*)&a, (void*)&b, (void*)&c };

// the element size of param
size_t size = sizeof(param)/sizeof(void*);

但現在,我希望將param傳遞給名為TryToGetTheSize的函數,並獲取一個大小作為返回值。

size_t TryToGetTheSize(void **array)
{
     // return the size of void* array
}

...

size_t size = TryToGetTheSize(param);

我已經從strlen的實現中嘗試了一個想法,它將char*指針遞增地移動到下一個連續的內存空間,並通過檢查計數當前位置的值是否為'\\0'

但是該方法不適用於void** ,沒有辦法檢查void*指示地址的驗證。

因此,僅使用void** array似乎無法知道大小,但是當我查找CUDA API時,我發現:

cudaLaunchKernel(const void* func, dim3 gridDim, dim3 blockDim, void** args, size_t sharedMem, cudaStream_t stream)

在CUDA中,我們通常使用<<<>>>作為內核啟動,但是如果我們手動設置arugments並直接調用cudaLaunchKernel則相同

cudaLaunchKerenl API中,我注意到第四個參數args用作內核函數func參數,並且沒有其他參數描述args的大小

所以,我有兩個問題:

1) cudaLaunchKernel如何知道void** args的大小?

2)如果cudaLaunchKernel不需要知道void** args的大小,它是如何工作的?

以下是我在內核啟動時使用cudaLaunchKernel而不是<<<>>>示例代碼。

#include<stdio.h>
#include<stdlib.h>
#include<cuda_runtime.h>

__global__
void saxpy(int n, float a, float *x, float *y)
{
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < n) y[i] = a * x[i] + y[i];
}

int main(void)
{
    int N = 1 << 20;
    float *hx, *hy, *dx, *dy;
    hx = (float*)malloc(N * sizeof(float));
    hy = (float*)malloc(N * sizeof(float));

    cudaMalloc(&dx, N * sizeof(float));
    cudaMalloc(&dy, N * sizeof(float));

    for (int idx = 0; idx < N; idx++)
    {
        hx[idx] = 1.0f;
        hy[idx] = 2.0f;
    }

    cudaMemcpy(dx, hx, N * sizeof(float), cudaMemcpyHostToDevice);
    cudaMemcpy(dy, hy, N * sizeof(float), cudaMemcpyHostToDevice);

    unsigned int threads = 256;
    unsigned int blocks = (N + 255) / threads;

    float ratio = 2.0f;

    //saxpy<<<blocks, threads>>>(N, ratio, dx, dy);

    void *args[] = { &N, &ratio, &dx, &dy };
    cudaLaunchKernel((void*)saxpy, dim3(blocks), dim3(threads), args, 0, NULL);

    cudaMemcpy(hy, dy, N * sizeof(float), cudaMemcpyDeviceToHost);

    float max_error = 0.0f;
    for (int jdx = 0; jdx < N; jdx++)
    {
        max_error = max(max_error, abs(hy[jdx] - 4.0f));
    }

    printf("Max Error: %f\n", max_error);

    cudaFree(dx);
    cudaFree(dy);
    free(hx);
    free(hy);

    return 0;
}

引自相關文檔

不需要指定內核參數的數量及其偏移量和大小,因為直接從內核的映像中檢索該信息。

每個CUDA設備函數都將其參數列表與靜態編譯的函數代碼一起存儲。 因此,API確切地知道調用cudaLaunchKernel需要多少個參數條目。 如果您為啟動呼叫提供的數量太少,您將獲得段錯誤或未定義的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM