Proyek ini sekarang diarsipkan dan hanya dapat dibaca
timemory di GitHub (Kode sumber)
Dokumentasi Umum timemory (ReadTheDocs)
Dokumentasi Kode Sumber timemory (Doxygen)
Dasbor Pengujian timemory (CDash)
Tutorial waktu
Tutorial ECP 2021 Hari 1 (YouTube)
Tutorial ECP 2021 Hari ke 2 (YouTube)
Wiki waktu
GitHub | git clone https://github.com/NERSC/timemory.git |
PyPi | pip install timemory |
Kekek | spack install timemory |
conda-forge | conda install -c conda-forge timemory |
Tujuan dari timemory adalah untuk membuat paket pengukuran dan analisis kinerja sumber terbuka dengan komponen modular dan dapat digunakan kembali yang dapat digunakan untuk beradaptasi dengan API pengukuran dan analisis kinerja C/C++ yang ada dan dapat diperluas secara sewenang-wenang oleh pengguna dalam aplikasi mereka. Timemory bukan sekadar alat pembuatan profil, ini adalah perangkat pembuatan profil yang menyederhanakan pembuatan alat pembuatan profil khusus melalui modularitas dan kemudian menggunakan perangkat tersebut untuk menyediakan beberapa alat yang sudah dibuat sebelumnya.
Dengan kata lain, timemory menyediakan banyak alat, perpustakaan, dan antarmuka yang telah dibuat sebelumnya, namun karena modularitasnya, kode hanya dapat menggunakan kembali bagian-bagian individual -- seperti kelas untuk mengukur interval waktu yang berbeda, penggunaan memori, dan penghitung perangkat keras - - tanpa "manajemen runtime" timemory.
Timemory menggunakan instalasi CMake standar. Beberapa contoh instalasi dapat ditemukan di Wiki. Lihat dokumentasi instalasi untuk informasi rinci tentang opsi CMake.
Dokumentasi lengkap tersedia di timemory.readthedocs.io. Dokumentasi sumber terperinci disediakan di bagian doygen dari dokumentasi lengkap. Tutorial tersedia di github.com/NERSC/timemory-tutorials.
Tujuan utama dari timemory adalah pengembangan kerangka umum untuk mengikat kode pemantauan perangkat lunak (yaitu analisis kinerja, debugging, logging) ke dalam antarmuka yang kompak dan sangat efisien.
Timemory muncul dari kebutuhan akan kit adaptor universal untuk berbagai API yang menyediakan beberapa alat yang ada dan metode yang mudah dan intuitif untuk membuat alat baru. Timemory memungkinkan untuk menggabungkan pengukuran kinerja deterministik, pengukuran kinerja statistik (yaitu pengambilan sampel), pesan debug, pencatatan data, dan validasi data ke dalam antarmuka yang sama untuk antarmuka pemantauan perangkat lunak khusus aplikasi, dengan mudah membuat alat seperti time
, netstat
, instrumentasi profiler, profiler pengambilan sampel, dan implementasi penulisan untuk MPI-P, MPI-T, OMPT, KokkosP, dll. Selanjutnya, timemory dapat meneruskan penandanya ke beberapa profiler pihak ketiga seperti LIKWID, Kaliper, TAU, gperftools, Perfetto, VTune, Allinea-MAP, CrayPAT, Nsight-Systems, Nsight-Compute, dan NVProf.
Timemory menyediakan API C/C++/Fortran front-end dan API Python yang memungkinkan pemilihan 50+ komponen berbeda secara sewenang-wenang mulai dari pengatur waktu, penghitung perangkat keras, hingga antarmuka dengan alat pihak ketiga. Ini semua dibuat secara umum dari API toolkit dengan kumpulan alat yang aman untuk tipe seperti: component_tuple<wall_clock, papi_vector, nvtx_marker, user_bundle>
di mana wall_clock
adalah pengatur waktu jam dinding, papi_vector
adalah pegangan untuk penghitung perangkat keras, nvxt_marker
membuat notasi di profiler NVIDIA CUDA, dan user_bundle
adalah komponen umum di mana pengguna hilir dapat memasukkan lebih banyak komponen ke dalamnya saat runtime.
Komponen pengukuran kinerja yang ditulis dengan timemory dapat diskalakan secara sewenang-wenang hingga sejumlah thread dan proses dan sepenuhnya mendukung pencampuran pengukuran yang berbeda di lokasi berbeda dalam program -- hal ini secara unik memungkinkan timemory diterapkan untuk mengumpulkan data kinerja dalam skala besar di HPC karena pengumpulannya sangat detail dapat terjadi di lokasi tertentu dalam program di mana pengumpulan di mana-mana akan menurunkan kinerja secara signifikan dan memerlukan jumlah memori yang sangat besar.
Timemory dapat digunakan sebagai backend untuk menggabungkan instrumentasi dan alat pengambilan sampel, mendukung serialisasi ke JSON/XML, dan menyediakan statistik serta kegunaan lainnya. Ini juga dapat digunakan sebagai front-end untuk menjalankan instrumentasi khusus dan alat pengambilan sampel. Timemory menggunakan istilah abstrak "komponen" untuk struktur yang merangkum beberapa operasi analisis kinerja. Strukturnya mungkin merangkum pemanggilan fungsi ke alat lain, mencatat stempel waktu untuk pengaturan waktu, mencatat nilai yang disediakan oleh aplikasi, menyediakan operator untuk mengganti fungsi dalam kode secara dinamis, mengaudit argumen masuk dan/atau nilai kembalian keluar dari fungsi, atau hanya menyediakan stub yang dapat kelebihan beban oleh linker.
Format keluaran asli timemory adalah JSON dan teks; format keluaran lain seperti XML juga didukung. Format teks dimaksudkan agar dapat dibaca manusia. Data JSON dimaksudkan untuk analisis dan hadir dalam dua bentuk: hierarki dan datar. Kemampuan pembuatan plot dasar tersedia melalui timemory-plotting
, tetapi pengguna sangat dianjurkan untuk menggunakan kapak untuk menganalisis data JSON hierarki dalam kerangka data pandas. Hatchet mendukung pemfilteran, penggabungan, penambahan, pengurangan, keluaran ke format dot
dan flamegraph, dan notebook Jupyter interaktif. Saat ini, timemory mendukung 45+ jenis metrik untuk analisis di Hatchet.
Ada 4 kategori utama dalam timemory: komponen, operasi, bundler, dan penyimpanan. Komponen menyediakan cara spesifik untuk melakukan perilaku tertentu, operasi menyediakan perancah untuk meminta komponen melakukan operasi dalam skenario yang kompleks, bundler mengelompokkan komponen ke dalam satu pegangan generik, dan penyimpanan mengelola pengumpulan data selama masa pakai aplikasi. Ketika keempat kategori digabungkan, timemory secara efektif menyerupai alat analisis kinerja standar yang secara pasif mengumpulkan data dan memberikan laporan serta analisis pada saat penghentian aplikasi. Namun, Timemory membuatnya sangat mudah untuk mengurangi penyimpanan dari persamaan dan, dengan melakukan hal tersebut, mengubah timemory menjadi perangkat untuk pengumpulan data yang disesuaikan.
tim::component::wall_clock
: pengatur waktu jam dinding sederhanatim::component::vtune_profiler
: komponen sederhana yang menghidupkan dan mematikan VTune Profiler (saat VTune aktif membuat profil aplikasi)tim::component::data_tracker_integer
: mengaitkan nilai integer dengan label saat aplikasi dijalankan (misalnya jumlah iterasi loop yang digunakan di suatu tempat)tim::component::papi_vector
: menggunakan perpustakaan PAPI untuk mengumpulkan nilai penghitung perangkat kerastim::component::user_bundle
: merangkum array komponen yang dapat dimanipulasi secara dinamis oleh pengguna selama runtimetim::operation::start<wall_clock>
akan mencoba memanggil fungsi anggota start()
pada instance komponen wall_clock
wall_clock
memiliki fungsi store(int)
? store()
?)tim::operation::start
: memerintahkan komponen untuk memulai pengumpulantim::operation::sample
: memerintahkan komponen untuk melakukan pengukuran individualtim::operation::derive
: data tambahan dari komponen lain jika tersediatim::auto_tuple
tim::component_tuple
tim::component_list
tim::lightweight_tuple
auto_tuple
memulai semua komponen ketika dibuat dan menghentikan semua komponen ketika dihancurkan sedangkan component_tuple
memerlukan permulaan yang eksplisitcomponent_tuple
mengalokasikan semua komponen pada tumpukan dan komponen "selalu aktif" sedangkan component_list
mengalokasikan komponen pada tumpukan dan dengan demikian komponen dapat diaktifkan/dinonaktifkan saat runtimelightweight_tuple
tidak secara implisit melakukan tindakan mahal apa pun, seperti pelacakan tumpukan panggilan di "Penyimpanan"CATATAN:
tim::lightweight_tuple
adalah paket yang direkomendasikan bagi mereka yang ingin menggunakan timemory sebagai perangkat untuk mengimplementasikan alat dan antarmuka khusus
timemory-avail
disediakan sebagai kelas Python yang berdiri sendiritime
UNIX yang mencakup informasi tambahan tentang penggunaan memori, sakelar konteks, dan penghitung perangkat kerasnvidia-smi
timemory-python-profiler
from timemory.profiler import Profile
timemory-python-trace
from timemory.trace import Trace
timemory-python-line-profiler
from timemory.line_profiler import LineProfiler
Berbagai makro didefinisikan untuk C di source/timemory/compat/timemory_c.h dan source/timemory/variadic/macros.hpp. Banyak contoh penggunaannya dapat ditemukan dalam contoh.
# include " timemory/timemory.hpp "
namespace comp = tim::component;
using namespace tim ;
// specific set of components
using specific_t = component_tuple<comp::wall_clock, comp::cpu_clock>;
using generic_t = component_tuple<comp::user_global_bundle>;
int
main ( int argc, char ** argv)
{
// configure default settings
settings::flat_profile () = true ;
settings::timing_units () = " msec " ;
// initialize with cmd-line
timemory_init (argc, argv);
// add argparse support
timemory_argparse (&argc, &argv);
// create a region "main"
specific_t m{ " main " };
m. start ();
m. stop ();
// pause and resume collection globally
settings::enabled () = false ;
specific_t h{ " hidden " };
h. start (). stop ();
settings::enabled () = true ;
// Add peak_rss component to specific_t
mpl:: push_back_t < specific_t , comp::peak_rss> wprss{ " with peak_rss " };
// create region collecting only peak_rss
component_tuple<comp::peak_rss> oprss{ " only peak_rss " };
// convert component_tuple to a type that starts/stops upon construction/destruction
{
scope::config _scope{};
if ( true ) _scope += scope::flat{};
if ( false ) _scope += scope::timeline{};
convert_t < specific_t , auto_tuple<>> scoped{ " scoped start/stop + flat " , _scope };
// will yield auto_tuple<comp::wall_clock, comp::cpu_clock>
}
// configure the generic bundle via set of strings
runtime::configure<comp::user_global_bundle>({ " wall_clock " , " peak_rss " });
// configure the generic bundle via set of enumeration ids
runtime::configure<comp::user_global_bundle>({ TIMEMORY_WALL_CLOCK, TIMEMORY_CPU_CLOCK });
// configure the generic bundle via component instances
comp::user_global_bundle::configure<comp::page_rss, comp::papi_vector>();
generic_t g{ " generic " , quirk::config<quirk::auto_start>{} };
g. stop ();
// Output the results
timemory_finalize ();
return 0 ;
}
# include " timemory/library.h "
# include " timemory/timemory.h "
int
main ( int argc, char ** argv)
{
// configure settings
int overwrite = 0 ;
int update_settings = 1 ;
// default to flat-profile
timemory_set_environ ( " TIMEMORY_FLAT_PROFILE " , " ON " , overwrite, update_settings);
// force timing units
overwrite = 1 ;
timemory_set_environ ( " TIMEMORY_TIMING_UNITS " , " msec " , overwrite, update_settings);
// initialize with cmd-line
timemory_init_library (argc, argv);
// check if inited, init with name
if (! timemory_library_is_initialized ())
timemory_named_init_library ( " ex-c " );
// define the default set of components
timemory_set_default ( " wall_clock, cpu_clock " );
// create a region "main"
timemory_push_region ( " main " );
timemory_pop_region ( " main " );
// pause and resume collection globally
timemory_pause ();
timemory_push_region ( " hidden " );
timemory_pop_region ( " hidden " );
timemory_resume ();
// Add/remove component(s) to the current set of components
timemory_add_components ( " peak_rss " );
timemory_remove_components ( " peak_rss " );
// get an identifier for a region and end it
uint64_t idx = timemory_get_begin_record ( " indexed " );
timemory_end_record (idx);
// assign an existing identifier for a region
timemory_begin_record ( " indexed/2 " , &idx);
timemory_end_record (idx);
// create region collecting a specific set of data
timemory_begin_record_enum ( " enum " , &idx, TIMEMORY_PEAK_RSS, TIMEMORY_COMPONENTS_END);
timemory_end_record (idx);
timemory_begin_record_types ( " types " , &idx, " peak_rss " );
timemory_end_record (idx);
// replace current set of components and then restore previous set
timemory_push_components ( " page_rss " );
timemory_pop_components ();
timemory_push_components_enum ( 2 , TIMEMORY_WALL_CLOCK, TIMEMORY_CPU_CLOCK);
timemory_pop_components ();
// Output the results
timemory_finalize_library ();
return 0 ;
}
program fortran_example
use timemory
use iso_c_binding, only : C_INT64_T
implicit none
integer (C_INT64_T) :: idx
! initialize with explicit name
call timemory_init_library( " ex-fortran " )
! initialize with name extracted from get_command_argument( 0 , ...)
! call timemory_init_library( " " )
! define the default set of components
call timemory_set_default( " wall_clock, cpu_clock " )
! Start region " main "
call timemory_push_region( " main " )
! Add peak_rss to the current set of components
call timemory_add_components( " peak_rss " )
! Nested region " inner " nested under " main "
call timemory_push_region( " inner " )
! End the " inner " region
call timemory_pop_region( " inner " )
! remove peak_rss
call timemory_remove_components( " peak_rss " )
! begin a region and get an identifier
idx = timemory_get_begin_record( " indexed " )
! replace current set of components
call timemory_push_components( " page_rss " )
! Nested region " inner " with only page_rss components
call timemory_push_region( " inner (pushed) " )
! Stop " inner " region with only page_rss components
call timemory_pop_region( " inner (pushed) " )
! restore previous set of components
call timemory_pop_components()
! end the " indexed " region
call timemory_end_record(idx)
! End " main "
call timemory_pop_region( " main " )
! Output the results
call timemory_finalize_library()
end program fortran_example
from timemory . bundle import marker
@ marker ([ "cpu_clock" , "peak_rss" ])
def foo ():
pass
from timemory . profiler import profile
def bar ():
with profile ([ "wall_clock" , "cpu_util" ]):
foo ()
from timemory . component import WallClock
def spam ():
wc = WallClock ( "spam" )
wc . start ()
bar ()
wc . stop ()
data = wc . get ()
print ( data )
import argparse
parser = argparse . ArgumentParser ( "example" )
# ...
timemory . add_arguments ( parser )
args = parser . parse_args ()
from timemory . storage import WallClockStorage
# data for current rank
data = WallClockStorage . get ()
# combined data on rank zero but all ranks must call it
dmp_data = WallClockStorage . dmp_get ()
Timemory berasal dari alat yang sangat sederhana untuk mencatat pengukuran waktu dan memori (sesuai dengan namanya) dalam C, C++, dan Python dan hanya mendukung tiga mode sebelum rilis 3.0.0: satu set pengatur waktu tetap, sepasang pengukuran memori, dan kombinasi keduanya. Sebelum rilis 3.0.0, timemory hampir seluruhnya ditulis ulang dari awal dengan satu-satunya pengecualian pada beberapa makro C/C++, misalnya TIMEMORY_AUTO_TIMER
, dan beberapa dekorator dan pengelola konteks Python, misalnya timemory.util.auto_timer
, yang perilakunya mampu sepenuhnya direplikasi dalam rilis baru. Oleh karena itu, meskipun timemory tampak sebagai proyek yang matang di v3.0+, pada dasarnya proyek ini masih dalam rilis besar pertamanya.
Untuk referensi timemory dalam sebuah publikasi, silakan mengutip makalah berikut:
Untuk informasi lebih lanjut, lihat dokumentasi.