mirror of
https://github.com/wassname/ray.git
synced 2026-06-27 22:23:17 +08:00
[xlang] Cross language serialize ActorHandle (#7134)
This commit is contained in:
@@ -29,14 +29,11 @@ public abstract class NativeRayActor implements RayActor, Externalizable {
|
||||
*/
|
||||
byte[] actorId;
|
||||
|
||||
private Language language;
|
||||
|
||||
NativeRayActor(long nativeCoreWorkerPointer, byte[] actorId, Language language) {
|
||||
NativeRayActor(long nativeCoreWorkerPointer, byte[] actorId) {
|
||||
Preconditions.checkState(nativeCoreWorkerPointer != 0);
|
||||
Preconditions.checkState(!ActorId.fromBytes(actorId).isNil());
|
||||
this.nativeCoreWorkerPointer = nativeCoreWorkerPointer;
|
||||
this.actorId = actorId;
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +61,7 @@ public abstract class NativeRayActor implements RayActor, Externalizable {
|
||||
}
|
||||
|
||||
public Language getLanguage() {
|
||||
return language;
|
||||
return Language.forNumber(nativeGetLanguage(nativeCoreWorkerPointer, actorId));
|
||||
}
|
||||
|
||||
public boolean isDirectCallActor() {
|
||||
@@ -73,29 +70,55 @@ public abstract class NativeRayActor implements RayActor, Externalizable {
|
||||
|
||||
@Override
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
out.writeObject(nativeSerialize(nativeCoreWorkerPointer, actorId));
|
||||
out.writeObject(language);
|
||||
out.writeObject(toBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
nativeCoreWorkerPointer = getNativeCoreWorkerPointer();
|
||||
actorId = nativeDeserialize(nativeCoreWorkerPointer, (byte[]) in.readObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize this actor handle to bytes.
|
||||
*
|
||||
* @return the bytes of the actor handle
|
||||
*/
|
||||
public byte[] toBytes() {
|
||||
return nativeSerialize(nativeCoreWorkerPointer, actorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize an actor handle from bytes.
|
||||
*
|
||||
* @return the bytes of an actor handle
|
||||
*/
|
||||
public static NativeRayActor fromBytes(byte[] bytes) {
|
||||
long nativeCoreWorkerPointer = getNativeCoreWorkerPointer();
|
||||
byte[] actorId = nativeDeserialize(nativeCoreWorkerPointer, bytes);
|
||||
Language language = Language.forNumber(nativeGetLanguage(nativeCoreWorkerPointer, actorId));
|
||||
Preconditions.checkNotNull(language);
|
||||
return create(nativeCoreWorkerPointer, actorId, language);
|
||||
}
|
||||
|
||||
private static long getNativeCoreWorkerPointer() {
|
||||
RayRuntime runtime = Ray.internal();
|
||||
if (runtime instanceof RayMultiWorkerNativeRuntime) {
|
||||
runtime = ((RayMultiWorkerNativeRuntime) runtime).getCurrentRuntime();
|
||||
}
|
||||
Preconditions.checkState(runtime instanceof RayNativeRuntime);
|
||||
|
||||
nativeCoreWorkerPointer = ((RayNativeRuntime) runtime).getNativeCoreWorkerPointer();
|
||||
actorId = nativeDeserialize(nativeCoreWorkerPointer, (byte[]) in.readObject());
|
||||
language = (Language) in.readObject();
|
||||
return ((RayNativeRuntime) runtime).getNativeCoreWorkerPointer();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void finalize() {
|
||||
// TODO(zhijunfu): do we need to free the ActorHandle in core worker?
|
||||
}
|
||||
|
||||
private static native int nativeGetLanguage(
|
||||
long nativeCoreWorkerPointer, byte[] actorId);
|
||||
|
||||
private static native boolean nativeIsDirectCallActor(
|
||||
long nativeCoreWorkerPointer, byte[] actorId);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.ray.runtime.generated.Common.Language;
|
||||
public class NativeRayJavaActor extends NativeRayActor {
|
||||
|
||||
NativeRayJavaActor(long nativeCoreWorkerPointer, byte[] actorId) {
|
||||
super(nativeCoreWorkerPointer, actorId, Language.JAVA);
|
||||
super(nativeCoreWorkerPointer, actorId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.ray.runtime.generated.Common.Language;
|
||||
public class NativeRayPyActor extends NativeRayActor implements RayPyActor {
|
||||
|
||||
NativeRayPyActor(long nativeCoreWorkerPointer, byte[] actorId) {
|
||||
super(nativeCoreWorkerPointer, actorId, Language.PYTHON);
|
||||
super(nativeCoreWorkerPointer, actorId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.ray.api.test;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -7,9 +8,13 @@ import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.ray.api.Ray;
|
||||
import org.ray.api.RayActor;
|
||||
import org.ray.api.RayObject;
|
||||
import org.ray.api.RayPyActor;
|
||||
import org.ray.api.TestUtils;
|
||||
import org.ray.api.annotation.RayRemote;
|
||||
import org.ray.runtime.actor.NativeRayActor;
|
||||
import org.ray.runtime.actor.NativeRayPyActor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testng.Assert;
|
||||
@@ -68,6 +73,33 @@ public class CrossLanguageInvocationTest extends BaseMultiLanguageTest {
|
||||
public void testPythonCallJavaActor() {
|
||||
RayObject res = Ray.callPy(PYTHON_MODULE, "py_func_call_java_actor", "1".getBytes());
|
||||
Assert.assertEquals(res.get(), "Counter1".getBytes());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPassActorHandleFromPythonToJava() {
|
||||
// Call a python function which creates a python actor
|
||||
// and pass the actor handle to callPythonActorHandle.
|
||||
RayObject res = Ray.callPy(PYTHON_MODULE, "py_func_pass_python_actor_handle");
|
||||
Assert.assertEquals(res.get(), "3".getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPassActorHandleFromJavaToPython() {
|
||||
// Create a java actor, and pass actor handle to python.
|
||||
RayActor<TestActor> javaActor = Ray.createActor(TestActor::new, "1".getBytes());
|
||||
Preconditions.checkState(javaActor instanceof NativeRayActor);
|
||||
byte[] actorHandleBytes = ((NativeRayActor) javaActor).toBytes();
|
||||
RayObject res = Ray.callPy(PYTHON_MODULE,
|
||||
"py_func_call_java_actor_from_handle", actorHandleBytes);
|
||||
Assert.assertEquals(res.get(), "12".getBytes());
|
||||
// Create a python actor, and pass actor handle to python.
|
||||
RayPyActor pyActor = Ray.createPyActor(PYTHON_MODULE, "Counter", "1".getBytes());
|
||||
Preconditions.checkState(pyActor instanceof NativeRayActor);
|
||||
actorHandleBytes = ((NativeRayActor) pyActor).toBytes();
|
||||
res = Ray.callPy(PYTHON_MODULE,
|
||||
"py_func_call_python_actor_from_handle", actorHandleBytes);
|
||||
Assert.assertEquals(res.get(), "3".getBytes());
|
||||
}
|
||||
|
||||
public static byte[] bytesEcho(byte[] value) {
|
||||
@@ -77,6 +109,15 @@ public class CrossLanguageInvocationTest extends BaseMultiLanguageTest {
|
||||
return ("[Java]bytesEcho -> " + valueStr).getBytes();
|
||||
}
|
||||
|
||||
public static byte[] callPythonActorHandle(byte[] value) {
|
||||
// This function will be called from test_cross_language_invocation.py
|
||||
NativeRayPyActor actor = (NativeRayPyActor)NativeRayActor.fromBytes(value);
|
||||
RayObject res = Ray.callPy(actor, "increase", "1".getBytes());
|
||||
Assert.assertEquals(res.get(), "3".getBytes());
|
||||
return (byte[])res.get();
|
||||
}
|
||||
|
||||
@RayRemote // Python can create java actors without @RayRemote
|
||||
public static class TestActor {
|
||||
public TestActor(byte[] v) {
|
||||
value = v;
|
||||
|
||||
@@ -31,6 +31,31 @@ def py_func_call_java_actor(value):
|
||||
return ray.get(r)
|
||||
|
||||
|
||||
@ray.remote
|
||||
def py_func_call_java_actor_from_handle(value):
|
||||
assert isinstance(value, bytes)
|
||||
actor_handle = ray.actor.ActorHandle._deserialization_helper(value, False)
|
||||
r = actor_handle.concat.remote(b"2")
|
||||
return ray.get(r)
|
||||
|
||||
|
||||
@ray.remote
|
||||
def py_func_call_python_actor_from_handle(value):
|
||||
assert isinstance(value, bytes)
|
||||
actor_handle = ray.actor.ActorHandle._deserialization_helper(value, False)
|
||||
r = actor_handle.increase.remote(2)
|
||||
return ray.get(r)
|
||||
|
||||
|
||||
@ray.remote
|
||||
def py_func_pass_python_actor_handle():
|
||||
counter = Counter.remote(2)
|
||||
f = ray.java_function("org.ray.api.test.CrossLanguageInvocationTest",
|
||||
"callPythonActorHandle")
|
||||
r = f.remote(counter._serialization_helper(False))
|
||||
return ray.get(r)
|
||||
|
||||
|
||||
@ray.remote
|
||||
class Counter(object):
|
||||
def __init__(self, value):
|
||||
|
||||
Reference in New Issue
Block a user