Skip to content

Commit

Permalink
python: add wrapper code for ITT-NERSC implementation to ensure compa…
Browse files Browse the repository at this point in the history
…tibility (#153)

* Added the wrapper code for ITT-NERSC implementation of ITTAPI

* Added unit testcases for ittapi.compat adapter code

* Added ittapi.compat section to README.md

* Added pt_region support to main ittapi module

* Updated ittapi version to 1.2.0 from 1.1.0
  • Loading branch information
mk-srivastava authored Aug 7, 2024
1 parent 4febd9a commit fc432d1
Show file tree
Hide file tree
Showing 19 changed files with 654 additions and 7 deletions.
8 changes: 5 additions & 3 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ ittapi is a Python binding to Intel Instrumentation and Tracing Technology (ITT)
to mark up the Python code for further performance analysis using performance analyzers from Intel like Intel VTune
or others.

NOTE: For compatibility and smooth migration with earlier versions of Python bindings([itt-python](https://github.com/oleksandr-pavlyk/itt-python/)), please replace `import itt` with `import ittapi.compat as itt`. For more details about `ittapi.compat`, visit [ittapi.compat page](./ittapi/compat/README.md).

ittapi supports following ITT APIs:
- Collection Control API
- Domain API
Expand Down Expand Up @@ -59,9 +61,9 @@ for `ittapi.task` in the same way as for the decorator form.

## Installation

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

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

## Build

Expand Down
6 changes: 5 additions & 1 deletion 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,14 +33,16 @@ 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 end of a processor trace control region"},
/* marks end of array */
{ nullptr },
};

PyModule_AddFunctions(module, ittapi_functions);

PyModule_AddStringConstant(module, "__author__", "Egor Suldin");
PyModule_AddStringConstant(module, "__version__", "1.1.0");
PyModule_AddStringConstant(module, "__version__", "1.2.0");
PyModule_AddIntConstant(module, "year", 2024);

return 0;
Expand All @@ -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
35 changes: 35 additions & 0 deletions python/ittapi.native/pt_region.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include <ittnotify.h>

#include "extensions/python.hpp"

namespace ittapi
{

struct PT_Region
{
PyObject_HEAD
PyObject* name;
__itt_pt_region handle;
};

extern PyTypeObject PT_RegionType;

inline PT_Region* pt_region_obj(PyObject* self);
PT_Region* pt_region_check(PyObject* self);
int exec_pt_region(PyObject* module);

/* Implementation of inline functions */
PT_Region* pt_region_obj(PyObject* self)
{
return pyext::pyobject_cast<PT_Region>(self);
}

PyObject* pt_region_begin(PyObject* self, PyObject* args);
PyObject* pt_region_end(PyObject* self, PyObject* args);

} // namespace ittapi
1 change: 1 addition & 0 deletions python/ittapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
from .string_handle import string_handle
from .task import NestedTask, OverlappedTask, task, nested_task, overlapped_task
from .thread_naming import thread_set_name
from .pt_region import pt_region
Loading

0 comments on commit fc432d1

Please sign in to comment.