Commit 94d3a016 authored by Jakob Luettgau's avatar Jakob Luettgau
Browse files

Add low-level interaction notebook example.

parent 447fb73f
%% Cell type:markdown id: tags:
# Direct Interaction with libdarshan-util.so
%% Cell type:markdown id: tags:
**Note:** In general be advised to use this interface with care until the API stablelized. Many parts of the functionality exposed here used to be for internal use by the command-line utilities only. For very performance sensitive analysis and for troubleshooting this notebook documents how to directly interface with libdarshan-util.so none the less.
%% Cell type:markdown id: tags:
A relatively convienient interface with C libraries is offered through CFFI:
https://cffi.readthedocs.io/en/latest/
"C Foreign Function Interface for Python. Interact with almost any C code from Python, based on C-like declarations that you can often copy-paste from header files or documentation."
To use, ensure cffi is installed:
pip install cffi
%% Cell type:code id: tags:
``` python
import cffi
import ctypes
```
%% Cell type:markdown id: tags:
CFFI can used in multiple different configruations allowing for different performance trade offs.
For PyDarshan we assume the library is proved as an already compiled binary (with CFFI in ABI mode), this way only valid header information for data types and function signatures have to be provided.
A valid set of headers is provided as part of `darshan.api_def_c`:
%% Cell type:code id: tags:
``` python
from darshan.api_def_c import load_darshan_header
API_def_c = load_darshan_header()
```
%% Cell type:markdown id: tags:
Setting up CFFI then only requires to initialize the Foreign Function Interface, and then load a shared library as follows:
%% Cell type:code id: tags:
``` python
ffi = cffi.FFI()
ffi.cdef(API_def_c)
libdutil = None
libdutil = ffi.dlopen("libdarshan-util.so")
```
%% Cell type:markdown id: tags:
Libdarshan-util provides functionality to interace with Darshan Log files. Analog to the typical C POSIX API darshan logs have first to be opened which returns a file handle which the user has to provide any followup operations.
%% Cell type:markdown id: tags:
The simplest interaction with library is just obtaining the library version which is hard coded into the library and can be obtained via ´darshan_log_get_lib_version()´ which returns a char*.
Similar to native C, a variable to hold the reference to the version string has to be provided which can be achieved like so and then gets populated by invoking the actual library function which is exposed as part of the CFFI Object:
%% Cell type:code id: tags:
``` python
ver = ffi.new("char **")
ver = libdutil.darshan_log_get_lib_version()
```
%% Cell type:markdown id: tags:
Before the string can be accessed as a normal Python object it needs to be transformed as follows:
%% Cell type:code id: tags:
``` python
version = ffi.string(ver).decode("utf-8")
version
```
%%%% Output: execute_result
'3.2.1'
%% Cell type:markdown id: tags:
### Fetching Records
%% Cell type:markdown id: tags:
A darshan log contains besides some metadata describing the instrumented execution primarily log records collected by the different modules in compressed form. To access these a number of library interactions have to be performed to capture individual records.
1) Open the log and optain a log handle
2) Request individual log records by requesting records for a particular index
Module indexes are defined in ´darshan-log-format.h´:
#define DARSHAN_MODULE_IDS \
X(DARSHAN_NULL_MOD, "NULL", DARSHAN_NULL_VER, NULL) \
X(DARSHAN_POSIX_MOD, "POSIX", DARSHAN_POSIX_VER, &posix_logutils) \
X(DARSHAN_MPIIO_MOD, "MPI-IO", DARSHAN_MPIIO_VER, &mpiio_logutils) \
X(DARSHAN_H5F_MOD, "H5F", DARSHAN_H5F_VER, &hdf5_file_logutils) \
X(DARSHAN_H5D_MOD, "H5D", DARSHAN_H5D_VER, &hdf5_dataset_logutils) \
X(DARSHAN_PNETCDF_MOD, "PNETCDF", DARSHAN_PNETCDF_VER, &pnetcdf_logutils) \
X(DARSHAN_BGQ_MOD, "BG/Q", DARSHAN_BGQ_VER, &bgq_logutils) \
X(DARSHAN_LUSTRE_MOD, "LUSTRE", DARSHAN_LUSTRE_VER, &lustre_logutils) \
X(DARSHAN_STDIO_MOD, "STDIO", DARSHAN_STDIO_VER, &stdio_logutils) \
/* DXT */ \
X(DXT_POSIX_MOD, "DXT_POSIX", DXT_POSIX_VER, &dxt_posix_logutils) \
X(DXT_MPIIO_MOD, "DXT_MPIIO", DXT_MPIIO_VER, &dxt_mpiio_logutils) \
X(DARSHAN_MDHIM_MOD, "MDHIM", DARSHAN_MDHIM_VER, &mdhim_logutils)
%% Cell type:code id: tags:
``` python
# open the log
handle = libdutil.darshan_log_open("example-logs/example.darshan".encode())
```
%% Cell type:code id: tags:
``` python
# fetch a posix record
buf = ffi.new("void **")
r = libdutil.darshan_log_get_record(handle, 1, buf)
rbuf = ffi.cast("struct darshan_posix_file **", buf)
```
%% Cell type:code id: tags:
``` python
dir(rbuf[0])
```
%%%% Output: execute_result
['base_rec', 'counters', 'fcounters']
%% Cell type:code id: tags:
``` python
"id: {}, rank: {}".format(rbuf[0].base_rec.id, rbuf[0].base_rec.rank)
```
%%%% Output: execute_result
'id: 6301063301082038805, rank: -1'
%% Cell type:code id: tags:
``` python
print([counter for counter in rbuf[0].counters])
```
%%%% Output: stream
[2049, -1, -1, 0, 16402, 16404, 0, 0, 0, 0, -1, -1, 0, 0, 0, 2199023259968, 0, 2199023261831, 0, 0, 0, 16384, 0, 0, 8, 16401, 1048576, 0, 134217728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 14, 0, 0, 0, 0, 0, 0, 16384, 0, 274743689216, 274743691264, 0, 0, 10240, 4096, 0, 0, 134217728, 272, 544, 328, 16384, 8, 2, 2, 597, 1073741824, 1312, 1073741824]
%% Cell type:code id: tags:
``` python
print([counter for counter in rbuf[0].fcounters])
```
%%%% Output: stream
[3.9191410541534424, 0.0, 3.940063953399658, 3.927093982696533, 3.936579942703247, 0.0, 115.0781660079956, 115.77035808563232, 0.0, 100397.60042190552, 11.300841808319092, 0.0, 17.940945863723755, 20.436099529266357, 85.47495031356812, 0.0, 0.0]
%% Cell type:code id: tags:
``` python
```
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment