Mengapa sulit untuk memberikan efisiensi saat menggunakan perpustakaan?


10

Setiap pemrosesan basis data kecil dapat dengan mudah ditangani oleh skrip Python / Perl / ..., yang menggunakan pustaka dan / atau bahkan utilitas dari bahasa itu sendiri. Namun, ketika datang ke kinerja, orang cenderung menjangkau bahasa C / C ++ / tingkat rendah. Kemungkinan menyesuaikan kode dengan kebutuhan tampaknya menjadi apa yang membuat bahasa ini begitu menarik untuk BigData - baik itu mengenai manajemen memori, paralelisme, akses disk, atau bahkan optimasi tingkat rendah (melalui perakitan konstruksi pada level C / C ++).

Tentu saja set manfaat seperti itu tidak akan datang tanpa biaya: menulis kode, dan kadang-kadang bahkan menciptakan kembali roda , bisa sangat mahal / melelahkan. Meskipun ada banyak perpustakaan yang tersedia, orang cenderung untuk menulis kode sendiri setiap kali mereka perlu memberikan kinerja. Apa yang menonaktifkan pernyataan kinerja dari menggunakan perpustakaan saat memproses basis data besar?

Misalnya, perhatikan perusahaan yang secara terus-menerus merayapi laman web dan mem-parsing data yang dikumpulkan. Untuk setiap jendela geser, algoritma penambangan data yang berbeda dijalankan pada data yang diekstraksi. Mengapa pengembang harus menggunakan pustaka / kerangka kerja yang tersedia (baik itu untuk perayapan, pemrosesan teks, dan penggalian data)? Menggunakan hal-hal yang sudah diimplementasikan tidak hanya akan meringankan beban pengkodean seluruh proses, tetapi juga akan menghemat banyak waktu.

Dalam satu tembakan :

  • apa yang membuat menulis kode sendiri menjadi jaminan kinerja?
  • mengapa berisiko mengandalkan kerangka / perpustakaan ketika Anda harus memastikan kinerja tinggi?

1
Bisakah Anda mengklarifikasi pertanyaan yang tepat? Mungkin beberapa jawaban yang mungkin ada dalam pikiran Anda juga dapat membantu.
Amir Ali Akbari

@AmirAliAkbari SeanOwen memposting jawaban dan saya perhatikan kurangnya spesifisitas dalam pertanyaan saya. Saya telah menambahkan komentar ke posnya. Tolong, jangan ragu untuk menyarankan perbaikan pada pos - saya berencana untuk menghapusnya, jika tidak.
Rubens

Jawaban:


4

Setelah melakukan permainan menulis ulang berulang-ulang (dan masih melakukannya), reaksi langsung saya adalah kemampuan beradaptasi .

Sementara kerangka kerja dan perpustakaan memiliki gudang besar (mungkin intertwinable) rutin untuk tugas-tugas standar, properti kerangka kerja mereka sering (selalu?) Melarang pintasan. Bahkan, sebagian besar kerangka kerja memiliki semacam infrastruktur inti di mana lapisan inti fungsi dasar diimplementasikan. Fungsionalitas yang lebih spesifik memanfaatkan lapisan dasar dan ditempatkan di lapisan kedua di sekitar inti.

Sekarang dengan cara pintas yang saya maksud langsung dari rutinitas lapisan kedua ke rutinitas lapisan kedua lainnya tanpa menggunakan inti. Contoh umum (dari domain saya) adalah cap waktu: Anda memiliki beberapa jenis sumber data timestamped. Sejauh ini tugasnya adalah hanya membaca data dari kabel dan meneruskannya ke inti sehingga kode Anda yang lain dapat berpesta dengannya.

Sekarang industri Anda mengubah format cap waktu default untuk alasan yang sangat bagus (dalam kasus saya mereka berubah dari waktu unix ke waktu GPS). Jika kerangka kerja Anda tidak spesifik untuk industri, maka sangat kecil kemungkinannya mereka bersedia mengubah representasi inti dari waktu, jadi Anda akhirnya menggunakan kerangka kerja yang hampir melakukan apa yang Anda inginkan. Setiap kali Anda mengakses data, Anda harus mengonversikannya ke format waktu industri terlebih dahulu, dan setiap kali Anda ingin memodifikasinya, Anda harus mengubahnya kembali ke apa pun yang dianggap tepat oleh inti. Tidak mungkin Anda dapat menyerahkan data langsung dari sumber ke bak cuci tanpa konversi ganda.

Di sinilah kerangka kerja kerajinan tangan Anda akan bersinar, itu hanya perubahan kecil dan Anda kembali memodelkan dunia nyata sedangkan semua kerangka kerja lainnya (non-industri-spesifik) sekarang akan memiliki kerugian kinerja.

Seiring waktu, perbedaan antara dunia nyata dan model akan bertambah. Dengan kerangka off-the-rak Anda akan segera menghadapi pertanyaan-pertanyaan seperti: Bagaimana saya bisa mewakili thisdalam thatatau bagaimana make rutin Xmenerima / produk Y.

