From 3b246a928ea04edddb61d2ea14587511457c4913 Mon Sep 17 00:00:00 2001 From: Juan Fumero Date: Tue, 10 Dec 2024 15:06:33 +0100 Subject: [PATCH 1/5] [api] Graph Selection for the Execution Plan supported --- tornado-api/src/main/java/module-info.java | 2 + .../tornado/api/ExecutionPlanType.java | 13 +++--- .../tornado/api/TornadoExecutionPlan.java | 33 +++++++++++++- .../tornado/api/TornadoExecutor.java | 29 ++++++++++--- .../tornado/api/plan/types/WithAllGraphs.java | 34 +++++++++++++++ .../tornado/api/plan/types/WithGraph.java | 36 ++++++++++++++++ .../unittests/executor/TestExecutor.java | 43 +++++++++++++++++++ 7 files changed, 178 insertions(+), 12 deletions(-) create mode 100644 tornado-api/src/main/java/uk/ac/manchester/tornado/api/plan/types/WithAllGraphs.java create mode 100644 tornado-api/src/main/java/uk/ac/manchester/tornado/api/plan/types/WithGraph.java diff --git a/tornado-api/src/main/java/module-info.java b/tornado-api/src/main/java/module-info.java index 3eb1b3838c..00cfabd26d 100644 --- a/tornado-api/src/main/java/module-info.java +++ b/tornado-api/src/main/java/module-info.java @@ -50,4 +50,6 @@ opens uk.ac.manchester.tornado.api.types.tensors; opens uk.ac.manchester.tornado.api.types; opens uk.ac.manchester.tornado.api.runtime; + exports uk.ac.manchester.tornado.api.plan.types; + opens uk.ac.manchester.tornado.api.plan.types; } diff --git a/tornado-api/src/main/java/uk/ac/manchester/tornado/api/ExecutionPlanType.java b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/ExecutionPlanType.java index 9b0f6d5458..1cec66080c 100644 --- a/tornado-api/src/main/java/uk/ac/manchester/tornado/api/ExecutionPlanType.java +++ b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/ExecutionPlanType.java @@ -22,6 +22,7 @@ import uk.ac.manchester.tornado.api.plan.types.OffPrintKernel; import uk.ac.manchester.tornado.api.plan.types.OffProfiler; import uk.ac.manchester.tornado.api.plan.types.OffThreadInfo; +import uk.ac.manchester.tornado.api.plan.types.WithAllGraphs; import uk.ac.manchester.tornado.api.plan.types.WithBatch; import uk.ac.manchester.tornado.api.plan.types.WithClearProfiles; import uk.ac.manchester.tornado.api.plan.types.WithCompilerFlags; @@ -30,6 +31,7 @@ import uk.ac.manchester.tornado.api.plan.types.WithDevice; import uk.ac.manchester.tornado.api.plan.types.WithDynamicReconfiguration; import uk.ac.manchester.tornado.api.plan.types.WithFreeDeviceMemory; +import uk.ac.manchester.tornado.api.plan.types.WithGraph; import uk.ac.manchester.tornado.api.plan.types.WithGridScheduler; import uk.ac.manchester.tornado.api.plan.types.WithMemoryLimit; import uk.ac.manchester.tornado.api.plan.types.WithPrintKernel; @@ -39,12 +41,11 @@ import uk.ac.manchester.tornado.api.plan.types.WithWarmUp; public abstract sealed class ExecutionPlanType extends TornadoExecutionPlan // - permits OffConcurrentDevices, OffMemoryLimit, OffPrintKernel, // - OffProfiler, OffThreadInfo, WithWarmUp, WithBatch, WithClearProfiles, // - WithCompilerFlags, WithConcurrentDevices, WithDefaultScheduler, // - WithDevice, WithDynamicReconfiguration, WithFreeDeviceMemory, // - WithGridScheduler, WithMemoryLimit, WithPrintKernel, WithProfiler, // - WithResetDevice, WithThreadInfo { + permits OffConcurrentDevices, OffMemoryLimit, OffPrintKernel, OffProfiler, // + OffThreadInfo, WithAllGraphs, WithBatch, WithClearProfiles, WithCompilerFlags, // + WithConcurrentDevices, WithDefaultScheduler, WithDevice, WithDynamicReconfiguration, // + WithFreeDeviceMemory, WithGraph, WithGridScheduler, WithMemoryLimit, WithPrintKernel, // + WithProfiler, WithResetDevice, WithThreadInfo, WithWarmUp { // public ExecutionPlanType(TornadoExecutionPlan parentNode) { diff --git a/tornado-api/src/main/java/uk/ac/manchester/tornado/api/TornadoExecutionPlan.java b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/TornadoExecutionPlan.java index aa59db77f0..6f9ff67f96 100644 --- a/tornado-api/src/main/java/uk/ac/manchester/tornado/api/TornadoExecutionPlan.java +++ b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/TornadoExecutionPlan.java @@ -17,9 +17,9 @@ */ package uk.ac.manchester.tornado.api; -import java.util.Objects; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import uk.ac.manchester.tornado.api.common.TornadoDevice; @@ -32,6 +32,7 @@ import uk.ac.manchester.tornado.api.plan.types.OffPrintKernel; import uk.ac.manchester.tornado.api.plan.types.OffProfiler; import uk.ac.manchester.tornado.api.plan.types.OffThreadInfo; +import uk.ac.manchester.tornado.api.plan.types.WithAllGraphs; import uk.ac.manchester.tornado.api.plan.types.WithBatch; import uk.ac.manchester.tornado.api.plan.types.WithClearProfiles; import uk.ac.manchester.tornado.api.plan.types.WithCompilerFlags; @@ -40,6 +41,7 @@ import uk.ac.manchester.tornado.api.plan.types.WithDevice; import uk.ac.manchester.tornado.api.plan.types.WithDynamicReconfiguration; import uk.ac.manchester.tornado.api.plan.types.WithFreeDeviceMemory; +import uk.ac.manchester.tornado.api.plan.types.WithGraph; import uk.ac.manchester.tornado.api.plan.types.WithGridScheduler; import uk.ac.manchester.tornado.api.plan.types.WithMemoryLimit; import uk.ac.manchester.tornado.api.plan.types.WithPrintKernel; @@ -165,6 +167,34 @@ public TornadoExecutionResult execute() { return executionResult; } + /** + * Select a graph from the {@link TornadoExecutionPlan} to execute. + * This method allows developers to select a specific graph from the + * execution plan to launch. Developers can choose which graph from + * the input list to use (passed in the constructor). + * + * + * @since 1.0.9 + * @param graphIndex + * @return {@link TornadoExecutionPlan} + */ + public TornadoExecutionPlan withGraph(int graphIndex) { + tornadoExecutor.selectGraph(graphIndex); + return new WithGraph(this, graphIndex); + } + + /** + * Select all graphs from the {@link TornadoExecutionPlan}. This method + * has an effect if the {@link #withGraph(int)} method was invoked. + * + * @since 1.0.9 + * @return {@link TornadoExecutionPlan} + */ + public TornadoExecutionPlan withAllGraphs() { + tornadoExecutor.selectAll(); + return new WithAllGraphs(this); + } + /** * It invokes the JIT compiler for all immutable tasks-graphs associated to an * executor. @@ -522,4 +552,5 @@ public TornadoExecutionResult getPlanResult(int index) { } return planResults.get(index); } + } diff --git a/tornado-api/src/main/java/uk/ac/manchester/tornado/api/TornadoExecutor.java b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/TornadoExecutor.java index f3c2445f2b..a1535d3585 100644 --- a/tornado-api/src/main/java/uk/ac/manchester/tornado/api/TornadoExecutor.java +++ b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/TornadoExecutor.java @@ -17,16 +17,16 @@ */ package uk.ac.manchester.tornado.api; -import uk.ac.manchester.tornado.api.common.TornadoDevice; -import uk.ac.manchester.tornado.api.enums.TornadoVMBackendType; -import uk.ac.manchester.tornado.api.exceptions.TornadoRuntimeException; -import uk.ac.manchester.tornado.api.runtime.ExecutorFrame; - import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; +import uk.ac.manchester.tornado.api.common.TornadoDevice; +import uk.ac.manchester.tornado.api.enums.TornadoVMBackendType; +import uk.ac.manchester.tornado.api.exceptions.TornadoRuntimeException; +import uk.ac.manchester.tornado.api.runtime.ExecutorFrame; + /** * Executor Class to dispatch Tornado Task-Graphs. An executor plan * {@link TornadoExecutionPlan} contains an executor object, which in turn, @@ -36,6 +36,7 @@ class TornadoExecutor { private final List immutableTaskGraphList; + private List subgraphList; TornadoExecutor(ImmutableTaskGraph... immutableTaskGraphs) { immutableTaskGraphList = new ArrayList<>(); @@ -222,4 +223,22 @@ long getTotalDeviceMemoryUsage() { long getCurrentDeviceMemoryUsage() { return immutableTaskGraphList.stream().mapToLong(ImmutableTaskGraph::getCurrentDeviceMemoryUsage).sum(); } + + void selectGraph(int graphIndex) { + if (subgraphList == null) { + subgraphList = new ArrayList<>(); + immutableTaskGraphList.forEach(g -> Collections.addAll(subgraphList, g)); + } + immutableTaskGraphList.clear(); + Collections.addAll(immutableTaskGraphList, subgraphList.get(graphIndex)); + } + + void selectAll() { + if (subgraphList == null) { + return; + } + immutableTaskGraphList.clear(); + subgraphList.forEach(g -> Collections.addAll(immutableTaskGraphList, g)); + subgraphList = null; + } } diff --git a/tornado-api/src/main/java/uk/ac/manchester/tornado/api/plan/types/WithAllGraphs.java b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/plan/types/WithAllGraphs.java new file mode 100644 index 0000000000..9e4531adcb --- /dev/null +++ b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/plan/types/WithAllGraphs.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024, APT Group, Department of Computer Science, + * The University of Manchester. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package uk.ac.manchester.tornado.api.plan.types; + +import uk.ac.manchester.tornado.api.ExecutionPlanType; +import uk.ac.manchester.tornado.api.TornadoExecutionPlan; + +public final class WithAllGraphs extends ExecutionPlanType { + + public WithAllGraphs(TornadoExecutionPlan parent) { + super(parent); + } + + @Override + public String toString() { + return parentLink.toString() + "\n -> withAllGraphs "; + } + +} diff --git a/tornado-api/src/main/java/uk/ac/manchester/tornado/api/plan/types/WithGraph.java b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/plan/types/WithGraph.java new file mode 100644 index 0000000000..aa4d2decc9 --- /dev/null +++ b/tornado-api/src/main/java/uk/ac/manchester/tornado/api/plan/types/WithGraph.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024, APT Group, Department of Computer Science, + * The University of Manchester. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package uk.ac.manchester.tornado.api.plan.types; + +import uk.ac.manchester.tornado.api.ExecutionPlanType; +import uk.ac.manchester.tornado.api.TornadoExecutionPlan; + +public final class WithGraph extends ExecutionPlanType { + + private final int graphIndexSelected; + + public WithGraph(TornadoExecutionPlan parent, int graphIndexSelected) { + super(parent); + this.graphIndexSelected = graphIndexSelected; + } + + @Override + public String toString() { + return parentLink.toString() + "\n -> withGraph(" + graphIndexSelected + ") "; + } +} diff --git a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java index d95fbcde5c..57450bdc90 100644 --- a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java +++ b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java @@ -303,5 +303,48 @@ public void test05() throws TornadoExecutionPlanException { } } + /** + * Test Multi-Graphs in an execution plan + * + * @throws TornadoExecutionPlanException + */ + @Test + public void test06() throws TornadoExecutionPlanException { + int numElements = 16; + IntArray a = new IntArray(numElements); + IntArray b = new IntArray(numElements); + IntArray c = new IntArray(numElements); + + a.init(1); + b.init(2); + + TaskGraph tg1 = new TaskGraph("s0") // + .transferToDevice(DataTransferMode.FIRST_EXECUTION, a, b) // + .task("t0", TestHello::add, a, b, c) // + .transferToHost(DataTransferMode.EVERY_EXECUTION, c); + + TaskGraph tg2 = new TaskGraph("s1") // + .transferToDevice(DataTransferMode.FIRST_EXECUTION, a, b) // + .task("t1", TestHello::add, a, b, c) // + .transferToHost(DataTransferMode.EVERY_EXECUTION, c); + + try (TornadoExecutionPlan executionPlan = new TornadoExecutionPlan(tg1.snapshot(), tg2.snapshot())) { + + // Select graph 1 (tg2) to execute + executionPlan.withGraph(1).execute(); + for (int i = 0; i < c.getSize(); i++) { + assertEquals(a.get(i) + b.get(i), c.get(i)); + } + + // Select the graph 0 (tg1) to execute + executionPlan.withGraph(0).execute(); + for (int i = 0; i < c.getSize(); i++) { + assertEquals(a.get(i) + b.get(i), c.get(i)); + } + + // Select all graphs (tg1 and tg2) to execute. + executionPlan.withAllGraphs().execute(); + } + } // CHECKSTYLE:ON } From c6f7a274a45154629a9f73ec9681a8e2494e5dec Mon Sep 17 00:00:00 2001 From: Juan Fumero Date: Tue, 10 Dec 2024 15:10:13 +0100 Subject: [PATCH 2/5] [javadoc] withGraph selection --- .../tornado/unittests/executor/TestExecutor.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java index 57450bdc90..430d858da8 100644 --- a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java +++ b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java @@ -304,7 +304,9 @@ public void test05() throws TornadoExecutionPlanException { } /** - * Test Multi-Graphs in an execution plan + * Test Multi-Graphs in an execution plan. An execution plan can hold and launch + * multiple immutable task graphs. This tests shows how to execute individual immutable + * task graphs in any order. * * @throws TornadoExecutionPlanException */ @@ -331,6 +333,8 @@ public void test06() throws TornadoExecutionPlanException { try (TornadoExecutionPlan executionPlan = new TornadoExecutionPlan(tg1.snapshot(), tg2.snapshot())) { // Select graph 1 (tg2) to execute + // Once selected, every time we call the execute method, + // TornadoVM will launch the passed task-graph. executionPlan.withGraph(1).execute(); for (int i = 0; i < c.getSize(); i++) { assertEquals(a.get(i) + b.get(i), c.get(i)); @@ -343,6 +347,10 @@ public void test06() throws TornadoExecutionPlanException { } // Select all graphs (tg1 and tg2) to execute. + // Since we selected individual task-graphs, we should be + // able to reverse this action and invoke all task-graph + // again. This is achieved with the `withAllGraphs` from the + // execution plan. executionPlan.withAllGraphs().execute(); } } From 21a984f175ebe4a82ed60aac1dc1be7c4ecb9506 Mon Sep 17 00:00:00 2001 From: Juan Fumero Date: Wed, 11 Dec 2024 12:34:19 +0100 Subject: [PATCH 3/5] [test] Multi-Graph copy dependency from one graph to another --- .../unittests/executor/TestExecutor.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java index 430d858da8..1214f1956a 100644 --- a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java +++ b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java @@ -22,6 +22,7 @@ import static org.junit.Assert.fail; import java.util.Arrays; +import java.util.Random; import org.junit.Test; @@ -354,5 +355,52 @@ public void test06() throws TornadoExecutionPlanException { executionPlan.withAllGraphs().execute(); } } + + /** + * Test Multi-Graphs in an execution plan. Based on the {@link #test06()}, this test checke + * task-graphs with different tasks and data. + * + * @throws TornadoExecutionPlanException + */ + @Test + public void test07() throws TornadoExecutionPlanException { + int numElements = 16; + IntArray a = new IntArray(numElements); + IntArray b = new IntArray(numElements); + IntArray c = new IntArray(numElements); + + Random r = new Random(); + for (int i = 0; i < a.getSize(); i++) { + a.set(i, r.nextInt()); + b.set(i, r.nextInt()); + } + + TaskGraph tg1 = new TaskGraph("s0") // + .transferToDevice(DataTransferMode.FIRST_EXECUTION, a, b) // + .task("t0", TestHello::add, a, b, c) // + .transferToHost(DataTransferMode.EVERY_EXECUTION, c); + + // Set dependency from graph tg1 to tg2 + + TaskGraph tg2 = new TaskGraph("s1") // + .transferToDevice(DataTransferMode.FIRST_EXECUTION, c) // + .task("t1", TestHello::compute, c) // + .transferToHost(DataTransferMode.EVERY_EXECUTION, c); + + try (TornadoExecutionPlan executionPlan = new TornadoExecutionPlan(tg1.snapshot(), tg2.snapshot())) { + + executionPlan.withGraph(0).execute(); + for (int i = 0; i < c.getSize(); i++) { + assertEquals(a.get(i) + b.get(i), c.get(i)); + } + + // Select the graph 0 (tg1) to execute + executionPlan.withGraph(1).execute(); + for (int i = 0; i < c.getSize(); i++) { + assertEquals((a.get(i) + b.get(i)) * 2, c.get(i)); + } + } + } + // CHECKSTYLE:ON } From 85ad9f6ae31b7012577ab38e1b670bb0d228ec74 Mon Sep 17 00:00:00 2001 From: Juan Fumero Date: Wed, 11 Dec 2024 12:37:49 +0100 Subject: [PATCH 4/5] minor change --- .../tornado/unittests/executor/TestExecutor.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java index 1214f1956a..656198a1c7 100644 --- a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java +++ b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java @@ -376,25 +376,26 @@ public void test07() throws TornadoExecutionPlanException { } TaskGraph tg1 = new TaskGraph("s0") // - .transferToDevice(DataTransferMode.FIRST_EXECUTION, a, b) // + .transferToDevice(DataTransferMode.EVERY_EXECUTION, a, b) // .task("t0", TestHello::add, a, b, c) // .transferToHost(DataTransferMode.EVERY_EXECUTION, c); // Set dependency from graph tg1 to tg2 TaskGraph tg2 = new TaskGraph("s1") // - .transferToDevice(DataTransferMode.FIRST_EXECUTION, c) // + .transferToDevice(DataTransferMode.EVERY_EXECUTION, c) // .task("t1", TestHello::compute, c) // .transferToHost(DataTransferMode.EVERY_EXECUTION, c); try (TornadoExecutionPlan executionPlan = new TornadoExecutionPlan(tg1.snapshot(), tg2.snapshot())) { + // Select graph 0 (tg1) and run executionPlan.withGraph(0).execute(); for (int i = 0; i < c.getSize(); i++) { assertEquals(a.get(i) + b.get(i), c.get(i)); } - // Select the graph 0 (tg1) to execute + // Select the graph 1 (tg2) and run executionPlan.withGraph(1).execute(); for (int i = 0; i < c.getSize(); i++) { assertEquals((a.get(i) + b.get(i)) * 2, c.get(i)); From 97234fd6328f62a2645448e4aa87bfdf05db5025 Mon Sep 17 00:00:00 2001 From: Thanos Stratikopoulos <34061419+stratika@users.noreply.github.com> Date: Wed, 11 Dec 2024 13:53:30 +0200 Subject: [PATCH 5/5] Update tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java --- .../ac/manchester/tornado/unittests/executor/TestExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java index 656198a1c7..30ebfe42f2 100644 --- a/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java +++ b/tornado-unittests/src/main/java/uk/ac/manchester/tornado/unittests/executor/TestExecutor.java @@ -357,7 +357,7 @@ public void test06() throws TornadoExecutionPlanException { } /** - * Test Multi-Graphs in an execution plan. Based on the {@link #test06()}, this test checke + * Test Multi-Graphs in an execution plan. Based on the {@link #test06()}, this test checks * task-graphs with different tasks and data. * * @throws TornadoExecutionPlanException