programing

cudaMalloc()가 포인터 투 포인터를 사용하는 이유는 무엇입니까?

linuxpc 2023. 6. 10. 08:30
반응형

cudaMalloc()가 포인터 투 포인터를 사용하는 이유는 무엇입니까?

를 들면, 들면를예,cudaMalloc((void**)&device_array, num_bytes);

이 질문은 이전에 질문을 받은 적이 있으며, 대답은 "왜냐하면cudaMalloc오류 코드를 반환합니다." 하지만 이해할 수 없습니다. 이중 포인터가 오류 코드를 반환하는 것과 무슨 관련이 있습니까?단순 포인터가 작업을 수행할 수 없는 이유는 무엇입니까?

내가 쓴다면,

cudaError_t catch_status;
catch_status = cudaMalloc((void**)&device_array, num_bytes);

는 「 」 「 」 「 」에 됩니다.catch_status그리고 할당된 GPU 메모리에 간단한 포인터만 돌려주면 충분하지 않나요?

C에서 데이터는 값 또는 시뮬레이션된 기준별 전달(즉, 데이터에 대한 포인터에 의해)을 통해 함수로 전달될 수 있습니다.기준 값은 단방향 방법론이며 포인터는 함수와 호출 환경 간의 양방향 데이터 흐름을 허용합니다.

데이터 항목이 함수 매개 변수 목록을 통해 함수로 전달되고 함수가 원래 데이터 항목을 수정하여 수정된 값이 호출 환경에 나타나도록 할 것으로 예상되는 경우, 이에 대한 올바른 C 방법은 포인터로 데이터 항목을 전달하는 것입니다.C에서 포인터로 전달할 때, 우리는 수정할 항목의 주소를 가져와서 포인터(이 경우에는 포인터에 대한 포인터)를 만들고 함수에 주소를 전달합니다.이렇게 하면 함수가 호출 환경에서 포인터를 통해 원래 항목을 수정할 수 있습니다.

은 통보.malloc포인터를 반환합니다. 그러면 호출 환경에서 할당을 사용하여 반환된 값을 원하는 포인터에 할당할 수 있습니다.cudaMallocCUDA 설계자는 반환된 값을 사용하여 포인터 대신 오류 상태를 전달하기로 선택했습니다.따라서 호출 환경에서 포인터 설정은 참조(즉, 포인터)를 통해 함수에 전달된 매개 변수 중 하나를 통해 이루어져야 합니다.설정하려는 포인터 값이기 때문에 포인터의 주소(포인터에 대한 포인터 만들기)를 가져와 해당 주소로 전달해야 합니다.cudaMalloc기능.

Robert의 답변에 덧붙이자면, 먼저 반복하자면, 이것은 C API이며, 이것은 참조를 지원하지 않는다는 것을 의미하며, 함수 내부에서 포인터의 값을 수정할 수 있습니다.로버트 크로벨라의 대답은 이것을 설명했습니다.또한 다음과 같이 해야 합니다.voidC 또한 함수 오버로드를 지원하지 않기 때문입니다.

또한 C++ 프로그램 내에서 C API를 사용할 때(그러나 당신은 이를 언급하지 않았습니다), 이러한 함수를 템플릿으로 래핑하는 것이 일반적입니다.예를들면,

template<typename T>
cudaError_t cudaAlloc(T*& d_p, size_t elements)
{
    return cudaMalloc((void**)&d_p, elements * sizeof(T));
}

위의 내용을 어떻게 부르는지에는 두 가지 차이점이 있습니다.cudaAlloc함수:

  1. 주소 연산자()를 사용하지 않고 장치 포인터를 직접 전달합니다.&) 그것을 부를 때, 그리고 캐스팅하지 않고.void유형.
  2. 두 번째 주장elements이제는 바이트 수가 아니라 요소 수가 됩니다.sizeof연산자가 이를 용이하게 합니다.요소를 지정하고 바이트를 걱정하지 않는 것이 더 직관적일 수 있습니다.

예:

float *d = nullptr;  // floats, 4 bytes per elements
size_t N = 100;      // 100 elements

cudaError_t err = cudaAlloc(d,N);      // modifies d, input is not bytes

if (err != cudaSuccess)
    std::cerr << "Unable to allocate device memory" << std::endl;

의 서명이 있을 것 같습니다.cudaMalloc함수는 예를 들어 더 잘 설명할 수 있습니다.기본적으로 다음 방법과 같이 포인터를 통해 버퍼에 버퍼를 할당하는 것입니다.

int cudaMalloc(void **memory, size_t size)
{
    int errorCode = 0;

    *memory = new char[size];

    return errorCode;
}

보다시피, 이 방법은 다음과 같습니다.memory포인터를 포인터로 이동하여 새 할당된 메모리를 저장합니다.그런 다음 오류 코드(이 경우 정수이지만 실제로는 열거형입니다)를 반환합니다.

cudaMalloc기능은 다음과 같이 설계할 수 있습니다.

void * cudaMalloc(size_t size, int * errorCode = nullptr)
{
    if(errorCode)
        errorCode = 0;

    char *memory = new char[size];

    return memory;
}

두 번째 경우, 오류 코드는 포인터 암시적으로 null로 설정됩니다(사람들이 오류 코드를 전혀 신경 쓰지 않는 경우).그러면 할당된 메모리가 반환됩니다.

번째 와 같이 사용할 수 .cudaMalloc지금 당장:

float *p;
int errorCode;
errorCode = cudaMalloc((void**)&p, sizeof(float));

두 번째는 다음과 같이 사용할 수 있습니다.

float *p;
int errorCode;
p = (float *) cudaMalloc(sizeof(float), &errorCode);

이 두 가지 방법은 기능적으로 동일하지만 서명이 다릅니다. 대부분의 사람들이 두 번째 방법이 더 좋았을 것이라고 말하는 반면, cuda 사람들은 오류 코드를 반환하고 포인터를 통해 메모리를 할당하면서 첫 번째 방법을 선택하기로 결정했습니다.

언급URL : https://stackoverflow.com/questions/12936986/why-does-cudamalloc-use-pointer-to-pointer

반응형