Logging
Section author: René Widera
Sometimes it is useful to get an overview about function call and additional low level information. Logging gives you a lightweight overview with a reduced callstack and meta information. Mostly leaf operation which calling native backends e.g.CUDA, HIP, and SYCL are instrumented. Via logging channels the scope of information can be filtered.
Logging Level
Via logging level the scope of information can be filtered.
Device=1- logs device information
Event=2- logs event information
Memory=4- logs memory information
Queue=8- logs queue information
Kernel=16- logs kernel information
CMake Logging Options
alpaka_LOG=<X>whereXcan beOFF- to disable logging, other CMake optionalpaka_LOG_*will not be available.static- will enable compile time logging where the logging level can be selected in CMake, additional CMake optionalpaka_LOG_STATIC_*will be available.dynamic- will enable runtime logging where the logging level can be selected via the environment variableALPAKA_LOG_DYNAMIC_LVL=<lvl>lvl- is the number of Logging Level or the sum of multiple lvl to select multiple levels at the within the same output
If logging is off there will be no runtime overhead introduced.
static- will introduce small overhead for message formating and the output. If a logging level is disabled these messages will be removed at compile time and no runtime overhead is introduced.dynamic- will introduce overhead for message formating and additional small overhead for a runtime lookup (one if condition).
alpaka_LOG_FUNCTIONS=<X>- whereXcan beONorOFFcreate a reduced call stack and show the function entry and exit. The exit will show the time in milliseconds between the entry and exit of the function.[Memory][+] void internal::generic::fill(auto:463&, auto:464, auto:465&&, T_Value) [with T_Value = unsigned int; auto:463 = onHost::cpu::Queue<...> > >; auto:464 = exec::CpuOmpBlocks; auto:465 = alpaka::View<...> >, alpaka::Alignment<...> >] [Memory][-] void internal::generic::fill(auto:463&, auto:464, auto:465&&, T_Value) [with T_Value = unsigned int; auto:463 = onHost::cpu::Queue<...> > >; auto:464 = exec::CpuOmpBlocks; auto:465 = alpaka::View<...> >, alpaka::Alignment<...> >] 0.247257 ms
alpaka_LOG_INFO=<X>- whereXcan beON` or ``OFFprovides meta information to different functions and objects. The alement of the output is the absolute path and line number of the file where the logging message is coming from[Memory] SharedBuffer{ dim=1, api= Host, extents={123456}, pitches={4} , alignment=16 } auto onHost::internal::Alloc::Op<...>, T_Extents>::operator()(onHost::cpu::Device<...>&, const T_Extents&) const [with T_Type = unsigned int; T_Platform = onHost::cpu::Platform<...>; T_Extents = alpaka::Vec<...> >] alpaka/api/host/Device.hpp:198
alpaka_LOG_DETAIL=<X>- whereXcan beshortorlongwhich will format the function name details.// short signature [Memory] SharedBuffer{ dim=1, api= Host, extents={123456}, pitches={4} , alignment=16 } auto onHost::internal::Alloc::Op<...>, T_Extents>::operator()(onHost::cpu::Device<...>&, const T_Extents&) const [with T_Type = unsigned int; T_Platform = onHost::cpu::Platform<...>; T_Extents = alpaka::Vec<...> >] alpaka/api/host/Device.hpp:198 // long signature [Memory] SharedBuffer{ dim=1, api= Host, extents={123456}, pitches={4} , alignment=16 } auto alpaka::onHost::internal::Alloc::Op<T_Type, alpaka::onHost::cpu::Device<T_Platform>, T_Extents>::operator()(alpaka::onHost::cpu::Device<T_Platform>&, const T_Extents&) const [with T_Type = unsigned int; T_Platform = alpaka::onHost::cpu::Platform<alpaka::deviceKind::Cpu>; T_Extents = alpaka::Vec<long unsigned int, 1, alpaka::ArrayStorage<long unsigned int, 1> >] alpaka/api/host/Device.hpp:198
alpaka_LOG_INDENT=<X>- whereXcan beONorOFFwhich will format the output fromalpaka_LOG_FUNCTIONSandalpaka_LOG_INFOdepending on the call stack depth.[Queue ][+]|- void onHost::internal::Fill::Op<...>, T_Dest, T_Value, T_Extents>::operator()(onHost::cpu::Queue<...>&, auto:515&&, T_Value, const T_Extents&) const requires (same_as<...>, T_Dest, T_Value, T_Extents>::operator()::dest)>::type, T_Dest>) && (same_as<...>, T_Dest, T_Value, T_Extents>::operator()::dest)>::type>::type, T_Value>) [with auto:515 = onHost::SharedBuffer<...> >, alpaka::Alignment<...> >&; T_Device = onHost::cpu::Device<...> >; T_Dest = onHost::SharedBuffer<...> >, alpaka::Alignment<...> >; T_Value = unsigned int; T_Extents = alpaka::Vec<...> >] [Memory][+]|--- void internal::generic::fill(auto:463&, auto:464, auto:465&&, T_Value) [with T_Value = unsigned int; auto:463 = onHost::cpu::Queue<...> > >; auto:464 = exec::CpuOmpBlocks; auto:465 = alpaka::View<...> >, alpaka::Alignment<...> >] [Memory] |----- fill{ extents={123456}, dst=View{ dim=1, api= Host, extents={123456}, pitches={4} , alignment=16 }, value_type=unsigned int, FrameSpec{ frames={15}, frameExtent={512}, ThreadSpec{ blocks={15}, threads={512} } } } void internal::generic::fill(auto:463&, auto:464, auto:465&&, T_Value) [with T_Value = unsigned int; auto:463 = onHost::cpu::Queue<...> > >; auto:464 = exec::CpuOmpBlocks; auto:465 = alpaka::View<...> >, alpaka::Alignment<...> >] /home/widera/workspace/alpaka2/include/alpaka/api/generic.hpp:63 [Memory][-]|--- void internal::generic::fill(auto:463&, auto:464, auto:465&&, T_Value) [with T_Value = unsigned int; auto:463 = onHost::cpu::Queue<...> > >; auto:464 = exec::CpuOmpBlocks; auto:465 = alpaka::View<...> >, alpaka::Alignment<...> >] 0.942437 ms [Queue ][-]|- void onHost::internal::Fill::Op<...>, T_Dest, T_Value, T_Extents>::operator()(onHost::cpu::Queue<...>&, auto:515&&, T_Value, const T_Extents&) const requires (same_as<...>, T_Dest, T_Value, T_Extents>::operator()::dest)>::type, T_Dest>) && (same_as<...>, T_Dest, T_Value, T_Extents>::operator()::dest)>::type>::type, T_Value>) [with auto:515 = onHost::SharedBuffer<...> >, alpaka::Alignment<...> >&; T_Device = onHost::cpu::Device<...> >; T_Dest = onHost::SharedBuffer<...> >, alpaka::Alignment<...> >; T_Value = unsigned int; T_Extents = alpaka::Vec<...> >] 1.12421 ms
The following CMake options requires alpaka_LOG=static
alpaka_LOG_STATIC_Device- activate logging for static device informationalpaka_LOG_STATIC_Event- activate logging for static event informationalpaka_LOG_STATIC_Memory- activate logging for static memory informationalpaka_LOG_STATIC_Queue- activate logging for static queue informationalpaka_LOG_STATIC_Kernel- activate logging for static kernel information
C++ Code logging
Logger level are required for both following calls:
alpaka::onHost::logger::Devicealpaka::onHost::logger::Eventalpaka::onHost::logger::Memoryalpaka::onHost::logger::Queuealpaka::onHost::logger::KernelThe logger function macro marking the scope of an function,
ALPAKA_LOG_FUNCTION()must be on the very beginning of the function. The entry is the macro function call and the exit is logged when the current scope is ending. This meansALPAKA_LOG_FUNCTION()is scope aware.void foo() { ALPAKA_LOG_FUNCTION(onHost::logger::device); // very complex code }
The logger function macro to output any kind of information,
ALPAKA_LOG_INFO()requires a lvl and a lambda function. The lambda is only called in case the logging level is selected. Capturing variable by reference preferred to keep the runtime overhead small.void foo(auto* ptr, auto extents) { ALPAKA_LOG_INFO( onHost::logger::memory, [&]() { std::stringstream ss; ss << "{extents=" << extents << ", ptr=" << ptr}"; return ss.str(); }); }
Logging levels can be combined via the plus operator. onHost::logger::memory + onHost::logger::device.
In this case the combined output level suffix will always show the first name even if this level is deactivated, this should keep the output readable.