Skip to content

Commit 421dd8b

Browse files
committed
[GR-33794] Multiprocessing fixes
PullRequest: graalpython/1961
2 parents e0eb8e9 + 80704c8 commit 421dd8b

File tree

8 files changed

+223
-93
lines changed

8 files changed

+223
-93
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
This changelog summarizes major changes between GraalVM versions of the Python
44
language runtime. The main focus is on user-observable behavior of the engine.
55

6+
## Version 21.3.0
7+
8+
* Remove PYPY_VERSION from our C extension emulation, enabling PyGame 2.0 and other extensions to work out of the box.
9+
* Intrinsify and optimize more of the core language for better startup and reduced footprint.
10+
* Implement a new binary compatible backend for HPy 0.0.3, which allows binary HPy wheels to run unmodified on CPython and GraalPython
11+
* Support the `multiprocessing` module via in-process nested contexts, allowing execution on multiple cores within the same process using the Python multiprocessing API
12+
* Add support for the `ctypes` module, enabling more native extensions to run that use the ctypes API
13+
* Fix multiple REPL issues reported on Github, you can now paste blocks of code and use the numpad in the REPL.
14+
* Make our marshal format compatible with CPython, so binary data can now be exchanged between CPython and GraalPython processes.
15+
* Make most `socket` module tests pass in native mode by using a native extension, allowing usage of all POSIX socket APIs where before only those supported on Java could be used.
16+
* Various compatibility fixes to make the `psutil` package work.
17+
618
## Version 21.2.0
719

