대용량 어레이 스토리지 (플랫 바이너리 파일 대신)에 HDF5를 사용하면 분석 속도 또는 메모리 사용 이점이 있습니까?


96

다양한 데이터 분석을 수행하기 위해 다양한 방법으로 슬라이스해야하는 경우가 많은 대형 3D 어레이를 처리하고 있습니다. 일반적인 "큐브"는 ~ 100GB 일 수 있습니다 (향후 더 커질 수 있음).

파이썬의 대규모 데이터 세트에 대한 일반적인 권장 파일 형식은 HDF5 (h5py 또는 pytables)를 사용하는 것 같습니다. 내 질문은 : HDF5를 사용하여 이러한 큐브를 단순한 플랫 바이너리 파일에 저장하는 것보다 저장 및 분석하는 데 속도 나 메모리 사용 이점이 있습니까? HDF5는 내가 작업하는 것과 같은 대형 어레이와 달리 테이블 형식 데이터에 더 적합합니까? HDF5가 좋은 압축을 제공 할 수 있지만 처리 속도와 메모리 오버플로 처리에 더 관심이 있습니다.

나는 종종 큐브의 큰 하위 집합을 하나만 분석하고 싶습니다. pytables와 h5py의 한 가지 단점은 배열의 한 조각을 가져 오면 항상 메모리를 사용하여 numpy 배열을 다시 얻는다는 것입니다. 그러나 플랫 바이너리 파일의 numpy memmap을 슬라이스하면 데이터를 디스크에 보관하는 뷰를 얻을 수 있습니다. 따라서 내 데이터의 특정 섹터를 메모리를 초과하지 않고 더 쉽게 분석 할 수있는 것 같습니다.

나는 pytables와 h5py를 모두 탐색했으며 지금까지 내 목적을 위해 어느 쪽의 이점도 보지 못했습니다.


1
HDF는 "청크"파일 형식입니다. 평균적으로 데이터 세트의 임의 조각에 대해 훨씬 더 빠른 읽기를 제공합니다. memmap은 빠른 최선의 경우이지만 매우 느린 최악의 경우를 갖습니다. h5py보다 귀하의 데이터 세트에 더 적합합니다 pytables. 또한 메모리 내 numpy 배열을 반환 h5py하지 않습니다 . 대신 하나처럼 동작하지만 메모리에로드되지 않는 무언가를 반환합니다 ( memmapped배열 과 유사 ). 나는 더 완전한 답변을 작성하고 있지만 (완료하지 않을 수도 있음) 그 동안이 의견이 약간 도움이되기를 바랍니다.
Joe Kington 2014

감사. h5py가 memmap과 유사한 데이터 세트를 반환한다는 데 동의합니다. 그러나 h5py 데이터 세트의 조각을 수행하면 numpy 배열이 반환됩니다. 이는 (?) 데이터가 불필요하게 메모리에 저장되었음을 의미합니다. memmamp는 가능한 경우 원래 memmap에 대한 뷰를 반환합니다. 즉 : type(cube)제공합니다 h5py._hl.dataset.Dataset. 동안 type(cube[0:1,:,:])제공합니다 numpy.ndarray.
Caleb

그러나 평균 읽기 시간에 대한 귀하의 요점은 흥미 롭습니다.
케일럽

4
I / O 병목 현상이있는 경우 많은 경우에 압축은 실제로 읽기 / 쓰기 성능을 향상시킬 수 있습니다 (특히 BLOSC 및 LZO와 같은 빠른 압축 라이브러리 사용). 일부 추가 CPU주기 비용으로 필요한 I / O 대역폭을 줄이기 때문입니다. . PyTables HDF5 파일을 사용하여 읽기-쓰기 성능을 최적화하는 방법에 대한 많은 정보가있는 이 페이지를 참조 할 수 있습니다 .
ali_m

2
"플랫 바이너리 파일의 numpy memmap을 슬라이스하면 데이터를 디스크에 보관하는 뷰를 얻을 수 있습니다."-사실 일 수 있지만 실제로 해당 배열의 값 으로 작업수행 하려는 경우 조만간 RAM에로드해야합니다. 메모리 매핑 배열은 일부 캡슐화 만 제공하므로 데이터를 정확히 언제 읽었는지 또는 시스템 메모리 용량을 초과할지 여부를 생각할 필요가 없습니다. 어떤 상황에서는 멤마 배열의 네이티브 캐싱 동작이 실제로 매우 차선책 일 수 있습니다 .
ali_m 2014

