RDMA (Remote Direct Memory Access)

네트워크 상의 한 컴퓨터에서 다른 컴퓨터의 메모리에 직접 접근할 수 있게 해주는 기술로, CPU의 개입 없이 데이터를 전송할 수 있는 고성능 네트워크 기술

주요 특징:

  1. 낮은 지연 시간(Low Latency):
    • CPU 개입 없이 메모리 간 직접 데이터 전송이 가능하므로, 전송 지연 시간이 매우 짧다.
  2. 높은 대역폭(High Bandwidth):
    • 데이터 복사 과정이 없기 때문에 빠르고 효율적으로 대량의 데이터를 처리할 수 있다.
  3. 낮은 CPU 사용률(Low CPU Utilization):
    • 데이터 전송 작업이 네트워크 어댑터(NIC)에서 이루어지기 때문에 CPU는 다른 작업에 집중할 수 있다.
  4. 제로-카피(Zero-Copy):
    • 데이터가 중간 버퍼링 없이 메모리에서 바로 전송되므로, 데이터 복사로 인한 오버헤드가 없다.
  5. 효율성(Efficiency):
    • 운영 체제와 CPU의 개입을 최소화하여 시스템 전체의 효율성을 높인다.

장점:

  1. 성능 향상: 낮은 지연 시간과 높은 대역폭으로 데이터 전송 성능을 크게 향상시킵니다.
  2. CPU 부하 감소: CPU 개입이 최소화되어 다른 작업에 더 많은 리소스를 할당할 수 있습니다.
  3. 확장성: 클러스터 및 분산 시스템에서 서버와 스토리지 장치 간 확장성이 뛰어납니다.
  4. 효율성: 운영 체제 및 중간 단계 없이 데이터를 직접 처리하여 효율성을 극대화합니다.

RDMA의 한계 및 고려사항:

  1. 네트워크 구성 복잡성: QoS(Quality of Service) 설정 및 트래픽 관리가 필요하다.
  2. 보안 문제: RDMA 트래픽에 대한 적절한 보안 조치가 필요하다.
  3. 호환성 문제: 다양한 네트워크 장치 및 프로토콜 간 호환성을 고려해야 한다.

구현 방식:

  1. InfiniBand: 고성능 컴퓨팅 환경에서 널리 사용되는 RDMA 프로토콜.
  2. RoCE(RDMA over Converged Ethernet): 이더넷 네트워크에서 RDMA를 구현한다.
  3. iWARP(Internet Wide Area RDMA Protocol): TCP/IP를 전송 계층으로 사용하여 이더넷에서 RDMA를 구현한다.

효과적으로 사용하기 위한 고려사항:

  1. 메모리 관리의 복잡성
  2. 보안 고려사항
  3. 하드웨어 지원 필요성
  4. 프로그래밍 모델의 복잡성

주요 작동 방식:

  1. 메모리 등록

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    class RDMAMemoryRegion:
        def register_memory(self, buffer):
            # 메모리 페이지를 고정(pin)하여 페이징되지 않도록 함
            self.pinned_pages = pin_memory_pages(buffer)
    
            # 메모리 영역의 가상 주소를 물리 주소로 변환
            self.physical_addresses = virtual_to_physical(self.pinned_pages)
    
            # RDMA 장치에 메모리 영역 등록
            self.rkey = rdma_device.register(self.physical_addresses)
    
            return self.rkey
    
  2. RDMA 연결 설정

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    class RDMAConnection:
        def establish_connection(self, remote_node):
            # QP(Queue Pair) 생성
            self.queue_pair = create_queue_pair()
    
            # 원격 노드와 QP 정보 교환
            remote_qp_info = exchange_qp_info(remote_node)
    
            # 연결 상태로 전환
            self.queue_pair.transition_to_rts(remote_qp_info)
    

주요 동작모드:

  1. Write 작업

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    def rdma_write(queue_pair, local_buffer, remote_address, rkey):
        # 원격 메모리에 직접 쓰기
        wr = WorkRequest(
            opcode=RDMA_WRITE,
            local_addr=local_buffer,
            remote_addr=remote_address,
            rkey=rkey,
            size=len(local_buffer)
        )
        queue_pair.post_send(wr)
    
  2. Read 작업

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    def rdma_read(queue_pair, local_buffer, remote_address, rkey):
        # 원격 메모리에서 직접 읽기
        wr = WorkRequest(
            opcode=RDMA_READ,
            local_addr=local_buffer,
            remote_addr=remote_address,
            rkey=rkey,
            size=len(local_buffer)
        )
        queue_pair.post_send(wr)
    
  3. Atomic 작업

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    def rdma_atomic_compare_and_swap(queue_pair, remote_address, 
                                    compare_value, swap_value, rkey):
        # 원자적 연산 수행
        wr = WorkRequest(
            opcode=RDMA_ATOMIC_CMP_AND_SWP,
            remote_addr=remote_address,
            compare_value=compare_value,
            swap_value=swap_value,
            rkey=rkey
        )
        queue_pair.post_send(wr)
    

전통적인 네트워크 통신과 RDMA의 차이

전통적인 네트워크 통신:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 전통적인 네트워크 통신의 의사 코드
def traditional_network_transfer(data, destination):
    # 1. 유저 공간에서 커널 공간으로 데이터 복사
    kernel_buffer = copy_to_kernel(data)
    
    # 2. 커널에서 네트워크 스택 처리
    packet = create_network_packet(kernel_buffer)
    
    # 3. 네트워크 카드로 전송
    network_card.send(packet)
    
    # 수신측에서도 비슷한 과정을 역순으로 수행
    # 많은 CPU 사이클과 컨텍스트 스위칭 발생

RDMA 통신:

1
2
3
4
5
6
7
8
# RDMA 통신의 의사 코드
def rdma_transfer(data, remote_memory_address):
    # 1. RDMA 네트워크 카드에 직접 전송 명령
    rdma_card.write_direct(
        local_buffer=data,
        remote_address=remote_memory_address
    )
    # 데이터가 CPU를 거치지 않고 직접 전송됨

RDMA의 응용 분야

RDMA를 사용할 경우 이점이 생기는 상황:

  • 대용량 데이터 전송이 필요한 경우
  • 초저지연이 요구되는 애플리케이션
  • CPU 리소스를 효율적으로 사용해야 하는 경우
  • 실시간 데이터 처리가 필요한 경우
  1. 고성능 컴퓨팅(HPC)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    
    class HPCCluster:
        def distribute_computation(self, data_chunks):
            # 각 노드에 데이터 분배
            for node, chunk in zip(self.compute_nodes, data_chunks):
                self.rdma_connections[node].write_direct(
                    chunk,
                    node.memory_address
                )
    
            # 결과 수집
            results = []
            for node in self.compute_nodes:
                result = self.rdma_connections[node].read_direct(
                    node.result_address
                )
                results.append(result)
    
  2. 데이터 센터 및 클라우드 컴퓨팅

  3. 스토리지 솔루션

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    class DistributedStorage:
        def replicate_data(self, data, replica_nodes):
            # 데이터를 여러 노드에 동시에 복제
            write_operations = []
            for node in replica_nodes:
                op = self.rdma_connections[node].async_write(
                    data,
                    node.storage_address
                )
                write_operations.append(op)
    
            # 모든 복제 완료 대기
            wait_for_completion(write_operations)
    
  4. 금융 거래 시스템

  5. 실시간 데이터 처리가 필요한 애플리케이션


용어 정리

용어설명

참고 및 출처