Skip to content

Commit 780a2bd

Browse files
committed
Multiprocessing spawn improvements
* Use new inner context builder * Reuse parsed and compiled code for worker context entrypoint
1 parent cec8a16 commit 780a2bd

File tree

3 files changed

+22
-15
lines changed

3 files changed

+22
-15
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,11 +1035,15 @@ public SharedMultiprocessingData getSharedMultiprocessingData() {
10351035

10361036
public long spawnTruffleContext(int fd, int sentinel, int[] fdsToKeep) {
10371037
ChildContextData data = new ChildContextData(isChildContext() ? childContextData.parentCtx : this);
1038-
1039-
Builder builder = data.parentCtx.env.newContextBuilder().config(PythonContext.CHILD_CONTEXT_DATA, data);
1038+
Builder builder = data.parentCtx.env.newInnerContextBuilder().//
1039+
forceSharing(getOption(PythonOptions.ForceSharingForInnerContexts)).//
1040+
inheritAllAccess(true).//
1041+
initializeCreatorContext(true).//
1042+
// TODO always force java posix in spawned: test_multiprocessing_spawn fails
1043+
// with that. Gives "OSError: [Errno 9] Bad file number"
1044+
// option("python.PosixModuleBackend", "java").//
1045+
config(PythonContext.CHILD_CONTEXT_DATA, data);
10401046
Thread thread = data.parentCtx.env.createThread(new ChildContextThread(fd, sentinel, data, builder));
1041-
1042-
// TODO always force java posix in spawned
10431047
long tid = thread.getId();
10441048
getSharedMultiprocessingData().putChildContextThread(tid, thread);
10451049
getSharedMultiprocessingData().putChildContextData(tid, data);
@@ -1065,6 +1069,11 @@ public synchronized List<Integer> getChildContextFDs() {
10651069
}
10661070

10671071
private static class ChildContextThread implements Runnable {
1072+
private static final TruffleLogger MULTIPROCESSING_LOGGER = PythonLanguage.getLogger(ChildContextThread.class);
1073+
private static final Source MULTIPROCESSING_SOURCE = Source.newBuilder(PythonLanguage.ID,
1074+
"from multiprocessing.spawn import spawn_truffleprocess; spawn_truffleprocess(fd, sentinel)",
1075+
"<spawned-child-context>").internal(true).build();
1076+
10681077
private final int fd;
10691078
private final ChildContextData data;
10701079
private final Builder builder;
@@ -1080,28 +1089,24 @@ public ChildContextThread(int fd, int sentinel, ChildContextData data, Builder b
10801089
@Override
10811090
public void run() {
10821091
try {
1083-
LOGGER.fine("starting spawned child context");
1084-
Source source = Source.newBuilder(PythonLanguage.ID,
1085-
"from multiprocessing.spawn import spawn_truffleprocess; spawn_truffleprocess(" + fd + ", " + sentinel + ")",
1086-
"<spawned-child-context>").internal(true).build();
1087-
CallTarget ct;
1092+
MULTIPROCESSING_LOGGER.fine("starting spawned child context");
10881093
TruffleContext ctx = builder.build();
10891094
data.setTruffleContext(ctx);
10901095
Object parent = ctx.enter(null);
1091-
ct = PythonContext.get(null).getEnv().parsePublic(source);
1096+
CallTarget ct = PythonContext.get(null).getEnv().parsePublic(MULTIPROCESSING_SOURCE, "fd", "sentinel");
10921097
try {
10931098
data.running.countDown();
1094-
Object res = ct.call();
1099+
Object res = ct.call(fd, sentinel);
10951100
int exitCode = CastToJavaIntLossyNode.getUncached().execute(res);
10961101
data.setExitCode(exitCode);
10971102
} finally {
10981103
ctx.leave(null, parent);
10991104
if (data.compareAndSetExiting(false, true)) {
11001105
try {
11011106
ctx.close();
1102-
LOGGER.log(Level.FINE, "closed spawned child context");
1107+
MULTIPROCESSING_LOGGER.log(Level.FINE, "closed spawned child context");
11031108
} catch (Throwable t) {
1104-
LOGGER.log(Level.FINE, t, () -> "exception while closing spawned child context");
1109+
MULTIPROCESSING_LOGGER.log(Level.FINE, "exception while closing spawned child context", t);
11051110
}
11061111
}
11071112
data.parentCtx.sharedMultiprocessingData.closePipe(sentinel);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ private PythonOptions() {
286286
@Option(category = OptionCategory.EXPERT, usageSyntax = "true|false", help = "Propagate append operations to lists created as literals back to where they were created, to inform overallocation to avoid having to grow them later.") //
287287
public static final OptionKey<Boolean> OverallocateLiteralLists = new OptionKey<>(true);
288288

289+
@Option(category = OptionCategory.EXPERT, usageSyntax = "true|false", help = "Forces AST sharing for inner contexts.") //
290+
public static final OptionKey<Boolean> ForceSharingForInnerContexts = new OptionKey<>(true);
291+
289292
@EngineOption @Option(category = OptionCategory.USER, usageSyntax = "true|false", help = "Emulate some Jython features that can cause performance degradation") //
290293
public static final OptionKey<Boolean> EmulateJython = new OptionKey<>(false);
291294

graalpython/lib-python/3/multiprocessing/spawn.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ def spawn_truffleprocess(fd, parent_sentinel):
144144
self = reduction.pickle.load(bytesIO)
145145
finally:
146146
del process.current_process()._inheriting
147-
exitcode = self._bootstrap(parent_sentinel)
148-
sys.exit(exitcode)
147+
return self._bootstrap(parent_sentinel)
149148
# End Truffle change
150149

151150
def _check_not_importing_main():

0 commit comments

Comments
 (0)