답변:


159

HDF5 장점 : 조직, 유연성, 상호 운용성

HDF5의 주요 장점 중 일부는 계층 구조 (폴더 / 파일과 유사), 각 항목에 저장된 선택적 임의 메타 데이터 및 유연성 (예 : 압축)입니다. 이 조직 구조와 메타 데이터 저장은 사소하게 들릴 수 있지만 실제로는 매우 유용합니다.

HDF의 또 다른 장점은 데이터 세트가 고정 크기 이거나 유연한 크기 일 입니다. 따라서 전체 새 사본을 만들지 않고도 대규모 데이터 세트에 데이터를 쉽게 추가 할 수 있습니다.

또한 HDF5는 거의 모든 언어에 사용할 수있는 라이브러리가 포함 된 표준화 된 형식이므로 Matlab, Fortran, R, C 및 Python간에 디스크상의 데이터를 공유하는 것은 HDF를 사용하여 매우 쉽습니다. (공정하게 말하면, C 대 F 순서를 알고 저장된 배열의 모양, dtype 등을 알고있는 한 큰 이진 배열도 너무 어렵지 않습니다.)

대형 어레이를위한 HDF 이점 : 임의 슬라이스의 더 빠른 I / O

TL / DR과 마찬가지로 : ~ 8GB 3D 어레이의 경우 모든 축을 따라 "전체"슬라이스를 읽는 데 청크 된 HDF5 데이터 세트의 경우 약 20 초가 걸렸고, 0.3 초 ​​(최상의 경우)에서 3 시간 이상 (최악의 경우)이 소요 되었습니다. 동일한 데이터의 memmapped 배열.

위에 나열된 것 외에도 HDF5와 같은 "청크"* 온 디스크 데이터 형식에는 또 다른 큰 이점이 있습니다. 디스크상의 데이터가 더 연속적이기 때문에 임의 슬라이스 (임의에 중점)를 읽는 것이 일반적으로 훨씬 빠릅니다. 평균.

*(HDF5는 청크 데이터 형식 일 필요는 없습니다. 청크를 지원하지만 필요하지 않습니다. 실제로 데이터 세트를 생성하는 기본값은 h5py제가 올바르게 기억하면 청크가 아닙니다.)

기본적으로 데이터 세트의 특정 슬라이스에 대한 최상의 디스크 읽기 속도와 최악의 디스크 읽기 속도는 청크 된 HDF 데이터 세트와 상당히 비슷합니다 (적절한 청크 크기를 선택하거나 라이브러리에서 대신 선택하도록 가정). 간단한 이진 배열을 사용하면 최상의 경우가 더 빠르지 만 최악의 경우는 훨씬 더 나쁩니다.

한 가지주의 할 점은 SSD가 있다면 읽기 / 쓰기 속도에 큰 차이를 느끼지 못할 것입니다. 그러나 일반 하드 드라이브에서는 순차적 읽기가 임의 읽기보다 훨씬 빠릅니다. (예 : 일반 하드 드라이브는 seek시간 이 오래 걸립니다.) HDF는 여전히 SSD에서 장점이 있지만 원시 속도보다는 다른 기능 (예 : 메타 데이터, 구성 등) 때문입니다.


먼저 혼란을 없애기 위해 h5py데이터 세트에 액세스하면 numpy 배열과 상당히 유사하게 작동하지만 슬라이스 될 때까지 데이터를 메모리로로드하지 않는 객체가 반환됩니다. (memmap과 유사하지만 동일하지는 않습니다.) 자세한 내용 은 h5py소개 를 참조하십시오.

데이터 세트를 슬라이스하면 데이터의 하위 집합이 메모리에로드되지만, 아마도이를 사용하여 무언가를하고 싶을 것입니다. 그 시점에서 어쨌든 메모리에 필요합니다.

