Array MATLAB hidup di memori dalam blok berurutan — makin besar array, makin cepat ruangnya habis dan makin sering Out of memory muncul di momen terburuk. Kabar baiknya: kebutuhan memori bisa kita audit, pangkas, dan bagi cerdas dengan beberapa kebiasaan. Chapter ini menutup lima chapter pertama Section Optimasi dan Performa dengan audit whos, ukuran tipe data, salinan implicit, operasi in-place, dan strategi untuk dataset besar. Cakupan materinya:

  • Audit memori per variabel dengan whos
  • Tabel ukuran tipe: double 8 byte vs single 4 byte vs int8 1 byte
  • Copy-on-write: kapan MATLAB menyalin array secara diam-diam
  • Operasi in-place dan pemrosesan per kolom untuk dataset besar

Audit Memori dengan whos #

Aturannya: whos melaporkan ukuran, kelas, dan jumlah byte tiap variabel di workspace. Mekanismenya: MATLAB menyimpan array sebagai blok data berurutan; whos menanyakan ukuran blok tersebut — hasilnya adalah numel dikali byte per elemen kelasnya. Empat variabel 1000×1000 berkelas berbeda memakan ruang yang sangat berbeda:

matlab
rng(42);
A = rand(1000, 1000);   % double : 8 byte per elemen
B = single(A);          % single : 4 byte per elemen
C = int8(A * 100);      % int8   : 1 byte per elemen
D = A > 0.5;            % logical: 1 byte per elemen

whos

Output yang Dihasilkan:

text
  Name      Size                Bytes  Class      Attributes

  A         1000x1000          8000000  double
  B         1000x1000          4000000  single
  C         1000x1000          1000000  int8
  D         1000x1000          1000000  logical

Empat array dengan bentuk sama menempati 14 MB total — dari 8 juta byte untuk double hingga 1 juta byte untuk int8 dan logical. Tampilan whos sedikit berbeda antar versi MATLAB, tetapi kolomnya selalu sama: nama, ukuran, byte, kelas, dan atribut.

Ukuran Tipe Data #

Aturannya: pilih kelas terkecil yang masih memuat data dan presisinya. Mekanismenya: jumlah byte per elemen ditentukan kelasnya, sehingga konversi kelas langsung membagi-bagi kebutuhan memori. Kita bisa memverifikasi hitungannya secara manual — numel(A) * 8 — dan mencocokkannya dengan laporan whos:

matlab
fprintf('variabel  kelas     elemen    byte/elem  total byte (whos)\n');
fprintf('%-9s %-8s %8d %11d %16d\n', 'A', class(A), numel(A), 8, whos('A').bytes);
fprintf('%-9s %-8s %8d %11d %16d\n', 'B', class(B), numel(B), 4, whos('B').bytes);
fprintf('%-9s %-8s %8d %11d %16d %s\n', 'C', class(C), numel(C), 1, whos('C').bytes, ...
    '(int8 membulatkan ke bilangan bulat)');
fprintf('%-9s %-8s %8d %11d %16d\n', 'D', class(D), numel(D), 1, whos('D').bytes);

Output yang Dihasilkan:

text
variabel  kelas     elemen    byte/elem  total byte (whos)
A         double    1000000           8          8000000
B         single    1000000           4          4000000
C         int8      1000000           1          1000000 (int8 membulatkan ke bilangan bulat)
D         logical   1000000           1          1000000

Tabel ringkas kelas yang paling sering kita jumpai:

KelasByte/elemenKapasitas / presisi
double8±1.8 × 10³⁰⁸, ~15–16 digit desimal
single4±3.4 × 10³⁸, ~7 digit desimal
int8 / uint81−128…127 / 0…255
int16 / uint162±32 767 / 0…65 535
int32 / uint324±2.1 × 10⁹ / 0…4.3 × 10⁹
int64 / uint648±9.2 × 10¹⁸ / 0…1.8 × 10¹⁹
logical1true/false
char2satu karakter (UTF-16)

Peringatannya: konversi ke kelas kecil memotong presisi dan jangkauan — int8(100.7) menghasilkan 101 (pembulatan), dan nilai di luar jangkauan terpotong ke batas. Untuk citra, mask, dan data sensor 8-bit, kelas kecil adalah kemenangan besar; untuk akumulasi numerik, double tetap default yang aman.

Salinan Implicit: Copy-on-Write #

Aturannya: assignment y = x tidak serta-merta menyalin data — MATLAB menunda penyalinan sampai salah satu variabel dimodifikasi. Mekanismenya: kedua nama mula-mula menunjuk blok data yang sama (copy-on-write); saat y(1) = 99 dieksekusi, barulah MATLAB menyalin blok tersebut agar x tidak ikut berubah. Dari sisi nilai, hasilnya identik dengan salinan penuh:

