2017-05-01 1 views
2

크기 10,000 * 800,000의 행렬 X에 대해 Y = XX^T를 계산하려고합니다. 행렬 X는 디스크에 h5py 파일로 저장됩니다. 결과 Y는 동일한 h5py 파일에 저장된 10,000 * 10,000 행렬이어야합니다. 여기에 재현 가능한 샘플 코드가 있습니다. 코어 외 행렬 다중 스케쥴링을 단축합니다.

import dask.array as da 
from blaze import into 

into("h5py:///tmp/dummy::/X", da.ones((10**4, 8*10**5), chunks=(10**4,10**4))) 
x = into(da.Array, "h5py:///tmp/dummy::/X", chunks=(10**4,10**4))) 
y = x.dot(x.T) 
into("h5py:///tmp/dummy::/Y", y) 

I는이 계산이 개별적 전치 내적이어서하고 최종 결과를 요약한다 각 (10,000 * 10,000) 청크 원활 예상. 그러나이 계산을 실행하면 결국 프로세스가 종료 될 때까지 내 RAM과 스왑 메모리가 모두 채워집니다. //dask.pydata.org/en/latest/scheduling-policy.html 는 I 기대 : HTTP를 sheduling의 문서에 따르면 Computation graph sample

: 여기

는 연산 그래프 시료 dot_graph 플롯 상위 텐도 롭 중개 결과는 개별적으로 계산되는 즉시 하나씩 최종 합계 결과로 합산됩니다. 이것은 이러한 tensordot 중개 결과의 기억을 해방 시켜서 우리가 기억 오류에 직면하지 않을 것입니다. 작은 장난감 예와 주변 재생

:

from dask.diagnostics import Profiler, CacheProfiler, ResourceProfiler 

# Experiment on a (1,0000 * 5,000) matrix X split into 500 chunks of size (1,000 * 10) 
x = into(da.Array, "h5py:///tmp/dummy::/X", chunks=(10**3,10)))[:10**3,5000] 
y = x.T.dot(x) 
with Profiler() as prof, CacheProfiler() as cprof, ResourceProfiler() as rprof: 
    into("h5py:///tmp/dummy::/X", y) 
rprof.visualize() 

나는 다음과 같은 디스플레이 수 : Ressource profiler

노란색과 보라색 막대가 각각 대표 get_array 및 tensordot 동안 녹색 막대는 총 운전을 나타냅니다 작업. 이것은 합계 연산이 모든 중간 텐로드 연산이 합쳐지기 전에 수행 될 때까지 기다리는 것을 나타냅니다. 이것은 또한 메모리 부족으로 죽어가는 과정을 설명합니다.

그래서 제 질문은 다음과 같습니다

  • 인가 그 총 운전의 정상적인 동작?
  • 중간 텐 덴토 제품이 계산되어 메모리에 저장되기 전에 중간 합계를 계산할 수있는 방법이 있습니까?
  • 그렇지 않은 경우 디스크에 흘러 들어가는 작업과 관련없는 해결 방법이 있습니까?

많은 도움을 주셨습니다.

답변

0

일반적으로 작은 공간에서 조밀 한 행렬 - 행렬 곱셈을 수행하는 것은 어렵습니다. 이는 모든 중간 청크가 여러 출력 청크에서 사용되기 때문입니다. //dask.pydata.org/en/latest/scheduling-policy.html 내가 위 tensordot의 중간 결과는 최종 합계로 하나 하나 요약 될 기대 : HTTP를 sheduling 문서에 따르면

결과가 개별적으로 계산되자 마자 결과가 나타납니다.

표시된 그래프에는 합계 기능에 대한 많은 입력이 있습니다. Dask는 sum 함수를 실행하기 전에 모든 입력이 완료 될 때까지 대기합니다. 작업 스케줄러는 sum이 연관적이고 하나씩 실행될 수 있다는 것을 전혀 모릅니다. 이러한 의미 정보의 부족은 전용 선형 대수 라이브러리가 아니라 Dask와 같은 일반 작업 스케줄링 시스템을 사용하여 지불하는 대가입니다. 당신의 목표가 밀도가 높은 선형 대수학을 가능한 한 효율적으로 수행하는 것이라면, 다른 곳을 바라 볼 수도 있습니다. 이것은 잘 다뤄진 분야입니다.

그래서 작성된 메모리 요구 사항이 가정, 적어도8e5 * 1e4 * dtype.itemsize이다 그 (이 대부분이해야 할) 정확히 올바른 순서 DASK 진행됩니다.

당신은 시도 할 수있는 다음 :

  1. 은 비 계약 치수
  2. 사용 후 0.14.1 이상 DASK 버전 (0.14.2은 2017 년 5 월 5 일 발표한다 따라 chunksize 영역을 감소) 여기서 우리는 그래프에서 큰 총 호출을 여러 개의 작은 호출로 명시합니다.
  3. 디스크에 데이터를보다 효율적으로 기록하는 분산 스케줄러를 사용하십시오.

    from dask.distributed import Client 
    client = Client(processes=False) # create a local cluster in this process 
    
+0

덕분에 많은 @MRocklin! – Grin

+0

옵션 3에 대해서는 https://github.com/dask/distributed/issues/927에 언급 된 문제가 발생합니다. Hdf5 직렬 배열은 분산 스케줄러와 잘 작동하지 않는 것 같습니다. 이 문제를 해결하면 배포 스케줄러의 실시간 진단/모니터링 도구를 사용할 수있게되어 매우 유용합니다. 또한 pydata/python 생태계에서 특수 ooc 선형 대수 라이브러리에 대해 알고 있습니까? 원래 Numpy API와 결합 된 핵심 선형 대수학 기능 때문에 dask를 사용하기 시작했습니다. – Grin