Skip to content

Commit

Permalink
Merge pull request #384 from jjfumero/fix/memory/fill
Browse files Browse the repository at this point in the history
Autoclosable Execution Plans for automatic memory management (free resources)
  • Loading branch information
jjfumero authored Apr 23, 2024
2 parents 940cb15 + 2d5f089 commit b8fdd54
Show file tree
Hide file tree
Showing 13 changed files with 278 additions and 59 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, APT Group, Department of Computer Science,
* Copyright (c) 2013-2024, APT Group, Department of Computer Science,
* The University of Manchester.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -50,7 +50,7 @@
* Tornado Task Graph API.
* <p>
* Task-based parallel API to express methods to be accelerated on any OpenCL,
* PTX or SPIRV compatible device.
* PTX or SPIR-V compatible device.
* </p>
*
* @since TornadoVM-0.15
Expand Down Expand Up @@ -913,4 +913,5 @@ void withoutPrintKernel() {
void withGridScheduler(GridScheduler gridScheduler) {
taskGraphImpl.withGridScheduler(gridScheduler);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import uk.ac.manchester.tornado.api.common.TornadoDevice;
import uk.ac.manchester.tornado.api.enums.ProfilerMode;
import uk.ac.manchester.tornado.api.exceptions.TornadoBackendNotFound;
import uk.ac.manchester.tornado.api.exceptions.TornadoExecutionPlanException;
import uk.ac.manchester.tornado.api.exceptions.TornadoRuntimeException;
import uk.ac.manchester.tornado.api.runtime.ExecutorFrame;
import uk.ac.manchester.tornado.api.runtime.TornadoRuntime;
Expand All @@ -38,7 +39,7 @@
*
* @since TornadoVM-0.15
*/
public class TornadoExecutionPlan {
public class TornadoExecutionPlan implements AutoCloseable {

/**
* Method to obtain the default device in TornadoVM. The default one corresponds
Expand Down Expand Up @@ -387,6 +388,11 @@ public TornadoExecutionPlan withoutPrintKernel() {
return this;
}

@Override
public void close() throws TornadoExecutionPlanException {
tornadoExecutor.freeDeviceMemory();
}

static class TornadoExecutor {

private final List<ImmutableTaskGraph> immutableTaskGraphList;
Expand Down
Original file line number Diff line number Diff line change
@@ -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.exceptions;

public class TornadoExecutionPlanException extends Exception {

private String reason;

public TornadoExecutionPlanException() {

}

public TornadoExecutionPlanException(String reason) {
this.reason = reason;
}

public String getReason() {
return reason;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public final class ByteArray extends TornadoNativeArray {
private int arrayHeaderSize;

private int baseIndex;
private int arraySizeHeaderPosition;

private long segmentByteSize;

Expand All @@ -55,7 +54,6 @@ public ByteArray(int numberOfElements) {
this.numberOfElements = numberOfElements;
arrayHeaderSize = (int) TornadoNativeArray.ARRAY_HEADER;
baseIndex = arrayHeaderSize / BYTE_BYTES;
arraySizeHeaderPosition = baseIndex - 4;
segmentByteSize = numberOfElements * BYTE_BYTES + arrayHeaderSize;

segment = Arena.ofAuto().allocate(segmentByteSize, 1);
Expand Down
9 changes: 7 additions & 2 deletions tornado-assembly/src/bin/tornado-test
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ __TEST_THE_WORLD__ = [
TestEntry("uk.ac.manchester.tornado.unittests.matrices.TestMatrixTypes"),
TestEntry("uk.ac.manchester.tornado.unittests.api.TestAPI"),
TestEntry("uk.ac.manchester.tornado.unittests.api.TestInitDataTypes"),
TestEntry("uk.ac.manchester.tornado.unittests.memoryplan.TestMemoryLimit"),
TestEntry("uk.ac.manchester.tornado.unittests.memory.TestMemoryLimit"),
TestEntry("uk.ac.manchester.tornado.unittests.api.TestIO"),
TestEntry("uk.ac.manchester.tornado.unittests.executor.TestExecutor"),
TestEntry("uk.ac.manchester.tornado.unittests.grid.TestGrid"),
Expand Down Expand Up @@ -154,7 +154,12 @@ __TEST_THE_WORLD__ = [
testParameters=[
"-Dtornado.device.desc=" + os.environ["TORNADO_SDK"] + "/examples/virtual-device-CPU.json",
"-Dtornado.virtual.device=True", "-Dtornado.feature.extraction=True",
"-Dtornado.features.dump.dir=" + os.environ["TORNADO_SDK"] + "/virtualFeaturesOut.out"])
"-Dtornado.features.dump.dir=" + os.environ["TORNADO_SDK"] + "/virtualFeaturesOut.out"]),

TestEntry(testName="uk.ac.manchester.tornado.unittests.memory.TestStressDeviceMemory",
testParameters=[
"-Dtornado.device.memory=4GB",
"-Xmx14g"])
]

## List of tests that can be ignored. The following either fail (we know it is a precision error), or they are not supported
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@
*/
package uk.ac.manchester.tornado.drivers.common;

import static uk.ac.manchester.tornado.runtime.common.TornadoOptions.DEVICE_AVAILABLE_MEMORY;

import java.util.ArrayList;

import uk.ac.manchester.tornado.api.TornadoDeviceContext;
import uk.ac.manchester.tornado.api.TornadoTargetDevice;
import uk.ac.manchester.tornado.api.exceptions.TornadoInternalError;
import uk.ac.manchester.tornado.api.exceptions.TornadoOutOfMemoryException;
import uk.ac.manchester.tornado.runtime.common.TornadoOptions;

import java.util.ArrayList;

import static uk.ac.manchester.tornado.runtime.common.TornadoOptions.DEVICE_AVAILABLE_MEMORY;

/**
* This class implements a cache of allocated buffers on the device and also
* handles the logic to allocate and free buffers. This class is extended for
Expand Down Expand Up @@ -189,19 +189,19 @@ public void resetBuffers() {
private record BufferContainer(long buffer, long size) {

@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof BufferContainer that)) {
return false;
}
return buffer == that.buffer && size == that.size;
public boolean equals(Object object) {
if (this == object) {
return true;
}

@Override
public int hashCode() {
return (int) buffer;
if (!(object instanceof BufferContainer that)) {
return false;
}
return buffer == that.buffer && size == that.size;
}

@Override
public int hashCode() {
return (int) buffer;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
*/
package uk.ac.manchester.tornado.drivers.opencl;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import uk.ac.manchester.tornado.api.exceptions.TornadoInternalError;
import uk.ac.manchester.tornado.api.exceptions.TornadoNoOpenCLPlatformException;
import uk.ac.manchester.tornado.api.exceptions.TornadoRuntimeException;
Expand All @@ -35,10 +39,6 @@
import uk.ac.manchester.tornado.runtime.common.TornadoLogger;
import uk.ac.manchester.tornado.runtime.common.TornadoOptions;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

public class OCLContext implements OCLExecutionEnvironment {

private final long contextID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public void freeMemory(long buffer, int deviceIndex) {
}

int result = levelZeroContext.zeMemFree(levelZeroContext.getDefaultContextPtr(), deviceBuffer);
LevelZeroUtils.errorLog("zeMemAllocDevice", result);
LevelZeroUtils.errorLog("zeMemFree", result);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package uk.ac.manchester.tornado.examples.memory;

import uk.ac.manchester.tornado.api.ImmutableTaskGraph;
import uk.ac.manchester.tornado.api.TaskGraph;
import uk.ac.manchester.tornado.api.TornadoExecutionPlan;
import uk.ac.manchester.tornado.api.annotations.Parallel;
import uk.ac.manchester.tornado.api.enums.DataTransferMode;
import uk.ac.manchester.tornado.api.exceptions.TornadoExecutionPlanException;
import uk.ac.manchester.tornado.api.types.arrays.FloatArray;

/**
* Full example to show to matrix addition with non vector types
* <p>
* How to run?
* </p>
* <code>
* tornado --jvm="-Dtornado.device.memory=4GB" -m tornado.examples/uk.ac.manchester.tornado.examples.memory.TestMemory
* </code>
*
*/
public class TestMemory {

public static void moveData(FloatArray inputArray, FloatArray outputArray) {
for (@Parallel int i = 0; i < inputArray.getSize(); i++) {
outputArray.set(i, inputArray.get(i));
}
}

public static void stressDataAllocationTest(int dataSizeFactor) throws TornadoExecutionPlanException {
System.out.println("Allocating size: " + (dataSizeFactor * 4) + " (bytes)");
FloatArray inputArray = new FloatArray(dataSizeFactor);
FloatArray outputArray = new FloatArray(dataSizeFactor);
inputArray.init(0.1f);
TaskGraph taskGraph = new TaskGraph("memory" + dataSizeFactor) //
.transferToDevice(DataTransferMode.EVERY_EXECUTION, inputArray) //
.task("stress", TestMemory::moveData, inputArray, outputArray) //
.transferToHost(DataTransferMode.EVERY_EXECUTION, outputArray);

ImmutableTaskGraph immutableTaskGraph = taskGraph.snapshot();
try (TornadoExecutionPlan executionPlan = new TornadoExecutionPlan(immutableTaskGraph)) {
executionPlan.execute();
}
}

/**
* Depending on the device, this test is expected to fail when using the
* OpenCL backend.
*/

public static void main(String[] args) {
// Starting in ~1.5GB and move up to ~2GB
for (int i = 400; i < 500; i += 10) {
int size = 1024 * 1024 * i;
try {
stressDataAllocationTest(size);
} catch (TornadoExecutionPlanException e) {
e.printStackTrace();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* 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
* 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,
Expand All @@ -17,24 +17,26 @@
*/
package uk.ac.manchester.tornado.unittests.executor;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.util.Arrays;

import org.junit.Test;

import uk.ac.manchester.tornado.api.ImmutableTaskGraph;
import uk.ac.manchester.tornado.api.TaskGraph;
import uk.ac.manchester.tornado.api.TornadoExecutionPlan;
import uk.ac.manchester.tornado.api.TornadoExecutionResult;
import uk.ac.manchester.tornado.api.TornadoProfilerResult;
import uk.ac.manchester.tornado.api.common.TornadoDevice;
import uk.ac.manchester.tornado.api.types.arrays.IntArray;
import uk.ac.manchester.tornado.api.enums.DataTransferMode;
import uk.ac.manchester.tornado.api.enums.ProfilerMode;
import uk.ac.manchester.tornado.api.exceptions.TornadoExecutionPlanException;
import uk.ac.manchester.tornado.api.types.arrays.IntArray;
import uk.ac.manchester.tornado.unittests.TestHello;
import uk.ac.manchester.tornado.unittests.common.TornadoTestBase;

import java.util.Arrays;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

/**
* How to run?
* <p>
Expand Down Expand Up @@ -65,33 +67,37 @@ public void test01() {
ImmutableTaskGraph immutableTaskGraph = tg.snapshot();

// 3. Create an execution plan
TornadoExecutionPlan executorPlan = new TornadoExecutionPlan(immutableTaskGraph);
try (TornadoExecutionPlan executionPlan = new TornadoExecutionPlan(immutableTaskGraph)) {

// Select the default device for the execution plan. This is optional: if no
// device is specified, TornadoVM will launch kernels on the default device.
// However, developers could print device information from the default device.
TornadoDevice defaultDevice = TornadoExecutionPlan.DEFAULT_DEVICE;
// Select the default device for the execution plan. This is optional: if no
// device is specified, TornadoVM will launch kernels on the default device.
// However, developers could print device information from the default device.
TornadoDevice defaultDevice = TornadoExecutionPlan.DEFAULT_DEVICE;

// e.g., Query the device name
String deviceName = defaultDevice.getPhysicalDevice().getDeviceName();
assertNotNull(deviceName);
// e.g., Query the device name
String deviceName = defaultDevice.getPhysicalDevice().getDeviceName();
assertNotNull(deviceName);

// 4. Add optimizations to the execution plan
executorPlan.withProfiler(ProfilerMode.SILENT) //
.withWarmUp() //
.withDevice(defaultDevice) //
.withDefaultScheduler();
// 4. Add optimizations to the execution plan
executionPlan.withProfiler(ProfilerMode.SILENT) //
.withWarmUp() //
.withDevice(defaultDevice) //
.withDefaultScheduler();

// 5. Execute all Immutable Task Graphs associated with an executor plan
TornadoExecutionResult executionResult = executorPlan.execute();
// 5. Execute all Immutable Task Graphs associated with an executor plan
TornadoExecutionResult executionResult = executionPlan.execute();

// 6. Obtain profiler result (only if the execution plan enabled the profiler).
TornadoProfilerResult profilerResult = executionResult.getProfilerResult();
// 6. Obtain profiler result (only if the execution plan enabled the profiler).
TornadoProfilerResult profilerResult = executionResult.getProfilerResult();

assertNotNull(profilerResult);
assertNotNull(profilerResult);

for (int i = 0; i < c.getSize(); i++) {
assertEquals(a.get(i) + b.get(i), c.get(i));
for (int i = 0; i < c.getSize(); i++) {
assertEquals(a.get(i) + b.get(i), c.get(i));
}

} catch (TornadoExecutionPlanException e) {
e.printStackTrace();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*
*/
package uk.ac.manchester.tornado.unittests.memoryplan;
package uk.ac.manchester.tornado.unittests.memory;

import static org.junit.Assert.assertEquals;

Expand All @@ -37,7 +37,7 @@
*
* <p>
* <code>
* tornado-test -V uk.ac.manchester.tornado.unittests.memoryplan.TestMemoryLimit
* tornado-test -V uk.ac.manchester.tornado.unittests.memory.TestMemoryLimit
* </code>
* </p>
*/
Expand Down
Loading

0 comments on commit b8fdd54

Please sign in to comment.