Dua catatan baseline dan dua catatan vectorized kini tersedia. Menganalisis hasil benchmark berarti tiga pekerjaan: merapikan angka menjadi tabel, menjelaskan pola di baliknya, dan menetapkan batas keabsahan kesimpulan. Kita kerjakan berurutan, ditutup laporan dan pemeriksaan akhir.
Membaca Tabel Hasil #
Tabel berikut merangkum contoh hasil pengukuran pada mesin penulis (2 CPU, 4 GB RAM, NumPy 2.1.3). Angka waktunya contoh — angka waktu bervariasi antar komputer — yang stabil adalah polanya:
| Skenario | Loop Python (contoh) | Vectorized (contoh) | Rasio (contoh) |
|---|---|---|---|
| Jumlah elemen | ~83 ms | ~0.46 ms | ~180x |
| Dot product | ~221 ms | ~0.33 ms | ~670x |
| Boolean filtering | ~110 ms | ~6.0 ms | ~18x |
Tiga interpretasi menjelaskan polanya:
- Loop Python membayar biaya tetap per elemen. Setiap iterasi mengeksekusi bytecode, membaca satu scalar dari array, dan membuat objek float baru. Satu juta elemen berarti satu juta kali biaya itu — inilah dasar rasio ratusan kali pada reduksi.
np.dotmemegang rasio terbesar. Di balik satu panggilan itu ada rutinitas BLAS dengan instruksi SIMD dan penggunaan cache yang rapi (bab Dot Product), sementaranp.sumtetap secepat satu loop C murni.- Boolean filtering menang paling tipis. Operasinya tidak hanya membaca:
data[data > ambang]harus mengalokasikan dan mengisi array baru berukuran sekitar 4 MB. Karena pekerjaannya mendekati memory-bound, rasionya turun ke belasan-puluhan kali — tetap berarti, jauh dari ratusan.
Kapan Rasio Percepatan Mengecil #
Rasio besar bukan hukum alam. Angka itu menyusut pada kondisi-kondisi berikut:
- Array kecil: biaya tetap satu pemanggilan NumPy (pembuatan objek, pemeriksaan bentuk) mendominasi; pada ratusan elemen, loop pun bisa kompetitif — bab Kapan NumPy Bukan Pilihan Terbaik membedah batas ini.
- Operasi memory-bound: kecepatan dibatasi transfer RAM, bukan logika komputasi; mengecilkan dtype (bab Memilih dtype yang Efisien) sering lebih berdampak daripada mengubah implementasi.
- Konversi dtype di tengah jalan: data yang harus dikonversi sebelum operasi NumPy menambah biaya salin yang ikut terukur.
- Operasi yang sudah vectorized: memanggil
np.sumdi dalam loop Python justru menggabungkan dua biaya; rasio kembali besar hanya bila loopnya dihilangkan, bukan diberi isi yang lebih cepat.
Yang tidak berubah oleh ukuran adalah kebenaran hasil. Pemeriksaan kesetaraan pada tiga skala berikut menegaskan bahwa loop dan vectorized selalu sepakat:
import numpy as np
def jumlah_loop(data):
total = 0.0
for nilai in data:
total += nilai
return total
rng = np.random.default_rng(42)
for n in [1_000, 100_000, 1_000_000]:
data = rng.random(n)
sama = np.isclose(jumlah_loop(data), np.sum(data))
print(f"n={n:>9,}: hasil sama -> {sama}")Output yang Dihasilkan:
n= 1,000: hasil sama -> True
n= 100,000: hasil sama -> True
n=1,000,000: hasil sama -> TruePenjelasannya:
- Baris 8 (
for n in [1_000, 100_000, 1_000_000]): tiga ukuran diuji berurutan; karena satu generator dipakai bergantian, datanya tetap deterministik meski berbeda antar ukuran. - Baris 10-11 (
np.isclose(...)): kesetaraan penjumlahan diuji dengan toleransi;Truedi ketiga skala berarti pilihan ukuran tidak mengubah kebenaran, hanya durasinya.
Checklist Benchmark yang Adil #
Sebelum memakai angka benchmark — milik sendiri maupun milik orang lain — periksa daftar ini:
- Tulis dulu pemeriksaan kebenaran (
array_equal/isclose), baru alat ukurnya. - Pakai data yang identik untuk kedua kubu: seed sama, dtype sama, ukuran sama.
- Gunakan
timeit.repeatdengannumberyang disesuaikan durasi; jangan puas dengan sekali ukur. - Laporkan nilai terkecil atau median, bukan rata-rata mentah yang mudah terseret gangguan.
- Warm-up dulu: jalankan sekali tanpa dicatat sebelum serangkaian pengukuran.
- Catat lingkungan: CPU, RAM, versi Python, dan versi NumPy.
- Jaga kondisi sama selama pengukuran — urutan kubu, suhu mesin, dan proses latar.
Laporan Proyek #
Seluruh hasil proyek dirangkum dalam satu tabel. Baris deterministik bisa diverifikasi ulang kapan saja; baris ilustratif hanya contoh dari satu mesin:
| Besaran | Nilai | Sifat |
|---|---|---|
| Input per array | 1.000.000 elemen float64 (8 MB) | deterministik |
| Kebenaran jumlah & dot | np.isclose True | deterministik |
| Kebenaran filter | np.array_equal True (499.793 elemen) | deterministik |
| Memori hasil filter | 3.998.344 byte (sekitar 4 MB) | deterministik |
| Rasio jumlah | ~150-180x | ilustratif |
| Rasio dot | ~650-700x | ilustratif |
| Rasio filter | ~18-23x | ilustratif |
Kesimpulan satu kalimat: untuk array besar, vectorization memberi percepatan puluhan hingga ratusan kali dengan hasil yang setara — dan setiap klaim kebenarannya tertaut ke pemeriksaan yang dapat dijalankan ulang. Bila proyek dikembangkan, struktur berkasnya natural: src/skenario.py menyimpan data dan enam fungsi kompetitor, sedangkan src/benchmark.py menjalankan timeit.repeat lalu menyusun tabel di atas.
Pemeriksaan Akhir #
Script terakhir merangkum seluruh klaim kebenaran proyek ke dalam satu blok yang berdiri sendiri:
import numpy as np
rng = np.random.default_rng(42)
data = rng.random(1_000_000)
bobot = rng.random(1_000_000)
def jumlah_loop(data):
total = 0.0
for nilai in data:
total += nilai
return total
def jumlah_vectorized(data):
return np.sum(data)
def dot_loop(a, b):
total = 0.0
for i in range(len(a)):
total += a[i] * b[i]
return total
def dot_vectorized(a, b):
return np.dot(a, b)
def filter_loop(data, ambang):
hasil = []
for nilai in data:
if nilai > ambang:
hasil.append(nilai)
return np.array(hasil)
def filter_vectorized(data, ambang):
return data[data > ambang]
assert np.isclose(jumlah_loop(data), jumlah_vectorized(data))
assert np.isclose(dot_loop(data, bobot), dot_vectorized(data, bobot))
assert np.array_equal(filter_loop(data, 0.5), filter_vectorized(data, 0.5))
print("Semua pemeriksaan lulus")Output yang Dihasilkan:
Semua pemeriksaan lulusCara kerjanya:
- Enam fungsi kompetitor didefinisikan ulang dalam satu blok agar script berdiri sendiri dan bisa disalin keluar dari halaman ini.
- Tiga assertion memeriksa ketiga skenario:
np.iscloseuntuk penjumlahan dan dot product (beda urutan penjumlahan),np.array_equaluntuk filter (identik bit-per-bit). Kegagalan mana pun menghentikan script denganAssertionError, sehingga barisprinthanya tercapai bila semuanya lulus.
Dengan itu, proyek benchmark selesai: klaim performa kini punya rancangan pengukuran, contoh angka yang jujur, interpretasi yang bisa dipertanggungjawabkan, dan pemeriksaan kebenaran yang menetap.