add java tutorial (#2491)

This commit is contained in:
Hao Chen
2018-07-29 08:09:30 +08:00
committed by Robert Nishihara
parent 90a3ea9443
commit 0ea7a6abf0
18 changed files with 811 additions and 385 deletions
+31
View File
@@ -0,0 +1,31 @@
Ray Java Tutorial
=================
- `Installation guide <https://github.com/ray-project/ray/tree/master/java/doc/installation.rst>`_
- `API document <https://github.com/ray-project/ray/tree/master/java/doc/api.rst>`_
Exercises
---------
Each file ``java/example/src/main/java/org/ray/exercise/Exercise*.java`` is a separate exercise.
To run a exercise case, set the ``RAY_CONFIG`` env variable and run the following command in ``ray/java/`` directory.
.. code-block:: shell
java -Djava.library.path=../build/src/plasma/:../build/src/local_scheduler/ -classpath "tutorial/target/ray-tutorial-1.0.jar:tutorial/lib/*" org.ray.exercise.Exercise01
`Exercise 1 <https://github.com/ray-project/ray/tree/master/java/tutorial/src/main/java/org/ray/exercise/Exercise01.java>`_: Define a remote function, and execute multiple remote functions in parallel.
`Exercise 2 <https://github.com/ray-project/ray/tree/master/java/tutorial/src/main/java/org/ray/exercise/Exercise02.java>`_: Execute remote functions in parallel with some dependencies.
`Exercise 3 <https://github.com/ray-project/ray/tree/master/java/tutorial/src/main/java/org/ray/exercise/Exercise03.java>`_: Call remote functions from within remote functions.
`Exercise 4 <https://github.com/ray-project/ray/tree/master/java/tutorial/src/main/java/org/ray/exercise/Exercise04.java>`_: Use ``Ray.wait`` to ignore stragglers.
`Exercise 5 <https://github.com/ray-project/ray/tree/master/java/tutorial/src/main/java/org/ray/exercise/Exercise05.java>`_: Use multiple heterogeneous return values.
`Exercise 6 <https://github.com/ray-project/ray/tree/master/java/tutorial/src/main/java/org/ray/exercise/Exercise06.java>`_: Usage of ``RayList<T>``.
`Exercise 7 <https://github.com/ray-project/ray/tree/master/java/tutorial/src/main/java/org/ray/exercise/Exercise07.java>`_: Usage of ``RayMap<L, T>``.
`Exercise 8 <https://github.com/ray-project/ray/tree/master/java/tutorial/src/main/java/org/ray/exercise/Exercise08.java>`_: Actor Support of create Actor and call Actor method.
+97
View File
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.ray.parent</groupId>
<artifactId>ray-superpom</artifactId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.ray</groupId>
<artifactId>ray-tutorial</artifactId>
<name>java tutorial</name>
<description>Tutorial of using Ray with Java</description>
<url></url>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.ray</groupId>
<artifactId>ray-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.ray</groupId>
<artifactId>ray-runtime-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.ray</groupId>
<artifactId>ray-runtime-native</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.ray</groupId>
<artifactId>ray-runtime-dev</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.ray</groupId>
<artifactId>ray-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
<configuration>
<environmentVariables>
<RAY_CONFIG>${basedir}/../ray.config.ini</RAY_CONFIG>
</environmentVariables>
<argLine>-ea
-Djava.library.path=${basedir}/../../build/src/plasma:${basedir}/../../build/src/local_scheduler
-noverify
-DlogOutput=console
</argLine>
<testSourceDirectory>${basedir}/src/main/java/</testSourceDirectory>
<testClassesDirectory>${project.build.directory}/classes/</testClassesDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,47 @@
package org.ray.exercise;
import java.io.Serializable;
import org.ray.api.Ray;
import org.ray.api.RayObject;
import org.ray.api.RayRemote;
import org.ray.core.RayRuntime;
/**
* Define a remote function, and execute multiple remote functions in parallel.
*/
public class Exercise01 implements Serializable {
/**
* A plain remote function.
*/
// `@RayRemote` annotation converts a normal function to a remote function.
@RayRemote
public static String sayHello() {
String ret = "hello";
System.out.println(ret);
return ret;
}
@RayRemote
public static String sayWorld() {
String ret = "world!";
System.out.println(ret);
return ret;
}
public static void main(String[] args) throws Exception {
try {
// Use `Ray.init` to initialize the Ray runtime.
Ray.init();
// Use `Ray.call` to call a remote function.
RayObject<String> hello = Ray.call(Exercise01::sayHello);
RayObject<String> world = Ray.call(Exercise01::sayWorld);
System.out.println("First remote call result:" + hello.get());
System.out.println("Second remote call result:" + world.get());
} catch (Throwable t) {
t.printStackTrace();
} finally {
RayRuntime.getInstance().cleanUp();
}
}
}
@@ -0,0 +1,54 @@
package org.ray.exercise;
import org.ray.api.Ray;
import org.ray.api.RayObject;
import org.ray.api.RayRemote;
import org.ray.core.RayRuntime;
/**
* Execute remote functions in parallel with some dependencies.
*/
public class Exercise02 {
@RayRemote
public static String sayHello() {
String ret = "hello";
System.out.println(ret);
return ret;
}
@RayRemote
public static String sayWorld() {
String ret = "world!";
System.out.println(ret);
return ret;
}
/**
* A remote function with dependency.
*/
@RayRemote
public static String merge(String hello, String world) {
return hello + "," + world;
}
public static String sayHelloWorld() {
RayObject<String> hello = Ray.call(Exercise02::sayHello);
RayObject<String> world = Ray.call(Exercise02::sayWorld);
// Pass unfinished results as the parameters to another remote function.
return Ray.call(Exercise02::merge, hello, world).get();
}
public static void main(String[] args) throws Exception {
try {
Ray.init();
String helloWorld = Exercise02.sayHelloWorld();
System.out.println(helloWorld);
assert helloWorld.equals("hello,world!");
} catch (Throwable t) {
t.printStackTrace();
} finally {
RayRuntime.getInstance().cleanUp();
}
}
}
@@ -0,0 +1,45 @@
package org.ray.exercise;
import org.ray.api.Ray;
import org.ray.api.RayObject;
import org.ray.api.RayRemote;
import org.ray.core.RayRuntime;
/**
* Call a remote function from within another remote function.
*/
public class Exercise03 {
/**
* A remote function which will call another remote function.
*/
@RayRemote
public static String sayHelloWithWorld() {
String ret = "hello";
System.out.println(ret);
RayObject<String> world = Ray.call(Exercise03::sayWorld);
return ret + "," + world.get();
}
/**
* A remote function which will be called by another remote function.
*/
@RayRemote
public static String sayWorld() {
String ret = "world!";
System.out.println(ret);
return ret;
}
public static void main(String[] args) throws Exception {
try {
Ray.init();
String helloWithWorld = Ray.call(Exercise03::sayHelloWithWorld).get();
System.out.println(helloWithWorld);
} catch (Throwable t) {
t.printStackTrace();
} finally {
RayRuntime.getInstance().cleanUp();
}
}
}
@@ -0,0 +1,74 @@
package org.ray.exercise;
import org.ray.api.Ray;
import org.ray.api.RayList;
import org.ray.api.RayObject;
import org.ray.api.RayRemote;
import org.ray.api.WaitResult;
import org.ray.core.RayRuntime;
/**
* Use Ray.wait to ignore stragglers
*/
public class Exercise04 {
@RayRemote
public static String f1() {
String ret = "f1";
System.out.println(ret);
return ret;
}
@RayRemote
public static String f2() {
String ret = "f2";
System.out.println(ret);
return ret;
}
/**
* A slow remote function.
*/
@RayRemote
public static String f3() {
String ret = "f3";
try {
Thread.sleep(5000L);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(ret);
return ret;
}
public static void main(String[] args) throws Exception {
try {
Ray.init();
RayObject<String> o1 = Ray.call(Exercise04::f1);
RayObject<String> o2 = Ray.call(Exercise04::f2);
RayObject<String> o3 = Ray.call(Exercise04::f3);
RayList<String> rayList = new RayList<>();
rayList.add(o1);
rayList.add(o2);
rayList.add(o3);
// Ray.wait will block until specified number of results are ready
// or specified timeout have passed.
// In this case, the result of f3 will be ignored.
WaitResult<String> waitResult = Ray.wait(rayList, 2, 3000);
RayList<String> readyOnes = waitResult.getReadyOnes();
RayList<String> remainOnes = waitResult.getRemainOnes();
System.out.println("Number of readyOnes: " + readyOnes.size());
for (int i = 0; i < readyOnes.size(); i++) {
System.out.println("The value of readyOnes " + i + " is " + readyOnes.get(i));
}
System.out.println("Number of remainOnes: " + remainOnes.size());
for (int i = 0; i < remainOnes.size(); i++) {
System.out.println("The value of remainOnes " + i + " is " + remainOnes.get(i));
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
RayRuntime.getInstance().cleanUp();
}
}
}
@@ -0,0 +1,38 @@
package org.ray.exercise;
import org.ray.api.Ray;
import org.ray.api.RayRemote;
import org.ray.api.returns.MultipleReturns2;
import org.ray.api.returns.RayObjects2;
import org.ray.core.RayRuntime;
/**
* Use multiple heterogeneous return values
* Java worker support at most four heterogeneous return values,
* To call such remote functions, use {@code Ray.call_X} as follows.
*/
public class Exercise05 {
public static void main(String[] args) {
try {
Ray.init();
RayObjects2<Integer, String> refs = Ray.call_2(Exercise05::sayMultiRet);
Integer obj1 = refs.r0().get();
String obj2 = refs.r1().get();
System.out.println(obj1);
System.out.println(obj2);
} catch (Throwable t) {
t.printStackTrace();
} finally {
RayRuntime.getInstance().cleanUp();
}
}
/**
* A remote function that returns multiple heterogeneous values.
*/
@RayRemote
public static MultipleReturns2<Integer, String> sayMultiRet() {
return new MultipleReturns2<Integer, String>(123, "123");
}
}
@@ -0,0 +1,46 @@
package org.ray.exercise;
import java.util.ArrayList;
import java.util.List;
import org.ray.api.Ray;
import org.ray.api.RayList;
import org.ray.api.RayObject;
import org.ray.api.RayRemote;
import org.ray.core.RayRuntime;
/**
* Show usage of RayList.
* RayList is a list of {@code RayObject}s, inherited from {@code List}.
* It can be used as the type for both return values and parameters.
*
*/
public class Exercise06 {
public static void main(String[] args) {
try {
Ray.init();
// The result is a `RayList`.
RayList<Integer> ns = Ray.call_n(Exercise06::sayList, 10, 10);
for (int i = 0; i < 10; i++) {
RayObject<Integer> obj = ns.Get(i);
System.out.println(obj.get());
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
RayRuntime.getInstance().cleanUp();
}
}
/**
* A remote function that returns a list.
*/
@RayRemote
public static List<Integer> sayList(Integer count) {
ArrayList<Integer> rets = new ArrayList<>();
for (int i = 0; i < count; i++) {
rets.add(i);
}
return rets;
}
}
@@ -0,0 +1,48 @@
package org.ray.exercise;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.ray.api.Ray;
import org.ray.api.RayMap;
import org.ray.api.RayObject;
import org.ray.api.RayRemote;
import org.ray.core.RayRuntime;
/**
* Show usage of RayMap.
* {@code RayMap} is a map of {@code RayObject}s, inherited from {@code Map}.
* It can be used as the type for both return values and parameters.
*/
public class Exercise07 {
public static void main(String[] args) {
try {
Ray.init();
RayMap<Integer, String> ns = Ray.call_n(Exercise07::sayMap,
Arrays.asList(1, 2, 4, 3), "n_futures_");
for (Map.Entry<Integer, RayObject<String>> ne : ns.EntrySet()) {
Integer key = ne.getKey();
RayObject<String> obj = ne.getValue();
System.out.println(obj.get());
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
RayRuntime.getInstance().cleanUp();
}
}
/**
* A remote function that returns a map.
*/
@RayRemote()
public static Map<Integer, String> sayMap(Collection<Integer> ids, String prefix) {
Map<Integer, String> ret = new HashMap<>();
for (int id : ids) {
ret.put(id, prefix + id);
}
return ret;
}
}
@@ -0,0 +1,48 @@
package org.ray.exercise;
import org.ray.api.Ray;
import org.ray.api.RayActor;
import org.ray.api.RayObject;
import org.ray.api.RayRemote;
import org.ray.core.RayRuntime;
/**
* Show usage of actors.
*/
public class Exercise08 {
public static void main(String[] args) {
try {
Ray.init();
// `Ray.create` creates an actor instance.
RayActor<Adder> adder = Ray.create(Adder.class);
// Use `Ray.call(actor, parameters)` to call an actor method.
RayObject<Integer> result1 = Ray.call(Adder::add, adder, 1);
RayObject<Integer> result2 = Ray.call(Adder::add, adder, 10);
System.out.println(result1.get());
System.out.println(result2.get());
} catch (Throwable t) {
t.printStackTrace();
} finally {
RayRuntime.getInstance().cleanUp();
}
}
/**
* An example actor.
*/
// `@RayRemote` annotation also converts a normal class to an actor.
@RayRemote
public static class Adder {
public Adder() {
sum = 0;
}
public Integer add(Integer n) {
return sum += n;
}
private Integer sum;
}
}