당신이 밖으로의 핵심 계산을 수행 할 경우, 당신은 비교적 쉽게와 테이블 형식의 데이터에 대한 수 pandas또는 pytables. 그것은 가능합니다 h5py(큰 ND 배열에 대한 좋네요),하지만 당신은 자신을 터치 낮은 수준 아래로 삭제하고 반복을 처리해야합니다.

그러나 numpy와 같은 out-of-core 계산의 미래는 Blaze입니다. 정말로 그 길을 가고 싶다면 그것을보십시오 .


"단순한"사건

먼저 디스크에 기록 된 3D C 순서 배열을 고려합니다 ( arr.ravel()결과를 더 잘 보이게 만들기 위해 결과 를 호출 하고 인쇄하여 시뮬레이션하겠습니다 ).

In [1]: import numpy as np

In [2]: arr = np.arange(4*6*6).reshape(4,6,6)

In [3]: arr
Out[3]:
array([[[  0,   1,   2,   3,   4,   5],
        [  6,   7,   8,   9,  10,  11],
        [ 12,  13,  14,  15,  16,  17],
        [ 18,  19,  20,  21,  22,  23],
        [ 24,  25,  26,  27,  28,  29],
        [ 30,  31,  32,  33,  34,  35]],

       [[ 36,  37,  38,  39,  40,  41],
        [ 42,  43,  44,  45,  46,  47],
        [ 48,  49,  50,  51,  52,  53],
        [ 54,  55,  56,  57,  58,  59],
        [ 60,  61,  62,  63,  64,  65],
        [ 66,  67,  68,  69,  70,  71]],

       [[ 72,  73,  74,  75,  76,  77],
        [ 78,  79,  80,  81,  82,  83],
        [ 84,  85,  86,  87,  88,  89],
        [ 90,  91,  92,  93,  94,  95],
        [ 96,  97,  98,  99, 100, 101],
        [102, 103, 104, 105, 106, 107]],

       [[108, 109, 110, 111, 112, 113],
        [114, 115, 116, 117, 118, 119],
        [120, 121, 122, 123, 124, 125],
        [126, 127, 128, 129, 130, 131],
        [132, 133, 134, 135, 136, 137],
        [138, 139, 140, 141, 142, 143]]])

값은 아래 4 행에 표시된대로 디스크에 순차적으로 저장됩니다. (지금은 파일 시스템 세부 정보와 조각화를 무시하겠습니다.)

In [4]: arr.ravel(order='C')
Out[4]:
array([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
        13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
        26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
        39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,
        52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
        65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,
        78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
        91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103,
       104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
       117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
       130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143])

최상의 시나리오에서 첫 번째 축을 따라 슬라이스를 취해 보겠습니다. 이것들은 배열의 처음 36 개 값에 불과합니다. 이것은 매우 빨리 읽을 것입니다! (하나의 검색, 하나의 읽기)

In [5]: arr[0,:,:]
Out[5]:
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23],
       [24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35]])

마찬가지로 첫 번째 축의 다음 슬라이스는 다음 36 개의 값이됩니다. 이 축을 따라 전체 슬라이스를 읽으려면 하나의 seek작업 만 필요 합니다. 우리가 읽을 모든 것이이 축을 따라 다양한 슬라이스라면, 이것이 완벽한 파일 구조입니다.

그러나 최악의 시나리오 인 마지막 축을 따른 슬라이스를 고려해 보겠습니다.

In [6]: arr[:,:,0]
Out[6]:
array([[  0,   6,  12,  18,  24,  30],
       [ 36,  42,  48,  54,  60,  66],
       [ 72,  78,  84,  90,  96, 102],
       [108, 114, 120, 126, 132, 138]])

이 슬라이스를 읽으려면 모든 값이 디스크에서 분리되어 있으므로 36 개의 검색과 36 개의 읽기가 필요합니다. 그들 중 누구도 인접하지 않습니다!

