Mengapa Pemrograman Paralel yang Efektif Harus Menyertakan Alokasi Memori yang Dapat Diskalakan

Prosesor multicore? Iya.

Tulis program untuk dijalankan secara paralel? Iya.

Apakah Anda ingat untuk menggunakan Pengalokasi Memori yang Dapat Diskalakan? Tidak? Kemudian baca terus…

Dalam pengalaman saya, memastikan "alokasi memori" untuk sebuah program siap untuk paralelisme adalah elemen yang sering diabaikan dalam membuat program paralel bekerja dengan baik. Saya dapat menunjukkan kepada Anda cara yang sangat mudah untuk melihat apakah ini masalah untuk program yang dikompilasi (C, C ++, Fortran, dll.) - serta cara memperbaikinya.

Bagian penting dari program paralel apa pun adalah alokasi memori yang dapat diskalakan, yang mencakup penggunaan  panggilan baru  dan eksplisit ke  malloc, calloc, atau realoc . Pilihannya termasuk TBBmalloc (Intel Threading Building Blocks), jemalloc, dan tcmalloc. TBBmalloc memiliki fitur "proxy" baru yang memudahkan untuk mencoba dalam waktu kurang dari 5 menit pada program yang dikompilasi.

Manfaat kinerja menggunakan pengalokasi memori yang dapat diskalakan sangatlah signifikan. TBBmalloc adalah salah satu pengalokasi memori skalabel pertama yang banyak digunakan, sebagian besar karena TBB tersedia gratis untuk membantu menyoroti pentingnya memasukkan pertimbangan alokasi memori dalam program paralel apa pun. Ini tetap sangat populer saat ini, dan masih menjadi salah satu pengalokasi memori terukur terbaik yang tersedia.

Solusi mudah tanpa perubahan kode apa pun

Dengan menggunakan metode proxy, kita dapat mengganti new / delete dan malloc / calloc / realloc / free / etc secara global . rutinitas dengan teknik penggantian antarmuka memori dinamis. Cara otomatis untuk menggantikan fungsi default untuk alokasi memori dinamis sejauh ini merupakan cara paling populer untuk menggunakan TBBmalloc. Mudah dan memadai untuk sebagian besar program.

Detail mekanisme yang digunakan pada setiap sistem operasi sedikit berbeda, tetapi efek bersihnya sama di semua tempat.

