2017-11-23 12 views
1

cupy (또는 chainer)으로 비동기식으로 메모리를 GPU로 전송할 수 있습니까?컵으로 비동기 GPU 메모리 전송

GPU 메모리에 맞지 않는 매우 큰 데이터를 가진 비교적 작은 네트워크를 교육하고 있습니다. 이 데이터는 CPU 메모리에 저장되고 GPIB에 제공되어야 미니 버스 계산이 순차적으로 수행됩니다.

메모리 전송 시간이이 응용 프로그램의 주요 병목 지점입니다. 비동기식 메모리 전송이이 문제를 해결한다고 생각합니다. 즉, 하나의 미니 바 계산 중에 , 다른 미니 바가 백그라운드에서 GPU로 전송됩니다.

나는 cupy.cuda.Stream 클래스에서 가능할 것이라고 생각하지만, 아직 잘 모른다. 모든 의견/조언을 부탁드립니다.

편집 : 다음 코드는 비동기식 메모리 전송을한다고 생각하지만 그렇지 않습니다.

import numpy as np 
import cupy as cp 

a_cpu = np.ones((10000, 10000), dtype=np.float32) 
b_cpu = np.ones((10000, 10000), dtype=np.float32) 

a_stream = cp.cuda.Stream(non_blocking=True) 
b_stream = cp.cuda.Stream(non_blocking=True) 

a_gpu = cp.empty_like(a_cpu) 
b_gpu = cp.empty_like(b_cpu) 

a_gpu.set(a_cpu, stream=a_stream) 
b_gpu.set(b_cpu, stream=b_stream) 

# This should start before b_gpu.set() is finished. 
a_gpu *= 2 

nvvp는 메모리 전송이 순차적으로 이루어지는 것을 나타냅니다.

답변

0

chainer source code으로 다이빙하여 한 가지 해결책을 찾았습니다.

np.ndarray을 구성 할 때 고정 된 메모리 버퍼를 유지하는 것처럼 보입니다.

def pinned_array(array): 
    # first constructing pinned memory 
    mem = cupy.cuda.alloc_pinned_memory(array.nbytes) 
    src = numpy.frombuffer(
       mem, array.dtype, array.size).reshape(array.shape) 
    src[...] = array 
    return src 

a_cpu = np.ones((10000, 10000), dtype=np.float32) 
b_cpu = np.ones((10000, 10000), dtype=np.float32) 
# np.ndarray with pinned memory 
a_cpu = pinned_array(a_cpu) 
b_cpu = pinned_array(b_cpu) 

a_stream = cp.cuda.Stream(non_blocking=True) 
b_stream = cp.cuda.Stream(non_blocking=True) 

a_gpu = cp.empty_like(a_cpu) 
b_gpu = cp.empty_like(b_cpu) 

a_gpu.set(a_cpu, stream=a_stream) 
b_gpu.set(b_cpu, stream=b_stream) 

# wait until a_cpu is copied in a_gpu 
a_stream.synchronize() 
# This line runs parallel to b_gpu.set() 
a_gpu *= 2