이것은 매우 사소한 것처럼 보일 수 있지만 더 크고 더 큰 어레이에 도달함에 따라 seek작업 의 수와 크기가 빠르게 증가합니다. 이런 방식으로 저장되고 다음을 통해 읽는 대규모 (~ 10Gb) 3D 어레이의 경우memmap 읽는 경우 "최악의"축을 따라 전체 슬라이스를 읽는 데는 최신 하드웨어를 사용하더라도 수십 분이 걸릴 수 있습니다. 동시에 최상의 축을 따라 슬라이스하는 데 1 초도 걸리지 않습니다. 단순화를 위해 단일 축을 따라 "전체"슬라이스 만 표시하지만 데이터 하위 집합의 임의 슬라이스에서도 똑같은 일이 발생합니다.

우연히도 이것을 활용하고 기본적으로 디스크 에 거대한 3D 어레이 의 세 복사본을 저장하는 여러 파일 형식이 있습니다 . 하나는 C 순서, 하나는 F 순서, 하나는 둘 사이의 중간에 있습니다. (이의 예는 Geoprobe의 D3D 형식이지만 어디에도 문서화되어 있는지는 모르겠습니다.) 최종 파일 크기가 4TB이면 누가 신경 쓰는지, 저장 용량은 저렴합니다! 그것에 대한 미친 점은 주요 사용 사례가 각 방향으로 단일 하위 슬라이스를 추출하는 것이므로 작성하려는 읽기가 매우 빠르다는 것입니다. 아주 잘 작동합니다!


간단한 "청크"케이스

3D 배열의 2x2x2 "청크"를 디스크에 연속 블록으로 저장한다고 가정 해 보겠습니다. 즉, 다음과 같습니다.

nx, ny, nz = arr.shape
slices = []
for i in range(0, nx, 2):
    for j in range(0, ny, 2):
        for k in range(0, nz, 2):
            slices.append((slice(i, i+2), slice(j, j+2), slice(k, k+2)))

chunked = np.hstack([arr[chunk].ravel() for chunk in slices])

따라서 디스크의 데이터는 다음과 같습니다 chunked.

array([  0,   1,   6,   7,  36,  37,  42,  43,   2,   3,   8,   9,  38,
        39,  44,  45,   4,   5,  10,  11,  40,  41,  46,  47,  12,  13,
        18,  19,  48,  49,  54,  55,  14,  15,  20,  21,  50,  51,  56,
        57,  16,  17,  22,  23,  52,  53,  58,  59,  24,  25,  30,  31,
        60,  61,  66,  67,  26,  27,  32,  33,  62,  63,  68,  69,  28,
        29,  34,  35,  64,  65,  70,  71,  72,  73,  78,  79, 108, 109,
       114, 115,  74,  75,  80,  81, 110, 111, 116, 117,  76,  77,  82,
        83, 112, 113, 118, 119,  84,  85,  90,  91, 120, 121, 126, 127,
        86,  87,  92,  93, 122, 123, 128, 129,  88,  89,  94,  95, 124,
       125, 130, 131,  96,  97, 102, 103, 132, 133, 138, 139,  98,  99,
       104, 105, 134, 135, 140, 141, 100, 101, 106, 107, 136, 137, 142, 143])

그리고 그것들이의 2x2x2 블록이라는 것을 보여주기 위해 arr, 이것들이 다음의 처음 8 개 값임을 주목하십시오 chunked:

In [9]: arr[:2, :2, :2]
Out[9]:
array([[[ 0,  1],
        [ 6,  7]],

       [[36, 37],
        [42, 43]]])

축을 따라 슬라이스를 읽기 위해 6 개 또는 9 개의 연속 된 청크 (필요한 데이터의 두 배)를 읽은 다음 원하는 부분 만 유지합니다. 이는 청크되지 않은 버전의 경우 최대 36 개의 검색에 비해 최악의 경우 최대 9 개의 검색입니다. (그러나 가장 좋은 경우는 여전히 memmapped 배열의 경우 6 개의 검색 대 1입니다.) 순차 읽기는 검색에 비해 매우 빠르기 때문에 임의의 하위 집합을 메모리로 읽는 데 걸리는 시간을 크게 줄입니다. 다시 한 번,이 효과는 배열이 클수록 더 커집니다.

HDF5는이를 몇 단계 더 발전시킵니다. 청크는 연속적으로 저장할 필요가 없으며 B- 트리에 의해 인덱싱됩니다. 또한 디스크에서 동일한 크기 일 필요가 없으므로 각 청크에 압축을 적용 할 수 있습니다.