Kami memulai uji coba 5 menit kami dengan mengunduh dan menginstal Threading Building Blocks (gratis dari //threadingbuildingblocks.org; ini juga disertakan sebagai bagian dari produk Intel Parallel Studio).

Gunakan proxy di Linux

Di Linux, kita dapat melakukan penggantian baik dengan memuat pustaka proxy pada waktu pemuatan program menggunakan variabel lingkungan LD_PRELOAD (tanpa mengubah file yang dapat dieksekusi), atau dengan menautkan file utama yang dapat dieksekusi dengan pustaka proxy ( -ltbbmalloc_proxy ). Pemuat program Linux harus dapat menemukan pustaka proxy dan pustaka pengalokasi memori yang dapat diskalakan pada waktu pemuatan program. Untuk itu kami dapat menyertakan direktori yang berisi perpustakaan di variabel lingkungan LD_LIBRARY_PATH atau menambahkannya ke /etc/ld.so.conf .

Coba sebagai berikut:

waktu ./a.out (atau apa pun sebutan program kami)

ekspor LD_PRELOAD = libtbbmalloc_proxy.so.2

waktu ./a.out (atau apa pun sebutan program kami)

Gunakan proxy di macOS

Di macOS, kita dapat melakukan penggantian dengan memuat pustaka proxy pada waktu muat program menggunakan variabel lingkungan DYLD_INSERT_LIBRARY (tanpa mengubah file yang dapat dieksekusi), atau dengan menautkan file utama yang dapat dijalankan dengan pustaka proxy ( -ltbbmalloc_proxy ). Pemuat program macOS harus dapat menemukan pustaka proxy dan pustaka pengalokasi memori yang dapat diskalakan pada waktu pemuatan program. Untuk itu, kami dapat menyertakan direktori yang berisi pustaka di variabel lingkungan DYLD_LIBRARY_PATH .

Coba sebagai berikut:

waktu ./a.out (atau apa pun sebutan program kami)

ekspor DYLD_INSERT_LIBRARY = $ TBBROOT / lib / libtbbmalloc_proxy.dylib

waktu ./a.out (atau apa pun sebutan program kami)

Gunakan proxy di Windows

Di Windows, kita harus memodifikasi file yang dapat dieksekusi. Kita bisa memaksa pustaka proxy untuk dimuat dengan menambahkan #include "tbb / tbbmalloc_proxy.h" di kode sumber kita, atau menggunakan opsi linker tertentu saat membuat executable:

Untuk win32:

            tbbmalloc_proxy.lib / TERMASUK: "___ TBB_malloc_proxy"

Untuk win64:

            tbbmalloc_proxy.lib / TERMASUK: "__ TBB_malloc_proxy"

Pemuat program Windows harus dapat menemukan pustaka proxy dan pustaka pengalokasi memori yang dapat diskalakan pada waktu pemuatan program. Untuk itu, kami dapat menyertakan direktori yang berisi pustaka dalam variabel lingkungan PATH . Cobalah dengan menggunakan Visual Studio "Performance Profiler" untuk mengatur waktu program dengan dan tanpa opsi sertakan atau tautan.

Menguji penggunaan pustaka proxy kami dengan program kecil

Saya mendorong Anda untuk mencoba program Anda sendiri seperti yang dijelaskan di atas. Jalankan dengan dan tanpa proxy, dan lihat seberapa besar manfaat yang didapat aplikasi Anda. Aplikasi dengan banyak paralelisme dan banyak alokasi memori sering kali mengalami peningkatan 10-20% (saya juga pernah melihat peningkatan 400%), sementara program dengan sedikit paralelisme atau sedikit alokasi mungkin tidak akan berpengaruh sama sekali. Tes cepat, yang dijelaskan sebelumnya, dengan pustaka proxy akan memberi tahu Anda di kategori mana aplikasi Anda berada.

Saya juga telah menulis program singkat untuk mengilustrasikan efek serta memberikan cara mudah untuk memeriksa bahwa segala sesuatunya telah terpasang dan bekerja seperti yang diharapkan. Kami dapat mencoba pustaka proxy dengan program sederhana:

#include

#include "tbb / tbb.h"

menggunakan namespace tbb;

const int N = 1000000;

int main () {

ganda * a [N];

parallel_for (0, N-1, [&] (int i) {a [i] = new double;});

parallel_for (0, N-1, [&] (int i) {delete a [i];});

kembali 0;

}

Program contoh saya memang menggunakan banyak ruang stack, jadi " ulimit –s unlimited " (Linux / macOS) atau " / STACK: 10000000 " (Visual Studio: Properties> Configuration Properties> Linker> System> Stack Reserve Size) akan menjadi penting untuk menghindari kerusakan langsung.

Setelah kompilasi, berikut adalah berbagai cara saya menjalankan program kecil saya untuk melihat kecepatan dengan dan tanpa pustaka proxy.

Menjalankan dan mengatur waktu tbb_mem.cpp pada mesin Linux virtual quadcore , saya melihat yang berikut:

% waktu ./tbb_mem 

0m0.160s nyata

pengguna 0m0.072s

sys 0m0.048s

%

% exportLD_PRELOAD = $ TBBROOT / lib / libtbbmalloc_proxy.dylib

%

% waktu ./tbb_mem 

0m0.043s nyata

pengguna 0m0.048s

sys 0m0.028s

Menjalankan dan menentukan waktu tbb_mem.cpp di quadcore iMac (macOS), saya melihat yang berikut:

% waktu ./tbb_mem

0m0.046s nyata

pengguna 0m0.078s

sys 0m0.053s

%

% ekspor DYLD_INSERT_LIBRARY = $ TBBROOT / lib / libtbbmalloc_proxy.dylib

%

% waktu ./tbb_mem 

0m0.019s nyata

pengguna 0m0.032s

sys 0m0.009s

Pada Windows, menggunakan Visual Studio “Performance Profiler” pada quadcore Intel NUC (Core i7) saya melihat waktu 94ms tanpa profiler memori yang dapat diskalakan dan 50ms dengannya (menambahkan #include "tbb / tbbmalloc_proxy.h" ke dalam program contoh) .

Pertimbangan kompilasi

Secara pribadi saya tidak memiliki masalah dengan kompiler yang melakukan "optimasi malloc," tetapi secara teknis saya akan menyarankan bahwa ketika mengkompilasi dengan program yang kompiler "optimasi malloc" harus dinonaktifkan. Sebaiknya periksa dokumentasi kompilator dari kompilator favorit Anda. Misalnya, dengan kompiler Intel atau gcc, yang terbaik adalah meneruskan tanda berikut:

-fno-builtin-malloc (di Windows: / Qfno-builtin-malloc)

-fno-builtin-calloc (di Windows: / Qfno-builtin-calloc)

-fno-builtin-realloc (di Windows: / Qfno-builtin-realloc)

-fno-builtin-free (pada Windows: / Qfno-builtin-free)

Kegagalan menggunakan tanda ini mungkin tidak menyebabkan masalah, tapi bukan ide yang buruk untuk aman.

Ringkasan

Menggunakan pengalokasi memori yang dapat diskalakan adalah elemen penting dalam program paralel apa pun. Saya telah menunjukkan bahwa TBBmalloc dapat dengan mudah disuntikkan tanpa memerlukan perubahan kode (meskipun menambahkan "include" pada Windows adalah solusi Windows favorit saya). Anda mungkin melihat percepatan yang bagus hanya dengan 5 menit kerja, dan Anda dapat menerapkannya ke banyak aplikasi dengan mudah. Di Linux dan macOS, Anda bahkan mungkin dapat mempercepat program tanpa kode sumber!

Klik di sini untuk mengunduh uji coba gratis 30 hari Intel Parallel Studio XE Anda.