Programing

coudamalloc()의 사용.왜 이중 포인터가 되는 거지?

c10106 2022. 4. 19. 20:23
반응형

coudamalloc()의 사용.왜 이중 포인터가 되는 거지?

나는 현재 CUDA를 배우기 위해 http://code.google.com/p/stanford-cs193g-sp2010/의 튜토리얼 예제를 검토하고 있다.강등되는 코드__global__기능은 다음과 같다.CPU에 1개, GPU에 1개 등 2개의 어레이를 만들어 GPU 어레이를 숫자 7로 채운 뒤 GPU 어레이 데이터를 CPU 어레이에 복사하면 된다.

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

__global__ void kernel(int *array)
{
  int index = blockIdx.x * blockDim.x + threadIdx.x;

  array[index] = 7;
}

int main(void)
{
  int num_elements = 256;

  int num_bytes = num_elements * sizeof(int);

  // pointers to host & device arrays
  int *device_array = 0;
  int *host_array = 0;

  // malloc a host array
  host_array = (int*)malloc(num_bytes);

  // cudaMalloc a device array
  cudaMalloc((void**)&device_array, num_bytes);

  int block_size = 128;
  int grid_size = num_elements / block_size;

  kernel<<<grid_size,block_size>>>(device_array);

  // download and inspect the result on the host:
  cudaMemcpy(host_array, device_array, num_bytes, cudaMemcpyDeviceToHost);

  // print out the result element by element
  for(int i=0; i < num_elements; ++i)
  {
    printf("%d ", host_array[i]);
  }

  // deallocate memory
  free(host_array);
  cudaFree(device_array);
} 

내 질문은 왜 그들이 그 단어를cudaMalloc((void**)&device_array, num_bytes);이중 포인터가 있는 문장?여기서도 coudamalloc()의 정의는 첫 번째 주장이 이중 포인터라고 말한다.

GPU의 할당된 메모리 시작 부분에 포인터를 단순히 반환하지 마십시오.mallocCPU에 기능이 있는가?

모든 CUDA API 함수는 오류 코드(또는 오류가 발생하지 않은 경우 cUDASuccessful)를 반환한다.다른 모든 파라미터는 참조에 의해 전달된다.그러나 일반 C에서는 참조를 가질 수 없으므로 반환 정보를 저장하려는 변수의 주소를 전달해야 한다.포인터를 돌려주므로 이중 포인터를 통과해야 한다.

동일한 이유로 주소에서 작동하는 또 다른 잘 알려진 기능은scanf기능을 하다이 글을 쓰는 것을 잊은 적이 몇 번인가.&값을 저장할 변수보다 먼저 선택하시겠습니까?;)

int i;
scanf("%d",&i);

이것은 단순히 끔찍하고 끔찍한 API 디자인이다.추상적(추상적)을 얻는 할당 함수에 대해 이중 포인터를 전달하는 문제void *)메모리는 타입의 임시변수를 만들어야 하는 것이다.void *결과를 보관한 다음 사용할 올바른 유형의 실제 포인터에 할당하십시오.주조(에 해당됨)(void**)&device_array는 유효하지 않은 C이며 정의되지 않은 행동을 초래한다.그냥 보통처럼 행동하는 포장지 함수를 써야 한다.malloc그리고 다음과 같이 포인터를 반환한다.

void *fixed_cudaMalloc(size_t len)
{
    void *p;
    if (cudaMalloc(&p, len) == success_code) return p;
    return 0;
}

C/C++에서는 를 호출하여 런타임에 메모리 블록을 동적으로 할당할 수 있다.malloc기능을 하다

int * h_array;
h_array = malloc(sizeof(int));

malloc함수는 어떤 종류의 포인터의 변수에 저장될 수 있는 할당된 메모리 블록의 주소를 반환한다.
CUDA에서의 메모리 할당은 두 가지 면에서 조금 다르다.

  1. cudamalloc메모리 블록에 대한 포인터가 아닌 오류 코드로 정수를 반환한다.
  2. 할당할 바이트 크기 외에,cudamalloc또한 첫 번째 파라미터로 이중 보이드 포인터가 필요하다.

    int * d_array cudamalloc((void **) &d_array, sizeof(int))

첫 번째 차이 뒤에 있는 이유는 모든 CUDA API 함수가 정수 오류 코드를 반환하는 관례를 따르기 때문이다.그래서 일관성을 유지하기 위해서cudamallocAPI도 정수를 반환한다.

함수 첫 번째 인수는 두 단계로 이해할 수 있으므로 이중 포인터에 대한 요구사항이 있다.

첫째, 우리는 이미 coudamalloc가 정수 값을 반환하도록 결정했기 때문에, 더 이상 할당 메모리의 주소를 반환하는 데 사용할 수 없다.C에서 함수가 통신할 수 있는 유일한 방법은 함수에 포인터나 주소를 전달하는 것이다.함수는 포인터가 가리키는 주소나 주소에 저장된 값을 변경할 수 있다.이러한 값에 대한 변경 사항은 동일한 메모리 주소를 사용하여 나중에 기능 범위 밖에서 검색할 수 있다.

이중 포인터의 작동 방식

다음 다이어그램은 이중 포인터를 사용하는 방법을 예시하였다.

int cudamalloc((void **) &d_array, int type_size) {
  *d_array = malloc(type_size);
  return return_code;
}

enter image description here

왜 이중 포인터가 필요하지?이 방법이 효과가 있는 이유

나는 보통 비단뱀 세상을 살아서 왜 이것이 작동하지 않는지 이해하려고 노력했다.

int cudamalloc((void *) d_array, int type_size) {
  d_array = malloc(type_size);
  ...
  return error_status;
}

그럼 왜 안 되는 거지?왜냐하면 C에서 언제cudamallocd_array라는 로컬 변수가 생성되어 첫 번째 함수 인수 값으로 할당된다.함수의 범위 밖에 있는 그 국부 변수의 값을 우리가 회수할 수 있는 방법은 없다.그래서 여기 포인터가 필요한 거야

int cudamalloc((void *) d_array, int type_size) {
  *d_array = malloc(type_size);
  ...
  return return_code;
}

enter image description here

우리는 그것이 포인터로 가는 포인터이기 때문에 그것을 이중 포인터로 던졌다.GPU 메모리의 포인터를 가리켜야 한다.cudaMalloc()가 하는 일은 GPU에 메모리 포인터를 할당하는 것이며, 이는 우리가 처음으로 제시하는 주장으로 지적된다.

문제: 두 가지 값을 반환해야 함:메모리에 대한 코드 AND 포인터를 반환하십시오(반환 코드가 성공을 나타내는 경우).그래서 그 중 하나를 반환할 포인터로 만들어야 한다.반환 유형으로 int(오류 코드의 경우)에 대한 반환 포인터 또는 메모리 주소(메모리 주소)에 대한 반환 포인터 중에서 선택할 수 있다.한 용액은 다른 용액만큼 좋다(그리고 그 중 하나는 포인터에게 포인터를 양보한다(이것은 이중 부동 소수점 번호에 대한 포인터처럼 들리므로 나는 이중 포인터 대신 이 용어를 사용하는 것을 선호한다).

malloc에서는 오류를 나타내는 null 포인터를 가질 수 있는 좋은 속성을 가지고 있으므로 기본적으로 하나의 반환 값만 있으면 된다.null 값이 없거나 잘못되었을 수 있으므로 장치 메모리에 대한 포인터를 사용하여 이 값이 가능한지 잘 모르겠다(기억:이것은 CUDA이고 Ansi C가 아니다.호스트 시스템의 null 포인터가 디바이스에 사용된 null과 완전히 다를 수 있으므로 오류를 나타내는 null 포인터의 반환이 작동하지 않으며 API를 이렇게 만들어야 한다(두 디바이스에 공통 NULL이 없음을 의미하기도 함).

참조URL: https://stackoverflow.com/questions/7989039/use-of-cudamalloc-why-the-double-pointer

반응형