NVIDIA RDMA GPUDIRECT는 항상 물리적 주소 만 작동합니까 (CPU의 물리적 주소 공간).

StackOverflow https://stackoverflow.com/questions/19841815

문제

우리가 아는 것처럼 : http://en.wikipedia.org/wiki/iommu#advantages

주변 메모리 페이징은 iommu. PCI-SIG PCIE 주소 변환 서비스 (ATS) 페이지 요청 인터페이스 (PRI) 확장을 사용하는 주변 장치는 메모리 관리자 서비스의 필요성을 감지하고 알 수 있습니다.

enter image description here

그러나 CUDA> = 5.0과 함께 NVIDIA GPU를 사용하면 rdma gpudirect를 사용할 수 있으며 다음을 알 수 있습니다.

http://docs.nvidia.com/cuda/gpudirect-rdma/index.html#how-gpudirect-rdma-works

전통적으로 Bar Windows와 같은 리소스는 CPU의 MMU를 메모리 매핑 I/O (MMIO) 주소로 사용하여 사용자 또는 커널 주소 공간에 매핑됩니다. 그러나 왜냐하면 현재 운영 체제는 드라이버 간 MMIO 영역을 교환하기에 충분한 메커니즘이 없습니다., NVIDIA 커널 드라이버는 필요한 주소 변환 및 매핑을 수행하기 위해 기능합니다.

http://docs.nvidia.com/cuda/gpudirect-rdma/index.html#supported-systems

gpudirect 용 RDMA는 현재 모든 물리적 주소에 의존합니다PCI 장치의 관점에서 동일합니다. 이로 인해 iommus와 호환되지 않으므로 gpudirect가 작동하기 위해 RDMA를 비활성화해야합니다.

CPU-RAM을 UVA에 할당하고 매핑하는 경우 여기와 같이.

#include <iostream>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

int main() {
    // Can Host map memory
    cudaSetDeviceFlags(cudaDeviceMapHost);  

    // Allocate memory
    unsigned char *host_src_ptr = NULL;
    cudaHostAlloc(&host_src_ptr, 1024*1024, cudaHostAllocMapped);
    std::cout << "host_src_ptr = " << (size_t)host_src_ptr << std::endl;

    // Get UVA-pointer
    unsigned int *uva_src_ptr = NULL;
    cudaHostGetDevicePointer(&uva_src_ptr, host_src_ptr, 0);
    std::cout << "uva_src_ptr  = " << (size_t)uva_src_ptr << std::endl;

    int b;  std::cin >> b;
    return 0;
}

우리는 Windwos7x64에서 동등한 포인터를 얻습니다. 즉, cudaHostGetDevicePointer() 아무것도하지 마세요:

host_src_ptr = 68719476736

UVA_SRC_PTR = 68719476736

"드라이버 간 MMIO 영역을 교환하기위한 충분한 메커니즘", 여기에 의미하는 메커니즘 및 가상 주소를 사용하여 PCIE를 통해 BAR의 물리적 영역에 액세스하여 IOMMU를 사용할 수없는 이유는 무엇입니까? ?

그리고 이것은 RDMA gpudirect가 항상 물리적 주소 (CPU의 물리적 주소 공간) 만 작동하지만 커널 기능으로 보내는 이유를 의미합니다. uva_src_ptr 그것은 동일합니다 host_src_ptr - CPU의 가상 주소 공간의 간단한 포인터?

도움이 되었습니까?

해결책

IOMMU는 매핑 레지스터 세트를 제공한다는 점에서 매우 유용합니다. 장치가 액세스 할 수있는 주소 범위 내에 물리적 메모리가 나타날 수 있으며, 물리적으로 산란 된 버퍼가 장치에 인접하게 보일 수 있습니다. 이것은 NVIDIA GPU의 원시 물리적 오프셋에 액세스하려고 시도하는 타사 PCI/PCI-EXPRESS 카드 또는 원격 기계에 적합하지 않습니다. 실제로 의도 된 메모리 영역에 액세스하거나 IOMMU 장치에 의해 카드 당으로 그러한 접근을 억제/제한하는 것. 그러므로 이것은 비활성화되어야합니다

"Gpudirect 용 RDMA는 현재 의존하고 있습니다 모든 물리 주소는 PCI 장치의 관점에서 동일합니다.."

-nvidia, RDMA 및 Gpudirect에 대한 설계 고려 사항

운전자가 커널 공간 내에서 사용하기 위해 CPU의 MMU 및 MAMIO (Memory Member Mapped I/O)의 MAP 영역을 활용하려고 시도하면 일반적으로 반환 된 주소를 메모리 매핑에서 스스로 유지합니다. 각 드라이버는 자체 컨텍스트 또는 네임 스페이스 내에서 작동하기 때문에 NVIDIA의 드라이버 (S)와 RDMA+GPUDIRECT를 지원하려는 다른 타사 공급 업체의 드라이버간에 이러한 매핑을 교환하기 때문에 매우 어렵고 공급 업체 별 솔루션 (아마도 제품조차 제품조차도 제품입니다. -특이 적 운전자가 제 3 자의 제품마다 크게 다르면). 또한 오늘날의 운영 체제에는 현재 운전자 간 MMIO 매핑을 교환하기위한 좋은 솔루션이 없으므로 NVIDIA는 제 3 자 드라이버가 커널 공간 내 에서이 정보에 쉽게 액세스 할 수있는 여러 기능을 수출합니다.

