Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-language invocation Part 1: Java calling Python functions and actors #4166

Merged
merged 12 commits into from
Mar 21, 2019

Conversation

raulchen
Copy link
Contributor

@raulchen raulchen commented Feb 26, 2019

What do these changes do?

Implements Java calling Python functions and actors.

Usage:

  • Call a Python function:
RayObject res = Ray.callPy("module_name", "function_name", arg1, arg2, ...);
  • Call a Python actor:
RayPyActor actor = Ray.createPyActor("module_name", "ClassName", arg1, arg2, ...);
RayObject res = Ray.callPy(actor, "function_name", arg1, arg2);

Note, currently arguments can only be raw binaries. And when putting a binary in object store, we use special metadata to indicate that the object is raw binary and doesn't need serialization/deserialization.

Not implemented in this PR:

  • Python calling Java.
  • Passing actor handle as parameter.

Related issue number

#2576

@raulchen raulchen changed the title [wip] Cross-language invocation: part 1 Cross-language invocation: part 1 Feb 26, 2019
@AmplabJenkins
Copy link

Test FAILed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/12321/
Test FAILed.

@pcmoritz
Copy link
Contributor

pcmoritz commented Feb 27, 2019

If we got the eternal bug https://issues.apache.org/jira/browse/ARROW-1692 resolved, we could pass data natively between Java arrow and python arrow :D

public static RayPyActor createPyActor(String moduleName, String className, Object obj0, Object obj1, Object obj2, Object obj3, Object obj4, Object obj5, ActorCreationOptions options) {
Object[] args = new Object[]{obj0, obj1, obj2, obj3, obj4, obj5};
return Ray.internal().createPyActor(moduleName, className, args, options);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these args are all untyped, why not use Java varargs? The only caveat is that you'll have to move the creation options a bit earlier.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, varargs would look nicer. But I wanted to make the order aligned with the regular createActor.

return className;
}

public RayPyActorImpl fork(boolean random) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the random arg for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, that's an internal hack. I'll remove it.

int language;
int functionDescriptorOffset;

if (task.functionDescriptor != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the nullability of functionDescriptor / pyFuncDescriptor confusing. Consider having one type for both, and methods task.functionDescriptor.getLanguage() instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good.

public final FunctionDescriptor functionDescriptor;

// Descriptor of the target Python function. This field is only valid for Python tasks.
public final PyFunctionDescriptor pyFunctionDescriptor;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider merging these two fields to avoid nulls.

actorImpl.setTaskCursor(spec.returnIds[1]);
actorImpl.clearNewActorHandles();
}
rayletClient.submitTask(spec);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

return actor;
}


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many newlines?

java/pom.xml Outdated
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's gson for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually needed for the next PR (serializing handle with json and pass it to Python), forgot to remove it.

Copy link
Contributor

@ericl ericl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments.

@AmplabJenkins
Copy link

Can one of the admins verify this patch?

1 similar comment
@AmplabJenkins
Copy link

Can one of the admins verify this patch?

@ericl
Copy link
Contributor

ericl commented Mar 16, 2019

@raulchen any follow-up here? Looks like there are some merge conflicts now.

@raulchen
Copy link
Contributor Author

@ericl I rebased the PR and addressed your comments.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/13036/
Test PASSed.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/13046/
Test PASSed.

@raulchen raulchen changed the title Cross-language invocation: part 1 Cross-language invocation Part 1: Java calling Python functions and actors Mar 20, 2019
@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/13070/
Test PASSed.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/13089/
Test PASSed.

@raulchen
Copy link
Contributor Author

CI failure is related, but I cannot reproduce it on my machine. Will check tomorrow.

/**
* Represents metadata of a Python function.
*/
public class PyFunctionDescriptor {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the sake of a little more type safety, how about having both this and FunctionDescriptor extend the same interface or base class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, will change.

Copy link
Contributor

@ericl ericl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good -- just one comment on having a common base class for a bit more type safety.

It would also be nice to add an example of Python->Java calls, if there is a use case for that.

@AmplabJenkins
Copy link

Test FAILed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/13100/
Test FAILed.

@raulchen
Copy link
Contributor Author

raulchen commented Mar 21, 2019

@ericl Python calling Java will be implemented in next PR. Although it's already doable with low-level api, I'd like to create a higher-level API for convenience in next PR. I haven't thought thoroughly about the API, it may be something like the following. Suggestions are welcome!

java_func = ray.experimental.java_task("package.name", "ClassName", "staticMethodName", "typeDescriptor")
java_func.remote(args)

java_actor = ray.experimental.create_java_actor("package.name", "ClassName")
java_actor.method("methodName", "typeDescriptor").remote(args)

@ericl
Copy link
Contributor

ericl commented Mar 21, 2019

Sounds good. I think the experimental syntax looks fine for an initial release; you could also try to wrap the actors to provide a bit more of a pythonic API.

@AmplabJenkins
Copy link

Test FAILed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/13126/
Test FAILed.

@AmplabJenkins
Copy link

Test FAILed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/13123/
Test FAILed.

@raulchen raulchen merged commit d03999d into ray-project:master Mar 21, 2019
@raulchen raulchen deleted the xlang branch March 21, 2019 05:34
@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/13127/
Test PASSed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants