Seperti orang lain berkata, masalah ini adalah toko ke lokasi memori dalam array: x[i][j]
. Inilah sedikit wawasan mengapa:
Anda memiliki larik 2 dimensi, tetapi memori di komputer pada dasarnya adalah 1 dimensi. Jadi, sementara Anda membayangkan array Anda seperti ini:
0,0 | 0,1 | 0,2 | 0,3
----+-----+-----+----
1,0 | 1,1 | 1,2 | 1,3
----+-----+-----+----
2,0 | 2,1 | 2,2 | 2,3
Komputer Anda menyimpannya dalam memori sebagai satu baris:
0,0 | 0,1 | 0,2 | 0,3 | 1,0 | 1,1 | 1,2 | 1,3 | 2,0 | 2,1 | 2,2 | 2,3
Pada contoh ke-2, Anda mengakses array dengan mengulangi angka ke-2 terlebih dahulu, yaitu:
x[0][0]
x[0][1]
x[0][2]
x[0][3]
x[1][0] etc...
Berarti Anda memukul semuanya secara berurutan. Sekarang lihat versi 1. Kamu lakukan:
x[0][0]
x[1][0]
x[2][0]
x[0][1]
x[1][1] etc...
Karena cara C meletakkan array 2-d dalam memori, Anda memintanya untuk melompat ke semua tempat. Tapi sekarang untuk si penendang: Mengapa ini penting? Semua akses memori sama, kan?
Tidak: karena cache. Data dari memori Anda akan dibawa ke CPU dalam potongan kecil (disebut 'cache lines'), biasanya 64 byte. Jika Anda memiliki bilangan bulat 4-byte, itu artinya Anda mendapatkan 16 bilangan bulat berturut-turut dalam satu bungkusan kecil yang rapi. Sebenarnya cukup lambat untuk mengambil potongan memori ini; CPU Anda dapat melakukan banyak pekerjaan dalam waktu yang dibutuhkan untuk satu baris cache untuk memuat.
Sekarang lihat kembali urutan akses: Contoh kedua adalah (1) mengambil sepotong 16 int, (2) memodifikasi semuanya, (3) ulangi 4000 * 4000/16 kali. Itu bagus dan cepat, dan CPU selalu memiliki sesuatu untuk dikerjakan.
Contoh pertama adalah (1) ambil sepotong 16 int, (2) memodifikasi hanya satu dari mereka, (3) ulangi 4000 * 4000 kali. Itu akan membutuhkan 16 kali jumlah "pengambilan" dari memori. CPU Anda sebenarnya harus menghabiskan waktu duduk-duduk menunggu memori itu muncul, dan sementara itu duduk di sekitar Anda membuang-buang waktu yang berharga.
Catatan penting:
Sekarang setelah Anda memiliki jawabannya, inilah catatan yang menarik: tidak ada alasan yang melekat bahwa contoh kedua Anda haruslah yang cepat. Misalnya, di Fortran, contoh pertama akan cepat dan yang kedua lambat. Itu karena alih-alih memperluas hal-hal menjadi "baris" konseptual seperti C, Fortran memperluas ke "kolom", yaitu:
0,0 | 1,0 | 2,0 | 0,1 | 1,1 | 2,1 | 0,2 | 1,2 | 2,2 | 0,3 | 1,3 | 2,3
Tata letak C disebut 'baris-utama' dan Fortran disebut 'kolom-utama'. Seperti yang Anda lihat, sangat penting untuk mengetahui apakah bahasa pemrograman Anda adalah baris-utama atau kolom-utama! Berikut ini tautan untuk info lebih lanjut: http://en.wikipedia.org/wiki/Row-major_order