NVIDIA는 GPUDIRECT를 위해 RDMA를 통해 각 카드에 액세스하기 위해 "물리적 주소"를 사용합니다. 이는 가상 주소 지정과 관련된 문제 (예 : 가상 주소를 물리적 주소로 해결)와 관련된 문제에 대해 걱정하지 않고 해당 컴퓨터의 PCI-Express 버스로 데이터를 이동하는 프로세스를 크게 단순화합니다. 각 카드에는 물리적 주소가 있으며이 오프셋에서 액세스 할 수 있습니다. RDMA 작업을 수행하려는 제 3 자 운전자에 작은 논리 만 추가해야합니다. 또한이 32- 또는 64 비트 기본 주소 레지스터는 표준 PCI 구성 공간의 일부이므로 NVIDIA의 드라이버가 얻은 매핑 주소를 얻지 않고 단순히 막대에서 읽음으로써 카드의 물리 주소를 쉽게 얻을 수 있습니다. 카드에 부착하면. NVIDIA의 UVA (Universal Virtual Addressing) 사용자 공간 그러한 응용 프로그램 :

CUDA Virtual Address Space

이러한 메모리 영역은 CPU, GPU 및 Free의 세 가지 유형으로 더 나뉩니다. 여기.

그러나 사용 사례로 돌아 가기 : 사용자 공간, 당신은 시스템의 물리적 주소 공간에 직접 액세스 할 수 없으며, 당신이 사용하는 주소는 아마도 NVIDIA의 UVA가 제공하는 가상 주소 일 것입니다. 이전 할당이 없다고 가정하면 메모리 할당은 오프셋 +0x00000000에 상주해야하므로 GPU 자체의 동일한 오프셋이 나타납니다. 두 번째 버퍼를 할당하려면 첫 번째 버퍼가 끝난 직후 에이 버퍼가 시작되는 것을 볼 수 있다고 생각합니다 (오프셋 +0x00100000에서 기본에서 가상 주소 1MB 할당의 경우 GPU의.

당신이 있었다면 커널 공간, 그러나 회사의 카드가 gpudirect를 위해 RDMA를 활용하기 위해 운전자를 작성하고 있으면 시스템의 BIOS 및/또는 OS에 직접 RDMA 데이터에 의해 GPU에 할당 된 32 또는 64 비트 물리적 주소를 사용하여 직접 RDMA 데이터를 사용합니다. GPU 자체.

또한 모든 DMA 엔진이 실제로 전송에 대한 가상 주소를 지원하는 것은 아닙니다. 실제로 DMA 엔진에서 가상 주소를 처리하는 것처럼 실제로는 물리적 주소가 필요합니다. 복잡해질 수 있습니다 (7 페이지), 따라서 많은 DMA 엔진은 이에 대한 지원이 부족합니다.

그러나 게시물 제목의 질문에 답하기 위해 : NVIDIA는 현재 RDMA+gpudirect의 물리적 주소 만 지원합니다. 커널 공간에서. 을 위한 사용자 공간 응용 프로그램은 항상 CPU의 가상 주소 공간에있는 NVIDIA의 UVA가 제공 한 GPU의 가상 주소를 사용하게됩니다.


응용 프로그램과 관련하여 다음은 RDMA 운영에 대해 수행 할 수있는 프로세스의 단순화 된 분석입니다.

  1. 당신의 사용자 공간 응용 프로그램은 통합 가상 주소 지정 공간의 범위에있는 버퍼를 생성합니다.
  2. 전화하십시오 cuPointerGetAttribute(...) P2P 토큰을 얻기 위해; 이 토큰은 Cuda의 맥락 내부의 기억과 관련이 있습니다.
  3. 이 모든 정보를 보내십시오 커널 공간 어떻게 든 (예 : IOCTL, 읽기/쓰기는 드라이버 등). 최소한이 세 가지가 당신의 커널 공간 운전사:
    • P2P 토큰이 반환되었습니다 cuPointerGetAttribute(...)
    • 버퍼의 UVA 가상 주소 (S)
    • 버퍼의 크기
  4. 이제 NVIDIA의 커널 공간 함수를 호출하여 해당 가상 주소를 해당 물리 주소로 번역합니다.이 주소는 NVIDIA의 페이지 테이블에서 개최되며 다음과 같은 기능의 NVIDIA의 내보내기로 액세스 할 수 있습니다. nvidia_p2p_get_pages(...), nvidia_p2p_put_pages(...), 그리고 nvidia_p2p_free_page_table(...).
  5. 이전 단계에서 획득 한 이러한 물리 주소를 사용하여 해당 버퍼를 조작 할 DMA 엔진을 초기화하십시오.

이 프로세스에 대한보다 심층적 인 설명을 찾을 수 있습니다. 여기.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top