matlab
p = [10 20 30 40];
q = p;                  % q berbagi data dengan p, belum menyalin
q(1) = 99;              % modifikasi pertama: data disalin untuk q
fprintf('p tetap utuh: %d %d %d %d\n', p);
fprintf('q sudah berubah: %d %d %d %d\n', q);

Output yang Dihasilkan:

text
p tetap utuh: 10 20 30 40
q sudah berubah: 99 20 30 40

Operasi In-Place #

Aturannya: bila hasil operasi menimpa variabel yang sama (x = x + 1), nyatakan dengan variabel yang sama di kedua sisi. Mekanismenya: MATLAB dapat memakai ulang buffer x untuk hasilnya bila aman — tidak ada nama lain yang menunjuk blok itu; bandingkan dengan y = x + 1 yang harus menyiapkan buffer kedua:

matlab
x = rand(1, 1000000);
fprintf('x (double, %d elemen): %d byte\n', numel(x), whos('x').bytes);
x = x + 1;              % pola in-place: ruang x dapat dipakai ulang
fprintf('setelah x = x + 1 : %d byte (ukuran tidak bertambah)\n', whos('x').bytes);
y = x + 1;              % bukan in-place: buffer baru untuk y
fprintf('setelah y = x + 1 : x = %d byte, y = %d byte\n', whos('x').bytes, whos('y').bytes);

Output yang Dihasilkan:

text
x (double, 1000000 elemen): 8000000 byte
setelah x = x + 1 : 8000000 byte (ukuran tidak bertambah)
setelah y = x + 1 : x = 8000000 byte, y = 8000000 byte

Pola a(i) = a(i) + 1 di dalam loop adalah varian indexed-nya: elemen diperbarui di tempat tanpa salinan array penuh.

Praktik Dataset Besar #

Dataset yang tidak muat sekaligus diproses bertahap. Pertama, proses per kolom dan simpan ringkasan, lalu buang variabel besar dengan clear segera setelah tidak terpakai:

matlab
data = repmat(1:300, 4000, 1);           % padanan dataset 4000x300
fprintf('data: %dx%d, %d byte\n', size(data, 1), size(data, 2), whos('data').bytes);

rataKolom = zeros(1, 300);               % prealokasi hasil
for j = 1:300
    rataKolom(j) = mean(data(:, j));     % satu kolom pada satu waktu
end
clear data                               % variabel besar dibuang segera
fprintf('rata-rata kolom 1-3: %.4f %.4f %.4f\n', rataKolom(1:3));

M = repmat(1:300, 4000, 1);
W = reshape(M, 300, 4000);               % hanya metadata, data tetap dibagikan
fprintf('M: %d byte, W: %d byte (whos melaporkan ukuran logis)\n', ...
    whos('M').bytes, whos('W').bytes);

Output yang Dihasilkan:

text
data: 4000x300, 9600000 byte
rata-rata kolom 1-3: 1.0000 2.0000 3.0000
M: 9600000 byte, W: 9600000 byte (whos melaporkan ukuran logis)

Mari kita bedah baris-baris kode di atas:

  1. Baris 6 (rataKolom(j) = mean(data(:, j));): hanya satu kolom (32 KB) yang dipegang pada satu waktu — kebutuhan memori puncak turun drastis dibanding memproses matriks hasil berukuran penuh.
  2. Baris 8 (clear data;): 9,6 MB dikembalikan ke sistem sebelum tahap berikutnya berjalan.
  3. Baris 12 (reshape(M, 300, 4000)): reshape hanya menulis ulang metadata dimensi; blok data tidak disalin, sehingga M dan W berbagi data yang sama.

Bila dataset benar-benar melampaui RAM, pecah proses menjadi beberapa tahap dan simpan hasil antara ke disk dengan save('tahap1.mat', 'hasil'), lalu load kembali di tahap berikutnya. Saat alokasi gagal, MATLAB melempar galat khas Out of memory. Type HELP MEMORY for your options. — sinyal untuk memecah data atau menurunkan kelas. Fungsi legacy pack (memampatkan workspace lewat disk) praktis tidak dibutuhkan pada MATLAB modern.

Ringkasan #

whos memberi kita angka pasti: double memakan 8 byte per elemen, single 4, int8 dan logical masing-masing 1 — verifikasi dengan numel × byte per elemen. Assignment murah berkat copy-on-write, namun modifikasi pertama memicu salinan penuh; x = x + 1 adalah bentuk in-place yang aman, dan reshape menata ulang dimensi tanpa menyalin. Untuk dataset besar: proses per kolom, clear segera, dan save hasil antara ke disk. Lima chapter pertama section ini melengkapi kotak alat performa dasar; lanjutan optimasi array dan function menempa alat itu lebih tajam.