Sejauh ini ini bukan tentang C / C ++. Tetapi jika, karena alasan tertentu, Anda tidak dapat mengubah kerangka kerja, yaitu Anda harus tahan dengan konversi data ganda untuk berpindah dari satu ujung ke ujung lainnya, maka Anda biasanya akan menggunakan sesuatu yang meminimalkan overhead tambahan. Dalam kasus saya, konverter TAI-> UTC atau UTC-> TAI sebaiknya diserahkan ke C mentah (atau FPGA). Tidak ada keanggunan mungkin, tidak ada struktur data pintar yang mendalam yang membuat masalah sepele. Itu hanya pernyataan beralih yang membosankan, dan mengapa tidak menggunakan bahasa yang kompilernya pandai mengoptimalkan hal itu?


1
+1 Itu mungkin salah saya karena tidak begitu jelas dalam pos saya, jadi orang lain belum mendapatkannya sebelumnya. Ini pasti jenis jawaban yang saya cari. Terima kasih.
Rubens

7

Saya tidak berpikir bahwa semua orang meraih C / C ++ ketika kinerja menjadi masalah.

Keuntungan menulis kode tingkat rendah adalah menggunakan lebih sedikit siklus CPU, atau terkadang, lebih sedikit memori. Tetapi saya perhatikan bahwa bahasa tingkat yang lebih tinggi dapat memanggil ke bahasa tingkat yang lebih rendah, dan memang, untuk mendapatkan beberapa nilai ini. Bahasa Python dan JVM dapat melakukan ini.

Ilmuwan data yang menggunakan, misalnya, scikit-belajar di desktop-nya sudah memanggil rutinitas asli yang sangat dioptimalkan untuk melakukan angka-angka. Tidak ada gunanya menulis kode baru untuk kecepatan.

Dalam konteks "data besar" yang didistribusikan, Anda lebih sering mengalami hambatan pada pergerakan data: transfer jaringan dan I / O. Kode asli tidak membantu. Yang membantu bukanlah menulis kode yang sama agar berjalan lebih cepat, tetapi menulis kode yang lebih cerdas.

Bahasa tingkat yang lebih tinggi akan memungkinkan Anda menerapkan algoritma terdistribusi lebih canggih dalam jumlah waktu pengembang tertentu daripada C / C ++. Pada skala, algoritma yang lebih cerdas dengan pergerakan data yang lebih baik akan mengalahkan kode asli bodoh.

Biasanya juga benar bahwa waktu pengembang, dan bug, lebih banyak menghabiskan biaya daripada perangkat keras baru. Setahun waktu pengembang senior mungkin $ 200K terisi penuh; lebih dari setahun yang juga menyewakan ratusan server senilai waktu komputasi. Mungkin tidak masuk akal dalam banyak kasus untuk repot-repot mengoptimalkan lebih dari melemparkan lebih banyak perangkat keras padanya.

Saya tidak mengerti tindak lanjut tentang "berikan" dan "nonaktifkan" dan "tegaskan"?


Maaf atas kesalahpahaman ini. Tujuan saya adalah untuk memunculkan jawaban mengenai pentingnya memiliki kendali atas aplikasi, dan bagaimana kontrol ini dilonggarkan oleh perpustakaan. Tentu saja Anda dapat mengasumsikan hal-hal tentang mereka (orang-orang biasanya tidak menulis ulang pthreads), tetapi jika data berubah (memuat, throughput, ...), Anda mungkin perlu mengakses sumber lib untuk memberikan kinerja. Dan ya, itu belum tentu C / C ++ - meskipun mereka biasanya bahasa yang dipilih untuk HPC. Bolehkah saya menghapus pertanyaan saya, atau Anda ingin mengubahnya menjadi sesuatu yang lebih spesifik? Saya menerima saran untuk memperbaikinya.
Rubens

1
Tidak, ini pertanyaan yang bagus, Anda dapat merefleksikan komentar Anda di sini dalam editan untuk pertanyaan itu jika Anda mau.
Sean Owen

Silakan periksa apakah pertanyaannya masuk akal sekarang. Saya telah menambahkan kasing kecil agar lebih mudah. Jika Anda ingin menambahkan beberapa pertimbangan dalam pertanyaan, silakan mengeditnya.
Rubens

4

Seperti yang kita ketahui, di dunia Digital ada banyak cara untuk melakukan pekerjaan yang sama / mendapatkan hasil yang diharapkan ..

Dan tanggung jawab / risiko yang berasal dari kode berada di pundak pengembang ..

Ini kecil tapi saya kira contoh yang sangat berguna dari dunia .NET ..

Begitu Banyak. NET developer menggunakan BinaryReader - BinaryWriter built-in pada serialisasi data mereka untuk kinerja / mendapatkan kontrol atas proses ..

Ini adalah kode sumber CSharp dari FrameWork yang dibangun di kelas BinaryWriter 'salah satu dari Metode Tulis yang kelebihan beban:

// Writes a boolean to this stream. A single byte is written to the stream
// with the value 0 representing false or the value 1 representing true.
// 
public virtual void Write(bool value) 
{
     //_buffer is a byte array which declared in ctor / init codes of the class
    _buffer = ((byte) (value? 1:0));

    //OutStream is the stream instance which BinaryWriter Writes the value(s) into it.
    OutStream.WriteByte(_buffer[0]);
}

Seperti yang Anda lihat, metode ini bisa ditulis tanpa tambahan tugas ke variabel _buffer:

public virtual void Write(bool value) 
{
    OutStream.WriteByte((byte) (value ? 1 : 0));
}

Tanpa menetapkan kita dapat memperoleh beberapa milidetik .. Beberapa milidetik ini dapat menerima sebagai "hampir tidak ada" tetapi bagaimana jika ada ribuan tulisan (yaitu dalam proses server)?

Mari kita anggap bahwa "beberapa" adalah 2 (milidetik) dan instance multi-Ribuan hanya 2.000 .. Ini berarti 4 detik lebih banyak waktu proses. 4 detik kemudian kembali ..

Jika kami terus tunduk pada .NET dan jika Anda dapat memeriksa kode sumber BCL - .NET Base Class Library- dari MSDN, Anda dapat melihat banyak kehilangan kinerja yang diputuskan oleh pengembang.

Titik mana pun dari sumber BCL Adalah normal bahwa Anda melihat pengembang memutuskan untuk menggunakan while () atau foreach () loop yang dapat mengimplementasikan loop for () yang lebih cepat dalam kode mereka.

Keuntungan kecil ini memberi kami kinerja total ..

Dan jika kita kembali ke Metode BinaryWriter.Write () ..

Sebenarnya penugasan ekstra untuk implementasi _buffer bukanlah kesalahan pengembang..Ini tepatnya memutuskan untuk "tetap aman"!

Misalkan kita memutuskan untuk tidak menggunakan _buffer dan memutuskan untuk menerapkan metode kedua .. Jika kita mencoba mengirim multi-ribuan byte melalui kabel (mis. Unggah / unduh data BLOB atau CLOB) dengan metode kedua, itu bisa gagal karena koneksi terputus..Karena kami mencoba mengirim semua data tanpa mekanisme kontrol dan pengecekan. Ketika koneksi terputus, Baik server dan Klien tidak pernah tahu data yang dikirim selesai atau tidak.

Jika pengembang memutuskan "tetap aman" maka biasanya itu berarti biaya kinerja bergantung pada mekanisme "tetap aman" yang diterapkan.

Tetapi jika pengembang memutuskan "menjadi berisiko, dapatkan kinerja" ini juga bukan kesalahan. Sampai ada beberapa diskusi tentang pengkodean "berisiko".

Dan sebagai catatan kecil: Pengembang perpustakaan komersial selalu berusaha untuk tetap aman karena mereka tidak tahu di mana kode mereka akan digunakan.


4

Berasal dari perspektif pemrogram, kerangka kerja jarang menargetkan kinerja sebagai prioritas tertinggi. Jika perpustakaan Anda akan dimanfaatkan secara luas, hal-hal yang cenderung dihargai oleh kebanyakan orang adalah kemudahan penggunaan, fleksibilitas, dan keandalan.

Kinerja umumnya dihargai di perpustakaan kompetitif sekunder. "Perpustakaan X lebih baik karena lebih cepat." Bahkan kemudian, perpustakaan-perpustakaan itu akan menukar solusi yang paling optimal untuk perpustakaan yang dapat dimanfaatkan secara luas.

Dengan menggunakan kerangka kerja apa pun Anda secara inheren mengambil risiko bahwa solusi yang lebih cepat ada. Saya mungkin mengatakan bahwa solusi yang lebih cepat hampir selalu ada.

Menulis sesuatu sendiri bukanlah jaminan kinerja, tetapi jika Anda tahu apa yang Anda lakukan dan memiliki serangkaian persyaratan yang cukup terbatas, itu bisa membantu.

Contohnya mungkin parsing JSON. Ada seratus perpustakaan di luar sana untuk berbagai bahasa yang akan mengubah JSON menjadi objek yang dapat dirujuk dan sebaliknya. Saya tahu satu implementasi yang melakukan semuanya dalam register CPU. Ini terukur lebih cepat dari semua parser lain, tetapi juga sangat terbatas dan batasan itu akan bervariasi berdasarkan pada apa CPU Anda bekerja dengan.

Apakah tugas membangun parser JSON berkinerja tinggi khusus merupakan ide bagus? Saya akan memanfaatkan perpustakaan yang dihormati 99 kali dari 100. Dalam satu contoh terpisah beberapa siklus CPU tambahan dikalikan sejuta iterasi akan membuat waktu pengembangan sepadan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.