청크 배열 h5py

기본적 h5py으로 디스크에 청크 HDF 파일을 만들지 않습니다 ( pytables반대로 그렇다고 생각합니다 ). chunks=True그러나 데이터 세트를 생성 할 때 지정 하면 디스크에 청크 배열이 생성됩니다.

빠르고 최소한의 예로서 :

import numpy as np
import h5py

data = np.random.random((100, 100, 100))

with h5py.File('test.hdf', 'w') as outfile:
    dset = outfile.create_dataset('a_descriptive_name', data=data, chunks=True)
    dset.attrs['some key'] = 'Did you want some metadata?'

참고 chunks=True알려줍니다 h5py자동으로 우리를 위해 청크 크기를 선택 할 수 있습니다. 가장 일반적인 사용 사례에 대해 더 많이 알고 있다면 모양 튜플을 지정하여 청크 크기 / 모양을 최적화 할 수 있습니다 (예 : (2,2,2)위의 간단한 예제). 이를 통해 특정 축을 따라 읽기를보다 효율적으로 수행하거나 특정 크기의 읽기 / 쓰기를 최적화 할 수 있습니다.


I / O 성능 비교

요점을 강조하기 위해 청크 된 HDF5 데이터 세트와 동일한 정확한 데이터를 포함하는 대형 (~ 8GB) Fortran 순서 3D 배열의 조각 읽기를 비교해 보겠습니다.

내가 한 모든 OS 캐시 삭제 우리는 "콜드"성능을보고하고 있으므로, 각 실행 사이를.

각 파일 유형에 대해 첫 번째 축을 따라 "전체"x- 슬라이스 및 마지막 축을 따라 "전체"z- 슬라이스에서 읽기를 테스트합니다. Fortran에서 정렬 된 memmapped 배열의 경우 "x"슬라이스가 최악의 경우이고 "z"슬라이스가 최상의 경우입니다.

사용 된 코드 는 요점에 있습니다 ( hdf파일 생성 포함 ). 여기에 사용 된 데이터를 쉽게 공유 할 수는 없지만 동일한 모양 ( 621, 4991, 2600)및 유형 np.uint8.

chunked_hdf.py다음과 같다 :

import sys
import h5py

def main():
    data = read()

    if sys.argv[1] == 'x':
        x_slice(data)
    elif sys.argv[1] == 'z':
        z_slice(data)

def read():
    f = h5py.File('/tmp/test.hdf5', 'r')
    return f['seismic_volume']

def z_slice(data):
    return data[:,:,0]

def x_slice(data):
    return data[0,:,:]

main()

memmapped_array.py유사하지만 슬라이스가 실제로 메모리에로드되도록하기 위해 좀 더 복잡합니다 (기본적으로 다른 memmapped배열이 반환되며 이는 사과 간 비교가 아닙니다).

import numpy as np
import sys

def main():
    data = read()

    if sys.argv[1] == 'x':
        x_slice(data)
    elif sys.argv[1] == 'z':
        z_slice(data)

def read():
    big_binary_filename = '/data/nankai/data/Volumes/kumdep01_flipY.3dv.vol'
    shape = 621, 4991, 2600
    header_len = 3072

    data = np.memmap(filename=big_binary_filename, mode='r', offset=header_len,
                     order='F', shape=shape, dtype=np.uint8)
    return data

def z_slice(data):
    dat = np.empty(data.shape[:2], dtype=data.dtype)
    dat[:] = data[:,:,0]
    return dat

def x_slice(data):
    dat = np.empty(data.shape[1:], dtype=data.dtype)
    dat[:] = data[0,:,:]
    return dat

main()

먼저 HDF 성능을 살펴 보겠습니다.

jofer at cornbread in ~ 
$ sudo ./clear_cache.sh

jofer at cornbread in ~ 
$ time python chunked_hdf.py z
python chunked_hdf.py z  0.64s user 0.28s system 3% cpu 23.800 total

jofer at cornbread in ~ 
$ sudo ./clear_cache.sh