820
* Support the `dict` type properly in interop using the new hash interop messages.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
from multiprocessing import Pool
41+
from time import time
42+
from itertools import permutations
43+
from pprint import pprint
44+
45+
46+
NGRAMS = 4
47+
48+
49+
def jaccard(fileA, fileB):
50+
with open(fileA) as f:
51+
x = f.read().split()
52+
x = set(zip(*[x[i:] for i in range(NGRAMS)]))
53+
with open(fileB) as f:
54+
y = f.read().split()
55+
y = set(zip(*[y[i:] for i in range(NGRAMS)]))
56+
intersection_cardinality = len(x & y)
57+
union_cardinality = len(x | y)
58+
return (intersection_cardinality, union_cardinality, intersection_cardinality / union_cardinality)
59+
60+
61+
def parallel_jaccard(pair):
62+
return pair, jaccard(*pair)
63+
64+
65+
if __name__ == '__main__':
66+
import sys, os
67+
68+
iterations = 50
69+
pairs = list(permutations([os.path.join(sys.argv[1], f) for f in os.listdir(sys.argv[1])], 2))
70+
71+
for i in range(4):
72+
print(f"Warmup run #{i}")
73+
start = time()
74+
for res in map(parallel_jaccard, pairs):
75+
print(f"\t{time() - start}s => {res[0]}: {res[1]}", flush=True)
76+
77+
with Pool(8) as p:
78+
for i in range(iterations):
79+
start = time()
80+
print(f"#{i + 1}:", end="", flush=True)
81+
for res in p.imap_unordered(parallel_jaccard, pairs):
82+
print(f"\t{time() - start}s => {res[0]}: {res[1]}", flush=True)
83+
# for pair in pairs:
84+
# value = jaccard(*pair)
85+
# print(f"\t{time() - start}s => {pair}: {value}", flush=True)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ private PythonModule getBuiltinModule(String name) {
357357
@GenerateNodeFactory
358358
public abstract static class ExecBuiltin extends PythonBuiltinNode {
359359
@Specialization
360+
@TruffleBoundary
360361
public Object exec(PythonModule pythonModule) {
361362
final Python3Core core = getCore();
362363
if (!ImageInfo.inImageBuildtimeCode()) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MultiprocessingModuleBuiltins.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,18 +361,18 @@ Object doGeneric(VirtualFrame frame, Object rlist,
361361
@Cached GilNode gil) {
362362
ArrayBuilder<Integer> notEmpty = new ArrayBuilder<>();
363363
SharedMultiprocessingData sharedData = getContext().getSharedMultiprocessingData();
364-
gil.release(true);
365-
try {
366-
PSequence pSequence = constructListNode.execute(frame, rlist);
367-
for (int i = 0; i < sizeNode.execute(frame, pSequence); i++) {
368-
Object pythonObject = callGetItemNode.executeObject(frame, pSequence, i);
369-
int fd = toInt(castToJava, pythonObject);
364+
PSequence pSequence = constructListNode.execute(frame, rlist);
365+
for (int i = 0; i < sizeNode.execute(frame, pSequence); i++) {
366+
Object pythonObject = callGetItemNode.executeObject(frame, pSequence, i);
367+
int fd = toInt(castToJava, pythonObject);
368+
gil.release(true);
369+
try {
370370
if (!sharedData.isBlocking(fd)) {
371371
notEmpty.add(fd);
372372
}
373+
} finally {
374+
gil.acquire();
373375
}
374-
} finally {
375-
gil.acquire();
376376
}
377377
return factory().createList(notEmpty.toObjectArray(new Object[0]));
378378
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/PythonAbstractObject.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@
113113
import com.oracle.graal.python.nodes.call.CallNode;
114114
import com.oracle.graal.python.nodes.call.special.CallBinaryMethodNode;
115115
import com.oracle.graal.python.nodes.call.special.CallTernaryMethodNode;
116-
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
117116
import com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode;
118117
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
119118
import com.oracle.graal.python.nodes.expression.CastToListExpressionNode.CastToListInteropNode;
@@ -534,7 +533,7 @@ public Object getMembers(boolean includeInternal,
534533
@Shared("getClassThis") @Cached GetClassNode getClass,
535534
@Cached PyMappingCheckNode checkMapping,
536535
@Shared("lookup") @Cached PyObjectLookupAttr lookupKeys,
537-
@Cached CallUnaryMethodNode callKeys,
536+
@Cached CallNode callKeys,
538537
@Shared("getItemNode") @Cached PInteropSubscriptNode getItemNode,
539538
@Cached SequenceNodes.LenNode lenNode,
540539
@Cached TypeNodes.GetMroNode getMroNode,
@@ -557,7 +556,7 @@ public Object getMembers(boolean includeInternal,
557556
if (checkMapping.execute(this)) {
558557
Object keysMethod = lookupKeys.execute(null, this, KEYS);
559558
if (keysMethod != PNone.NO_VALUE) {
560-
PList mapKeys = castToList.executeWithGlobalState(callKeys.executeObject(keysMethod, this));
559+
PList mapKeys = castToList.executeWithGlobalState(callKeys.execute(keysMethod));
561560
int len = lenNode.execute(mapKeys);
562561
for (int i = 0; i < len; i++) {
563562
Object key = getItemNode.execute(mapKeys, i);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/queue/SimpleQueueBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ Object doNoTimeout(PSimpleQueue self, boolean block, @SuppressWarnings("unused")
165165
} catch (InterruptedException e) {
166166
CompilerDirectives.transferToInterpreter();
167167
Thread.currentThread().interrupt();
168-
return PNone.NO_VALUE;
168+
return PNone.NONE;
169169
} finally {
170170
ensureGil().acquire();
171171
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/SemLockBuiltins.java

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,11 @@
5757
import com.oracle.graal.python.nodes.ErrorMessages;
5858
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
5959
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
60-
import com.oracle.graal.python.nodes.function.builtins.PythonQuaternaryBuiltinNode;
60+
import com.oracle.graal.python.nodes.function.builtins.PythonClinicBuiltinNode;
6161
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
6262
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryClinicBuiltinNode;
6363
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
6464
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
65-
import com.oracle.graal.python.nodes.util.CannotCastException;
66-
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
6765
import com.oracle.graal.python.runtime.PythonContext.SharedMultiprocessingData;
6866
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
6967
import com.oracle.truffle.api.dsl.Cached;
@@ -201,19 +199,17 @@ Object doEnter(VirtualFrame frame, AbstractPythonLock self, Object blocking, Obj
201199
}
202200

203201
@Builtin(name = "_rebuild", minNumOfPositionalArgs = 4, parameterNames = {"handle", "kind", "maxvalue", "name"})
202+
@ArgumentClinic(name = "kind", conversion = ArgumentClinic.ClinicConversion.Int)
203+
@ArgumentClinic(name = "name", conversion = ArgumentClinic.ClinicConversion.String)
204204
@GenerateNodeFactory
205-
abstract static class RebuildNode extends PythonQuaternaryBuiltinNode {
206-
@Specialization
207-
Object doEnter(@SuppressWarnings("unused") Object handle, int kind, @SuppressWarnings("unused") Object maxvalue, Object nameObj,
208-
@Cached CastToJavaStringNode castNameNode) {
209-
210-
String name;
211-
try {
212-
name = castNameNode.execute(nameObj);
213-
} catch (CannotCastException e) {
214-
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.ARG_D_MUST_BE_S_NOT_P, "_rebuild", 4, "str", nameObj);
215-
}
205+
abstract static class RebuildNode extends PythonClinicBuiltinNode {
206+
@Override
207+
protected ArgumentClinicProvider getArgumentClinic() {
208+
return SemLockBuiltinsClinicProviders.RebuildNodeClinicProviderGen.INSTANCE;
209+
}
216210

211+
@Specialization
212+
Object doEnter(@SuppressWarnings("unused") Object handle, int kind, @SuppressWarnings("unused") Object maxvalue, String name) {
217213
SharedMultiprocessingData multiprocessing = getContext().getSharedMultiprocessingData();
218214
Semaphore semaphore = multiprocessing.getNamedSemaphore(name);
219215
if (semaphore == null) {

0 commit comments

Comments
 (0)