Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python: add wrapper code for ITT-NERSC implementation to ensure compatibility #153

Merged
merged 34 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a200a14
Added the wrapper code for ITT-NERSC on ITTAPI
mk-srivastava Jul 21, 2024
1306c7a
VASP-30439: debug messages removed
mk-srivastava Jul 21, 2024
862ac92
VASP-30439: Function message changes
mk-srivastava Jul 21, 2024
d61277f
VASP-30439: collection_control sample added
mk-srivastava Jul 21, 2024
3bd826c
VASP-30439: comments changed
mk-srivastava Jul 21, 2024
79b88e8
VASP-30439: minor changes related to messages and include libraries
mk-srivastava Jul 21, 2024
781ccfb
minor changes related to removal the debug messages
mk-srivastava Jul 21, 2024
020db31
VASP-31359: Added unit testcases for NERSC adapter code
mk-srivastava Jul 22, 2024
e61caf1
removed itt_NERSC namespace from ittapi.native and renamed the module…
mk-srivastava Jul 24, 2024
e217e55
renaming the adapter module to 'compat'
mk-srivastava Jul 25, 2024
ea6c08a
renaming the adapter module to 'ittapi.compat'
mk-srivastava Jul 25, 2024
4a73f7f
removed redundant files
mk-srivastava Jul 25, 2024
df1ffe6
removed redundant functions from module ittapi.compat by existing fun…
mk-srivastava Jul 26, 2024
737f068
indentation changed
mk-srivastava Jul 31, 2024
d29dde4
ittapi.compat section added to README.md
mk-srivastava Aug 2, 2024
4495846
ittapi.compat section added to README.md
mk-srivastava Aug 2, 2024
ddc77ca
function message changed
mk-srivastava Aug 2, 2024
0632d80
README related changes for ittapi.compat
mk-srivastava Aug 2, 2024
cd68713
indentation changes
mk-srivastava Aug 2, 2024
61978b6
ittapi.compat README wording changed
mk-srivastava Aug 2, 2024
7c8279c
coding section format changed in readme
mk-srivastava Aug 3, 2024
c2c8b0c
indentation changes
mk-srivastava Aug 3, 2024
639a663
Merge branch 'master' into dev_VASP-30439
eparshut Aug 5, 2024
0f32a6c
added pt_region support to main ittapi module
mk-srivastava Aug 5, 2024
dcd802a
minor hyperlink related change
mk-srivastava Aug 5, 2024
5c920a7
hyperlink related changes
mk-srivastava Aug 5, 2024
9818309
indentation changes
mk-srivastava Aug 5, 2024
48a579d
indentation changes
mk-srivastava Aug 5, 2024
ab3fdb9
pt_region_create function moved to main ittapi module
mk-srivastava Aug 6, 2024
3ea58aa
pt_region_create, pt_region_begin and pt_region_end removed from main…
mk-srivastava Aug 6, 2024
d50f14d
endline related fixes
mk-srivastava Aug 7, 2024
292bccd
endline related fixes
mk-srivastava Aug 7, 2024
8430c7f
ittapi.compat README changes
mk-srivastava Aug 7, 2024
8535d44
ittapi updated to 1.2.0 from 1.1.0
mk-srivastava Aug 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 68 additions & 14 deletions python/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
# ittapi

ittapi is a Python binding to Intel Instrumentation and Tracing Technology (ITT) API. It provides a convenient way
to mark up the Python code for further performance analysis using performance analyzers from Intel like Intel VTune
or others.

ittapi supports following ITT APIs:
- Collection Control API
- Domain API
- Event API
- Id API
- String Handle API
- Task API
- Thread Naming API
ittapi is a Python binding to Intel Instrumentation and Tracing Technology (ITT) API. It provides a convenient way to mark up the Python code for further performance analysis using performance analyzers from Intel like Intel VTune or others.

The ittapi package has following modules:
- ittapi module - The module consists of main ITT APIs and supports following ITT APIs:

- Collection Control API
- Domain API
- Event API
- Id API
- String Handle API
- Task API
- Thread Naming API

- ittapi.compat module : The module is a wrapper to an earlier implementation of ITT API: (https://github.com/oleksandr-pavlyk/itt-python/tree/master). The idea is to allow users to effortlessly migrate to this new package without losing any existing functionality. The module is a wrapper to following ITT APIs:
eparshut marked this conversation as resolved.
Show resolved Hide resolved

- Collection Control API
- Domain API
- Task API
- Process Trace Region API


## Usage

### ittapi module

The main goal of the project is to provide the ability to instrument a Python code using ITT API in the Pythonic way.
ittapi provides wrappers that simplify markup of Python code.

Expand Down Expand Up @@ -57,11 +67,55 @@ If the task name is not specified, the `ittapi.task` uses call site information
the name to the task. A custom name for the task and other task parameters can be specified via arguments
for `ittapi.task` in the same way as for the decorator form.

### ittapi.compat module

#### Collection Control API

The `pause` and `resume` enables to focus the collection on a specific section of code while profiling, and start the application run with collection paused.

The `detach` detaches the data collection. Application continues to work but no data is collected while profiling.

import ittapi.compat as itt
# ... uninteresting code
itt.resume()
# ... very interesting code
itt.pause()
# ... boring stuff again
itt.resume()
# ... interesting code
itt.detach()
# ... uninteresting code like writing output

If the above code snipped is profiled with VTune or others, the execution begins with collection paused and only the interesting part of the code is profiled.

#### Domain API

A domain enables tagging trace data for different modules or libraries in a program.

import ittapi.compat as itt

domain = itt.domain_create("<Domain Name>")

Above code snippet creates a domain with the given `Domain name` and returns a Domain object created with the given name. If `Domain name` is left empty then default Domain object with name as `ittapi` will be returned.

#### Task API

import ittapi.compat as itt

domain = itt.domain_create("ittapi")
itt.task_begin(domain, <Task Name>)
# ... Task code
itt.task_end(domain)

If the above code is profiled with the VTune or others,
`task_begin` creates a task instance on a thread with name as `Task Name`. This becomes the current task instance for that thread. A call to `task_end` on the same thread ends the current task instance.


## Installation

[TODO] intel-ittapi package is available on PyPi and can be installed in the usual way for the supported configurations:
ittapi package is available on PyPi and can be installed in the usual way for the supported configurations:

[TODO] pip install intel-ittapi
pip install ittapi
mk-srivastava marked this conversation as resolved.
Show resolved Hide resolved

## Build

Expand Down
4 changes: 4 additions & 0 deletions python/ittapi.native/ittapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "string_handle.hpp"
#include "task.hpp"
#include "thread_naming.hpp"
#include "pt_region.hpp"


namespace ittapi
Expand All @@ -32,6 +33,8 @@ static int exec_ittapi_module(PyObject* module)
{"task_end", task_end, METH_VARARGS, "Marks the end of a task."},
{"task_begin_overlapped", task_begin_overlapped, METH_VARARGS, "Marks the beginning of an overlapped task."},
{"task_end_overlapped", task_end_overlapped, METH_VARARGS, "Marks the end of an overlapped task."},
{"pt_region_begin", pt_region_begin, METH_VARARGS, "Marks the begining of a processor trace control region"},
{"pt_region_end", pt_region_end, METH_VARARGS, "Marks the ending of a processor trace control region"},
eparshut marked this conversation as resolved.
Show resolved Hide resolved
/* marks end of array */
{ nullptr },
};
Expand Down Expand Up @@ -61,6 +64,7 @@ PyMODINIT_FUNC PyInit_native()
{ Py_mod_exec, reinterpret_cast<void*>(exec_event) },
{ Py_mod_exec, reinterpret_cast<void*>(exec_id) },
{ Py_mod_exec, reinterpret_cast<void*>(exec_string_handle) },
{ Py_mod_exec, reinterpret_cast<void*>(exec_pt_region) },
{ 0, nullptr }
};

Expand Down
269 changes: 269 additions & 0 deletions python/ittapi.native/pt_region.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
#include "pt_region.hpp"

#include <structmember.h>

#include "string_handle.hpp"
#include "extensions/string.hpp"

namespace ittapi
{

template<typename T>
T* pt_region_cast(PT_Region* self);

template <>
PyObject* pt_region_cast(PT_Region* self)
{
return reinterpret_cast<PyObject*>(self);
}

static PyObject* pt_region_new(PyTypeObject* type, PyObject* args, PyObject* kwargs);
static void pt_region_dealloc(PyObject* self);

static PyObject* pt_region_repr(PyObject* self);
static PyObject* pt_region_str(PyObject* self);

static PyMemberDef pt_region_attrs[] =
{
{"name", T_OBJECT, offsetof(PT_Region, name), READONLY, "a pt_region name"},
{nullptr},
};

PyTypeObject PT_RegionType =
{
.ob_base = PyVarObject_HEAD_INIT(nullptr, 0)
.tp_name = "ittapi.native.PT_Region",
.tp_basicsize = sizeof(PT_Region),
.tp_itemsize = 0,

/* Methods to implement standard operations */
.tp_dealloc = pt_region_dealloc,
.tp_vectorcall_offset = 0,
.tp_getattr = nullptr,
.tp_setattr = nullptr,
.tp_as_async = nullptr,
.tp_repr = pt_region_repr,

/* Method suites for standard classes */
.tp_as_number = nullptr,
.tp_as_sequence = nullptr,
.tp_as_mapping = nullptr,

/* More standard operations (here for binary compatibility) */
.tp_hash = nullptr,
.tp_call = nullptr,
.tp_str = pt_region_str,
.tp_getattro = nullptr,
.tp_setattro = nullptr,

/* Functions to access object as input/output buffer */
.tp_as_buffer = nullptr,

/* Flags to define presence of optional/expanded features */
.tp_flags = Py_TPFLAGS_DEFAULT,

/* Documentation string */
.tp_doc = "A class that represents a __itt_pt_region(__itt_pt_region -> unsigned char)",

/* Assigned meaning in release 2.0 call function for all accessible objects */
.tp_traverse = nullptr,

/* Delete references to contained objects */
.tp_clear = nullptr,

/* Assigned meaning in release 2.1 rich comparisons */
.tp_richcompare = nullptr,

/* weak reference enabler */
.tp_weaklistoffset = 0,

/* Iterators */
.tp_iter = nullptr,
.tp_iternext = nullptr,

/* Attribute descriptor and subclassing stuff */
.tp_methods = nullptr,
.tp_members = pt_region_attrs,
.tp_getset = nullptr,

/* Strong reference on a heap type, borrowed reference on a static type */
.tp_base = nullptr,
.tp_dict = nullptr,
.tp_descr_get = nullptr,
.tp_descr_set = nullptr,
.tp_dictoffset = 0,
.tp_init = nullptr,
.tp_alloc = nullptr,
.tp_new = pt_region_new,

/* Low-level free-memory routine */
.tp_free = nullptr,

/* For PyObject_IS_GC */
.tp_is_gc = nullptr,
.tp_bases = nullptr,

/* method resolution order */
.tp_mro = nullptr,
.tp_cache = nullptr,
.tp_subclasses = nullptr,
.tp_weaklist = nullptr,
.tp_del = nullptr,

/* Type attribute cache version tag. Added in version 2.6 */
.tp_version_tag = 0,

.tp_finalize = nullptr,
.tp_vectorcall = nullptr,
};

static PyObject* pt_region_new(PyTypeObject* type, PyObject* args, PyObject* kwargs)
{
PT_Region* self = pt_region_obj(type->tp_alloc(type,0));
if (self == nullptr)
{
return nullptr;
}

char name_key[] = { "name" };
char* kwlist[] = { name_key, nullptr };

PyObject* name = nullptr;

if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &name))
{
return nullptr;
}

if (name && PyUnicode_Check(name))
{
self->name = pyext::new_ref(name);
}
else if (name && Py_TYPE(name) == &StringHandleType)
{
self->name = pyext::new_ref(string_handle_obj(name)->str);
}
else
{
Py_DecRef(pt_region_cast<PyObject>(self));

PyErr_SetString(PyExc_TypeError, "The passed string to create pt_region is not a valid instance of neither str nor StringHandle");
return nullptr;
}

pyext::string name_str = pyext::string::from_unicode(self->name);
if (name_str.c_str() == nullptr)
{
Py_DecRef(pt_region_cast<PyObject>(self));
return nullptr;
}

#if defined(_WIN32)
self->handle=__itt_pt_region_createW(name_str.c_str());
#else
self->handle=__itt_pt_region_create(name_str.c_str());
#endif

return pt_region_cast<PyObject>(self);
}

static void pt_region_dealloc(PyObject* self)
{
if (self == nullptr)
{
return;
}

PT_Region* obj = pt_region_obj(self);
Py_XDECREF(obj->name);
}

static PyObject* pt_region_repr(PyObject* self)
{
PT_Region* obj = pt_region_check(self);
if (obj == nullptr)
{
return nullptr;
}

if (obj->name == nullptr)
{
PyErr_SetString(PyExc_AttributeError, "The name attribute has not been initialized.");
return nullptr;
}

return PyUnicode_FromFormat("%s('%U')", PT_RegionType.tp_name, obj->name);
}

static PyObject* pt_region_str(PyObject* self)
{
PT_Region* obj = pt_region_check(self);
if (obj == nullptr)
{
return nullptr;
}

if (obj->name == nullptr)
{
PyErr_SetString(PyExc_AttributeError, "The name attribute has not been initialized.");
return nullptr;
}

return pyext::new_ref(obj->name);
}

PT_Region* pt_region_check(PyObject* self)
{
if (self == nullptr || Py_TYPE(self) != &PT_RegionType)
{
PyErr_SetString(PyExc_TypeError, "The passed pt_region is not a valid instance of PT_Region type.");
return nullptr;
}

return pt_region_obj(self);
}

int exec_pt_region(PyObject* module)
{
return pyext::add_type(module, &PT_RegionType);
}

PyObject* pt_region_begin(PyObject* self, PyObject* args)
{
PyObject* pt_region = nullptr;
if (!PyArg_ParseTuple(args, "O", &pt_region))
{
return nullptr;
}

PT_Region *pt_region_obj = pt_region_check(pt_region);
if (pt_region_obj == nullptr)
{
return nullptr;
}

__itt_mark_pt_region_begin(pt_region_obj->handle);

Py_RETURN_NONE;
}

PyObject* pt_region_end(PyObject* self, PyObject* args)
{
PyObject* pt_region = nullptr;
if (!PyArg_ParseTuple(args, "O", &pt_region))
{
return nullptr;
}

PT_Region *pt_region_obj = pt_region_check(pt_region);
if (pt_region_obj == nullptr)
{
return nullptr;
}

__itt_mark_pt_region_end(pt_region_obj->handle);

Py_RETURN_NONE;
}

} // namespace ittapi
eparshut marked this conversation as resolved.
Show resolved Hide resolved
Loading