jofer at cornbread in ~ 
$ time python chunked_hdf.py x
python chunked_hdf.py x  0.12s user 0.30s system 1% cpu 21.856 total

"전체"x- 슬라이스와 "전체"z- 슬라이스는 거의 동일한 시간 (~ 20 초)이 걸립니다. 이것이 8GB 어레이라는 점을 고려하면 그리 나쁘지 않습니다. 대부분의 경우

그리고 이것을 memmapped 배열 시간과 비교하면 (Fortran 순서입니다. "z-slice"가 가장 좋은 경우이고 "x-slice"가 가장 나쁜 경우입니다.)

jofer at cornbread in ~ 
$ sudo ./clear_cache.sh

jofer at cornbread in ~ 
$ time python memmapped_array.py z
python memmapped_array.py z  0.07s user 0.04s system 28% cpu 0.385 total

jofer at cornbread in ~ 
$ sudo ./clear_cache.sh

jofer at cornbread in ~ 
$ time python memmapped_array.py x
python memmapped_array.py x  2.46s user 37.24s system 0% cpu 3:35:26.85 total

예, 당신은 그 권리를 읽었습니다. 한 슬라이스 방향으로 0.3 초, 다른 슬라이스 방향으로 ~ 3.5 시간 .

"x"방향으로 슬라이스하는 시간 은 전체 8GB 어레이를 메모리에로드하고 원하는 슬라이스를 선택하는 데 걸리는 시간보다 훨씬 깁니다! (다시 말하지만, 이것은 Fortran 순서 배열입니다. 반대 x / z 슬라이스 타이밍은 C 순서 배열의 경우입니다.)

그러나 항상 최선의 방향으로 슬라이스를 취하고 싶다면 디스크의 큰 바이너리 배열이 매우 좋습니다. (~ 0.3 초!)

memmapped 어레이를 사용하면이 I / O 불일치가 발생합니다 (또는 이방성이 더 나은 용어 일 수 있음). 그러나 청크 된 HDF 데이터 세트를 사용하면 액세스가 동일하거나 특정 사용 사례에 최적화되도록 청크 크기를 선택할 수 있습니다. 훨씬 더 많은 유연성을 제공합니다.

요약해서 말하자면

어쨌든 이것이 질문의 한 부분을 해결하는 데 도움이되기를 바랍니다. HDF5는 "원시"memmap에 비해 다른 많은 장점이 있지만 여기에서는 모두 확장 할 여지가 없습니다. 압축은 일부 작업의 속도를 높일 수 있으며 (내가 작업하는 데이터는 압축의 이점이별로 없기 때문에 거의 사용하지 않습니다.) OS 수준 캐싱은 "원시"memmap보다 HDF5 파일에서 더 잘 재생되는 경우가 많습니다. 그 외에도 HDF5는 정말 환상적인 컨테이너 형식입니다. 데이터 관리에 많은 유연성을 제공하며 어느 프로그래밍 언어에서나 사용할 수 있습니다.

전반적으로 시도해보고 사용 사례에 잘 맞는지 확인하십시오. 깜짝 놀랄 것 같아요.


3
좋은 대답입니다. 청킹 레이아웃을 일반적인 데이터 액세스 패턴에 맞게 사용자 지정할 수 있다는 점을 추가하고 싶습니다. 액세스 패턴에 상당히 예측 가능한 스텐실 크기가있는 경우 일반적으로 항상 최적에 가까운 속도를 달성하기 위해 청킹을 선택할 수 있습니다.
Eelco Hoogendoorn

2
좋은 대답입니다! 청크에 대해 언급되지 않은 한 가지는 청크 캐시의 효과입니다. 각 열린 데이터 세트에는 자체 청크 캐시가 있으며 기본 크기는 1MB이며 C에서 H5Pset_chunk_cache ()를 사용하여 조정할 수 있습니다. 일반적으로 액세스 패턴을 고려할 때 메모리에 유지할 수있는 청크 수를 고려하는 것이 유용합니다. 예를 들어 캐시가 8 개의 청크를 보유 할 수 있고 데이터 세트가 스캔 방향으로 10 개의 청크 인 경우 많은 스 래시가 발생하고 성능이 끔찍할 것입니다.
Dana Robinson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.