ข้อดีของ HDF5: องค์กรความยืดหยุ่นความสามารถในการทำงานร่วมกัน
ข้อดีหลักบางประการของ HDF5 คือโครงสร้างลำดับชั้น (คล้ายกับโฟลเดอร์ / ไฟล์) ข้อมูลเมตาที่เป็นทางเลือกที่จัดเก็บไว้ในแต่ละรายการและความยืดหยุ่น (เช่นการบีบอัด) โครงสร้างองค์กรและการจัดเก็บข้อมูลเมตานี้อาจฟังดูไม่สำคัญ แต่มีประโยชน์มากในทางปฏิบัติ
ข้อดีอีกอย่างของ HDF คือชุดข้อมูลสามารถมีขนาดคงที่หรือขนาดที่ยืดหยุ่นได้ ดังนั้นจึงเป็นเรื่องง่ายที่จะผนวกข้อมูลเข้ากับชุดข้อมูลขนาดใหญ่โดยไม่ต้องสร้างสำเนาใหม่ทั้งหมด
นอกจากนี้ HDF5 เป็นรูปแบบมาตรฐานที่มีไลบรารีพร้อมใช้งานสำหรับเกือบทุกภาษาดังนั้นการแชร์ข้อมูลบนดิสก์ระหว่าง Matlab, Fortran, R, C และ Python นั้นทำได้ง่ายมากเมื่อใช้ HDF (เพื่อความเป็นธรรมมันไม่ยากเกินไปกับอาร์เรย์ไบนารีขนาดใหญ่เช่นกันตราบใดที่คุณทราบถึงลำดับ C เทียบกับ F และรู้จักรูปร่างประเภท d และอื่น ๆ ของอาร์เรย์ที่เก็บไว้)
ข้อดีของ HDF สำหรับอาร์เรย์ขนาดใหญ่: I / O ที่เร็วขึ้นของชิ้นส่วนตามอำเภอใจ
เช่นเดียวกับ TL / DR:สำหรับอาร์เรย์ 3 มิติ ~ 8GB การอ่านชิ้นส่วน "เต็ม" ตามแกนใด ๆ ใช้เวลาประมาณ 20 วินาทีโดยใช้ชุดข้อมูล HDF5 แบบรวมและ 0.3 วินาที (กรณีที่ดีที่สุด) ถึงมากกว่าสามชั่วโมง (กรณีที่แย่ที่สุด) สำหรับ อาร์เรย์ memmapped ของข้อมูลเดียวกัน
นอกเหนือจากสิ่งที่ระบุไว้ข้างต้นแล้วยังมีข้อได้เปรียบอีกอย่างหนึ่งสำหรับรูปแบบข้อมูลบนดิสก์ที่ "เป็นก้อน" * เช่น HDF5: การอ่านชิ้นส่วนตามอำเภอใจ (เน้นตามอำเภอใจ) โดยทั่วไปจะเร็วกว่ามากเนื่องจากข้อมูลในดิสก์จะติดกันมากกว่า เฉลี่ย.
*
(HDF5 ไม่จำเป็นต้องเป็นรูปแบบข้อมูลที่แยกh5py
เป็นก้อนรองรับการแบ่งเป็นกลุ่ม แต่ไม่จำเป็นต้องใช้อันที่จริงค่าเริ่มต้นสำหรับการสร้างชุดข้อมูลในนั้นไม่ได้เป็นแบบก้อนถ้าฉันจำได้ถูกต้อง)
โดยพื้นฐานแล้วความเร็วในการอ่านดิสก์กรณีที่ดีที่สุดและความเร็วในการอ่านดิสก์กรณีที่เลวร้ายที่สุดของคุณสำหรับชุดข้อมูลที่กำหนดจะค่อนข้างใกล้เคียงกับชุดข้อมูล HDF ที่แยกเป็นชิ้น ๆ (สมมติว่าคุณเลือกขนาดก้อนที่เหมาะสมหรือให้ไลบรารีเลือกให้คุณ) กับอาร์เรย์ไบนารีง่ายๆกรณีที่ดีที่สุดคือการได้เร็วขึ้น แต่ที่เลวร้ายที่สุดกรณีที่เป็นมากที่เลวร้ายยิ่ง
ข้อแม้อย่างหนึ่งหากคุณมี SSD คุณอาจไม่สังเกตเห็นความแตกต่างอย่างมากในความเร็วในการอ่าน / เขียน ด้วยฮาร์ดไดรฟ์ปกติการอ่านตามลำดับจะเร็วกว่าการอ่านแบบสุ่มมาก (เช่นฮาร์ดไดรฟ์ปกติใช้seek
เวลานาน) HDF ยังคงมีข้อได้เปรียบใน SSD แต่เนื่องจากคุณสมบัติอื่น ๆ (เช่นข้อมูลเมตาองค์กร ฯลฯ ) มากกว่าเนื่องจากความเร็วดิบ
ก่อนอื่นเพื่อล้างความสับสนการเข้าถึงh5py
ชุดข้อมูลจะส่งคืนอ็อบเจ็กต์ที่ทำงานค่อนข้างคล้ายกับอาร์เรย์ numpy แต่จะไม่โหลดข้อมูลลงในหน่วยความจำจนกว่าจะถูกแบ่งส่วน (คล้ายกับ memmap แต่ไม่เหมือนกัน) ดูข้อมูลเพิ่มเติมได้ที่h5py
บทนำ
การแบ่งชุดข้อมูลจะโหลดข้อมูลส่วนย่อยลงในหน่วยความจำ แต่คุณคงต้องการทำอะไรบางอย่างกับมันซึ่ง ณ จุดนี้คุณจะต้องใช้มันในหน่วยความจำอยู่ดี
หากคุณไม่ต้องการที่จะทำออกจากการคำนวณหลักคุณสามารถค่อนข้างง่ายสำหรับตารางข้อมูลด้วยหรือpandas
pytables
เป็นไปได้ด้วยh5py
(ดีกว่าสำหรับอาร์เรย์ ND ขนาดใหญ่) แต่คุณต้องเลื่อนลงไปแตะที่ระดับล่างและจัดการการวนซ้ำด้วยตัวเอง
อย่างไรก็ตามอนาคตของการคำนวณนอกคอร์ที่ไม่เหมือนใครก็คือ Blaze ลองดูสิถ้าคุณต้องการใช้เส้นทางนั้นจริงๆ
กรณี "unchunked"
ก่อนอื่นให้พิจารณาอาร์เรย์ที่สั่งซื้อ 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
ดำเนินการจะเพิ่มขึ้นอย่างรวดเร็ว สำหรับอาร์เรย์ 3 มิติขนาดใหญ่ (~ 10Gb) ที่จัดเก็บด้วยวิธีนี้และอ่านผ่านmemmap
การอ่านส่วนเต็มตามแกนที่ "แย่ที่สุด" อาจใช้เวลาหลายสิบนาทีได้อย่างง่ายดายแม้จะใช้ฮาร์ดแวร์ที่ทันสมัยก็ตาม ในขณะเดียวกันชิ้นงานตามแกนที่ดีที่สุดอาจใช้เวลาน้อยกว่าหนึ่งวินาที เพื่อความง่ายฉันจะแสดงเฉพาะส่วน "เต็ม" ตามแกนเดียว แต่สิ่งเดียวกันนี้เกิดขึ้นกับชิ้นส่วนย่อยของข้อมูลใด ๆ โดยพลการ
บังเอิญมีรูปแบบไฟล์หลายรูปแบบที่ใช้ประโยชน์จากสิ่งนี้และโดยทั่วไปแล้วจะจัดเก็บสำเนาของอาร์เรย์ 3 มิติขนาดใหญ่ไว้ในดิสก์สามชุด: หนึ่งในลำดับ C หนึ่งในลำดับ F และอีกหนึ่งรายการอยู่ตรงกลางระหว่างสอง (ตัวอย่างนี้คือรูปแบบ D3D ของ Geoprobe แม้ว่าฉันจะไม่แน่ใจว่ามีการบันทึกไว้ที่ใดก็ตาม) ใครจะสนใจว่าขนาดไฟล์สุดท้ายคือ 4TB พื้นที่เก็บข้อมูลก็ถูก! สิ่งที่บ้าเกี่ยวกับเรื่องนี้ก็คือเนื่องจากกรณีการใช้งานหลักกำลังแยกชิ้นส่วนย่อยเดียวในแต่ละทิศทางการอ่านที่คุณต้องการทำนั้นรวดเร็วมาก ได้ผลดีมาก!
กรณี "ก้อน" ที่เรียบง่าย
สมมติว่าเราจัดเก็บ "ชิ้น" 2x2x2 ของอาร์เรย์ 3 มิติเป็นบล็อกที่ต่อเนื่องกันบนดิสก์ กล่าวอีกนัยหนึ่งเช่น:
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 ชิ้นที่ต่อเนื่องกัน (ข้อมูลมากเป็นสองเท่าที่เราต้องการ) จากนั้นเก็บเฉพาะส่วนที่เราต้องการ นั่นเป็นกรณีที่เลวร้ายที่สุดสูงสุด 9 การค้นหาเทียบกับสูงสุด 36 การค้นหาสำหรับเวอร์ชันที่ไม่เป็นกลุ่ม (แต่กรณีที่ดีที่สุดยังคงเป็น 6 Seeks vs 1 สำหรับอาร์เรย์ memmapped) เนื่องจากการอ่านตามลำดับนั้นเร็วมากเมื่อเทียบกับการค้นหาจึงช่วยลดระยะเวลาที่ใช้ในการอ่านชุดย่อยโดยพลการลงในหน่วยความจำได้อย่างมาก อีกครั้งเอฟเฟกต์นี้จะใหญ่ขึ้นด้วยอาร์เรย์ที่ใหญ่ขึ้น
HDF5 ก้าวไปอีกไม่กี่ก้าว ไม่จำเป็นต้องจัดเก็บชิ้นส่วนให้ติดกันและถูกจัดทำดัชนีโดย B-Tree นอกจากนี้พวกเขาไม่จำเป็นต้องมีขนาดเท่ากันบนดิสก์ดังนั้นจึงสามารถใช้การบีบอัดกับแต่ละชิ้นได้
อาร์เรย์แบบก้อนที่มี 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 แบบก้อนและอาร์เรย์ 3 มิติขนาดใหญ่ (~ 8GB) ที่สั่งโดย Fortran ซึ่งมีข้อมูลที่ตรงกันทั้งหมด
ฉันได้ล้างแคช OS ทั้งหมดระหว่างการรันแต่ละครั้งดังนั้นเราจึงเห็นประสิทธิภาพ "เย็น"
สำหรับไฟล์แต่ละประเภทเราจะทดสอบการอ่านแบบ x-slice "เต็ม" ตามแกนแรกและสไลซ์ z "เต็ม" ตามแกนสุดท้าย สำหรับอาร์เรย์ memmapped ที่สั่งซื้อโดย Fortran สไลซ์ "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-slice "เต็ม" และ z-slice "เต็ม" ใช้เวลาประมาณเท่ากัน (~ 20 วินาที) เมื่อพิจารณาว่านี่เป็นอาร์เรย์ 8GB ก็ไม่เลวนัก เวลาส่วนใหญ่
และถ้าเราเปรียบเทียบสิ่งนี้กับเวลาอาร์เรย์ที่มีเมมแมป (มันเป็นคำสั่งของ Fortran: A "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 slice จะเป็นกรณีของอาร์เรย์ที่สั่งซื้อด้วย C)
อย่างไรก็ตามหากเราต้องการแบ่งส่วนตามทิศทางกรณีที่ดีที่สุดอยู่เสมออาร์เรย์ไบนารีขนาดใหญ่บนดิสก์จะดีมาก (~ 0.3 วินาที!)
ด้วยอาร์เรย์แบบเมมแมปคุณจะติดอยู่กับความคลาดเคลื่อนของ I / O นี้ (หรือบางที anisotropy เป็นคำที่ดีกว่า) อย่างไรก็ตามด้วยชุดข้อมูล HDF แบบแยกส่วนคุณสามารถเลือกขนาดชิ้นเพื่อให้การเข้าถึงเท่ากันหรือปรับให้เหมาะสมกับกรณีการใช้งานเฉพาะ ช่วยให้คุณมีความยืดหยุ่นมากขึ้น
สรุป
หวังว่าจะช่วยให้ส่วนหนึ่งของคำถามของคุณกระจ่างขึ้นไม่ว่าในกรณีใด ๆ HDF5 มีข้อได้เปรียบอื่น ๆ มากมายเหนือ memmaps "ดิบ" แต่ฉันไม่มีที่ว่างให้ขยายทั้งหมดที่นี่ การบีบอัดอาจทำให้บางอย่างเร็วขึ้น (ข้อมูลที่ฉันใช้ไม่ได้รับประโยชน์มากนักจากการบีบอัดดังนั้นฉันจึงไม่ค่อยได้ใช้) และการแคชระดับ OS มักเล่นกับไฟล์ HDF5 ได้ดีกว่าเมมแมป "ดิบ" นอกจากนั้น HDF5 ยังเป็นรูปแบบคอนเทนเนอร์ที่ยอดเยี่ยมจริงๆ ช่วยให้คุณมีความยืดหยุ่นอย่างมากในการจัดการข้อมูลของคุณและสามารถใช้งานได้จากภาษาโปรแกรมใด ๆ ไม่มากก็น้อย
โดยรวมแล้วลองดูว่าใช้ได้ดีกับกรณีการใช้งานของคุณหรือไม่ ฉันคิดว่าคุณอาจจะแปลกใจ
h5py
pytables
ยังh5py
ไม่ได้กลับ numpy อาร์เรย์ในหน่วยความจำ แต่จะส่งคืนสิ่งที่ทำหน้าที่เหมือน แต่ไม่ได้โหลดลงในหน่วยความจำ (คล้ายกับmemmapped
อาร์เรย์) ฉันกำลังเขียนคำตอบที่สมบูรณ์กว่านี้ (อาจจะยังไม่จบ) แต่หวังว่าความคิดเห็นนี้จะช่วยได้เล็กน้อยในระหว่างนี้