Realm
A distributed, event-based tasking library
Loading...
Searching...
No Matches
python_internal.h
Go to the documentation of this file.
1/*
2 * Copyright 2025 Stanford University, NVIDIA Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef REALM_PYTHON_INTERNAL_H
19#define REALM_PYTHON_INTERNAL_H
20
21#include "realm/proc_impl.h"
22
24
25#if defined(REALM_USE_OPENMP) && !defined(REALM_OPENMP_SYSTEM_RUNTIME)
27#endif
28
29namespace Realm {
30
31#define USE_PYGILSTATE_CALLS
32
33 // these are all defined in Python.h, which we currently do not include
34 struct PyObject;
35 struct PyInterpreterState;
39 struct PyInterpreterState *interp;
40 // lots more stuff here
41 };
42 typedef ssize_t Py_ssize_t;
43#ifdef USE_PYGILSTATE_CALLS
49#endif
50
51 // This class contains interpreter-specific instances of Python API calls.
52 class PythonAPI {
53 public:
55
56 protected:
57 template <typename T>
58 void get_symbol(T &fn, const char *symbol, bool missing_ok = false);
59
60 protected:
61 void *handle;
62
63 public:
64 // Python API calls
65 void (*Py_DecRef)(PyObject *); // non-macro version of PyDECREF
66 void (*Py_Finalize)(void);
67 void (*Py_InitializeEx)(int);
68
69 PyObject *(*PyByteArray_FromStringAndSize)(const char *, Py_ssize_t);
70
71 void (*PyEval_InitThreads)(void);
72
73#ifdef USE_PYGILSTATE_CALLS
76#else
77 PyThreadState *(*PyThreadState_New)(PyInterpreterState *);
78 void (*PyThreadState_Clear)(PyThreadState *);
79 void (*PyThreadState_Delete)(PyThreadState *);
80#endif
82 PyThreadState *(*PyEval_SaveThread)(void);
83
84 PyThreadState *(*PyGILState_GetThisThreadState)(void);
85 PyThreadState *(*PyThreadState_Swap)(PyThreadState *);
86 PyThreadState *(*PyThreadState_Get)(void);
87 PyObject *(*PyThreadState_GetDict)(void);
88
89 void (*PyErr_PrintEx)(int set_sys_last_vars);
90
91 PyObject *(*PyImport_ImportModule)(const char *);
92
93 PyObject *(*PyModule_GetDict)(PyObject *);
94
95 PyObject *(*PyLong_FromUnsignedLong)(unsigned long);
96
97 PyObject *(*PyObject_CallFunction)(PyObject *, const char *, ...);
98 PyObject *(*PyObject_CallObject)(PyObject *callable, PyObject *args);
99 PyObject *(*PyObject_GetAttrString)(PyObject *, const char *);
100 // PyObject_Print is not abi3 compatible and is used exclusively for debugging
101 // int (*PyObject_Print)(PyObject *, FILE *, int);
102
103 PyObject *(*Py_CompileString)(const char *, const char *, int);
104 PyObject *(*PyEval_EvalCode)(PyObject *, PyObject *, PyObject *);
105
106 PyObject *(*PyTuple_New)(Py_ssize_t len);
107 int (*PyTuple_SetItem)(PyObject *p, Py_ssize_t pos, PyObject *o);
108 };
109
111 public:
114
116
117 void import_module(const std::string &module_name);
118 void run_string(const std::string &script_text);
120
121 protected:
122 void *handle;
123#ifdef REALM_USE_DLMOPEN
124 void *dlmproxy_handle;
125#endif
126
127 public:
129 };
130
132
133 // this is nearly identical to a LocalCPUProcessor, but it asks for its thread(s)
134 // to run on the specified numa domain
136 public:
137 LocalPythonProcessor(RuntimeImpl *runtime_impl, Processor _me, int _numa_node,
138 CoreReservationSet &crs, size_t _stack_size,
139#ifdef REALM_USE_OPENMP
140 int _omp_workers,
141#endif
142 const std::vector<std::string> &_import_modules,
143 const std::vector<std::string> &_init_scripts);
145
146 virtual void enqueue_task(Task *task);
147 virtual void enqueue_tasks(Task::TaskList &tasks, size_t num_tasks);
148
149 virtual void spawn_task(Processor::TaskFuncID func_id, const void *args,
150 size_t arglen, const ProfilingRequestSet &reqs,
151 Event start_event, GenEventImpl *finish_event,
152 EventImpl::gen_t finish_gen, int priority);
153
155 const ByteArrayRef &task_args);
156
157 // starts worker threads and performs any per-processor initialization
158 virtual void start_threads(void);
159
160 virtual void shutdown(void);
161
162 virtual void add_to_group(ProcessorGroupImpl *group);
163
165
166 virtual bool register_task(Processor::TaskFuncID func_id, CodeDescriptor &codedesc,
167 const ByteArrayRef &user_data);
168
169 // void worker_main(void);
170
185
186 protected:
191
194#if defined(REALM_USE_OPENMP) && !defined(REALM_OPENMP_SYSTEM_RUNTIME)
195 ThreadPool *omp_threadpool;
196#endif
197 const std::vector<std::string> &import_modules;
198 const std::vector<std::string> &init_scripts;
199
203
209
210 std::map<Processor::TaskFuncID, TaskTableEntry> task_table;
211
212 TaskQueue task_queue; // ready tasks
215 };
216
217 // based on KernelThreadTaskScheduler, deals with the python GIL and thread
218 // state changes as well
219
220 // Note! If you ever go to change the PythonThreadTaskScheduler to use the
221 // UserLevelTaskScheduler, you will need to update the implementation of
222 // how Python tasks are run. The CPython interpreter now has thread-local
223 // variables that track the PyThreadState object. It's not safe to use
224 // the same PyThreadState object across multiple live tasks running on
225 // the same kernel thread. Instead you'll need to modify the tasks running
226 // on the Python processor to each create their own PyThreadState object
227 // and then check that whenever they have been preempted (wait on an event)
228 // that this has been saved onto the stack and restored after the wait ends.
230 public:
232
233 // entry point for python worker threads - falls through to scheduler_loop
235
236 // called by a worker thread when it needs to wait for something (and we
237 // should release the GIL)
238 virtual void thread_blocking(Thread *thread);
239
240 virtual void thread_ready(Thread *thread);
241
242 protected:
243 // both real and internal tasks need to be wrapped with acquires of the GIL
244 virtual bool execute_task(Task *task);
246
247 virtual Thread *worker_create(bool make_active);
248 virtual void worker_terminate(Thread *switch_to);
249
252 std::map<Thread *, PyThreadState *> pythreads;
253 };
254
255}; // namespace Realm
256
257#endif // defined REALM_PYTHON_INTERNAL_H
Definition bytearray.h:30
Definition bytearray.h:53
Definition codedesc.h:249
Definition threads.h:382
Definition threads.h:342
unsigned gen_t
Definition event_impl.h:87
Definition event.h:50
Definition event_impl.h:198
Definition tasks.h:181
Definition tasks.h:392
Definition python_internal.h:171
virtual void execute_on_processor(Processor p)
Definition python_internal.h:175
LocalPythonProcessor * proc
Definition python_internal.h:180
CodeDescriptor * codedesc
Definition python_internal.h:182
virtual ~TaskRegistration()
Definition python_internal.h:173
Processor::TaskFuncID func_id
Definition python_internal.h:181
ByteArray user_data
Definition python_internal.h:183
Definition python_internal.h:135
int numa_node
Definition python_internal.h:192
LocalPythonProcessor(RuntimeImpl *runtime_impl, Processor _me, int _numa_node, CoreReservationSet &crs, size_t _stack_size, const std::vector< std::string > &_import_modules, const std::vector< std::string > &_init_scripts)
virtual bool register_task(Processor::TaskFuncID func_id, CodeDescriptor &codedesc, const ByteArrayRef &user_data)
virtual void enqueue_task(Task *task)
virtual void start_threads(void)
std::map< Processor::TaskFuncID, TaskTableEntry > task_table
Definition python_internal.h:210
CoreReservation * core_rsrv
Definition python_internal.h:193
virtual void remove_from_group(ProcessorGroupImpl *group)
TaskQueue task_queue
Definition python_internal.h:212
virtual ~LocalPythonProcessor(void)
PyThreadState * master_thread
Definition python_internal.h:202
PythonInterpreter * interpreter
Definition python_internal.h:201
virtual void enqueue_tasks(Task::TaskList &tasks, size_t num_tasks)
virtual void spawn_task(Processor::TaskFuncID func_id, const void *args, size_t arglen, const ProfilingRequestSet &reqs, Event start_event, GenEventImpl *finish_event, EventImpl::gen_t finish_gen, int priority)
const std::vector< std::string > & import_modules
Definition python_internal.h:197
bool perform_task_registration(TaskRegistration *treg)
DeferredSpawnCache deferred_spawn_cache
Definition python_internal.h:214
virtual void execute_task(Processor::TaskFuncID func_id, const ByteArrayRef &task_args)
const std::vector< std::string > & init_scripts
Definition python_internal.h:198
ProfilingGauges::AbsoluteRangeGauge< int > ready_task_count
Definition python_internal.h:213
PythonThreadTaskScheduler * sched
Definition python_internal.h:200
virtual void shutdown(void)
virtual void add_to_group(ProcessorGroupImpl *group)
Definition proc_impl.h:254
Definition proc_impl.h:51
Definition processor.h:37
::realm_task_func_id_t TaskFuncID
Definition processor.h:58
void(* TaskFuncPtr)(const void *args, size_t arglen, const void *user_data, size_t user_data_len, Processor proc)
Definition processor.h:59
Definition profiling.h:363
Definition python_internal.h:52
void(* Py_DecRef)(PyObject *)
Definition python_internal.h:65
void(* Py_Finalize)(void)
Definition python_internal.h:66
int(* PyTuple_SetItem)(PyObject *p, Py_ssize_t pos, PyObject *o)
Definition python_internal.h:107
void(* PyGILState_Release)(PyGILState_STATE)
Definition python_internal.h:75
void(* PyEval_InitThreads)(void)
Definition python_internal.h:71
void(* PyErr_PrintEx)(int set_sys_last_vars)
Definition python_internal.h:89
void(* PyEval_RestoreThread)(PyThreadState *)
Definition python_internal.h:81
void get_symbol(T &fn, const char *symbol, bool missing_ok=false)
PyGILState_STATE(* PyGILState_Ensure)(void)
Definition python_internal.h:74
void(* Py_InitializeEx)(int)
Definition python_internal.h:67
void * handle
Definition python_internal.h:61
PythonAPI(void *handle)
Definition python_internal.h:110
PyObject * find_or_import_function(const PythonSourceImplementation *psi)
void * handle
Definition python_internal.h:122
PythonAPI * api
Definition python_internal.h:128
void import_module(const std::string &module_name)
void run_string(const std::string &script_text)
Definition python_source.h:25
Definition python_internal.h:229
virtual void execute_internal_task(InternalTask *task)
virtual void thread_ready(Thread *thread)
virtual bool execute_task(Task *task)
virtual void worker_terminate(Thread *switch_to)
bool interpreter_ready
Definition python_internal.h:251
PythonThreadTaskScheduler(LocalPythonProcessor *_pyproc, CoreReservation &_core_rsrv)
std::map< Thread *, PyThreadState * > pythreads
Definition python_internal.h:252
virtual Thread * worker_create(bool make_active)
LocalPythonProcessor * pyproc
Definition python_internal.h:250
virtual void thread_blocking(Thread *thread)
Definition runtime_impl.h:264
Definition tasks.h:131
Definition tasks.h:41
Definition openmp_threadpool.h:66
Definition threads.h:89
Definition activemsg.h:38
PyGILState_STATE
Definition python_internal.h:45
@ PyGILState_LOCKED
Definition python_internal.h:46
@ PyGILState_UNLOCKED
Definition python_internal.h:47
ssize_t Py_ssize_t
Definition python_internal.h:42
#define REALM_USE_OPENMP
Definition realm_defines.h:46
Definition python_internal.h:204
PyObject * python_fnptr
Definition python_internal.h:205
ByteArray user_data
Definition python_internal.h:207
Processor::TaskFuncPtr cpp_fnptr
Definition python_internal.h:206
Definition python_internal.h:36
struct PyThreadState * next
Definition python_internal.h:38
struct PyThreadState * prev
Definition python_internal.h:37
struct PyInterpreterState * interp
Definition python_internal.h:39