Berkas data modern mudah melampaui memori kerja komputer: rekaman sensor berbulan-bulan, dataset citra, atau hasil simulasi berukuran gigabyte. Pendekatan biasa — np.fromfile atau np.load — memuat seluruh berkas ke RAM sebelum satu nilai pun bisa dipakai. NumPy menyediakan jalan lain: memory-mapped array, array yang isinya dipetakan langsung ke berkas di disk, sehingga sistem operasi hanya membaca bagian yang benar-benar diakses.

Konstruktor np.memmap menghasilkan ndarray biasa dari sisi pemakaian — diindeks, di-slice, dijumlahkan — tetapi penyimpanannya berada di berkas, bukan di RAM penuh. Bab ini membahas empat mode pembukaannya beserta pola penulisan yang aman.

Membuat dan Membaca memmap #

np.memmap membutuhkan dtype dan shape secara eksplisit, karena berkas biner mentah tidak menyimpan metadata. Mode w+ membuat berkas baru (atau mengosongkan yang ada); setelah diisi, berkas yang sama dapat dibuka dari proses atau sesi lain dengan mode r:

python
import numpy as np

m = np.memmap("besar.bin", dtype=np.float64, mode="w+", shape=(4, 3))
m[:] = np.arange(12, dtype=np.float64).reshape(4, 3)
m.flush()
print(m.shape, m.dtype)
r = np.memmap("besar.bin", dtype=np.float64, mode="r", shape=(4, 3))
print(r[0])
print(r[:, 0])

Output yang Dihasilkan:

text
(4, 3) float64
[0. 1. 2.]
[0. 3. 6. 9.]

Mari kita bedah:

  1. Baris 3 (mode="w+", shape=(4, 3)): berkas 96 byte disiapkan (12 × 8 byte); shape dan dtype wajib disebut karena tidak ada header yang menyimpannya.
  2. Baris 4-5 (m[:] = ...; m.flush()): pengisian dilakukan lewat slice penuh, lalu flush() memaksa isi memori dituliskan ke berkas.
  3. Baris 7-9: pembukaan kedua memakai mode r (hanya baca); indexing dan slicing berjalan seperti array biasa, dan r[:, 0] membaca kolom pertama tanpa menyalin seluruh berkas ke array.

Mode r+ membuka berkas yang sudah ada untuk dibaca dan ditulis. Perubahan pada memmap bekerja seperti array biasa, tetapi hanya menjadi permanen di berkas setelah flush() dipanggil:

python
import numpy as np

np.arange(100, 106, dtype=np.int32).tofile("log.bin")
m = np.memmap("log.bin", dtype=np.int32, mode="r+", shape=(6,))
m[0] = 999
m.flush()
print(np.fromfile("log.bin", dtype=np.int32))

Output yang Dihasilkan:

text
[999 101 102 103 104 105]

Penjelasan tiap bagian:

  1. Baris 3 (tofile(...)): berkas berisi [100 101 102 103 104 105] disiapkan sebagai bahan uji.
  2. Baris 4-5 (mode="r+"): elemen pertama diubah menjadi 999 lewat memmap; operasi penugasan ini sama persis dengan array biasa.
  3. Baris 6-7: setelah flush(), pembacaan ulang lewat jalur terpisah (np.fromfile) membuktikan nilai baru benar-benar tertulis ke berkas — tanpa flush(), perubahan masih mengendap di memori.

Mode c: Perubahan yang Tidak Tertulis #

Mode c (copy-on-write) adalah mode ketiga: array bisa diubah di memori, tetapi setiap perubahan tidak pernah sampai ke berkas. Berguna ketika kita ingin bereksperimen pada data tanpa merusak sumbernya:

python
import numpy as np

np.arange(100, 106, dtype=np.int32).tofile("log.bin")
c = np.memmap("log.bin", dtype=np.int32, mode="c", shape=(6,))
c[1] = -1
print(c)
print(np.fromfile("log.bin", dtype=np.int32))

Output yang Dihasilkan:

text
[100  -1 102 103 104 105]
[100 101 102 103 104 105]

Mari kita telaah:

  1. Baris 3-4 (mode="c"): elemen kedua diubah menjadi -1 dan terlihat berubah pada cetakan pertama.
  2. Baris 5-6: pembacaan berkas yang sama memperlihatkan isi asli [100 101 102 103 104 105] — perubahan hanya hidup di memori proses tersebut.
  3. Perbandingan dengan bagian sebelumnya menegaskan perannya: r+ menulis permanen setelah flush, c tidak pernah menulis.

offset: Memetakan Sebagian Berkas #

Parameter offset memetakan berkas mulai dari byte ke-N, sehingga satu berkas besar dapat dipotong-potong menjadi beberapa tampilan tanpa memuat sisanya. Nilai offset harus kelipatan ukuran satu elemen:

python
import numpy as np

np.arange(100, 106, dtype=np.int32).tofile("log.bin")
p = np.memmap("log.bin", dtype=np.int32, mode="r", offset=4, shape=(5,))
print(p)

Output yang Dihasilkan:

text
[101 102 103 104 105]

Penjelasan tiap bagian:

  1. Baris 3 (offset=4): pemetaan dimulai pada byte keempat, yaitu tepat setelah elemen int32 pertama.
  2. Baris 3 (shape=(5,)): dari titik itu, hanya lima elemen sisanya yang dipetakan.
  3. Baris keluaran: hasilnya [101 102 103 104 105] — elemen pertama berkas tidak pernah disentuh.
ModeBacaTulisPerubahan ke berkas
ryatidaktidak ada penulisan sama sekali
r+yayapermanen setelah flush()
cyayahanya di memori, berkas tetap asli
w+yayaberkas baru dibuat lalu diisi