Buat optimisasi tetap lokal, jelaskan, dokumentasikan dengan baik, dan buat mudah untuk membandingkan versi yang dioptimalkan satu sama lain dan dengan versi yang tidak dioptimalkan, baik dalam hal kode sumber dan kinerja run-time.
Jawaban penuh
Jika optimisasi seperti itu benar - benar penting bagi produk Anda, maka Anda perlu tahu tidak hanya mengapa optimisasi bermanfaat sebelumnya, tetapi juga memberikan informasi yang cukup untuk membantu pengembang mengetahui apakah mereka akan berguna di masa depan.
Idealnya, Anda perlu mengabadikan pengujian kinerja ke dalam proses pembuatan Anda, sehingga Anda mengetahui kapan teknologi baru membatalkan optimisasi lama.
Ingat:
Aturan Pertama Optimalisasi Program: Jangan lakukan itu.
Aturan Kedua tentang Pengoptimalan Program (hanya untuk para ahli!): Jangan lakukan itu dulu. "
- Michael A. Jackson
Untuk mengetahui apakah sekarang saatnya membutuhkan benchmarking dan pengujian.
Seperti yang Anda sebutkan, masalah terbesar dengan kode yang sangat optimal adalah sulitnya mempertahankannya, sejauh mungkin, Anda perlu menjaga bagian yang dioptimalkan terpisah dari bagian yang tidak dioptimalkan. Apakah Anda melakukan ini melalui menghubungkan waktu kompilasi, panggilan fungsi virtual runtime atau sesuatu di antaranya tidak masalah. Yang penting adalah bahwa ketika Anda menjalankan tes Anda, Anda ingin dapat menguji terhadap semua versi yang saat ini Anda minati.
Saya akan cenderung untuk membangun suatu sistem sedemikian rupa sehingga versi dasar kode produksi yang tidak dioptimalkan dapat selalu digunakan untuk memahami maksud dari kode tersebut, kemudian membangun berbagai modul yang dioptimalkan bersama dengan ini berisi versi atau versi yang dioptimalkan, secara eksplisit mendokumentasikan di mana pun versi yang dioptimalkan berbeda dari garis dasar. Ketika Anda menjalankan tes (unit dan integrasi), Anda menjalankannya pada versi yang tidak dioptimalkan dan pada semua modul yang dioptimalkan saat ini.
Contoh
Misalnya, katakanlah Anda memiliki fungsi Fast Fourier Transform . Mungkin Anda memiliki dasar, implementasi algoritmik, fft.c
dan pengujian fft_tests.c
.
Kemudian datanglah Pentium dan Anda memutuskan untuk mengimplementasikan versi titik tetap dalam fft_mmx.c
menggunakan instruksi MMX . Kemudian pentium 3 datang dan Anda memutuskan untuk menambahkan versi yang menggunakan Streaming SIMD Extensions di fft_sse.c
.
Sekarang Anda ingin menambahkan CUDA , jadi Anda menambahkan fft_cuda.c
, tetapi temukan bahwa dengan dataset uji yang telah Anda gunakan selama bertahun-tahun, versi CUDA lebih lambat daripada versi SSE! Anda melakukan beberapa analisis dan akhirnya menambahkan dataset yang 100 kali lebih besar dan Anda mendapatkan kecepatan yang Anda harapkan, tetapi sekarang Anda tahu bahwa waktu pengaturan untuk menggunakan versi CUDA adalah signifikan dan dengan dataset kecil Anda harus menggunakan algoritma tanpa biaya pengaturan itu.
Dalam setiap kasus Anda menerapkan algoritma yang sama, semua harus berperilaku dengan cara yang sama, tetapi akan berjalan dengan efisiensi dan kecepatan yang berbeda pada arsitektur yang berbeda (jika mereka akan berjalan sama sekali). Dari sudut pandang kode, Anda dapat membandingkan setiap pasangan file sumber untuk mencari tahu mengapa antarmuka yang sama diimplementasikan dalam cara yang berbeda dan biasanya, cara termudah adalah merujuk kembali ke versi asli yang tidak dioptimalkan.
Semua hal yang sama berlaku untuk implementasi OOP di mana kelas dasar yang mengimplementasikan algoritma yang tidak dioptimalkan, dan kelas turunan menerapkan optimisasi yang berbeda.
Yang penting adalah menjaga hal-hal yang sama yang sama , sehingga perbedaannya jelas .