From c7575d8b386c49d0b90283f243aa59f55c827eb2 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Fri, 17 Sep 2021 21:03:53 -0700 Subject: [PATCH 01/46] double add fused op --- install.py | 4 +- legate/numpy/array.py | 197 ++++++++++++++++- legate/numpy/config.py | 8 + legate/numpy/deferred.py | 56 ++++- src/fused/fused_op.cc | 73 +++++++ src/fused/fused_op.cu | 79 +++++++ src/fused/fused_op.h | 64 ++++++ src/fused/fused_op_omp.cc | 72 +++++++ src/fused/fused_op_template.inl | 105 +++++++++ src/fused/fused_op_util.h | 346 ++++++++++++++++++++++++++++++ src/legate_numpy_c.h | 1 + src/matrix/matvecmul.cc | 2 +- src/matrix/matvecmul_template.inl | 7 +- src/numpy.mk | 7 +- src/unary/scalar_unary_red_omp.cc | 4 +- 15 files changed, 1014 insertions(+), 11 deletions(-) create mode 100644 src/fused/fused_op.cc create mode 100644 src/fused/fused_op.cu create mode 100644 src/fused/fused_op.h create mode 100644 src/fused/fused_op_omp.cc create mode 100644 src/fused/fused_op_template.inl create mode 100644 src/fused/fused_op_util.h diff --git a/install.py b/install.py index f9f12cf1d..e8a47881d 100755 --- a/install.py +++ b/install.py @@ -434,7 +434,7 @@ def driver(): parser.add_argument( "--cuda", action=BooleanFlag, - default=os.environ.get("USE_CUDA", "1") == "1", + default=False, #os.environ.get("USE_CUDA", "1") == "1", help="Build Legate NumPy with CUDA support.", ) parser.add_argument( @@ -461,7 +461,7 @@ def driver(): "--clean", dest="clean_first", action=BooleanFlag, - default=True, + default=False, help="Clean before build.", ) parser.add_argument( diff --git a/legate/numpy/array.py b/legate/numpy/array.py index df96f7693..c2b7c246d 100644 --- a/legate/numpy/array.py +++ b/legate/numpy/array.py @@ -22,7 +22,8 @@ from legate.core import Array -from .config import BinaryOpCode, NumPyOpCode, UnaryOpCode, UnaryRedCode +from .config import BinaryOpCode, NumPyOpCode, UnaryOpCode, UnaryRedCode, FusedOpCode +#from .config import BinaryOpCode, NumPyOpCode, UnaryOpCode, UnaryRedCode from .doc_utils import copy_docstring from .runtime import runtime from .utils import unimplemented @@ -345,8 +346,34 @@ def __ge__(self, rhs): out_dtype=np.dtype(np.bool_), ) - # __getattribute__ + def fuse1(self, rhs1, rhs2): + print(type(self)) + rhs_array1 = self.convert_to_legate_ndarray(rhs1) + rhs_array2 = self.convert_to_legate_ndarray(rhs2) + + #a,b,c + arrs = [self.convert_to_legate_ndarray(self), rhs_array1, rhs_array2] + in_starts = np.ndarray([0,1]) + in_ends = [1,2] + in_starts = self.convert_to_legate_ndarray(in_starts) + in_ends = self.convert_to_legate_ndarray(in_starts) + #in_ends = self.convert_to_legate_ndarray(in_ends) + + out_starts = [3] + out_end = [3] + #out_starts = self.convert_to_legate_ndarray(out_starts) + #out_end = self.convert_to_legate_ndarray(out_ends) + + print(type(rhs_array1)) + return self.perform_fused_op( + FusedOpCode.FUSE, + self, + rhs_array1, + rhs_array2, + check_types=False + ) + # __getattribute__ def _convert_key(self, key, stacklevel=2, first=True): # Convert any arrays stored in a key to a legate array if ( @@ -1897,6 +1924,172 @@ def perform_unary_reduction( ) return dst +# Return a new legate array for a binary operation + @classmethod + def perform_fused_op( + cls, + op, + one, + two, + three, + out=None, + dtype=None, + args=None, + where=True, + out_dtype=None, + check_types=False, + stacklevel=2, + ): + temp_dtype = cls.find_common_type(one, two) + # Compute the output shape + if out is None: + # Compute the output shape and confirm any broadcasting + if isinstance(where, ndarray): + print("using where array.py") + temp_shape = broadcast_shapes(one.shape, where.shape) + out_shape = broadcast_shapes(one.shape, two.shape, where.shape) + else: + print("not using where array.py") + temp_shape = broadcast_shapes(one.shape, two.shape) + out_shape = broadcast_shapes(one.shape, two.shape, three.shape) + print("out_shape", out_shape) + print("temp_shape", temp_shape) + if dtype is not None: + temprw = ndarray( + shape=temp_shape, + dtype=temp_dtype, + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + out = ndarray( + shape=out_shape, + dtype=dtype, + stacklevel=(stacklevel + 1), + inputs=(temp, three, where), + ) + elif out_dtype is not None: + temprw = ndarray( + shape=temp_shape, + dtype=temp_dtype, + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + + out = ndarray( + shape=out_shape, + dtype=out_dtype, + stacklevel=(stacklevel + 1), + inputs=(one, two,three, where), + ) + else: + out_dtype = cls.find_common_type(one, two,three) + temprw = ndarray( + shape=temp_shape, + dtype=temp_dtype, + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + out = ndarray( + shape=out_shape, + dtype=out_dtype, + stacklevel=(stacklevel + 1), + inputs=(one, two,three, where), + ) + else: + if isinstance(where, ndarray): + out_shape = broadcast_shapes( + one.shape, two.shape,three.shape, out.shape, where.shape + ) + else: + out_shape = broadcast_shapes(one.shape, two.shape, three.shape, out.shape) + if out.shape != out_shape: + raise ValueError( + "non-broadcastable output operand with shape " + + str(out.shape) + + " doesn't match the broadcast shape " + + str(out_shape) + ) + # Quick exit + if where is False: + return out + if out_dtype is None: + out_dtype = cls.find_common_type(one, two) + out_dtype = cls.find_common_type(out_dtype, three) + if check_types: + if one.dtype != two.dtype: + common_type = cls.find_common_type(one, two) + if one.dtype != common_type: + temp = ndarray( + shape=one.shape, + dtype=common_type, + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + temp._thunk.convert( + one._thunk, stacklevel=(stacklevel + 1) + ) + one = temp + if two.dtype != common_type: + temp = ndarray( + shape=two.shape, + dtype=common_type, + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + temp._thunk.convert( + two._thunk, stacklevel=(stacklevel + 1) + ) + two = temp + if out.dtype != out_dtype: + temp = ndarray( + shape=out.shape, + dtype=out_dtype, + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + temp._thunk.binary_op( + op, + one._thunk, + two._thunk, + cls.get_where_thunk( + where, out.shape, stacklevel=(stacklevel + 1) + ), + args, + stacklevel=(stacklevel + 1), + ) + out._thunk.convert(temp._thunk, stacklevel=(stacklevel + 1)) + else: + out._thunk.binary_op( + op, + one._thunk, + two._thunk, + cls.get_where_thunk( + where, out.shape, stacklevel=(stacklevel + 1) + ), + args, + stacklevel=(stacklevel + 1), + ) + #if check_types + else: + thunks = [one._thunk, two._thunk, three._thunk] + print("running fused op with out_shape=", out.shape) + out._thunk.fused_op( + op, + one._thunk, + two._thunk, + temprw._thunk, + three._thunk, + cls.get_where_thunk( + where, out.shape, stacklevel=(stacklevel + 1) + ), + args, + stacklevel=(stacklevel + 1), + ) + return out + + + + # Return a new legate array for a binary operation @classmethod def perform_binary_op( diff --git a/legate/numpy/config.py b/legate/numpy/config.py index 15862d028..c7ca5d7c7 100644 --- a/legate/numpy/config.py +++ b/legate/numpy/config.py @@ -73,6 +73,8 @@ def destroy(self): self.runtime.destroy() +#import pdb +#pdb.set_trace() NUMPY_LIB_NAME = "legate.numpy" numpy_lib = NumPyLib(NUMPY_LIB_NAME) numpy_context = get_legate_runtime().register_library(numpy_lib) @@ -129,6 +131,12 @@ class NumPyOpCode(IntEnum): ARANGE = legate_numpy.NUMPY_ARANGE TRANSPOSE = legate_numpy.NUMPY_TRANSPOSE NONZERO = legate_numpy.NUMPY_NONZERO + FUSED_OP = legate_numpy.NUMPY_FUSED_OP + + +@unique +class FusedOpCode(IntEnum): + FUSE = 1 @unique diff --git a/legate/numpy/deferred.py b/legate/numpy/deferred.py index 531497e6b..8eafa9d95 100644 --- a/legate/numpy/deferred.py +++ b/legate/numpy/deferred.py @@ -27,7 +27,6 @@ from .thunk import NumPyThunk from .utils import get_arg_value_dtype - def _complex_field_dtype(dtype): if dtype == np.complex64: return np.dtype(np.float32) @@ -1397,6 +1396,56 @@ def unary_reduction( callsite=callsite, ) +# Perform the fused operation and put the result in the lhs array + @profile + @auto_convert([2, 3, 4,5]) + @shadow_debug("fused_op", [2, 3, 4,5]) + def fused_op( + self, op_code, src1, src2, temp, src3, where, args, stacklevel=0, callsite=None + ): + lhs = self.base + + rhs1 = src1._broadcast(lhs.shape) + rhs2 = src2._broadcast(lhs.shape) + rhs3 = src3._broadcast(lhs.shape) + temp1 = temp._broadcast(lhs.shape) + # Populate the Legate launcher + all_scalar_rhs = rhs1.scalar and rhs2.scalar + + if all_scalar_rhs: + task_id = NumPyOpCode.SCALAR_BINARY_OP + else: + task_id = NumPyOpCode.FUSED_OP + + task = self.context.create_task(task_id) + task.add_output(lhs) + + task.add_temp(temp1) + + task.add_output(lhs) + task.add_input(rhs1) + task.add_input(rhs2) + task.add_input(rhs3) + task.add_scalar_arg(op_code.value, ty.int32) + self.add_arguments(task, args) + + #task.add_broadcast(rhs.base) + + task.add_alignment(lhs, rhs1) + task.add_alignment(lhs, rhs2) + task.add_alignment(lhs, rhs3) + + task.add_alignment(lhs, temp1) + print("about to execute fused_op!!", task_id) + print("the shapes:") + print(rhs1.shape) + print(rhs2.shape) + print(rhs3.shape) + print("temp1", temp1.shape) + task.execute() + + + # Perform the binary operation and put the result in the lhs array @profile @auto_convert([2, 3]) @@ -1415,11 +1464,14 @@ def binary_op( task_id = NumPyOpCode.SCALAR_BINARY_OP else: task_id = NumPyOpCode.BINARY_OP - + task = self.context.create_task(task_id) + #print("output",lhs) + #print("input", rhs1, rhs2) task.add_output(lhs) task.add_input(rhs1) task.add_input(rhs2) + print("binary op code", op_code.value) task.add_scalar_arg(op_code.value, ty.int32) self.add_arguments(task, args) diff --git a/src/fused/fused_op.cc b/src/fused/fused_op.cc new file mode 100644 index 000000000..c1f52e2cb --- /dev/null +++ b/src/fused/fused_op.cc @@ -0,0 +1,73 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "fused/fused_op.h" +#include "fused/fused_op_template.inl" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct FusedOpImplBody { + using OP = FusedOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRW temp, + AccessorRO in1, + AccessorRO in2, + AccessorRO in3, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + const size_t volume = rect.volume(); + if (dense) { + auto outptr = out.ptr(rect); + auto tempptr = temp.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + auto in3ptr = in3.ptr(rect); + for (size_t idx = 0; idx < volume; ++idx) { + tempptr[idx] = func(in1ptr[idx], in2ptr[idx]); + outptr[idx] = func(tempptr[idx], in3ptr[idx]); + } + } else { + for (size_t idx = 0; idx < volume; ++idx) { + auto p = pitches.unflatten(idx, rect.lo); + temp[p] = func(in1[p], in2[p]); + out[p] = func(temp[p], in3[p]); + } + } + } +}; + +/*static*/ void FusedOpTask::cpu_variant(TaskContext& context) +{ + fused_op_template(context); +} + +namespace // unnamed +{ +static void __attribute__((constructor)) register_tasks(void) { FusedOpTask::register_variants(); } +} // namespace + +} // namespace numpy +} // namespace legate diff --git a/src/fused/fused_op.cu b/src/fused/fused_op.cu new file mode 100644 index 000000000..a2a048ed4 --- /dev/null +++ b/src/fused/fused_op.cu @@ -0,0 +1,79 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "fused/binary_op.h" +#include "fused_op_template.inl" + +#include "cuda_help.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) + dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + out[idx] = func(in1[idx], in2[idx]); +} + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( + size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + auto point = pitches.unflatten(idx, rect.lo); + out[point] = func(in1[point], in2[point]); +} + +template +struct FusedOpImplBody { + using OP = FusedOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + size_t volume = rect.volume(); + const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); + } else { + generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); + } + } +}; + +/*static*/ void FusedOpTask::gpu_variant(TaskContext& context) +{ + fused_op_template(context); +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused/fused_op.h b/src/fused/fused_op.h new file mode 100644 index 000000000..7c818b591 --- /dev/null +++ b/src/fused/fused_op.h @@ -0,0 +1,64 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy.h" +#include "fused/fused_op_util.h" + +namespace legate { +namespace numpy { + +struct FusedOpArgs { + const Array& in1; + const Array& in2; + const Array& in3; + const Array& temp; + const Array& out; + FusedOpCode op_code; + std::vector args; +}; + + +struct FusedOpArgs2 { + std::vector ins; + std::vector outs; + std::vector inStarts; + std::vector inSizes; + std::vector outStarts; + std::vector outSizes; + std::vector op_codes; + std::vector args; +}; + + + +class FusedOpTask : public NumPyTask { + public: + static const int TASK_ID = NUMPY_FUSED_OP; + + public: + static void cpu_variant(TaskContext& context); +#ifdef LEGATE_USE_OPENMP + static void omp_variant(TaskContext& context); +#endif +#ifdef LEGATE_USE_CUDA + static void gpu_variant(TaskContext& context); +#endif +}; + +} // namespace numpy +} // namespace legate diff --git a/src/fused/fused_op_omp.cc b/src/fused/fused_op_omp.cc new file mode 100644 index 000000000..a716f0062 --- /dev/null +++ b/src/fused/fused_op_omp.cc @@ -0,0 +1,72 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "fused/fused_op.h" +#include "fused_op_template.inl" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct FusedOpImplBody { + using OP = FusedOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRW temp, + AccessorRO in1, + AccessorRO in2, + AccessorRO in3, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + const size_t volume = rect.volume(); + if (dense) { + auto outptr = out.ptr(rect); + auto tempptr = temp.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + auto in3ptr = in3.ptr(rect); +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) { + tempptr[idx] = func(in1ptr[idx], in2ptr[idx]); + outptr[idx] = func(tempptr[idx], in3ptr[idx]); + //outptr[idx] = func(func(in1ptr[idx], in2ptr[idx]), in3ptr[idx]); + } + } else { +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) { + auto p = pitches.unflatten(idx, rect.lo); + //out[p] = func(func(in1[p], in2[p]), in3[p]); + temp[p] = func(in1[p], in2[p]); + out[p] = func(temp[p], in3[p]); + } + } + } +}; + +/*static*/ void FusedOpTask::omp_variant(TaskContext& context) +{ + fused_op_template(context); +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused/fused_op_template.inl b/src/fused/fused_op_template.inl new file mode 100644 index 000000000..88c833fa8 --- /dev/null +++ b/src/fused/fused_op_template.inl @@ -0,0 +1,105 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "fused/fused_op_util.h" +#include "pitches.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct FusedOpImplBody; + +template +struct FusedOpImpl { + template ::valid>* = nullptr> + void operator()(FusedOpArgs& args) const + { + using OP = FusedOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + auto rect = args.out.shape(); + + Pitches pitches; + size_t volume = pitches.flatten(rect); + + if (volume == 0) return; + + auto out = args.out.write_accessor(rect); + auto temp = args.temp.read_write_accessor(rect); + auto in1 = args.in1.read_accessor(rect); + auto in2 = args.in2.read_accessor(rect); + auto in3 = args.in2.read_accessor(rect); + +#ifndef LEGION_BOUNDS_CHECKS + // Check to see if this is dense or not + bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && + in2.accessor.is_dense_row_major(rect) && in3.accessor.is_dense_row_major(rect) && + temp.accessor.is_dense_row_major(rect); +#else + // No dense execution if we're doing bounds checks + bool dense = false; +#endif + + OP func{args.args}; + FusedOpImplBody()(func, out,temp, in1, in2,in3, pitches, rect, dense); + } + + template ::valid>* = nullptr> + void operator()(FusedOpArgs& args) const + { + assert(false); + } +}; + +template +struct FusedOpDispatch { + template + void operator()(FusedOpArgs& args) const + { + auto dim = std::max(args.in1.dim(), args.in2.dim()); + dim = std::max(args.in3.dim(), dim); + double_dispatch(dim, args.in1.code(), FusedOpImpl{}, args); + } +}; + +template +static void fused_op_template(TaskContext& context) +{ + auto& inputs = context.inputs(); + auto& outputs = context.outputs(); + auto& scalars = context.scalars(); + + std::vector extra_args; + for (size_t idx = 3; idx < inputs.size(); ++idx) + extra_args.push_back(inputs[idx].scalar()); + + FusedOpArgs args{ + inputs[0], inputs[1], inputs[2], outputs[0], outputs[1], scalars[0].value(), std::move(extra_args)}; + op_dispatch(args.op_code, FusedOpDispatch{}, args); + //op_dispatch(args.op_code1, FusedOpDispatch{}, args1); + //op_dispatch(args.op_code2, FusedOpDispatch{}, args2); +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused/fused_op_util.h b/src/fused/fused_op_util.h new file mode 100644 index 000000000..48fa349bd --- /dev/null +++ b/src/fused/fused_op_util.h @@ -0,0 +1,346 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy.h" + +namespace legate { +namespace numpy { + +enum class FusedOpCode : int { + ADD = 1, + DIVIDE, + EQUAL, + FLOOR_DIVIDE, + GREATER, + GREATER_EQUAL, + LESS, + LESS_EQUAL, + MAXIMUM, + MINIMUM, + MOD, + MULTIPLY, + NOT_EQUAL, + POWER, + SUBTRACT, + ALLCLOSE, +}; + +template +constexpr decltype(auto) op_dispatch(FusedOpCode op_code, Functor f, Fnargs&&... args) +{ + switch (op_code) { + case FusedOpCode::ADD: + return f.template operator()(std::forward(args)...); + case FusedOpCode::DIVIDE: + return f.template operator()(std::forward(args)...); + //case FusedOpCode::EQUAL: + // return f.template operator()(std::forward(args)...); + case FusedOpCode::FLOOR_DIVIDE: + return f.template operator()(std::forward(args)...); + //case FusedOpCode::GREATER: + // return f.template operator()(std::forward(args)...); + //case FusedOpCode::GREATER_EQUAL: + // return f.template operator()(std::forward(args)...); + //case FusedOpCode::LESS: + // return f.template operator()(std::forward(args)...); + //case FusedOpCode::LESS_EQUAL: + // return f.template operator()(std::forward(args)...); + case FusedOpCode::MAXIMUM: + return f.template operator()(std::forward(args)...); + case FusedOpCode::MINIMUM: + return f.template operator()(std::forward(args)...); + case FusedOpCode::MOD: + return f.template operator()(std::forward(args)...); + case FusedOpCode::MULTIPLY: + return f.template operator()(std::forward(args)...); + //case FusedOpCode::NOT_EQUAL: + // return f.template operator()(std::forward(args)...); + case FusedOpCode::POWER: + return f.template operator()(std::forward(args)...); + case FusedOpCode::SUBTRACT: + return f.template operator()(std::forward(args)...); + default: break; + } + assert(false); + return f.template operator()(std::forward(args)...); +} + +template +constexpr decltype(auto) reduce_op_dispatch(FusedOpCode op_code, Functor f, Fnargs&&... args) +{ + switch (op_code) { + //case FusedOpCode::EQUAL: + // return f.template operator()(std::forward(args)...); + //case FusedOpCode::ALLCLOSE: + // return f.template operator()(std::forward(args)...); + default: break; + } + assert(false); + //return f.template operator()(std::forward(args)...); +} + +template +struct FusedOp { + static constexpr bool valid = false; +}; + +template +struct FusedOp : std::plus> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; + +template +struct FusedOp : std::divides> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; +/* +template +struct FusedOp : std::equal_to> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; +*/ +using std::floor; +template +struct FusedOp { + using T = legate_type_of; + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return floor(a / b); } +}; + +template <> +struct FusedOp { + static constexpr bool valid = false; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; + +template <> +struct FusedOp { + static constexpr bool valid = false; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; +/* +template +struct FusedOp : std::greater> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; + +template +struct FusedOp : std::greater_equal> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; + +template +struct FusedOp : std::less> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; + +template +struct FusedOp : std::less_equal> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; +*/ +template +struct FusedOp { + using T = legate_type_of; + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return std::max(a, b); } +}; + +template +struct FusedOp { + using T = legate_type_of; + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return std::min(a, b); } +}; + +template +constexpr T real_mod(const T& a, const T& b) +{ + T res = std::fmod(a, b); + if (res) { + if ((b < static_cast(0)) != (res < static_cast(0))) res += b; + } else { + res = std::copysign(static_cast(0), b); + } + return res; +} + +template +struct FusedOp { + using T = legate_type_of; + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} + template ::value>* = nullptr> + constexpr _T operator()(const _T& a, const _T& b) const + { + return a % b; + } + + template ::value>* = nullptr> + constexpr _T operator()(const _T& a, const _T& b) const + { + return real_mod(a, b); + } +}; + +template <> +struct FusedOp { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const + { + return static_cast<__half>(real_mod(static_cast(a), static_cast(b))); + } +}; + +template <> +struct FusedOp { + static constexpr bool valid = false; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; + +template <> +struct FusedOp { + static constexpr bool valid = false; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; + +template +struct FusedOp : std::multiplies> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; +/* +template +struct FusedOp : std::not_equal_to> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; +*/ +template +struct FusedOp { + using VAL = legate_type_of; + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} + constexpr VAL operator()(const VAL& a, const VAL& b) const { return std::pow(a, b); } +}; + +template <> +struct FusedOp { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const + { + return pow(a, b); + } +}; + +template <> +struct FusedOp { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX complex operator()(const complex& a, + const complex& b) const + { + return pow(a, b); + } +}; + +template <> +struct FusedOp { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX complex operator()(const complex& a, + const complex& b) const + { + return pow(a, b); + } +}; + +template +struct FusedOp : std::minus> { + static constexpr bool valid = true; + FusedOp() {} + FusedOp(const std::vector& args) {} +}; +/* +template +struct FusedOp { + using VAL = legate_type_of; + static constexpr bool valid = true; + + FusedOp() {} + FusedOp(const std::vector& args) + { + assert(args.size() == 2); + rtol_ = args[0].value(); + atol_ = args[1].value(); + } + + template ::value>* = nullptr> + constexpr bool operator()(const T& a, const T& b) const + { + using std::fabs; + return fabs(static_cast(a) - static_cast(b)) <= + atol_ + rtol_ * static_cast(fabs(b)); + } + + template ::value>* = nullptr> + constexpr bool operator()(const T& a, const T& b) const + { + return static_cast(abs(a - b)) <= atol_ + rtol_ * static_cast(abs(b)); + } + + double rtol_{0}; + double atol_{0}; +}; +*/ +} // namespace numpy +} // namespace legate diff --git a/src/legate_numpy_c.h b/src/legate_numpy_c.h index c94afc88c..cebcc4509 100644 --- a/src/legate_numpy_c.h +++ b/src/legate_numpy_c.h @@ -46,6 +46,7 @@ enum NumPyOpCode { NUMPY_TRANSPOSE = 400024, NUMPY_TILE = 400025, NUMPY_NONZERO = 400026, + NUMPY_FUSED_OP = 400027, }; // Match these to NumPyRedopCode in legate/numpy/config.py diff --git a/src/matrix/matvecmul.cc b/src/matrix/matvecmul.cc index 028139668..2650b8f88 100644 --- a/src/matrix/matvecmul.cc +++ b/src/matrix/matvecmul.cc @@ -18,7 +18,7 @@ #include "matrix/matvecmul_template.inl" #include "matrix/util.h" #include "matrix/util.h" - +// #include #ifdef LEGATE_USE_OPENMP #include diff --git a/src/matrix/matvecmul_template.inl b/src/matrix/matvecmul_template.inl index 262bc2305..b3b83d1b6 100644 --- a/src/matrix/matvecmul_template.inl +++ b/src/matrix/matvecmul_template.inl @@ -75,7 +75,12 @@ struct MatVecMulImpl { size_t lhs_strides[2]; auto lhs = args.lhs.reduce_accessor, true, 2>().ptr(shape, lhs_strides); - + //std::cout<()<()<<" "<()(m, n, lhs, mat, vec, mat_stride, transpose_mat); } diff --git a/src/numpy.mk b/src/numpy.mk index 5146c598c..95566989a 100644 --- a/src/numpy.mk +++ b/src/numpy.mk @@ -11,11 +11,14 @@ # 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. +# fused/fused_op.cc +#fused/fused_op_omp.cc +#fused/fused_op.cu # - # List all the application source files that need OpenMP separately # since we have to add the -fopenmp flag to CC_FLAGS for them GEN_CPU_SRC += ternary/where.cc \ + fused/fused_op.cc \ binary/binary_op.cc \ binary/scalar_binary_op.cc \ binary/binary_red.cc \ @@ -50,6 +53,7 @@ GEN_CPU_SRC += ternary/where.cc \ ifeq ($(strip $(USE_OPENMP)),1) GEN_CPU_SRC += ternary/where_omp.cc \ + fused/fused_op_omp.cc \ binary/binary_op_omp.cc \ binary/binary_red_omp.cc \ unary/unary_op_omp.cc \ @@ -72,6 +76,7 @@ GEN_CPU_SRC += ternary/where_omp.cc \ endif GEN_GPU_SRC += ternary/where.cu \ + fused/fused_op.cu \ binary/binary_op.cu \ binary/binary_red.cu \ unary/scalar_unary_red.cu \ diff --git a/src/unary/scalar_unary_red_omp.cc b/src/unary/scalar_unary_red_omp.cc index 4aa2ab145..b9710160f 100644 --- a/src/unary/scalar_unary_red_omp.cc +++ b/src/unary/scalar_unary_red_omp.cc @@ -127,7 +127,7 @@ struct ScalarUnaryRedImplBody Date: Sun, 19 Sep 2021 19:58:05 -0700 Subject: [PATCH 02/46] all inputs serialized for fused op --- legate/numpy/array.py | 15 +- legate/numpy/config.py | 10 + legate/numpy/deferred.py | 15 +- src/double_binary/double_binary_op.cc | 73 ++++ src/double_binary/double_binary_op.cu | 79 ++++ src/double_binary/double_binary_op.h | 64 ++++ src/double_binary/double_binary_op_omp.cc | 72 ++++ .../double_binary_op_template.inl | 103 ++++++ src/double_binary/double_binary_op_util.h | 346 ++++++++++++++++++ src/fused/fused_op_template.inl | 16 +- src/legate_numpy_c.h | 3 +- src/numpy.mk | 15 +- 12 files changed, 780 insertions(+), 31 deletions(-) create mode 100644 src/double_binary/double_binary_op.cc create mode 100644 src/double_binary/double_binary_op.cu create mode 100644 src/double_binary/double_binary_op.h create mode 100644 src/double_binary/double_binary_op_omp.cc create mode 100644 src/double_binary/double_binary_op_template.inl create mode 100644 src/double_binary/double_binary_op_util.h diff --git a/legate/numpy/array.py b/legate/numpy/array.py index c2b7c246d..0e79d49bf 100644 --- a/legate/numpy/array.py +++ b/legate/numpy/array.py @@ -22,7 +22,7 @@ from legate.core import Array -from .config import BinaryOpCode, NumPyOpCode, UnaryOpCode, UnaryRedCode, FusedOpCode +from .config import BinaryOpCode, NumPyOpCode, UnaryOpCode, UnaryRedCode, FusedOpCode, DoubleBinaryOpCode #from .config import BinaryOpCode, NumPyOpCode, UnaryOpCode, UnaryRedCode from .doc_utils import copy_docstring from .runtime import runtime @@ -346,7 +346,7 @@ def __ge__(self, rhs): out_dtype=np.dtype(np.bool_), ) - def fuse1(self, rhs1, rhs2): + def double_binary(self, rhs1, rhs2): print(type(self)) rhs_array1 = self.convert_to_legate_ndarray(rhs1) rhs_array2 = self.convert_to_legate_ndarray(rhs2) @@ -364,9 +364,8 @@ def fuse1(self, rhs1, rhs2): #out_starts = self.convert_to_legate_ndarray(out_starts) #out_end = self.convert_to_legate_ndarray(out_ends) - print(type(rhs_array1)) - return self.perform_fused_op( - FusedOpCode.FUSE, + return self.perform_double_binary_op( + DoubleBinaryOpCode.DOUBLE_BINARY, self, rhs_array1, rhs_array2, @@ -1926,7 +1925,7 @@ def perform_unary_reduction( # Return a new legate array for a binary operation @classmethod - def perform_fused_op( + def perform_double_binary_op( cls, op, one, @@ -2072,8 +2071,8 @@ def perform_fused_op( #if check_types else: thunks = [one._thunk, two._thunk, three._thunk] - print("running fused op with out_shape=", out.shape) - out._thunk.fused_op( + print("running double binary op with out_shape=", out.shape) + out._thunk.double_binary_op( op, one._thunk, two._thunk, diff --git a/legate/numpy/config.py b/legate/numpy/config.py index c7ca5d7c7..19d9a586a 100644 --- a/legate/numpy/config.py +++ b/legate/numpy/config.py @@ -131,6 +131,7 @@ class NumPyOpCode(IntEnum): ARANGE = legate_numpy.NUMPY_ARANGE TRANSPOSE = legate_numpy.NUMPY_TRANSPOSE NONZERO = legate_numpy.NUMPY_NONZERO + DOUBLE_BINARY_OP = legate_numpy.NUMPY_DOUBLE_BINARY_OP FUSED_OP = legate_numpy.NUMPY_FUSED_OP @@ -139,6 +140,11 @@ class FusedOpCode(IntEnum): FUSE = 1 +@unique +class DoubleBinaryOpCode(IntEnum): + DOUBLE_BINARY = 1 + + @unique class BinaryOpCode(IntEnum): ADD = 1 @@ -285,3 +291,7 @@ class NumPyMappingTag(IntEnum): GPU_ONLY_TASK_TAG = legate_numpy.NUMPY_GPU_ONLY_TAG NO_MEMOIZE_TAG = 0 # Turn this off for now since it doesn't help KEY_REGION_TAG = legate_numpy.NUMPY_KEY_REGION_TAG + +#hack!!! this is for prototyping reason and needs to be addressed before making a PR +numpy_context.fused_id = NumPyOpCode.FUSED_OP +#numpy_context.fused_id = NumPyOpCode.DOUBLE_BINARY_OP diff --git a/legate/numpy/deferred.py b/legate/numpy/deferred.py index 8eafa9d95..2bf2ef98d 100644 --- a/legate/numpy/deferred.py +++ b/legate/numpy/deferred.py @@ -1399,8 +1399,8 @@ def unary_reduction( # Perform the fused operation and put the result in the lhs array @profile @auto_convert([2, 3, 4,5]) - @shadow_debug("fused_op", [2, 3, 4,5]) - def fused_op( + @shadow_debug("double_binary_op", [2, 3, 4,5]) + def double_binary_op( self, op_code, src1, src2, temp, src3, where, args, stacklevel=0, callsite=None ): lhs = self.base @@ -1415,14 +1415,14 @@ def fused_op( if all_scalar_rhs: task_id = NumPyOpCode.SCALAR_BINARY_OP else: - task_id = NumPyOpCode.FUSED_OP + task_id = NumPyOpCode.DOUBLE_BINARY_OP task = self.context.create_task(task_id) + task.add_output(temp1) task.add_output(lhs) - task.add_temp(temp1) + #task.add_temp(temp1) - task.add_output(lhs) task.add_input(rhs1) task.add_input(rhs2) task.add_input(rhs3) @@ -1436,7 +1436,7 @@ def fused_op( task.add_alignment(lhs, rhs3) task.add_alignment(lhs, temp1) - print("about to execute fused_op!!", task_id) + print("about to execute double_binary_op!!", task_id) print("the shapes:") print(rhs1.shape) print(rhs2.shape) @@ -1466,12 +1466,9 @@ def binary_op( task_id = NumPyOpCode.BINARY_OP task = self.context.create_task(task_id) - #print("output",lhs) - #print("input", rhs1, rhs2) task.add_output(lhs) task.add_input(rhs1) task.add_input(rhs2) - print("binary op code", op_code.value) task.add_scalar_arg(op_code.value, ty.int32) self.add_arguments(task, args) diff --git a/src/double_binary/double_binary_op.cc b/src/double_binary/double_binary_op.cc new file mode 100644 index 000000000..4cf0b2e6a --- /dev/null +++ b/src/double_binary/double_binary_op.cc @@ -0,0 +1,73 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "double_binary/double_binary_op.h" +#include "double_binary/double_binary_op_template.inl" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct DoubleBinaryOpImplBody { + using OP = DoubleBinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRW temp, + AccessorRO in1, + AccessorRO in2, + AccessorRO in3, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + const size_t volume = rect.volume(); + if (dense) { + auto outptr = out.ptr(rect); + auto tempptr = temp.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + auto in3ptr = in3.ptr(rect); + for (size_t idx = 0; idx < volume; ++idx) { + tempptr[idx] = func(in1ptr[idx], in2ptr[idx]); + outptr[idx] = func(tempptr[idx], in3ptr[idx]); + } + } else { + for (size_t idx = 0; idx < volume; ++idx) { + auto p = pitches.unflatten(idx, rect.lo); + temp[p] = func(in1[p], in2[p]); + out[p] = func(temp[p], in3[p]); + } + } + } +}; + +/*static*/ void DoubleBinaryOpTask::cpu_variant(TaskContext& context) +{ + double_binary_op_template(context); +} + +namespace // unnamed +{ +static void __attribute__((constructor)) register_tasks(void) { DoubleBinaryOpTask::register_variants(); } +} // namespace + +} // namespace numpy +} // namespace legate diff --git a/src/double_binary/double_binary_op.cu b/src/double_binary/double_binary_op.cu new file mode 100644 index 000000000..1d0bfc349 --- /dev/null +++ b/src/double_binary/double_binary_op.cu @@ -0,0 +1,79 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "double_binary/binary_op.h" +#include "double_binary_op_template.inl" + +#include "cuda_help.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) + dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + out[idx] = func(in1[idx], in2[idx]); +} + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( + size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + auto point = pitches.unflatten(idx, rect.lo); + out[point] = func(in1[point], in2[point]); +} + +template +struct DoubleBinaryOpImplBody { + using OP = DoubleBinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + size_t volume = rect.volume(); + const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); + } else { + generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); + } + } +}; + +/*static*/ void DoubleBinaryOpTask::gpu_variant(TaskContext& context) +{ + double_binary_op_template(context); +} + +} // namespace numpy +} // namespace legate diff --git a/src/double_binary/double_binary_op.h b/src/double_binary/double_binary_op.h new file mode 100644 index 000000000..35cb311a1 --- /dev/null +++ b/src/double_binary/double_binary_op.h @@ -0,0 +1,64 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy.h" +#include "double_binary/double_binary_op_util.h" + +namespace legate { +namespace numpy { + +struct DoubleBinaryOpArgs { + const Array& in1; + const Array& in2; + const Array& in3; + const Array& temp; + const Array& out; + DoubleBinaryOpCode op_code; + std::vector args; +}; + + +struct DoubleBinaryOpArgs2 { + std::vector ins; + std::vector outs; + std::vector inStarts; + std::vector inSizes; + std::vector outStarts; + std::vector outSizes; + std::vector op_codes; + std::vector args; +}; + + + +class DoubleBinaryOpTask : public NumPyTask { + public: + static const int TASK_ID = NUMPY_DOUBLE_BINARY_OP; + + public: + static void cpu_variant(TaskContext& context); +#ifdef LEGATE_USE_OPENMP + static void omp_variant(TaskContext& context); +#endif +#ifdef LEGATE_USE_CUDA + static void gpu_variant(TaskContext& context); +#endif +}; + +} // namespace numpy +} // namespace legate diff --git a/src/double_binary/double_binary_op_omp.cc b/src/double_binary/double_binary_op_omp.cc new file mode 100644 index 000000000..652424b25 --- /dev/null +++ b/src/double_binary/double_binary_op_omp.cc @@ -0,0 +1,72 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "double_binary/double_binary_op.h" +#include "double_binary_op_template.inl" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct DoubleBinaryOpImplBody { + using OP = DoubleBinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRW temp, + AccessorRO in1, + AccessorRO in2, + AccessorRO in3, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + const size_t volume = rect.volume(); + if (dense) { + auto outptr = out.ptr(rect); + auto tempptr = temp.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + auto in3ptr = in3.ptr(rect); +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) { + tempptr[idx] = func(in1ptr[idx], in2ptr[idx]); + outptr[idx] = func(tempptr[idx], in3ptr[idx]); + //outptr[idx] = func(func(in1ptr[idx], in2ptr[idx]), in3ptr[idx]); + } + } else { +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) { + auto p = pitches.unflatten(idx, rect.lo); + //out[p] = func(func(in1[p], in2[p]), in3[p]); + temp[p] = func(in1[p], in2[p]); + out[p] = func(temp[p], in3[p]); + } + } + } +}; + +/*static*/ void DoubleBinaryOpTask::omp_variant(TaskContext& context) +{ + double_binary_op_template(context); +} + +} // namespace numpy +} // namespace legate diff --git a/src/double_binary/double_binary_op_template.inl b/src/double_binary/double_binary_op_template.inl new file mode 100644 index 000000000..28ebbe792 --- /dev/null +++ b/src/double_binary/double_binary_op_template.inl @@ -0,0 +1,103 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "double_binary/double_binary_op_util.h" +#include "pitches.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct DoubleBinaryOpImplBody; + +template +struct DoubleBinaryOpImpl { + template ::valid>* = nullptr> + void operator()(DoubleBinaryOpArgs& args) const + { + using OP = DoubleBinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + auto rect = args.out.shape(); + + Pitches pitches; + size_t volume = pitches.flatten(rect); + + if (volume == 0) return; + + auto out = args.out.write_accessor(rect); + auto temp = args.temp.read_write_accessor(rect); + auto in1 = args.in1.read_accessor(rect); + auto in2 = args.in2.read_accessor(rect); + auto in3 = args.in2.read_accessor(rect); + +#ifndef LEGION_BOUNDS_CHECKS + // Check to see if this is dense or not + bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && + in2.accessor.is_dense_row_major(rect) && in3.accessor.is_dense_row_major(rect) && + temp.accessor.is_dense_row_major(rect); +#else + // No dense execution if we're doing bounds checks + bool dense = false; +#endif + + OP func{args.args}; + DoubleBinaryOpImplBody()(func, out,temp, in1, in2,in3, pitches, rect, dense); + } + + template ::valid>* = nullptr> + void operator()(DoubleBinaryOpArgs& args) const + { + assert(false); + } +}; + +template +struct DoubleBinaryOpDispatch { + template + void operator()(DoubleBinaryOpArgs& args) const + { + auto dim = std::max(args.in1.dim(), args.in2.dim()); + dim = std::max(args.in3.dim(), dim); + double_dispatch(dim, args.in1.code(), DoubleBinaryOpImpl{}, args); + } +}; + +template +static void double_binary_op_template(TaskContext& context) +{ + auto& inputs = context.inputs(); + auto& outputs = context.outputs(); + auto& scalars = context.scalars(); + + std::vector extra_args; + for (size_t idx = 3; idx < inputs.size(); ++idx) + extra_args.push_back(inputs[idx].scalar()); + + DoubleBinaryOpArgs args{ + inputs[0], inputs[1], inputs[2], outputs[0], outputs[1], scalars[0].value(), std::move(extra_args)}; + op_dispatch(args.op_code, DoubleBinaryOpDispatch{}, args); +} + +} // namespace numpy +} // namespace legate diff --git a/src/double_binary/double_binary_op_util.h b/src/double_binary/double_binary_op_util.h new file mode 100644 index 000000000..064e63fc5 --- /dev/null +++ b/src/double_binary/double_binary_op_util.h @@ -0,0 +1,346 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy.h" + +namespace legate { +namespace numpy { + +enum class DoubleBinaryOpCode : int { + ADD = 1, + DIVIDE, + EQUAL, + FLOOR_DIVIDE, + GREATER, + GREATER_EQUAL, + LESS, + LESS_EQUAL, + MAXIMUM, + MINIMUM, + MOD, + MULTIPLY, + NOT_EQUAL, + POWER, + SUBTRACT, + ALLCLOSE, +}; + +template +constexpr decltype(auto) op_dispatch(DoubleBinaryOpCode op_code, Functor f, Fnargs&&... args) +{ + switch (op_code) { + case DoubleBinaryOpCode::ADD: + return f.template operator()(std::forward(args)...); + case DoubleBinaryOpCode::DIVIDE: + return f.template operator()(std::forward(args)...); + //case DoubleBinaryOpCode::EQUAL: + // return f.template operator()(std::forward(args)...); + case DoubleBinaryOpCode::FLOOR_DIVIDE: + return f.template operator()(std::forward(args)...); + //case DoubleBinaryOpCode::GREATER: + // return f.template operator()(std::forward(args)...); + //case DoubleBinaryOpCode::GREATER_EQUAL: + // return f.template operator()(std::forward(args)...); + //case DoubleBinaryOpCode::LESS: + // return f.template operator()(std::forward(args)...); + //case DoubleBinaryOpCode::LESS_EQUAL: + // return f.template operator()(std::forward(args)...); + case DoubleBinaryOpCode::MAXIMUM: + return f.template operator()(std::forward(args)...); + case DoubleBinaryOpCode::MINIMUM: + return f.template operator()(std::forward(args)...); + case DoubleBinaryOpCode::MOD: + return f.template operator()(std::forward(args)...); + case DoubleBinaryOpCode::MULTIPLY: + return f.template operator()(std::forward(args)...); + //case DoubleBinaryOpCode::NOT_EQUAL: + // return f.template operator()(std::forward(args)...); + case DoubleBinaryOpCode::POWER: + return f.template operator()(std::forward(args)...); + case DoubleBinaryOpCode::SUBTRACT: + return f.template operator()(std::forward(args)...); + default: break; + } + assert(false); + return f.template operator()(std::forward(args)...); +} + +template +constexpr decltype(auto) reduce_op_dispatch(DoubleBinaryOpCode op_code, Functor f, Fnargs&&... args) +{ + switch (op_code) { + //case DoubleBinaryOpCode::EQUAL: + // return f.template operator()(std::forward(args)...); + //case DoubleBinaryOpCode::ALLCLOSE: + // return f.template operator()(std::forward(args)...); + default: break; + } + assert(false); + //return f.template operator()(std::forward(args)...); +} + +template +struct DoubleBinaryOp { + static constexpr bool valid = false; +}; + +template +struct DoubleBinaryOp : std::plus> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; + +template +struct DoubleBinaryOp : std::divides> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; +/* +template +struct DoubleBinaryOp : std::equal_to> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; +*/ +using std::floor; +template +struct DoubleBinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return floor(a / b); } +}; + +template <> +struct DoubleBinaryOp { + static constexpr bool valid = false; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; + +template <> +struct DoubleBinaryOp { + static constexpr bool valid = false; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; +/* +template +struct DoubleBinaryOp : std::greater> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; + +template +struct DoubleBinaryOp : std::greater_equal> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; + +template +struct DoubleBinaryOp : std::less> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; + +template +struct DoubleBinaryOp : std::less_equal> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; +*/ +template +struct DoubleBinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return std::max(a, b); } +}; + +template +struct DoubleBinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return std::min(a, b); } +}; + +template +constexpr T real_mod(const T& a, const T& b) +{ + T res = std::fmod(a, b); + if (res) { + if ((b < static_cast(0)) != (res < static_cast(0))) res += b; + } else { + res = std::copysign(static_cast(0), b); + } + return res; +} + +template +struct DoubleBinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} + template ::value>* = nullptr> + constexpr _T operator()(const _T& a, const _T& b) const + { + return a % b; + } + + template ::value>* = nullptr> + constexpr _T operator()(const _T& a, const _T& b) const + { + return real_mod(a, b); + } +}; + +template <> +struct DoubleBinaryOp { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const + { + return static_cast<__half>(real_mod(static_cast(a), static_cast(b))); + } +}; + +template <> +struct DoubleBinaryOp { + static constexpr bool valid = false; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; + +template <> +struct DoubleBinaryOp { + static constexpr bool valid = false; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; + +template +struct DoubleBinaryOp : std::multiplies> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; +/* +template +struct DoubleBinaryOp : std::not_equal_to> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; +*/ +template +struct DoubleBinaryOp { + using VAL = legate_type_of; + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} + constexpr VAL operator()(const VAL& a, const VAL& b) const { return std::pow(a, b); } +}; + +template <> +struct DoubleBinaryOp { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const + { + return pow(a, b); + } +}; + +template <> +struct DoubleBinaryOp { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX complex operator()(const complex& a, + const complex& b) const + { + return pow(a, b); + } +}; + +template <> +struct DoubleBinaryOp { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX complex operator()(const complex& a, + const complex& b) const + { + return pow(a, b); + } +}; + +template +struct DoubleBinaryOp : std::minus> { + static constexpr bool valid = true; + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) {} +}; +/* +template +struct DoubleBinaryOp { + using VAL = legate_type_of; + static constexpr bool valid = true; + + DoubleBinaryOp() {} + DoubleBinaryOp(const std::vector& args) + { + assert(args.size() == 2); + rtol_ = args[0].value(); + atol_ = args[1].value(); + } + + template ::value>* = nullptr> + constexpr bool operator()(const T& a, const T& b) const + { + using std::fabs; + return fabs(static_cast(a) - static_cast(b)) <= + atol_ + rtol_ * static_cast(fabs(b)); + } + + template ::value>* = nullptr> + constexpr bool operator()(const T& a, const T& b) const + { + return static_cast(abs(a - b)) <= atol_ + rtol_ * static_cast(abs(b)); + } + + double rtol_{0}; + double atol_{0}; +}; +*/ +} // namespace numpy +} // namespace legate diff --git a/src/fused/fused_op_template.inl b/src/fused/fused_op_template.inl index 88c833fa8..98408fcbe 100644 --- a/src/fused/fused_op_template.inl +++ b/src/fused/fused_op_template.inl @@ -88,15 +88,17 @@ static void fused_op_template(TaskContext& context) { auto& inputs = context.inputs(); auto& outputs = context.outputs(); - auto& scalars = context.scalars(); + //auto& scalars = context.scalars(); - std::vector extra_args; - for (size_t idx = 3; idx < inputs.size(); ++idx) - extra_args.push_back(inputs[idx].scalar()); + std::cout<<"fused inputs"< extra_args; + //for (size_t idx = 3; idx < inputs.size(); ++idx) + // extra_args.push_back(inputs[idx].scalar()); - FusedOpArgs args{ - inputs[0], inputs[1], inputs[2], outputs[0], outputs[1], scalars[0].value(), std::move(extra_args)}; - op_dispatch(args.op_code, FusedOpDispatch{}, args); + + //FusedOpArgs args{ + // inputs[0], inputs[1], inputs[2], outputs[0], outputs[1], scalars[0].value(), std::move(extra_args)}; + //op_dispatch(args.op_code, FusedOpDispatch{}, args); //op_dispatch(args.op_code1, FusedOpDispatch{}, args1); //op_dispatch(args.op_code2, FusedOpDispatch{}, args2); } diff --git a/src/legate_numpy_c.h b/src/legate_numpy_c.h index cebcc4509..6fcdb2aaa 100644 --- a/src/legate_numpy_c.h +++ b/src/legate_numpy_c.h @@ -46,7 +46,8 @@ enum NumPyOpCode { NUMPY_TRANSPOSE = 400024, NUMPY_TILE = 400025, NUMPY_NONZERO = 400026, - NUMPY_FUSED_OP = 400027, + NUMPY_DOUBLE_BINARY_OP = 400027, + NUMPY_FUSED_OP = 400028, }; // Match these to NumPyRedopCode in legate/numpy/config.py diff --git a/src/numpy.mk b/src/numpy.mk index 95566989a..7dadb298a 100644 --- a/src/numpy.mk +++ b/src/numpy.mk @@ -11,14 +11,15 @@ # 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. -# fused/fused_op.cc -#fused/fused_op_omp.cc -#fused/fused_op.cu +# double_binary/double_binary_op.cc +#double_binary/double_binary_op_omp.cc +#double_binary/double_binary_op.cu # # List all the application source files that need OpenMP separately # since we have to add the -fopenmp flag to CC_FLAGS for them GEN_CPU_SRC += ternary/where.cc \ - fused/fused_op.cc \ + double_binary/double_binary_op.cc \ + fused/fused_op.cc \ binary/binary_op.cc \ binary/scalar_binary_op.cc \ binary/binary_red.cc \ @@ -53,7 +54,8 @@ GEN_CPU_SRC += ternary/where.cc \ ifeq ($(strip $(USE_OPENMP)),1) GEN_CPU_SRC += ternary/where_omp.cc \ - fused/fused_op_omp.cc \ + double_binary/double_binary_op_omp.cc \ + fused/fused_op_omp.cc \ binary/binary_op_omp.cc \ binary/binary_red_omp.cc \ unary/unary_op_omp.cc \ @@ -76,7 +78,8 @@ GEN_CPU_SRC += ternary/where_omp.cc \ endif GEN_GPU_SRC += ternary/where.cu \ - fused/fused_op.cu \ + double_binary/double_binary_op.cu \ + fused/fused_op.cu \ binary/binary_op.cu \ binary/binary_red.cu \ unary/scalar_unary_red.cu \ From 0a5fae3cd21b9ea093657e7891b8c9a7e7dfc071 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 26 Sep 2021 22:20:20 -0700 Subject: [PATCH 03/46] fusion via inlining, as well as function based fusion in fused_binary --- src/binary/binary_op.cc | 1 + src/fused/{fused_op.cu => binary_op.cu} | 14 +- src/fused/{fused_op.h => binary_op.h} | 22 +- src/fused/binary_op_template.inl | 136 +++++++ .../{fused_op_util.h => binary_op_util.h} | 243 ++++++------ src/fused/fused_op.cc | 132 ++++++- src/fused/fused_op_omp.cc | 26 +- src/fused/fused_op_template.inl | 107 ------ src/fused_binary/binary_op.cu | 79 ++++ src/fused_binary/binary_op.h | 48 +++ src/fused_binary/binary_op_template.inl | 136 +++++++ src/fused_binary/binary_op_util.h | 345 ++++++++++++++++++ src/fused_binary/binary_red.cc | 68 ++++ src/fused_binary/binary_red.cu | 85 +++++ src/fused_binary/binary_red.h | 48 +++ src/fused_binary/binary_red_omp.cc | 63 ++++ src/fused_binary/binary_red_template.inl | 95 +++++ src/fused_binary/fused_op.cc | 117 ++++++ src/fused_binary/fused_op_omp.cc | 62 ++++ src/fused_binary/makeshift_serializer.h | 80 ++++ src/fused_binary/scalar_binary_op.cc | 96 +++++ src/fused_binary/scalar_binary_op.h | 34 ++ src/numpy.mk | 3 - 23 files changed, 1748 insertions(+), 292 deletions(-) rename src/fused/{fused_op.cu => binary_op.cu} (87%) rename src/fused/{fused_op.h => binary_op.h} (74%) create mode 100644 src/fused/binary_op_template.inl rename src/fused/{fused_op_util.h => binary_op_util.h} (50%) delete mode 100644 src/fused/fused_op_template.inl create mode 100644 src/fused_binary/binary_op.cu create mode 100644 src/fused_binary/binary_op.h create mode 100644 src/fused_binary/binary_op_template.inl create mode 100644 src/fused_binary/binary_op_util.h create mode 100644 src/fused_binary/binary_red.cc create mode 100644 src/fused_binary/binary_red.cu create mode 100644 src/fused_binary/binary_red.h create mode 100644 src/fused_binary/binary_red_omp.cc create mode 100644 src/fused_binary/binary_red_template.inl create mode 100644 src/fused_binary/fused_op.cc create mode 100644 src/fused_binary/fused_op_omp.cc create mode 100644 src/fused_binary/makeshift_serializer.h create mode 100644 src/fused_binary/scalar_binary_op.cc create mode 100644 src/fused_binary/scalar_binary_op.h diff --git a/src/binary/binary_op.cc b/src/binary/binary_op.cc index c7a3ff989..a5764c042 100644 --- a/src/binary/binary_op.cc +++ b/src/binary/binary_op.cc @@ -53,6 +53,7 @@ struct BinaryOpImplBody { /*static*/ void BinaryOpTask::cpu_variant(TaskContext& context) { + std::cout<<"launching binary op"<(context); } diff --git a/src/fused/fused_op.cu b/src/fused/binary_op.cu similarity index 87% rename from src/fused/fused_op.cu rename to src/fused/binary_op.cu index a2a048ed4..a83792b69 100644 --- a/src/fused/fused_op.cu +++ b/src/fused/binary_op.cu @@ -14,8 +14,8 @@ * */ -#include "fused/binary_op.h" -#include "fused_op_template.inl" +#include "binary/binary_op.h" +#include "binary_op_template.inl" #include "cuda_help.h" @@ -43,9 +43,9 @@ static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) gen out[point] = func(in1[point], in2[point]); } -template -struct FusedOpImplBody { - using OP = FusedOp; +template +struct BinaryOpImplBody { + using OP = BinaryOp; using ARG = legate_type_of; using RES = std::result_of_t; @@ -70,9 +70,9 @@ struct FusedOpImplBody { } }; -/*static*/ void FusedOpTask::gpu_variant(TaskContext& context) +/*static*/ void BinaryOpTask::gpu_variant(TaskContext& context) { - fused_op_template(context); + binary_op_template(context); } } // namespace numpy diff --git a/src/fused/fused_op.h b/src/fused/binary_op.h similarity index 74% rename from src/fused/fused_op.h rename to src/fused/binary_op.h index 7c818b591..91da88101 100644 --- a/src/fused/fused_op.h +++ b/src/fused/binary_op.h @@ -17,35 +17,19 @@ #pragma once #include "numpy.h" -#include "fused/fused_op_util.h" +#include "fused/binary_op_util.h" namespace legate { namespace numpy { -struct FusedOpArgs { +struct BinaryOpArgs { const Array& in1; const Array& in2; - const Array& in3; - const Array& temp; const Array& out; - FusedOpCode op_code; + BinaryOpCode op_code; std::vector args; }; - -struct FusedOpArgs2 { - std::vector ins; - std::vector outs; - std::vector inStarts; - std::vector inSizes; - std::vector outStarts; - std::vector outSizes; - std::vector op_codes; - std::vector args; -}; - - - class FusedOpTask : public NumPyTask { public: static const int TASK_ID = NUMPY_FUSED_OP; diff --git a/src/fused/binary_op_template.inl b/src/fused/binary_op_template.inl new file mode 100644 index 000000000..d3ab7e975 --- /dev/null +++ b/src/fused/binary_op_template.inl @@ -0,0 +1,136 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "fused/binary_op_util.h" +#include "pitches.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryOpImplBody; + +template +struct BinaryOpImpl { + template ::valid>* = nullptr> + void operator()(BinaryOpArgs& args) const + { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + auto rect = args.out.shape(); + + Pitches pitches; + size_t volume = pitches.flatten(rect); + + if (volume == 0) return; + + auto out = args.out.write_accessor(rect); + auto in1 = args.in1.read_accessor(rect); + auto in2 = args.in2.read_accessor(rect); + +#ifndef LEGION_BOUNDS_CHECKS + // Check to see if this is dense or not + bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && + in2.accessor.is_dense_row_major(rect); +#else + // No dense execution if we're doing bounds checks + bool dense = false; +#endif + + OP func{args.args}; + BinaryOpImplBody()(func, out, in1, in2, pitches, rect, dense); + } + + template ::valid>* = nullptr> + void operator()(BinaryOpArgs& args) const + { + assert(false); + } +}; + +template +struct BinaryOpDispatch { + template + void operator()(BinaryOpArgs& args) const + { + auto dim = std::max(args.in1.dim(), args.in2.dim()); + double_dispatch(dim, args.in1.code(), BinaryOpImpl{}, args); + } +}; + + + +template +static void binary_op_template(TaskContext& context) +{ + auto& inputs = context.inputs(); + auto& outputs = context.outputs(); + auto& scalars = context.scalars(); +/* + std::vector extra_args; + for (size_t idx = 2; idx < inputs.size(); ++idx) + extra_args.push_back(inputs[idx].scalar()); + std::cout<<"extra args size"<(), std::move(extra_args)}; + op_dispatch(args.op_code, BinaryOpDispatch{}, args); +*/ + //std::cout<<"fused inputs"<().hi.x; + //std::cout<<"nops "<(); + auto opcode_i = static_cast::type>(opcode); + //std::cout<<"opcode "<().lo.x<<" "<().hi.x< extra_args; + //for (size_t idx = 3; idx < inputs.size(); ++idx) + // extra_args.push_back(inputs[idx].scalar()); + + int inputStart=4; + int outputStart=0; + + for (int i=0; i(), std::move(extra_args)}; + op_dispatch(args.op_code, BinaryOpDispatch{}, args); + inputStart+=2; + outputStart+=1; + } + /* + BinaryOpArgs args2{ + inputs[6], inputs[7], outputs[1], scalars[1].value(), std::move(extra_args)}; + op_dispatch(args2.op_code, BinaryOpDispatch{}, args2); + */ +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused/fused_op_util.h b/src/fused/binary_op_util.h similarity index 50% rename from src/fused/fused_op_util.h rename to src/fused/binary_op_util.h index 48fa349bd..08f85ad2e 100644 --- a/src/fused/fused_op_util.h +++ b/src/fused/binary_op_util.h @@ -21,7 +21,7 @@ namespace legate { namespace numpy { -enum class FusedOpCode : int { +enum class BinaryOpCode : int { ADD = 1, DIVIDE, EQUAL, @@ -41,152 +41,151 @@ enum class FusedOpCode : int { }; template -constexpr decltype(auto) op_dispatch(FusedOpCode op_code, Functor f, Fnargs&&... args) +constexpr decltype(auto) op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) { switch (op_code) { - case FusedOpCode::ADD: - return f.template operator()(std::forward(args)...); - case FusedOpCode::DIVIDE: - return f.template operator()(std::forward(args)...); - //case FusedOpCode::EQUAL: - // return f.template operator()(std::forward(args)...); - case FusedOpCode::FLOOR_DIVIDE: - return f.template operator()(std::forward(args)...); - //case FusedOpCode::GREATER: - // return f.template operator()(std::forward(args)...); - //case FusedOpCode::GREATER_EQUAL: - // return f.template operator()(std::forward(args)...); - //case FusedOpCode::LESS: - // return f.template operator()(std::forward(args)...); - //case FusedOpCode::LESS_EQUAL: - // return f.template operator()(std::forward(args)...); - case FusedOpCode::MAXIMUM: - return f.template operator()(std::forward(args)...); - case FusedOpCode::MINIMUM: - return f.template operator()(std::forward(args)...); - case FusedOpCode::MOD: - return f.template operator()(std::forward(args)...); - case FusedOpCode::MULTIPLY: - return f.template operator()(std::forward(args)...); - //case FusedOpCode::NOT_EQUAL: - // return f.template operator()(std::forward(args)...); - case FusedOpCode::POWER: - return f.template operator()(std::forward(args)...); - case FusedOpCode::SUBTRACT: - return f.template operator()(std::forward(args)...); + case BinaryOpCode::ADD: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::DIVIDE: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::FLOOR_DIVIDE: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::GREATER: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::GREATER_EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::LESS: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::LESS_EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MAXIMUM: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MINIMUM: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MOD: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MULTIPLY: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::NOT_EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::POWER: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::SUBTRACT: + return f.template operator()(std::forward(args)...); default: break; } assert(false); - return f.template operator()(std::forward(args)...); + return f.template operator()(std::forward(args)...); } template -constexpr decltype(auto) reduce_op_dispatch(FusedOpCode op_code, Functor f, Fnargs&&... args) +constexpr decltype(auto) reduce_op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) { switch (op_code) { - //case FusedOpCode::EQUAL: - // return f.template operator()(std::forward(args)...); - //case FusedOpCode::ALLCLOSE: - // return f.template operator()(std::forward(args)...); + case BinaryOpCode::EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::ALLCLOSE: + return f.template operator()(std::forward(args)...); default: break; } assert(false); - //return f.template operator()(std::forward(args)...); + return f.template operator()(std::forward(args)...); } -template -struct FusedOp { +template +struct BinaryOp { static constexpr bool valid = false; }; template -struct FusedOp : std::plus> { +struct BinaryOp : std::plus> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; template -struct FusedOp : std::divides> { +struct BinaryOp : std::divides> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; -/* + template -struct FusedOp : std::equal_to> { +struct BinaryOp : std::equal_to> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; -*/ + using std::floor; template -struct FusedOp { +struct BinaryOp { using T = legate_type_of; static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} constexpr T operator()(const T& a, const T& b) const { return floor(a / b); } }; - template <> -struct FusedOp { +struct BinaryOp { static constexpr bool valid = false; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; template <> -struct FusedOp { +struct BinaryOp { static constexpr bool valid = false; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; -/* + template -struct FusedOp : std::greater> { +struct BinaryOp : std::greater> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; template -struct FusedOp : std::greater_equal> { +struct BinaryOp : std::greater_equal> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; template -struct FusedOp : std::less> { +struct BinaryOp : std::less> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; template -struct FusedOp : std::less_equal> { +struct BinaryOp : std::less_equal> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; -*/ + template -struct FusedOp { +struct BinaryOp { using T = legate_type_of; static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} constexpr T operator()(const T& a, const T& b) const { return std::max(a, b); } }; template -struct FusedOp { +struct BinaryOp { using T = legate_type_of; static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} constexpr T operator()(const T& a, const T& b) const { return std::min(a, b); } }; @@ -203,11 +202,11 @@ constexpr T real_mod(const T& a, const T& b) } template -struct FusedOp { +struct BinaryOp { using T = legate_type_of; static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} template ::value>* = nullptr> constexpr _T operator()(const _T& a, const _T& b) const { @@ -222,10 +221,10 @@ struct FusedOp { }; template <> -struct FusedOp { +struct BinaryOp { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const { return static_cast<__half>(real_mod(static_cast(a), static_cast(b))); @@ -233,47 +232,47 @@ struct FusedOp { }; template <> -struct FusedOp { +struct BinaryOp { static constexpr bool valid = false; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; template <> -struct FusedOp { +struct BinaryOp { static constexpr bool valid = false; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; template -struct FusedOp : std::multiplies> { +struct BinaryOp : std::multiplies> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; -/* + template -struct FusedOp : std::not_equal_to> { +struct BinaryOp : std::not_equal_to> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; -*/ + template -struct FusedOp { +struct BinaryOp { using VAL = legate_type_of; static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} constexpr VAL operator()(const VAL& a, const VAL& b) const { return std::pow(a, b); } }; template <> -struct FusedOp { +struct BinaryOp { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const { return pow(a, b); @@ -281,10 +280,10 @@ struct FusedOp { }; template <> -struct FusedOp { +struct BinaryOp { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} LEGATE_DEVICE_PREFIX complex operator()(const complex& a, const complex& b) const { @@ -293,10 +292,10 @@ struct FusedOp { }; template <> -struct FusedOp { +struct BinaryOp { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} LEGATE_DEVICE_PREFIX complex operator()(const complex& a, const complex& b) const { @@ -305,19 +304,19 @@ struct FusedOp { }; template -struct FusedOp : std::minus> { +struct BinaryOp : std::minus> { static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) {} + BinaryOp() {} + BinaryOp(const std::vector& args) {} }; -/* + template -struct FusedOp { +struct BinaryOp { using VAL = legate_type_of; static constexpr bool valid = true; - FusedOp() {} - FusedOp(const std::vector& args) + BinaryOp() {} + BinaryOp(const std::vector& args) { assert(args.size() == 2); rtol_ = args[0].value(); @@ -341,6 +340,6 @@ struct FusedOp { double rtol_{0}; double atol_{0}; }; -*/ + } // namespace numpy } // namespace legate diff --git a/src/fused/fused_op.cc b/src/fused/fused_op.cc index c1f52e2cb..66f26e439 100644 --- a/src/fused/fused_op.cc +++ b/src/fused/fused_op.cc @@ -14,26 +14,27 @@ * */ -#include "fused/fused_op.h" -#include "fused/fused_op_template.inl" +#include "utilities/makeshift_serializer.h" +#include "fused/binary_op.h" +#include "fused/binary_op_template.inl" +#include "legion.h" + namespace legate { namespace numpy { using namespace Legion; -template -struct FusedOpImplBody { - using OP = FusedOp; +template +struct BinaryOpImplBody { + using OP = BinaryOp; using ARG = legate_type_of; using RES = std::result_of_t; void operator()(OP func, AccessorWO out, - AccessorRW temp, AccessorRO in1, AccessorRO in2, - AccessorRO in3, const Pitches& pitches, const Rect& rect, bool dense) const @@ -41,27 +42,126 @@ struct FusedOpImplBody { const size_t volume = rect.volume(); if (dense) { auto outptr = out.ptr(rect); - auto tempptr = temp.ptr(rect); auto in1ptr = in1.ptr(rect); auto in2ptr = in2.ptr(rect); - auto in3ptr = in3.ptr(rect); - for (size_t idx = 0; idx < volume; ++idx) { - tempptr[idx] = func(in1ptr[idx], in2ptr[idx]); - outptr[idx] = func(tempptr[idx], in3ptr[idx]); - } + for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); } else { for (size_t idx = 0; idx < volume; ++idx) { auto p = pitches.unflatten(idx, rect.lo); - temp[p] = func(in1[p], in2[p]); - out[p] = func(temp[p], in3[p]); + out[p] = func(in1[p], in2[p]); } } } }; +void inline_leaf_task(const Task *task, + const std::vector ®ions, + Context ctx, Runtime *runtime) +{ + printf("Hello from 'inline_leaf_task' being inlined into leaf 'fused op'\n"); +} + +//op id refers not to the op's type, but the index in the list of fused ops +void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) +{ + //grab all the stores + const int nMetaDataArrs=4; + Store& inputStartsStore = context.inputs()[0]; + Store& outputStartsStore = context.inputs()[1]; + Store& offsetStartsStore = context.inputs()[2]; + Store& offsetsStore = context.inputs()[3]; + + //grab pointers to all the metadata arrays + using ARG = legate_type_of; + auto opRect = context.inputs()[0].shape<1>(); //iterator over range(0,nOps) + auto offsetMetaRect = context.inputs()[3].shape<1>(); //iter over range(0, nInputs+nOutputs) + + auto inputStarts = inputStartsStore.read_accessor().ptr(opRect); + auto outputStarts = outputStartsStore.read_accessor().ptr(opRect); + auto offsetStarts = offsetStartsStore.read_accessor().ptr(opRect); + auto offsets = offsetsStore.read_accessor().ptr(offsetMetaRect); + + + //pack inputs + unsigned nInputs = (inputStarts[opID+1]-inputStarts[opID]); //want to pack this as a 32 bit uint + ms.pack((uint32_t) nInputs); + //std::cout<<"inputs "<0) + { + bufferID--; + //std::cout<<"packing input "<(context); + const int INLINE_LEAF_TASK_ID =0; + int nOps = context.inputs()[0].shape<1>().hi.x; + auto offsetMetaRect = context.inputs()[3].shape<1>(); + //std::cout<; + const Store& offsetsStore = context.inputs()[3]; + auto offsets = offsetsStore.read_accessor().ptr(offsetMetaRect); + + //pack inputs + for (int i=0; iindex_point; + for (int i=0; i< context.task_->regions.size();i++) + { + auto& req = context.task_->regions[i]; + leaf_launcher.add_region_requirement(req); + } + + leaf_launcher.enable_inlining=true; + context.runtime_->execute_task(context.context_, leaf_launcher); + } } namespace // unnamed diff --git a/src/fused/fused_op_omp.cc b/src/fused/fused_op_omp.cc index a716f0062..0d4151442 100644 --- a/src/fused/fused_op_omp.cc +++ b/src/fused/fused_op_omp.cc @@ -14,26 +14,24 @@ * */ -#include "fused/fused_op.h" -#include "fused_op_template.inl" +#include "fused/binary_op.h" +#include "fused/binary_op_template.inl" namespace legate { namespace numpy { using namespace Legion; -template -struct FusedOpImplBody { - using OP = FusedOp; +template +struct BinaryOpImplBody { + using OP = BinaryOp; using ARG = legate_type_of; using RES = std::result_of_t; void operator()(OP func, AccessorWO out, - AccessorRW temp, AccessorRO in1, AccessorRO in2, - AccessorRO in3, const Pitches& pitches, const Rect& rect, bool dense) const @@ -41,23 +39,15 @@ struct FusedOpImplBody { const size_t volume = rect.volume(); if (dense) { auto outptr = out.ptr(rect); - auto tempptr = temp.ptr(rect); auto in1ptr = in1.ptr(rect); auto in2ptr = in2.ptr(rect); - auto in3ptr = in3.ptr(rect); #pragma omp parallel for schedule(static) - for (size_t idx = 0; idx < volume; ++idx) { - tempptr[idx] = func(in1ptr[idx], in2ptr[idx]); - outptr[idx] = func(tempptr[idx], in3ptr[idx]); - //outptr[idx] = func(func(in1ptr[idx], in2ptr[idx]), in3ptr[idx]); - } + for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); } else { #pragma omp parallel for schedule(static) for (size_t idx = 0; idx < volume; ++idx) { auto p = pitches.unflatten(idx, rect.lo); - //out[p] = func(func(in1[p], in2[p]), in3[p]); - temp[p] = func(in1[p], in2[p]); - out[p] = func(temp[p], in3[p]); + out[p] = func(in1[p], in2[p]); } } } @@ -65,7 +55,7 @@ struct FusedOpImplBody { /*static*/ void FusedOpTask::omp_variant(TaskContext& context) { - fused_op_template(context); + binary_op_template(context); } } // namespace numpy diff --git a/src/fused/fused_op_template.inl b/src/fused/fused_op_template.inl deleted file mode 100644 index 98408fcbe..000000000 --- a/src/fused/fused_op_template.inl +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "fused/fused_op_util.h" -#include "pitches.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct FusedOpImplBody; - -template -struct FusedOpImpl { - template ::valid>* = nullptr> - void operator()(FusedOpArgs& args) const - { - using OP = FusedOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - auto rect = args.out.shape(); - - Pitches pitches; - size_t volume = pitches.flatten(rect); - - if (volume == 0) return; - - auto out = args.out.write_accessor(rect); - auto temp = args.temp.read_write_accessor(rect); - auto in1 = args.in1.read_accessor(rect); - auto in2 = args.in2.read_accessor(rect); - auto in3 = args.in2.read_accessor(rect); - -#ifndef LEGION_BOUNDS_CHECKS - // Check to see if this is dense or not - bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && - in2.accessor.is_dense_row_major(rect) && in3.accessor.is_dense_row_major(rect) && - temp.accessor.is_dense_row_major(rect); -#else - // No dense execution if we're doing bounds checks - bool dense = false; -#endif - - OP func{args.args}; - FusedOpImplBody()(func, out,temp, in1, in2,in3, pitches, rect, dense); - } - - template ::valid>* = nullptr> - void operator()(FusedOpArgs& args) const - { - assert(false); - } -}; - -template -struct FusedOpDispatch { - template - void operator()(FusedOpArgs& args) const - { - auto dim = std::max(args.in1.dim(), args.in2.dim()); - dim = std::max(args.in3.dim(), dim); - double_dispatch(dim, args.in1.code(), FusedOpImpl{}, args); - } -}; - -template -static void fused_op_template(TaskContext& context) -{ - auto& inputs = context.inputs(); - auto& outputs = context.outputs(); - //auto& scalars = context.scalars(); - - std::cout<<"fused inputs"< extra_args; - //for (size_t idx = 3; idx < inputs.size(); ++idx) - // extra_args.push_back(inputs[idx].scalar()); - - - //FusedOpArgs args{ - // inputs[0], inputs[1], inputs[2], outputs[0], outputs[1], scalars[0].value(), std::move(extra_args)}; - //op_dispatch(args.op_code, FusedOpDispatch{}, args); - //op_dispatch(args.op_code1, FusedOpDispatch{}, args1); - //op_dispatch(args.op_code2, FusedOpDispatch{}, args2); -} - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/binary_op.cu b/src/fused_binary/binary_op.cu new file mode 100644 index 000000000..a83792b69 --- /dev/null +++ b/src/fused_binary/binary_op.cu @@ -0,0 +1,79 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "binary/binary_op.h" +#include "binary_op_template.inl" + +#include "cuda_help.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) + dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + out[idx] = func(in1[idx], in2[idx]); +} + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( + size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + auto point = pitches.unflatten(idx, rect.lo); + out[point] = func(in1[point], in2[point]); +} + +template +struct BinaryOpImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + size_t volume = rect.volume(); + const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); + } else { + generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); + } + } +}; + +/*static*/ void BinaryOpTask::gpu_variant(TaskContext& context) +{ + binary_op_template(context); +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/binary_op.h b/src/fused_binary/binary_op.h new file mode 100644 index 000000000..91da88101 --- /dev/null +++ b/src/fused_binary/binary_op.h @@ -0,0 +1,48 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy.h" +#include "fused/binary_op_util.h" + +namespace legate { +namespace numpy { + +struct BinaryOpArgs { + const Array& in1; + const Array& in2; + const Array& out; + BinaryOpCode op_code; + std::vector args; +}; + +class FusedOpTask : public NumPyTask { + public: + static const int TASK_ID = NUMPY_FUSED_OP; + + public: + static void cpu_variant(TaskContext& context); +#ifdef LEGATE_USE_OPENMP + static void omp_variant(TaskContext& context); +#endif +#ifdef LEGATE_USE_CUDA + static void gpu_variant(TaskContext& context); +#endif +}; + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/binary_op_template.inl b/src/fused_binary/binary_op_template.inl new file mode 100644 index 000000000..d3ab7e975 --- /dev/null +++ b/src/fused_binary/binary_op_template.inl @@ -0,0 +1,136 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "fused/binary_op_util.h" +#include "pitches.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryOpImplBody; + +template +struct BinaryOpImpl { + template ::valid>* = nullptr> + void operator()(BinaryOpArgs& args) const + { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + auto rect = args.out.shape(); + + Pitches pitches; + size_t volume = pitches.flatten(rect); + + if (volume == 0) return; + + auto out = args.out.write_accessor(rect); + auto in1 = args.in1.read_accessor(rect); + auto in2 = args.in2.read_accessor(rect); + +#ifndef LEGION_BOUNDS_CHECKS + // Check to see if this is dense or not + bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && + in2.accessor.is_dense_row_major(rect); +#else + // No dense execution if we're doing bounds checks + bool dense = false; +#endif + + OP func{args.args}; + BinaryOpImplBody()(func, out, in1, in2, pitches, rect, dense); + } + + template ::valid>* = nullptr> + void operator()(BinaryOpArgs& args) const + { + assert(false); + } +}; + +template +struct BinaryOpDispatch { + template + void operator()(BinaryOpArgs& args) const + { + auto dim = std::max(args.in1.dim(), args.in2.dim()); + double_dispatch(dim, args.in1.code(), BinaryOpImpl{}, args); + } +}; + + + +template +static void binary_op_template(TaskContext& context) +{ + auto& inputs = context.inputs(); + auto& outputs = context.outputs(); + auto& scalars = context.scalars(); +/* + std::vector extra_args; + for (size_t idx = 2; idx < inputs.size(); ++idx) + extra_args.push_back(inputs[idx].scalar()); + std::cout<<"extra args size"<(), std::move(extra_args)}; + op_dispatch(args.op_code, BinaryOpDispatch{}, args); +*/ + //std::cout<<"fused inputs"<().hi.x; + //std::cout<<"nops "<(); + auto opcode_i = static_cast::type>(opcode); + //std::cout<<"opcode "<().lo.x<<" "<().hi.x< extra_args; + //for (size_t idx = 3; idx < inputs.size(); ++idx) + // extra_args.push_back(inputs[idx].scalar()); + + int inputStart=4; + int outputStart=0; + + for (int i=0; i(), std::move(extra_args)}; + op_dispatch(args.op_code, BinaryOpDispatch{}, args); + inputStart+=2; + outputStart+=1; + } + /* + BinaryOpArgs args2{ + inputs[6], inputs[7], outputs[1], scalars[1].value(), std::move(extra_args)}; + op_dispatch(args2.op_code, BinaryOpDispatch{}, args2); + */ +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/binary_op_util.h b/src/fused_binary/binary_op_util.h new file mode 100644 index 000000000..08f85ad2e --- /dev/null +++ b/src/fused_binary/binary_op_util.h @@ -0,0 +1,345 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy.h" + +namespace legate { +namespace numpy { + +enum class BinaryOpCode : int { + ADD = 1, + DIVIDE, + EQUAL, + FLOOR_DIVIDE, + GREATER, + GREATER_EQUAL, + LESS, + LESS_EQUAL, + MAXIMUM, + MINIMUM, + MOD, + MULTIPLY, + NOT_EQUAL, + POWER, + SUBTRACT, + ALLCLOSE, +}; + +template +constexpr decltype(auto) op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) +{ + switch (op_code) { + case BinaryOpCode::ADD: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::DIVIDE: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::FLOOR_DIVIDE: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::GREATER: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::GREATER_EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::LESS: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::LESS_EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MAXIMUM: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MINIMUM: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MOD: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MULTIPLY: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::NOT_EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::POWER: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::SUBTRACT: + return f.template operator()(std::forward(args)...); + default: break; + } + assert(false); + return f.template operator()(std::forward(args)...); +} + +template +constexpr decltype(auto) reduce_op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) +{ + switch (op_code) { + case BinaryOpCode::EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::ALLCLOSE: + return f.template operator()(std::forward(args)...); + default: break; + } + assert(false); + return f.template operator()(std::forward(args)...); +} + +template +struct BinaryOp { + static constexpr bool valid = false; +}; + +template +struct BinaryOp : std::plus> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::divides> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::equal_to> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +using std::floor; +template +struct BinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return floor(a / b); } +}; +template <> +struct BinaryOp { + static constexpr bool valid = false; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template <> +struct BinaryOp { + static constexpr bool valid = false; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::greater> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::greater_equal> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::less> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::less_equal> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return std::max(a, b); } +}; + +template +struct BinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return std::min(a, b); } +}; + +template +constexpr T real_mod(const T& a, const T& b) +{ + T res = std::fmod(a, b); + if (res) { + if ((b < static_cast(0)) != (res < static_cast(0))) res += b; + } else { + res = std::copysign(static_cast(0), b); + } + return res; +} + +template +struct BinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} + template ::value>* = nullptr> + constexpr _T operator()(const _T& a, const _T& b) const + { + return a % b; + } + + template ::value>* = nullptr> + constexpr _T operator()(const _T& a, const _T& b) const + { + return real_mod(a, b); + } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const + { + return static_cast<__half>(real_mod(static_cast(a), static_cast(b))); + } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = false; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template <> +struct BinaryOp { + static constexpr bool valid = false; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::multiplies> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::not_equal_to> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp { + using VAL = legate_type_of; + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} + constexpr VAL operator()(const VAL& a, const VAL& b) const { return std::pow(a, b); } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const + { + return pow(a, b); + } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX complex operator()(const complex& a, + const complex& b) const + { + return pow(a, b); + } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX complex operator()(const complex& a, + const complex& b) const + { + return pow(a, b); + } +}; + +template +struct BinaryOp : std::minus> { + static constexpr bool valid = true; + BinaryOp() {} + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp { + using VAL = legate_type_of; + static constexpr bool valid = true; + + BinaryOp() {} + BinaryOp(const std::vector& args) + { + assert(args.size() == 2); + rtol_ = args[0].value(); + atol_ = args[1].value(); + } + + template ::value>* = nullptr> + constexpr bool operator()(const T& a, const T& b) const + { + using std::fabs; + return fabs(static_cast(a) - static_cast(b)) <= + atol_ + rtol_ * static_cast(fabs(b)); + } + + template ::value>* = nullptr> + constexpr bool operator()(const T& a, const T& b) const + { + return static_cast(abs(a - b)) <= atol_ + rtol_ * static_cast(abs(b)); + } + + double rtol_{0}; + double atol_{0}; +}; + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/binary_red.cc b/src/fused_binary/binary_red.cc new file mode 100644 index 000000000..efb72bf83 --- /dev/null +++ b/src/fused_binary/binary_red.cc @@ -0,0 +1,68 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "binary/binary_red.h" +#include "binary/binary_red_template.inl" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryRedImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + + UntypedScalar operator()(OP func, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + size_t volume = rect.volume(); + if (dense) { + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + for (size_t idx = 0; idx < volume; ++idx) + if (!func(in1ptr[idx], in2ptr[idx])) return UntypedScalar(false); + } else { + for (size_t idx = 0; idx < volume; ++idx) { + auto point = pitches.unflatten(idx, rect.lo); + if (!func(in1[point], in2[point])) return UntypedScalar(false); + } + } + + return UntypedScalar(true); + } +}; + +/*static*/ UntypedScalar BinaryRedTask::cpu_variant(TaskContext& context) +{ + return binary_red_template(context); +} + +namespace // unnamed +{ +static void __attribute__((constructor)) register_tasks(void) +{ + BinaryRedTask::register_variants_with_return(); +} +} // namespace + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/binary_red.cu b/src/fused_binary/binary_red.cu new file mode 100644 index 000000000..e05d47325 --- /dev/null +++ b/src/fused_binary/binary_red.cu @@ -0,0 +1,85 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "binary/binary_red.h" +#include "binary/binary_red_template.inl" + +#include "cuda_help.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) + dense_kernel(size_t volume, Function func, RES out, const ARG* in1, const ARG* in2) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + if (!func(in1[idx], in2[idx])) out <<= false; +} + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( + size_t volume, Function func, RES out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + auto point = pitches.unflatten(idx, rect.lo); + if (!func(in1[point], in2[point])) out <<= false; +} + +template +struct BinaryRedImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + + UntypedScalar operator()(OP func, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + size_t volume = rect.volume(); + const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + DeferredReduction> result; + cudaStream_t stream; + cudaStreamCreate(&stream); + if (dense) { + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + dense_kernel<<>>(volume, func, result, in1ptr, in2ptr); + } else { + generic_kernel<<>>( + volume, func, result, in1, in2, pitches, rect); + } + + cudaStreamSynchronize(stream); + cudaStreamDestroy(stream); + + return UntypedScalar(result.read()); + } +}; + +/*static*/ UntypedScalar BinaryRedTask::gpu_variant(TaskContext& context) +{ + return binary_red_template(context); +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/binary_red.h b/src/fused_binary/binary_red.h new file mode 100644 index 000000000..3f5300889 --- /dev/null +++ b/src/fused_binary/binary_red.h @@ -0,0 +1,48 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy.h" +#include "scalar.h" +#include "binary/binary_op_util.h" + +namespace legate { +namespace numpy { + +struct BinaryRedArgs { + const Array& in1; + const Array& in2; + BinaryOpCode op_code; + std::vector args; +}; + +class BinaryRedTask : public NumPyTask { + public: + static const int TASK_ID = NUMPY_BINARY_RED; + + public: + static UntypedScalar cpu_variant(TaskContext& context); +#ifdef LEGATE_USE_OPENMP + static UntypedScalar omp_variant(TaskContext& context); +#endif +#ifdef LEGATE_USE_CUDA + static UntypedScalar gpu_variant(TaskContext& context); +#endif +}; + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/binary_red_omp.cc b/src/fused_binary/binary_red_omp.cc new file mode 100644 index 000000000..3e9c912b7 --- /dev/null +++ b/src/fused_binary/binary_red_omp.cc @@ -0,0 +1,63 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "binary/binary_red.h" +#include "binary/binary_red_template.inl" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryRedImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + + UntypedScalar operator()(OP func, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + size_t volume = rect.volume(); + bool result = true; + if (dense) { + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) + if (!func(in1ptr[idx], in2ptr[idx])) result = false; + } else { +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) { + auto point = pitches.unflatten(idx, rect.lo); + if (!func(in1[point], in2[point])) result = false; + } + } + + return UntypedScalar(result); + } +}; + +/*static*/ UntypedScalar BinaryRedTask::omp_variant(TaskContext& context) +{ + return binary_red_template(context); +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/binary_red_template.inl b/src/fused_binary/binary_red_template.inl new file mode 100644 index 000000000..ef9d75094 --- /dev/null +++ b/src/fused_binary/binary_red_template.inl @@ -0,0 +1,95 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "binary/binary_op_util.h" +#include "pitches.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryRedImplBody; + +template +struct BinaryRedImpl { + template ::valid>* = nullptr> + UntypedScalar operator()(BinaryRedArgs& args) const + { + using OP = BinaryOp; + using ARG = legate_type_of; + + auto rect = args.in1.shape(); + + Pitches pitches; + size_t volume = pitches.flatten(rect); + + if (volume == 0) return UntypedScalar(true); + + auto in1 = args.in1.read_accessor(rect); + auto in2 = args.in2.read_accessor(rect); + +#ifndef LEGION_BOUNDS_CHECKS + // Check to see if this is dense or not + bool dense = in1.accessor.is_dense_row_major(rect) && in2.accessor.is_dense_row_major(rect); +#else + // No dense execution if we're doing bounds checks + bool dense = false; +#endif + + OP func(args.args); + return BinaryRedImplBody()(func, in1, in2, pitches, rect, dense); + } + + template ::valid>* = nullptr> + UntypedScalar operator()(BinaryRedArgs& args) const + { + assert(false); + return UntypedScalar(); + } +}; + +template +struct BinaryRedDispatch { + template + UntypedScalar operator()(BinaryRedArgs& args) const + { + auto dim = std::max(args.in1.dim(), args.in2.dim()); + return double_dispatch(dim, args.in1.code(), BinaryRedImpl{}, args); + } +}; + +template +static UntypedScalar binary_red_template(TaskContext& context) +{ + auto& inputs = context.inputs(); + auto& scalars = context.scalars(); + + std::vector extra_args; + for (size_t idx = 2; idx < inputs.size(); ++idx) + extra_args.push_back(inputs[idx].scalar()); + + BinaryRedArgs args{inputs[0], inputs[1], scalars[0].value(), std::move(extra_args)}; + return reduce_op_dispatch(args.op_code, BinaryRedDispatch{}, args); +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/fused_op.cc b/src/fused_binary/fused_op.cc new file mode 100644 index 000000000..6897f1aa4 --- /dev/null +++ b/src/fused_binary/fused_op.cc @@ -0,0 +1,117 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "fused/makeshift_serializer.h" +#include "fused/binary_op.h" +#include "fused/binary_op_template.inl" +#include "legion.h" +//#include "legion/legion_utilities.h" +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryOpImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + const size_t volume = rect.volume(); + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); + } else { + for (size_t idx = 0; idx < volume; ++idx) { + auto p = pitches.unflatten(idx, rect.lo); + out[p] = func(in1[p], in2[p]); + } + } + } +}; + +void inline_leaf_task(const Task *task, + const std::vector ®ions, + Context ctx, Runtime *runtime) +{ + printf("Hello from 'inline_leaf_task' being inlined into leaf 'fused op'\n"); +} + +/*static*/ void FusedOpTask::cpu_variant(TaskContext& context) +{ +/* +TaskLauncher(TaskID tid, + TaskArgument arg, + Predicate pred = Predicate::TRUE_PRED, + MapperID id = 0, + MappingTagID tag = 0); + + Deserializer dez(task, regions); + inputs_ = dez.unpack>(); + outputs_ = dez.unpack>(); + reductions_ = dez.unpack>(); + scalars_ = dez.unpack>(); +*/ + const int INLINE_LEAF_TASK_ID =0; + MakeshiftSerializer ms; + + //pack inputs + ms.pack(context.inputs().size()); + for (auto& input : context.inputs()) + { + ms.pack(input.is_future()); //is_future + ms.pack(input.dim()); + int code = input.code(); + ms.pack(code); + } + //pack inputs + //pack outputs + //pack reductions + //pack scalars + + + TaskLauncher inline_leaf_launcher(INLINE_LEAF_TASK_ID, TaskArgument()); + std::cout<<"trying to launch leaf task"<execute_task(ctx, inline_leaf_launcher); + + + //../legate.core/legion//examples/local_function_tasks/local_function_tasks.cc + binary_op_template(context); +} + +namespace // unnamed +{ +static void __attribute__((constructor)) register_tasks(void) { FusedOpTask::register_variants(); } +} // namespace + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/fused_op_omp.cc b/src/fused_binary/fused_op_omp.cc new file mode 100644 index 000000000..0d4151442 --- /dev/null +++ b/src/fused_binary/fused_op_omp.cc @@ -0,0 +1,62 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "fused/binary_op.h" +#include "fused/binary_op_template.inl" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryOpImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + const size_t volume = rect.volume(); + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); + } else { +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) { + auto p = pitches.unflatten(idx, rect.lo); + out[p] = func(in1[p], in2[p]); + } + } + } +}; + +/*static*/ void FusedOpTask::omp_variant(TaskContext& context) +{ + binary_op_template(context); +} + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/makeshift_serializer.h b/src/fused_binary/makeshift_serializer.h new file mode 100644 index 000000000..ac8abf004 --- /dev/null +++ b/src/fused_binary/makeshift_serializer.h @@ -0,0 +1,80 @@ +#include +#include + +class MakeshiftSerializer{ + + public: + MakeshiftSerializer(){ + size=4; + raw.resize(size); + write_offset=0; + read_offset=0; + } + + template void pack(T& arg) + { + if (size<=write_offset+sizeof(T)) + { + resize(sizeof(T)); + } + raw[write_offset] = *reinterpret_cast(&arg); + write_offset+=sizeof(T); + } + + template void pack(T&& arg) + { + T copy = arg; + pack(copy); + } + + template T read() + { + if (read_offset(raw.data()+read_offset); + read_offset+=sizeof(T); + return datum; + } + else{ + std::cout<<"finished reading buffer"< raw; +}; +/* +int main(){ + MakeshiftSerializer ms; + int a=3; + char g='a'; + ms.pack(a); + ms.pack(g); + ms.pack(a); + ms.pack(g); + std::cout<()<()<()<()<()<()< +struct BinaryOpImpl { + template ::valid>* = nullptr> + UntypedScalar operator()(const UntypedScalar& in1, + const UntypedScalar& in2, + const std::vector& args) const + { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + OP func{args}; + + auto a = in1.value(); + auto b = in2.value(); + auto result = func(a, b); + + return UntypedScalar(result); + } + + template ::valid>* = nullptr> + UntypedScalar operator()(const UntypedScalar& in1, + const UntypedScalar& in2, + const std::vector& args) const + { + assert(false); + return UntypedScalar(); + } +}; + +struct BinaryOpDispatch { + template + UntypedScalar operator()(const UntypedScalar& in1, + const UntypedScalar& in2, + const std::vector& args) const + { + return type_dispatch(in1.code(), BinaryOpImpl{}, in1, in2, args); + } +}; + +/*static*/ UntypedScalar ScalarBinaryOpTask::cpu_variant(TaskContext& context) +{ + auto op_code = context.scalars()[0].value(); + + auto& inputs = context.inputs(); + + auto& in1 = inputs[0]; + auto& in2 = inputs[1]; + + std::vector args; + for (auto idx = 2; idx < inputs.size(); ++idx) + args.push_back(inputs[idx].scalar()); + + if (op_code == BinaryOpCode::ALLCLOSE) + return BinaryOpDispatch{}.operator()( + in1.scalar(), in2.scalar(), args); + else + return op_dispatch( + op_code, BinaryOpDispatch{}, in1.scalar(), in2.scalar(), args); +} + +namespace // unnamed +{ +static void __attribute__((constructor)) register_tasks(void) +{ + ScalarBinaryOpTask::register_variants_with_return(); +} +} // namespace + +} // namespace numpy +} // namespace legate diff --git a/src/fused_binary/scalar_binary_op.h b/src/fused_binary/scalar_binary_op.h new file mode 100644 index 000000000..04c55806c --- /dev/null +++ b/src/fused_binary/scalar_binary_op.h @@ -0,0 +1,34 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy.h" +#include "scalar.h" + +namespace legate { +namespace numpy { + +class ScalarBinaryOpTask : public NumPyTask { + public: + static const int TASK_ID = NUMPY_SCALAR_BINARY_OP; + + public: + static UntypedScalar cpu_variant(TaskContext& contex); +}; + +} // namespace numpy +} // namespace legate diff --git a/src/numpy.mk b/src/numpy.mk index 7dadb298a..d599113d3 100644 --- a/src/numpy.mk +++ b/src/numpy.mk @@ -18,7 +18,6 @@ # List all the application source files that need OpenMP separately # since we have to add the -fopenmp flag to CC_FLAGS for them GEN_CPU_SRC += ternary/where.cc \ - double_binary/double_binary_op.cc \ fused/fused_op.cc \ binary/binary_op.cc \ binary/scalar_binary_op.cc \ @@ -54,7 +53,6 @@ GEN_CPU_SRC += ternary/where.cc \ ifeq ($(strip $(USE_OPENMP)),1) GEN_CPU_SRC += ternary/where_omp.cc \ - double_binary/double_binary_op_omp.cc \ fused/fused_op_omp.cc \ binary/binary_op_omp.cc \ binary/binary_red_omp.cc \ @@ -78,7 +76,6 @@ GEN_CPU_SRC += ternary/where_omp.cc \ endif GEN_GPU_SRC += ternary/where.cu \ - double_binary/double_binary_op.cu \ fused/fused_op.cu \ binary/binary_op.cu \ binary/binary_red.cu \ From 2b0b3b0aa326b1aee04afbed96109a09d6d2b6e1 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Wed, 29 Sep 2021 07:34:34 -0700 Subject: [PATCH 04/46] scalars reductions and opids, need to remove dynamic allocations --- src/binary/binary_op.cc | 1 - src/fused/fused_op.cc | 23 ++++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/binary/binary_op.cc b/src/binary/binary_op.cc index a5764c042..c7a3ff989 100644 --- a/src/binary/binary_op.cc +++ b/src/binary/binary_op.cc @@ -53,7 +53,6 @@ struct BinaryOpImplBody { /*static*/ void BinaryOpTask::cpu_variant(TaskContext& context) { - std::cout<<"launching binary op"<(context); } diff --git a/src/fused/fused_op.cc b/src/fused/fused_op.cc index 66f26e439..488391706 100644 --- a/src/fused/fused_op.cc +++ b/src/fused/fused_op.cc @@ -65,11 +65,13 @@ void inline_leaf_task(const Task *task, void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) { //grab all the stores - const int nMetaDataArrs=4; + const int nMetaDataArrs=7; Store& inputStartsStore = context.inputs()[0]; Store& outputStartsStore = context.inputs()[1]; Store& offsetStartsStore = context.inputs()[2]; Store& offsetsStore = context.inputs()[3]; + Store& reductionStartsStore = context.inputs()[4]; + Store& scalarStartsStore = context.inputs()[5]; //grab pointers to all the metadata arrays using ARG = legate_type_of; @@ -80,7 +82,8 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) auto outputStarts = outputStartsStore.read_accessor().ptr(opRect); auto offsetStarts = offsetStartsStore.read_accessor().ptr(opRect); auto offsets = offsetsStore.read_accessor().ptr(offsetMetaRect); - + auto reductionStarts = reductionStartsStore.read_accessor().ptr(opRect); + auto scalarStarts = scalarStartsStore.read_accessor().ptr(opRect); //pack inputs unsigned nInputs = (inputStarts[opID+1]-inputStarts[opID]); //want to pack this as a 32 bit uint @@ -126,18 +129,21 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) } //pack reductions - int32_t nReductions = 0; + int32_t nReductions = (reductionStarts[opID+1]-reductionStarts[opID]); ms.pack((uint32_t) nReductions); //pack scalars - int32_t nScalars = 1; + int32_t nScalars = (scalarStarts[opID+1]-scalarStarts[opID]); ms.pack((uint32_t) nScalars); - ms.packScalar(context.scalars()[opID]); + for (unsigned i = 0; i().hi.x; auto offsetMetaRect = context.inputs()[3].shape<1>(); //std::cout<().ptr(offsetMetaRect); + const Store& taskIDStore = context.inputs()[6]; + auto opRect = context.inputs()[6].shape<1>(); + auto taskIDs = offsetsStore.read_accessor().ptr(opRect); + //pack inputs for (int i=0; iindex_point; for (int i=0; i< context.task_->regions.size();i++) From c301582abd9b51564b443585e0b1d9a2919c26ef Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Wed, 29 Sep 2021 15:59:29 -0700 Subject: [PATCH 05/46] fusion metadata passed via serialization now --- src/fused/fused_op.cc | 46 ++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/fused/fused_op.cc b/src/fused/fused_op.cc index 488391706..6b0a568ca 100644 --- a/src/fused/fused_op.cc +++ b/src/fused/fused_op.cc @@ -65,6 +65,7 @@ void inline_leaf_task(const Task *task, void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) { //grab all the stores + /* const int nMetaDataArrs=7; Store& inputStartsStore = context.inputs()[0]; Store& outputStartsStore = context.inputs()[1]; @@ -72,18 +73,29 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) Store& offsetsStore = context.inputs()[3]; Store& reductionStartsStore = context.inputs()[4]; Store& scalarStartsStore = context.inputs()[5]; - + */ //grab pointers to all the metadata arrays - using ARG = legate_type_of; - auto opRect = context.inputs()[0].shape<1>(); //iterator over range(0,nOps) - auto offsetMetaRect = context.inputs()[3].shape<1>(); //iter over range(0, nInputs+nOutputs) - + //using ARG = legate_type_of; + //auto opRect = context.inputs()[0].shape<1>(); //iterator over range(0,nOps) + //auto offsetMetaRect = context.inputs()[3].shape<1>(); //iter over range(0, nInputs+nOutputs) + + /* auto inputStarts = inputStartsStore.read_accessor().ptr(opRect); auto outputStarts = outputStartsStore.read_accessor().ptr(opRect); auto offsetStarts = offsetStartsStore.read_accessor().ptr(opRect); auto offsets = offsetsStore.read_accessor().ptr(offsetMetaRect); auto reductionStarts = reductionStartsStore.read_accessor().ptr(opRect); auto scalarStarts = scalarStartsStore.read_accessor().ptr(opRect); + */ + auto inputStarts = context.fusionMetadata.inputStarts; + auto outputStarts = context.fusionMetadata.outputStarts; + auto offsetStarts = context.fusionMetadata.offsetStarts; + auto offsets = context.fusionMetadata.offsets; + auto reductionStarts = context.fusionMetadata.reductionStarts; + auto scalarStarts = context.fusionMetadata.scalarStarts; + + //the leaf task cannot be fused ops currently + ms.pack((bool) false); //pack inputs unsigned nInputs = (inputStarts[opID+1]-inputStarts[opID]); //want to pack this as a 32 bit uint @@ -100,10 +112,8 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) { bufferID--; //std::cout<<"packing input "<().hi.x; - auto offsetMetaRect = context.inputs()[3].shape<1>(); + //int nOps = context.inputs()[0].shape<1>().hi.x; + //auto offsetMetaRect = context.inputs()[3].shape<1>(); //std::cout<; - const Store& offsetsStore = context.inputs()[3]; - auto offsets = offsetsStore.read_accessor().ptr(offsetMetaRect); + //using ARG = legate_type_of; + //const Store& offsetsStore = context.inputs()[3]; + //auto offsets = offsetsStore.read_accessor().ptr(offsetMetaRect); - const Store& taskIDStore = context.inputs()[6]; - auto opRect = context.inputs()[6].shape<1>(); - auto taskIDs = offsetsStore.read_accessor().ptr(opRect); + //const Store& taskIDStore = context.inputs()[6]; + //auto opRect = context.inputs()[6].shape<1>(); + //auto taskIDs = offsetsStore.read_accessor().ptr(opRect); + int nOps = context.fusionMetadata.nOps; //pack inputs for (int i=0; i Date: Fri, 1 Oct 2021 14:33:28 -0700 Subject: [PATCH 06/46] reuse serializer --- src/fused/fused_op.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/fused/fused_op.cc b/src/fused/fused_op.cc index 6b0a568ca..ccd57bb41 100644 --- a/src/fused/fused_op.cc +++ b/src/fused/fused_op.cc @@ -166,11 +166,12 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) int nOps = context.fusionMetadata.nOps; //pack inputs + MakeshiftSerializer ms; for (int i=0; iindex_point; for (int i=0; i< context.task_->regions.size();i++) { From 72e03b31deb851cccbbfbc89ba87d98cc4016225 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 3 Oct 2021 20:31:37 -0700 Subject: [PATCH 07/46] some timing scripts, also stuff --- bench.sh | 1 + build.sh | 8 + examples/testbench/contrived.py | 49 + .../dataflow_legion_python_main_1.pdf | Bin 0 -> 33085 bytes .../dataflow_legion_python_main_1.pdf | Bin 0 -> 31513 bytes .../event_graph_legion_python_main_1.pdf | Bin 0 -> 27557 bytes examples/testbench/decent_band/index.html | 115 + examples/testbench/decent_band/js/timeline.js | 2734 +++++++++++++++++ examples/testbench/decent_band/js/util.js | 378 +++ .../testbench/decent_band/legion_prof_ops.tsv | 90 + .../decent_band/legion_prof_processor.tsv | 9 + ...000,_System_Memory_0x1e00000000000000).tsv | 3 + .../decent_band/tsv/0 (CPU)_util.tsv | 288 ++ .../decent_band/tsv/0 (Channel)_util.tsv | 4 + .../decent_band/tsv/0 (Python)_util.tsv | 14 + .../tsv/0 (System Memory)_util.tsv | 24 + .../decent_band/tsv/0 (Utility)_util.tsv | 924 ++++++ .../tsv/Mem_0x1e00000000000000.tsv | 12 + examples/testbench/decent_band/tsv/None.tsv | 5 + .../tsv/Proc_0x1d00000000000000.tsv | 297 ++ .../tsv/Proc_0x1d00000000000001.tsv | 266 ++ .../tsv/Proc_0x1d00000000000002.tsv | 93 + .../tsv/Proc_0x1d00000000000003.tsv | 52 + .../tsv/Proc_0x1d00000000000004.tsv | 17 + .../decent_band/tsv/all (CPU)_util.tsv | 288 ++ .../decent_band/tsv/all (Channel)_util.tsv | 4 + .../decent_band/tsv/all (Python)_util.tsv | 14 + .../tsv/all (System Memory)_util.tsv | 24 + .../decent_band/tsv/all (Utility)_util.tsv | 924 ++++++ .../event_graph_legion_python_main_1.pdf | Bin 0 -> 25345 bytes examples/testbench/go.sh | 15 + .../dataflow_legion_python_main_1.pdf | Bin 0 -> 31522 bytes .../event_graph_legion_python_main_1.pdf | Bin 0 -> 27545 bytes examples/testbench/good_band/index.html | 115 + examples/testbench/good_band/js/timeline.js | 2734 +++++++++++++++++ examples/testbench/good_band/js/util.js | 378 +++ .../testbench/good_band/legion_prof_ops.tsv | 90 + .../good_band/legion_prof_processor.tsv | 9 + ...000,_System_Memory_0x1e00000000000000).tsv | 3 + .../testbench/good_band/tsv/0 (CPU)_util.tsv | 208 ++ .../good_band/tsv/0 (Channel)_util.tsv | 4 + .../good_band/tsv/0 (Python)_util.tsv | 16 + .../good_band/tsv/0 (System Memory)_util.tsv | 24 + .../good_band/tsv/0 (Utility)_util.tsv | 992 ++++++ .../good_band/tsv/Mem_0x1e00000000000000.tsv | 12 + examples/testbench/good_band/tsv/None.tsv | 5 + .../good_band/tsv/Proc_0x1d00000000000000.tsv | 304 ++ .../good_band/tsv/Proc_0x1d00000000000001.tsv | 287 ++ .../good_band/tsv/Proc_0x1d00000000000002.tsv | 67 + .../good_band/tsv/Proc_0x1d00000000000003.tsv | 38 + .../good_band/tsv/Proc_0x1d00000000000004.tsv | 20 + .../good_band/tsv/all (CPU)_util.tsv | 208 ++ .../good_band/tsv/all (Channel)_util.tsv | 4 + .../good_band/tsv/all (Python)_util.tsv | 16 + .../tsv/all (System Memory)_util.tsv | 24 + .../good_band/tsv/all (Utility)_util.tsv | 992 ++++++ .../dataflow_legion_python_main_1.pdf | Bin 0 -> 33085 bytes .../event_graph_legion_python_main_1.pdf | Bin 0 -> 25345 bytes examples/testbench/legion_prof/index.html | 115 + examples/testbench/legion_prof/js/timeline.js | 2734 +++++++++++++++++ examples/testbench/legion_prof/js/util.js | 378 +++ .../testbench/legion_prof/legion_prof_ops.tsv | 59 + .../legion_prof/legion_prof_processor.tsv | 6 + .../legion_prof/tsv/0 (CPU)_util.tsv | 206 ++ .../legion_prof/tsv/0 (Python)_util.tsv | 16 + .../tsv/0 (System Memory)_util.tsv | 16 + .../legion_prof/tsv/0 (Utility)_util.tsv | 648 ++++ .../tsv/Mem_0x1e00000000000000.tsv | 8 + .../tsv/Proc_0x1d00000000000000.tsv | 174 ++ .../tsv/Proc_0x1d00000000000001.tsv | 169 + .../tsv/Proc_0x1d00000000000002.tsv | 103 + .../tsv/Proc_0x1d00000000000003.tsv | 20 + .../legion_prof/tsv/all (CPU)_util.tsv | 206 ++ .../legion_prof/tsv/all (Python)_util.tsv | 16 + .../tsv/all (System Memory)_util.tsv | 16 + .../legion_prof/tsv/all (Utility)_util.tsv | 648 ++++ examples/testbench/test.py | 104 + src/fused/binary_op_template.inl | 4 +- src/fused/fused_op.cc | 72 +- time.sh | 1 + 80 files changed, 18870 insertions(+), 51 deletions(-) create mode 100644 bench.sh create mode 100755 build.sh create mode 100644 examples/testbench/contrived.py create mode 100644 examples/testbench/dataflow_legion_python_main_1.pdf create mode 100644 examples/testbench/decent_band/dataflow_legion_python_main_1.pdf create mode 100644 examples/testbench/decent_band/event_graph_legion_python_main_1.pdf create mode 100644 examples/testbench/decent_band/index.html create mode 100644 examples/testbench/decent_band/js/timeline.js create mode 100644 examples/testbench/decent_band/js/util.js create mode 100644 examples/testbench/decent_band/legion_prof_ops.tsv create mode 100644 examples/testbench/decent_band/legion_prof_processor.tsv create mode 100644 examples/testbench/decent_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv create mode 100644 examples/testbench/decent_band/tsv/0 (CPU)_util.tsv create mode 100644 examples/testbench/decent_band/tsv/0 (Channel)_util.tsv create mode 100644 examples/testbench/decent_band/tsv/0 (Python)_util.tsv create mode 100644 examples/testbench/decent_band/tsv/0 (System Memory)_util.tsv create mode 100644 examples/testbench/decent_band/tsv/0 (Utility)_util.tsv create mode 100644 examples/testbench/decent_band/tsv/Mem_0x1e00000000000000.tsv create mode 100644 examples/testbench/decent_band/tsv/None.tsv create mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000000.tsv create mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000001.tsv create mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000002.tsv create mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000003.tsv create mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000004.tsv create mode 100644 examples/testbench/decent_band/tsv/all (CPU)_util.tsv create mode 100644 examples/testbench/decent_band/tsv/all (Channel)_util.tsv create mode 100644 examples/testbench/decent_band/tsv/all (Python)_util.tsv create mode 100644 examples/testbench/decent_band/tsv/all (System Memory)_util.tsv create mode 100644 examples/testbench/decent_band/tsv/all (Utility)_util.tsv create mode 100644 examples/testbench/event_graph_legion_python_main_1.pdf create mode 100644 examples/testbench/go.sh create mode 100644 examples/testbench/good_band/dataflow_legion_python_main_1.pdf create mode 100644 examples/testbench/good_band/event_graph_legion_python_main_1.pdf create mode 100644 examples/testbench/good_band/index.html create mode 100644 examples/testbench/good_band/js/timeline.js create mode 100644 examples/testbench/good_band/js/util.js create mode 100644 examples/testbench/good_band/legion_prof_ops.tsv create mode 100644 examples/testbench/good_band/legion_prof_processor.tsv create mode 100644 examples/testbench/good_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv create mode 100644 examples/testbench/good_band/tsv/0 (CPU)_util.tsv create mode 100644 examples/testbench/good_band/tsv/0 (Channel)_util.tsv create mode 100644 examples/testbench/good_band/tsv/0 (Python)_util.tsv create mode 100644 examples/testbench/good_band/tsv/0 (System Memory)_util.tsv create mode 100644 examples/testbench/good_band/tsv/0 (Utility)_util.tsv create mode 100644 examples/testbench/good_band/tsv/Mem_0x1e00000000000000.tsv create mode 100644 examples/testbench/good_band/tsv/None.tsv create mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000000.tsv create mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000001.tsv create mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000002.tsv create mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000003.tsv create mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000004.tsv create mode 100644 examples/testbench/good_band/tsv/all (CPU)_util.tsv create mode 100644 examples/testbench/good_band/tsv/all (Channel)_util.tsv create mode 100644 examples/testbench/good_band/tsv/all (Python)_util.tsv create mode 100644 examples/testbench/good_band/tsv/all (System Memory)_util.tsv create mode 100644 examples/testbench/good_band/tsv/all (Utility)_util.tsv create mode 100644 examples/testbench/legion_prof/dataflow_legion_python_main_1.pdf create mode 100644 examples/testbench/legion_prof/event_graph_legion_python_main_1.pdf create mode 100644 examples/testbench/legion_prof/index.html create mode 100644 examples/testbench/legion_prof/js/timeline.js create mode 100644 examples/testbench/legion_prof/js/util.js create mode 100644 examples/testbench/legion_prof/legion_prof_ops.tsv create mode 100644 examples/testbench/legion_prof/legion_prof_processor.tsv create mode 100644 examples/testbench/legion_prof/tsv/0 (CPU)_util.tsv create mode 100644 examples/testbench/legion_prof/tsv/0 (Python)_util.tsv create mode 100644 examples/testbench/legion_prof/tsv/0 (System Memory)_util.tsv create mode 100644 examples/testbench/legion_prof/tsv/0 (Utility)_util.tsv create mode 100644 examples/testbench/legion_prof/tsv/Mem_0x1e00000000000000.tsv create mode 100644 examples/testbench/legion_prof/tsv/Proc_0x1d00000000000000.tsv create mode 100644 examples/testbench/legion_prof/tsv/Proc_0x1d00000000000001.tsv create mode 100644 examples/testbench/legion_prof/tsv/Proc_0x1d00000000000002.tsv create mode 100644 examples/testbench/legion_prof/tsv/Proc_0x1d00000000000003.tsv create mode 100644 examples/testbench/legion_prof/tsv/all (CPU)_util.tsv create mode 100644 examples/testbench/legion_prof/tsv/all (Python)_util.tsv create mode 100644 examples/testbench/legion_prof/tsv/all (System Memory)_util.tsv create mode 100644 examples/testbench/legion_prof/tsv/all (Utility)_util.tsv create mode 100644 examples/testbench/test.py create mode 100644 time.sh diff --git a/bench.sh b/bench.sh new file mode 100644 index 000000000..54cda33f6 --- /dev/null +++ b/bench.sh @@ -0,0 +1 @@ +time ../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/build.sh b/build.sh new file mode 100755 index 000000000..1c3802966 --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +#!/bin/bash +#touch src/matrix/matvecmul.cc +#touch src/fused/fused_op.cc +cd ../legate.core/ +python setup.py --no-cuda +cd ../legate.numpy/ +python setup.py --with-core /Users/shivsundram/Desktop/coding/legate/legate.core/install/ --with-openblas /usr/local/opt/openblas/ -j 4 --verbose +#../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/examples/testbench/contrived.py b/examples/testbench/contrived.py new file mode 100644 index 000000000..f9cfed24b --- /dev/null +++ b/examples/testbench/contrived.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime + +#import pdb +#pdb.set_trace() +import legate.numpy as np +import numpy as npo +#import numpy as np +N=6000 +b1 = np.zeros(N) +b2 = np.zeros(N) +b3 = np.zeros(N) +b1.fill(2) +b2.fill(3) +b3.fill(4) + +#dummy ops +# dumb hack so the loop starts at nOps=10 +# so the window/pipe is empty +b3.fill(4) +b3.fill(4) +b3.fill(4) +b3.fill(4) + + +#for i in range(10000): +for i in range(10000): + b3=b1+b2 + +"" diff --git a/examples/testbench/dataflow_legion_python_main_1.pdf b/examples/testbench/dataflow_legion_python_main_1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..49ba1be92373ebda1448adea7f5931c32ec07b29 GIT binary patch literal 33085 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 z z&3+2GMf3o2Nh%93zrH$ciiQ5dqCG;lrjN7K$jPITP2(P~P^=7WUgyL~g z?i_`6-RvGJF}13WDe`PS0)8r+Vr0!)HHVu!@JkU}gi#$Jo19DM2&gwAsG|Iam$dbSz(VPpy@m`qTjCB6BJl!cc69g z;t`NEFWG1&-f5Vbu;!A=SNkYR(*Qs6=dhM~NPNFLm#Ax?e_iZkIX|U8Sa%dS(xd*V zg8)Odhm@Hw72HR{*r3eIH9 zNRr$J!;N$nzFf+)>Ywi1*&cA;TJo4EP%xN5_>8>_e=Fk`+#wM8KIzi-yk(EvSAAVi zZB+Il@maXZi)Dtb{E7=rneLnsOJmBMCKfh?27V{=IMbJMWd|sTZWlc> zS-D;J&FWQ<-y2HQ>~j7iJLTruZdr`7KJUb&qH<{*~N|*{E6ge2^$haG%JWW z53F)mtm*0dD_Yjimkb_EjF^v|c5B?_eaQ|zYfcA>vgV>9#lGOb!kbCFNEN(_KXmQU zdkC|;-QB}D#QU-EZSX6PjW*cM4%$uFs5}VH}BiHb^P%VZg!PkluO*+2j=f%SX6Y@*S%5l5#Ncyz5Hu z#0HWa2TZrlr5^3=TMr`33XJLHB|`ybht|r@x({2Fi%6DUeo}VWEN&uvOlXRNu~-SY z#hERe-_yS4p89+6F%+-MUpASP?b+**2OZuyM-CI{YQBgWoE2>F@xH z+*cF?=pZHIf-dm+ZvhNjh{lUjp&82jWX+64X*EvJ(_fxJ##-!gi$ow?8G72;d?oxO z&L7+U{L0XR{!M_PY7)=9`!t6Z&d>#>O_sb=KgPQrO%eI73$EuF+q`D@HRx&z3R)?A z)*rR+><-t1D6``zsgm4XiidFslwZ@XTlGld(|#GHd+_P3?JVc40etWPMXtadmA>3&9!63Qq1s8__lBBJ^b(Y<3SmyBJkzGKns(DcWdCrFNOrbgX1v zoZMlXMaueNR97+k2(BPhCVV(?srtZqsKvZV)b;a;QH4$-`(_O6Sk5ZH(<*cTs`XvcM<3-jcp}`g zcl$2;n#OU4He>E$J1}zdvrC{PBQTT?Dl#dDPDbI+v};x8x4SC34%Xg`c80nYiq3Sz z)Tm6QqzXy&(GCZ@DOv< zI&Ka6T!;V;mChcRnkvWklAR9I#*}axw~q(Al30{1gjZdfN3Y@pexjsInR@suPK)1n zoRUMFmQL+h_gCh=;*95WVO_D-8S&oEGyz(($~T zV#NtHc=)Bw$rRV-?I#UH86I!1Q0}Uo3^NXCIt1A$?knM{@fABxb9^Tqno#Ge^7bDukweXW!VkNU zmtj`E@%uDG_wHVuA8u6!p-L0Co!!2??uYmwBoi_F4$dVD)u#MFcL_F^ZA*mVsMvtf z`iC`!dLC`Jj0!S2^=rps@WXKGD3-@#G5GPm0Gsf@W=I9zbm@E{gX}2XIZ9}1mS{bx zn^`CLsqB--W8X*ro17VP2$xcP1^g{IauLz2c5c{B>>e|Vu-er~(ZhJ6EgvPGh*!o) z8(kqBIo<&iX=Cez}YJX?1jACuwE_>F=xx|x1ik-jtrcpGkK`T-WR1`nFAVjVG4cLX z0*D*tRGCmWZrodw!&hEo(a6ih%lt<~Fe_X^S-tiv?njl&TyIC)kCB6@a5^QP!N&HX z>pKhu8-sre*OH+p*FdXlKc@Z^!zG3AF5HG>z8}irEMBt1>haAT;Wg8MaCuQhuAfLo zzJhX5Nt?3aB%i*5Vv#wu&6~1Z#p92wxMonNY|ik6V0e!>i`$)}WYw|tkyo5^a#2v+ zkS+4f(k|_CHl3r(VSy?!U`rYu$D{Q*B^1yYDn|}Z=kT%h7K=<)o<%=&u%vc z7kriuQo=H^A0?*n=)NCF5rr4Zbq8_>;L&b>xi2>DC@kQR$|thD zj~24lZQ~!Kt&7d6g^IjwdNFEc?FuiVNVXWGiv@*sktgKb#>jE!y6r8n#bb)a$BSx6 z^_F-c-+(~NXHtlWA)RR*OOLHIOK)saaVR-6C+1uiviyFUPO!#Tm7u?7!AICw5Y@`? zqlr21yN$wV6~|UJ9S7Eg#=@KB+HOSts+(g({sQ4XW2Tm#IH5E(R{w^|tmkYnNe6lY z#1_$oLp;lUymJuGb-ZtsFUue=n)MkeRwZrHdSQhU$Ri5H;uE4#ZPH}7i7V-*9#@NH z4&3*QrJ4$(CZJ>$;iFy~UEE^zBg3_8Sr-h(=~O!_Gq}7~L=LUfn;xwhTI!$asJq!l zAwJr_gYOW7f*$p0GV5@7OGaU9$3@;kER=y79dNO72L|8U1dTGoZ!P$x?gC*s2OnCg z^cGeN*J)ADB3f$iV;N>EVu%F+?ZC6X#2(*$z>b^cq7SbxZ!g2*w)G`L2wahf6Fj1< z+eQAeYvG6v^o(Uy@Pki`Gh0)BQ4!Jsdi;TC|K;o~q`Q`YPuThi;W9MT7DkLactrPs zcD(tyy{+rTrmlAYMZ2J6lleI@6z#>CP-XX)6zM|s5C`7|MHII(bc)(Gqv{HgLu6(K zuWUiUn7_-W!lr^WlFT}I)I$}SpdNF;4}7pvgyr%Dr^)Gn^Del))^9#T`Cgy<7De_RV7; z&(gVhhE}ZjE>ffqtVn1vsFB1poE~0S0Al}KX=8bh^dh%G$xWD6YU#B=j8JQ;PFUF( zCzP*7=PXhY<_J|WHc5GaAF5Po4ik(g?~l?g+`bQe1N#%sg5cQ?bU0y{2fKlO3quUy zubXji3JSdHXI!>Z^6?o$9wzRosgs3i-|FKT^PeFKWw^vVTTALCxlfC=I^)thVeM}E zfp8M0#(K`tqTNAf2K=B;0_!OA=B&a67GE==f*6f6-kaJBg91Dq!ZO8XF zFbGIpn4!s0*lDTqr^Cov6?JoEX|{v=0=Kx5Rp{J`O%?9=-^2Kmy&g7Nrm(TE&=$ba z%fVNdpsIue+`IFbg}#nrRt9Yb3BP)ko&3s^@UqHMixZKv6}<;pzU!I_Q2@q}F}YIU zdSFnKqWrD2dJ|5wY~bS@TSUNZb{k5Zxd#S406LK?_=fb7r32z%9;U(f9r>7Ou!~Fs zgU}j7aKh&;j=m-6>+)xaG|#szF~61trK&4c!CO(YA1hHL10++is~yOV)B4y`iz^kz}9rNi#1*oyXyk*v!yugUU+gF z@~Fd+sKY{Hr&?mpu40qe;}m2^`}fO!7DvV>=eM4QMH|E!sWZInmo8RzTVM5NOB(7` z$z80l8rg)Czidw+EDwjd*6q4&qrl9*ZepuD3~H>*ERpg|gFae9E@=7WQR5D_P=L2?lR<)?LUMlPBpM8osx#2+_hD>bhsI2un>9Sa2Z% z*K^~X)=nU|CzW))U(V^-qlZm)U6zTJmnBdkv3&<0HicOgJm=VU#G!PA{m|i`lmfC*C=F_s|!3rY9}>7`G*?ssOP<*r5N5}L)zcu0(|K8XY`Nw0lf0z6IvF7q%b zJWDS*OBxmpIbFPBItUFi+~#hbc2o|X9j~7&R=1KY5dJ78SW4FPB$i%S@#S*Oy9`5g zIz6cNX=^I%@6S*!=G$vQwX0&}4lpM;s*smeRPxkpCrs{bYL3jlX>A@!i<0pPx@~^4`Vw+aa8Uw|8n!OKkOP*H!oOFjetuc@uiP zh|^5u`c0RkymL29a@D7k_a4oRh&7|ch=pX24E+^fR2uUq=p^%+vQ+iY^rbIpu&$EW z5fOaTW28H+RgP40vwtKya*v`~LNJ57GYO0ymKIpFadhj<0Hj<=VM{{32$ zIpXr@ToR&C7fXAO%9^6&z_>@z;KCu>RQ1D4e;r7nr@#OU$C(Ne2xKu znh*X*+7oweyO%@hx0RkkB0$2Nt?Y98lD{f3*K=L$8=u?C27jDak*C;i{6`>{#_s~Y^1T>qB<3IEu$_K@Ig!;t9_k;B1;1jQx6_`yC^ui=x+!C? z^XVP7i?yqj@S3izJ+!ckPpy+4wTjQ2qT;vK^-H^>-(HwYlD9RuB+NQbHWYAQXl&Se z1dDnwmH#&+;t59Z2PJ};gN^M^OawCsxA0GL0SMIa-^m3)7{Z^}a(&gN=y?Fj-ZdsY zQ;+cHs{!z!z~zbhK1jzCa5QOdh*#3t>z)3@BO@yi`5)b?Qwa~E8-{ncPc2j27krqk z`8M?xPvc}-%P-NYh)zunzUE9?M&Hh-@vXUjQ&Wu`jhWA^EHc$mU)tS}y!V(N6czN9 z*?liaUG92Xp0BsDo}1;@l9|G@RJX6#x?ws~&O_unpqhBgVq+L)J^dC#FiYiL;4o%W z=OX6#^pojA|7{>c5BvH&N4H++dYt-Ft>l8@r1CoD{pB!sQk3c)KgJZVZi%h#>z&u= zdarkUvGhcHU{)a=B)@}8uEGxK#OUzCRpeOJezl?FkZ?f!a3}y@k#o_m^P+~S%op6u z9;+oKum;kqe>-@s|9C6#hUg~r2KpwH05UqK5LG_Y+M&WY3(42ZiH|GO+%tV0(y?9d zjI=#W$PY!p{PO)m>{@qew@+sS-(dKQv+4HvXg{~3$yu3nZ{=4`)r@8k7aU6y_+5N`jKZS0KPo2bJ`pl|Ptq8+^p7txGu2>;sfeO;gK zB4uRLk3PrF6?&|yXBUQ$jQjKZ-RC`-Er;UG$ts#6Ny={Ex&WqYU&A_A(Zst4h*Yhk zl>ab{ejz-7^a?gk?q6UJ=D%PgzsMdSc!-#(v$2zV$Sx7+GkKZvMAUevg$@CLG0!sVya;~pj zo|q?UK+p&%?kQBn$k`N>y%kIDxOa?u=WzCTC{|JF6THd|%BP9C zsU3(ppPB}95C!Ypb4{DJ$C>l$gMY~n`Es`Hp<;g*Ngt0CPij=yUU6m)+3&Lp#LEv7 zpFbF&<;&+|ptZ$cHMHQ@+R19eqOQiE+qYR8yJLrxl0D$Amg6_p+J5GoWkjt+XR>c> zGM{XF=sMsG7gXFyrU_146|k|)*|Qk~3>d}t;PuXbB|x!}=gZd$rpny>OrW8QE>gH~ zoYVAaL0#qZ-kUbp&bFcJ*tRL|l`x&h;3dzH!Z%Kasl4R@q4O*#Z5I&*>+$AmclLtA zd0VhGYR;e5t(B15RAyw|3~i$?R|#6dopzW;7%GNonu@RRopu;$IsCi|1#L5%w9@m| zuYG%(mGs;C$c}1Lxt*d~IEZ^GV zLrzI>=9`ny{hczGfX^B=}=Nf?K-s)X&=mIFS9Q!a+y*F$~=e&B&|NtqpD=YtSo$j-@&5d=(*$@^Lp zU%5GbX-9@{KkQk!YNU0hRGHuNC04^Ufds#;M zP!!Jw;#TAI*K0@MdhD5O4`2e{WU;WL{GpjzlrJZ*hlBV|W|7lACd^xXhXH?c37Z~T z=a7UNkODxy%kJ>n3PC(#zv9@=410bA{rN;TCw-NzbKe0ay0a_0Ybh^ysk;{{Y~1>+ z%Qit+u-rS~12^(vSDP_jYj`CN_m^TLB^xNLF>SLOQV)X6;KNTc%a}oq^-+W#yp>0% z2;;?U6|ugwuJR#RSMcTEz<5jIB$tbhXglUHYEVj#G`(buFVbsJYuMG~Snnn7 z?Mb!Zb&c@%!XOh4Asyfif|kY%?%}A$LKTLx2_%lu{QAI?zhK7JWu4+*Q~Rrc8A;Wf zz-b-G@@3#~PU9ovR^mNMPdT6U^yOt#QfUb>TNy#Q2;oetR35U8_PQ@qAavoJA3*2@ z%L2gR(&b$>jQJM>d5>;AkPN$GxTBq&(0b@s57shCxCUFk=r31Y>9xMAT-H49y?SwF z9-Nm{lQf(J!_YO2Y9eCMhmB&g5W0F31dk=mOb1fc zjIvu2brz~e(lUnWIYD~h40WCRGJHmZVhJ)*6*A+F825BGF=T={q}8`zhI#^COMkmw z6gMNmgU*F3TLLl7{qBJJZgHIPeN%&kUbC z`F@8!K!&Go%gO0G$zjt*+5OEjx-R!24^&UrKlI9{?%4kh9rMZ+!6Ej=JTGXXs^$BZMQtjfz zzV=!ZvS-5??^}2;BQHyHKDLr=CubDxYOyspwM*7bALNyk3w16h&g$x8@X@+_v6c+u zE0DF}P$JnIYG?WuNv0)JhovFCJifo0U+j}Czc0N%7nf`K=ZlwmA?&CUuD+D{r}{=2 zksom^DZN5-w{dwFU42LVB%lu4giD+~-|F*^OIQteP)c)j)>qs{SZ}}UXQ<;Om~gb` zN(oN!{``iBvX3IxPurdPT*kgyP=r71LWy2>7@k&NM=PvWiC%S>Ek$MYz4av-C%b7` zbwzdbin!g(0fpbAuJkq2r~>o;$bGbf?Cp6gNn}2oa%$suTWDqK87P|_ZLskJC=&@q zoRR^7g>jS!9_$I)g}6<%A6x3#Z&er{k0awMq$AizJuz|mYfo(Yqu)T8Vf#gS4(9w5l?mf8|KzM78q{wlK>A2ya*P+T!GY_Zp7n#6zc8 z{Mt4Llhjvfa9W)~jv?pNxt1Y6tAH`I%S7FaU$wL8MlYT_S$U+ON6aJMfTs_p0ah|k zTETJGJa2rD+8a5}hhT*XYA2rrsSuKf){(%5RsHoF-ZVIjy4Aw!PP`D>qP6qci!V8= z{s#{0ZwW7yYZJ}FHt&gDJsy&`9j20Z9L|S%n**FG%m^#4A9s&B@p%y5-(~yf3AWn0 zet4uUoRxpLjnquN8jdcS68kZkx0**obh`8??YYJX0L1Ujfj#QA_@18pqzY=@#!IjJ) zuV;OOKCNmp9lWwc75D`g#2Bq(Mb|;@6UfIe$81>zhRFFdvtSv;*xbAe+6ri{anwke z%imsp`3)&7LO||}#GKTo$nfDU#jI2u=ocEe2KtNyszw@7GJ0<=BWHuts#OFX zCpVM$DcUAGcSKe1SViU+_fMGfS@MYnbA0kVqSyf%T99ZO-4_hW2JJ<{(5T31r!6~d z+CH*aOarS%+Rc(!hV8G%B;GU);Z9lFuG-IahjM(XmDl@5B@h<5l}SccS&02+6#LDw z$Z=T6>WGMAwh}!<{#2KXE7oz?#$7foXCyIaq@Xnxu_e|eMB{NmLFB@-#T=uNqM;+a{tHjgBc!2vM;R4-&jx&0VZ6rQT{8WcTgfYF-20LN^BOYQ&c*57DlvTRCKCnQ=(((ilw7B)O;- z_Ki^srQG9s{S+g=%CAaJsg(?=GPrtV#cOyRCMCTfXSbx%S>?A)IyF}>8%*43ZkSkY z-<=?POB*50ZsRGJnv7teZI+~oszsZqhrD2<9Pgl1- ze_~T*+feIr>(VqSFf1^Y`KoTd+^s`lb2^iV)2}G$V>0K$j!7TwM{R)Ri(WIvYddF) z%`J;hmDSNzGn0qx*sd^{08MS%MBlIJ}~HN zbofIS^i$mb2NB{o;wdXD8{khB;`evoKhc^%WdQhA?tdv|z3Z^*0w9DQ`oR;NGM10`tC97n!$J9fCnD;j8}5r7@D|`dBo8u z60nRTHD&J5vEfTwlp&|0v+S3_sz7*MoC(Zz4VO~25;rab^lQF zK5hb8K?;|4s&;v7(7BRoVJJBJxzA4e7HQ>+jt7D)YZ0#GhE~bX<16V=;v8(bR_mq38 z@gGx;nfXr%6{varyKz4$!%y1j|FC^1>liDGIv}76LzEGW@HHgne<=5tMhmV;^v=QUSI_!+L_QRz(ck11@`H6yiKl`&^^w&vk>;uGK$x5^ zn)B1!-^&vFKwo!^BPDcP2gu3l&7wuIU6Z6@jm_U}?bw>f2h$&YWJuW%sHbj3`eBZm zJcO^8$sBz~0VdSSigpX=Sij{UQ0z*b$S{M)O&G&_r-yrKHIbGAXA)A$kF~J5uk%r` zcP0sTZjMuu0zWp%g#Hs8dV~TEVurJhQoFy7H%eZWV5nk|sQymjSDBg*PRP9iMvptV z!xcaf(t_mMDwyNIk;H=cZXYrYTfiK5{zI4j%{y~|5`YHIuTYTF_-{T56wdn8gMWEg z00{$tk%I%k4ANd1Ik>r5Kojrhv;(D*H*#^Z1i`jJa|)RF=bxYPzXk=#(}4N;4;7?J zD>>O4I|EhXpS=ze`Tx|bfBK2Pu2hiy-vatUw<4?Laa0gwGUjh!) z-!)g3fBJ*pSFV2A0fZBGekw=S(gfsLo`&F`yl_{bpJe{c;{jI={+e^ZmYBF21Gng< zHa4#n+fffNhNbLRy18{J20K4)ZVO*dkg1?6WfP>rvqZo|5+Cx3Y`tuFMm(R z#tH!T{y)Q5{&hWe0QbMbxIk9=M_w*=_J6120MT72GNS-Fn(|wY&i;F%VG z{*Wn(iqkRCv%!$H-u(K6VFfS(9E`1DczFQ~vS#)cu9g6{f08l`003YRx3YCLbN+X> zHF7l*H8XKAHG|>jhjDRrHZ!t=@yxx^vuQs5?ey&*FyhV3@1 zT%>hB+LzrOK_ite-igag4iW1lzq7tmxiV${EvOxFW zrGp&EtgD}AgTnTV1#Y)@f%Z3<_rC@N{C`Qd(<17N@`vgX1NbVxc5V$U!B!Dkxw1mx zD%=9x-|Y-|SkI5v5S2K=1(3RCmubl2B3HpI%c2MS<@`LqZx1B)x|8eg$Mgf9?*ANJ zQPdIseUl0sb0|>t{W_HTGsf`nc$1Qx5a9iBbY)-+ttRvJPBHmcv%26p0HDU#6Aa`3 zRQi47VG$D+Gcs6WMgI^nMo~ua7eC+@Q$bqb=US?3EMZoiL}JsXVJ*OO@`T^Z&+LAx za%*2ySpu}A0RE$lsdWIhZrf_(RH$_U`pON&u+B~Orbm2b7Dvq{)YT%~e6m4U>u3>W z=#q6k#_-6SqNZ!Dp%Zo}`e-8{v;yu4M0}8%O4S(>+@vU&-yvHe+=bHT*YWT`tf8Ho zDh`AS8L&uIe{=!dX&;{z9t+kWZ>GT!=MVN6lR+=nr{m%HP|ydO@E~9Bn8X)HE%h3Q z??(XwcO6?oziDlz1AP$V0y;U2(V<2Eus}rAQXm36Ad0!4R-{GL$}zZ?YkxS6(IgL( zJu^faSbTbDe8A(HtzFOvF&z{(0?GQoeE6NR<%M}8faCkwV`twS z%`dcozZz)L{BUQ9Cew27;6>mb=kM3N-^CeJMr?H3OTn7LfKY3_tnb&4)W+D~e74~0 zC;|d>cJ&k^UwzF4g;2N`$?~PW&WNSxQiQ}u?EGJYM3R9aT$YUF{S-5%`?d44q|k!V z`{co0hC42-f+hNY&AQq6p-*f~a*+`V_qH<&`-zE}^z5h35(@aOWD>Pv<#LT|J0xf>~RiVDJnbj^OmenN&w1)5Jgj`ea%(`M_*Anic#V6&$KO7z)45xuU)0@e4aGNzVhhnpr4`cjg5>(XqdOO4DVTHbH;G2;{vn?To98 zk3QWgj8J8q{e{l>K_Z;>myjdz!0*qBcOvgHv0}xv^>c)~?pJyK7L#iY%Acpu+WLXf> zu#3M7yr@SPTrquaNZ>`*zLo0%@%d7dgZL)gkiedELNE3;N*UIWVG#e^Ky zA}FMd_=7PA0U~b@j3yNXZ*GlB+60THOTMCgI~~`P(H%Rl*wz0B#$ldn^rKG?vs{o} z)Kl?^?@p+Kk!jFGnY>)*9IY%5Zl!LGYIDnrn#s;?;%D)eYcw=#z(R*b z3Xc+%{(4U}+Oydr`+5&Zu+*Jsnc;(v)}j-3ekGdD;k&=xSh;7h@^#7~jeQoLf@-u* zl5ZGm%4w8zBXB;05|z8e)5(FHA{89HRzE7fYP54jCE82p68xlDjkHle1-L5$ zu~^mljUr3tM`@*`60F=RWlQjjp$)j zunpF_Atn-43p6nZX-ff}a_VSXQH3dd6(O9ta zB~g7$-XG7&DN#2$_q~W^pE;uGmFRiO3j3_p$Xb{haG*rf&uP4QRPi3?kkyPSS@qH- zJ7KG_W4?2XWk^FdGGUKBv8ou#O#C@#V|Guc(jE!4A&3gZ7H4E07-3FRLC!b+6ruW= ztWyzWY&G?+QNNVA?EN8A=Karb_mv5%(-19$HmUH!(T2o51IJ#`2~&KyKdSKlXRyuw z4R#b-LZiLIxJzT)<}g}z-}Ms9MBb=;cY_auoGk-mQ*W^OA`g7t{=JXi+_b4D4tFC_ zJOe{+2bzKig}c-PdYf!~MG-0o@gEo~@|mUisFx>SA?A!ztMlPq%U<4Ysv^|;eGpy* z6z+w+sv^{r&II#wh8z)!R1|#*9G-?~lchZj3g2zVCvnG2SI0 zwr&wTr&?gK-gnqzFkt5WHAn8u@vG)JbxZGz+mzza<9!W!Tc5ES9cwJRI!Z9A@gzx- z=23hCC%W43a4{+yyvvV=YhLWw_%uF!ei3Q*WcL@TLNnm^-Lr51XyhjW4%oG1J%{LH zMVFMGcip~zCFk?%>q_ij;oK-LDlMK}ILE1x(a#vs?PVE36L z?TU_zXXjML)^CzBJco-4w%Arh{alQ;HYBBGNt zKp|v1wT$c^U|j$a3s$;-kkAl4-y9$b-yP`M&wc0%sal_R2^8Q!$Q@e$Z7Y_-(tL$D zc`pu~VCc?BAfnu-gVz&GW29zdf3dF?y?8-s8rE#%IG)S3Cv?MRX%Iw|raJ(}1r5_n zK6~vn$f8y9?g@qEUA=)fI%TzgZ4wG~bKLz2Wst#wWptG;xTW3$$fUl~0%ZRA_Lk~$ z4S?1%uKl}}LB?pkTQQtL78`LA32(tssu?=*8BTAMmXqVnVO0F=jaq9UJD zEW5utGm2X*iYB_ZjH)9lZg_?&G6LDP<~x0ObYf zT+PFx&P^3DIyI8uI9?Z5pulcgS3pLMxWY)JX}Y2?W&h4M1okz-$}K~IRSg4{&{Ht| zaiS}YZKW7H5%)0$S~@RFCJN&5GUN~_{Uu)@GGZm;1 z4y{55uL--^!HZW1V?>1zL8?+mGjAC?sJ&Lc<|suMBkQ_p>Cjdh9v8ZCI@+JH5d$yL zt)txMxjlwE{oa$LqrT@;jv0iDxgtx9nHiI;BONQFK-5Pmhnt!<%T3d%LO13p}kzInW8mruT0k2EK(nrKv37kcPE?NT^Cu9@TyHxfl?%z9{H; zhagnm9mwF(uQn-V^`c$!m3;YP>SRn=`Sfe&US)qzo9Am;N4W#Dk>}vKW!=@zSXp`o z&F-+WSPOQpTCSUPEjAi;YYVr;I5bOFq#IA&S8KimcOGM z#$K9jIToOe_fRvOu&wrSKvt~S$PY?dT2 zRt4rK7ZWPg$1NEWOCR}&D&pF@;&f=T`k}wqS0OZ6kZ$T=3Gi=1HYLT$xNOPYLT=iD z#2squVxY_%lMtZa>TX0qZ*kd~&bg8UbUd~o)-a6iO`_bl0DEKMQBg5?mZ|XK(^)4} z)USPDw(b5XlI3d>XXC+i?-g2R5(-K$7h($P=qxYx)NT$mE~fr0Ty9{tg9G6P=LVj* zyvljAQF%r2KBa3>F*cU9@XgbgvrRa|QwRmTjZ;5Sg%-1|Qrb)(6uun!Z6!CQc*R{W%p5&2-ok>)hf39fyLEU-9Rvh%iGj}#h13--%?QuE_XoD z7-_+{LPC1kd7+B3>vm1X;Tt_a;^vpL)%hFBNwn;Q|w9DqC#0Y zsG>?r)7vGf%x~erln|UQC6twtjdP6AFnZ=#;3rR8p-QTXEN@h0ZW?xm94XN+`pD%ZQ39QHD!KAMl8fj#zbEp@b<*9o~}J zMiFa-ewH?|!Gv|y8w;lSEKt&0qy1E&QnQyU!BHATqrtp^s`E8FtHOY*5F`YgR--8@ z&_ZT8NSDv^LpxwdJ}GijGnHf8i5692nMtF;)M?zs?MW6>?*FS`cPYJ9^wjcClnAHS zDV+yq-o=jdvqn?Zynx`8i#vs8znpo&RT{;hp|O7=QI$`3T4Q8Uk086bm`1~xmdiSc z?&vI1Q5SD;haqT7-rc0RX53t&fqG{NgPXly$5lR=OpRy%U@2jH?hz|M<9IJ761Zm&&#~bj;rqM_)6!Y}2b6FC}eFOGz&|+A` zDr7LOj}r#S9h(IrO&^lKnaVZSTPZP?q<#m7X8j255UBr1oIslYK)U&`rvWKv1?K@R zQeouGeOF?gkOv^0ovKd|g7<76BVO)o^L&6kQhmo*5~QkgL@=PoUdY}RMtBC)YK<;D zHNIL0t_pCh!-jb*I|1Dk25vD^(-3GM#70(!IZsFH4N|?;d@0t>$)Fnwb7=>SiB6__ zFnBm2B)DRI?HENh7}k1wZn?aHXOwhXk1x<9yf;=(TB?o~7c`X@pQ6z)Gfb$}3A&+e%!k5YDDH@nv_d9sd9CS+q zZN1?H7AD7U923>O9!r))qqh)mHkpAsvEu{$4YN`E6|G-=e1L1|D#szqGNqu&lD zOlY--VQT80Qg4k|y{wj)6el>Pu>R?iOweDn$i#ZxrBSign5kR0)q3L>q&kL!a;QZ9 zhzxS2^PoHmq3?V-lc*P7!3E^PEipG|(W*&tSv11DxjAGps(<3L=!EfdeJo;FDKW22 zkq`H-NwrJ|!!bZD+c${O*l^buiwnc^XoDLbG?Y!*L$jc_wBW>(a;Stia?+@jm8Rv; zi>`ahRFgm~+{>Yq=-jiZlozIE(28>XOH`AhZR~$Rwa#ActrQn#;C)64?@*bLUf8}NF+76S+JGZrKMY>xq&_Sr#>{aT zy!f6@Oix|9L4-NbuMLdB>0WOU4tIYNuB&L@r#3Do#?EmZym=0P9IGnWY(ifdw<|F% zW-=Qo5jQg*BC@ZJB%h1~>)`q$Xy3n05rhKIMIy3*<9<*#5zhkMh1JV8te2Z^i^TLE zggL@^56Tc3`GDfdRBim;T8Xs;%0MmK9)vmkeE_bHmTU;AkMw4t5`-B>_nw3)IvvdUqifcm;=v5u0HLgJ@dr%w_3d|9 z>*BRO4T~@q9v~7dhEnA}k%f9-hOD{qf!05e;I}-{nJC3 zd}F|jaxwA%hQml+wCCgx4rK5@$vleVHs|QS4ifzbcDc&|ivy(rWaFD@8qQ z$Kpz3f(@wkro$LyDNt_%hR0La`oUWz7DssJxrvrq|NSTrWF@mI3yGw~Fosl9S+ggy zDl55^>P~BQ0c>S&|LCX2P(_ifP&=o=O7GF0{Ob~GOx=&&WM?HJzkgQEp~{vwPbeM* zlVV{E8Xc9j{v;d4#o3b>x}V)YElJTQBpb%Ryl%DpFssE(HYG*PE1g?R!AFMB&w|+lDU}4wa;54 zF_x%)8;9m_33n6dpGuxUW^*xT5Pr3?D5zsOYiAu&x|kBEpe-1GMv;J5UJoZ7?rqcB zlmfj|+JsW+Z1dQZiv8xC#W}dZ;E}?~YLc-CgO|fG`WShW$FW+Vi%${vjDL`K7B9bE z)Vd+&un0xrq_HRk$vTZ?G>eftiB%OPJo!&C?=)8R-PuK)x^9o!sB|!!Jl65%3F7s< z){L6_c0nr@Hkm;=HAdQBtmEGdfHxBF9an5QjX^sJK8}Ig!+8{wmnn7x zW)u0$le;&#FkT)tf^A6-Oa%H4#$L>evkVQt8sI3X)YPr5!nSG8ljVw76THAO!zqhr zxWx1EK+vrhhc{*q$#V8)GGV_9<$4tQIdRC2F%ut8q2B8M!ur|WewL-$QyZ}`^^fNh z+WP8pu+HhLE7(0!;YG>chD-T#(#`b6me_FV|J?->R(u9#>0lGqGr6KoE3fMamjVyp z>E6sIQD-<%@hK{p`DAFa+_4XZ@M&%K(G&AIS{!X}KHMNICJ$B+^0SHi8PZ%2p+ej8 zHUywz+|K-7-F=A6S6|fN?xp$&3uw~qE)oyeIA*bgwy#swJ1qzA@8jvG+k@4_DF+ib zC0jYs8-mY_@EnTi){7Ol7-WBk(^JCrJ{UQ;ql!8dP=(;nf!zljGyM4hu)-t2f52Ht z%RgYVf^g9uu<+JLov;Yj7h0@=9kFr3Uk_8!r#R86f7x1T0vJB)gIvi8s58}x7wO*T3{3(`-{U>e%-!Na5PC^*03HLr z$yK-ixSCNPD{{Cdju&w;xjW}f71ADd!n$}5=X@7&!b8ia-+xr*{)Fc&$6~|p)K$vL zjjZMg0$Q?XS)-U9Yn2)ftcV1TN85)4CCnR?1$j?SS2Wq6Avg;|MmV`_aA(n1RjlJ+sSA&pouO1RO-IgLlWBu{AzJ^MdVGHz)O7 zJ#tP*&?tmrdL7z7f=y#3%}HtXPbo4Q)wNjce2R6)F0PYx$G(p4&P`Q@w1j3btvj#l|QV2$}8_Ybhl{fD&jB}KJbW3 zhIDFp$Wv@9Hpn|XFvH1G@;V}EpNqUQ({e)XFGx}`0^ob#mbe(+ZLmlee6Z(a+^Gon zH7qG1X2Vq{O4f|(l*mmjhHz44jMXKK`~8?rRvl^w1&c5&Ky8HUg+n00TuN7$Z*A8r zucV?NAjSg!I*b1i37^laP{JbC)r;6oC)&(Q#Y_2#!J%HucSF94%|-!m#wN4ny|QPN z0g3D{P2S%0KwKA0-TQavy8=!H# zG?@M&ym<59L5(4RxD7IM8ps!+uT^e;oNdF?hR!_3XnSw`j=`u=dllT@{Ea7*4r|^v zTF7wxlwjnF&;m~*^IlzAv*Y0#^mitI)Jp1^RlM^Eg>`|z4bq;9cdPalk{mG_uZ+hr zO0CU}qHXzroJ*ny*sz#o!God=uYJ&3!1b*1_|I-;)%>N$u6m*)-L5V4V0`4&s`OcW3HWN!8V(t6KUi z%zQ(CD1K;c+c#m_V@%`KkhzMkH;2uax&6}Pu!wz#K|6#HJIsc=v9Bls< zh5koo`9IY5zc{U!r>lgD>pw;d;N|^~@NZ)gu9n(LFQ==Fen;Xm;uND zO#c;+qLH)Nzvh|#_g)4$GgB)gVFyou&OeC}z|79h3SeVr1L*yixyZj*{@J?#{sW`` zn>(a?pY)Z@TpZk-P0U;X|LIEQ|0^}lfA#+l5a;?oVg3IB@&EMIf0J`205dZaE9d_U zk)L#X_~Nas2>9Nm=4I72_q^?F=-H*TXxFLhOO;q}I48yBz&UfY8|o%8?F%=@1?>x- zgI$MO1JdK{OshfJ%Q>M*1tY1529QA1lPQ=;2XU%h2t-J?!&{4*<`RjC-m>TgmNA;tr;mB zDa_Y$p@~fc&R)eI^p8{G-{ZxTr?Vg5BLY-mRMbR+R@+;2n)SG8iNrl%uf1qBSdFif z7x=!gFQQPidH~3ugC36sy?Gso)?1Q$EN!O1iYR(fCKJih(kdoWDNass76=laDZi7u zOxu_-id^bg1`P81J+#rM5fE!?G}tdHsA_5!?>>Hzwt`z+&TqP%mzy8p#}F1HPabi4 ztS6xEspwlIT=e=Rd1H=UIV8kGNN8jBd^sfjYci;B%?fgC!*6*vW=r3hL(*DtK4ru7 z6&tisH1SaJnN3Kj6a8XXL__suX4~ogmAO@c%DuXZXT=swH!VaIyrwdRJnj|P9d5Tv zmvfVpWeY$4gqLvMuOdWP&wEqec%OqI#QfT7){nRWw0M)A31ha;<~Yt8Luy7De*L_XHP&zLq(x}3GP9YMlR1mRTT;YC7^dd`^9C1BpN zx$`5gUKY$OJyV%xyKd8d(|-E1H4oO%95uBbR(?W7yXbG=a{Rqp=gf9(UDv@m8qTh| zF=+1SJLei?SQ?^Pt7Irf`eTSlmH{vau9{f=B0kC!&rDJ0jIfNktOmS6+1U^|*)ZTX z`UPiw1iT@A@nbdAI%`qkf{}%iK`@4hFyWDa8zHA@%)Kd+V4unN3ttOJA}ZhG;wN#j>TWcA$!NE-Gb9+jV)y9eKVZ<&sAnQUS7n zaOO$~K9bjU{3HC~yiJLg(2$ppKh_T9Hx7?W2jm%hm;jw5nj_ebOFe!AMzy=@SMU}7 zYW)*shqba~ql_fttXLsTn-+0b+49Xhl~qPIVNN{}ED9;(TN)I!6Z8|}K z)qtr@j$`XcoQ+FsmUYdD@2+=s5QN~WGc-cNY)xDVX9>Ie9Bp`arTJj$?@pPkEoqgp z<(MULHZbdvS7pqf`4KaQ!3wbmK_nr!R*i`r{uvE)>^Etu4JzXdnGHuKf8))`N;Vze zn&xOnU^1y?wr7LmxMTiOVPfl1>xV;zuqBWIQEs$QZqNG1-LIp`F|`D%{IlKtUD-aZ zKSXavClA#r+lFQK+&Pui4V~TO43p=snjGcaYB}}N=c$rL#&TJVDb}@WjdAeR=H*<3 z2Wl6mFpbuFw0ezQ!IeNLF_Y>#!y6cuMVrIGAa_=Fz|@HO$(7qW@45`gAEMg&RgM?% z>QR`Vi#@*wOcE2bRLWl}N6QUW?MC2`SD|1A0ETpAfbyhAfXn!$5JrvCJ|8Cv*@|R8 zmX(_;>Xpz(ctQx;~ai+zdmWPP^&l$bxzVOWka<8^%nf;us(9W<3L4 zeVb^@Y<8qx=ED48joz9JT<|#^ZozsXb~N#}NOXgmM&Y=-m3=@=LQYo_tOFwT zpzQpeYNi_LBS$sXnQzbJQaL^VN(mcU0?lfPh=pC|il4YYHc&Sd8(Z{|7wAADGT~T_ zK_O`7MCFOURidAs0Hl7D!LV(X3Q))pKNc}z6&jWYtUXbKPZ>#yA_a>-ftIe`Jy>g@ zj&BGhF(an2{iA+yM@Szqr;*TM$Hw8X;W%|(x7-JUpj1T3uZey4u~u`J>d!|a^yjKZ zeopS^Bc3OENk;}O`32GvSy;vZ{==m9oP|URP1BDkX0DK5KOG2yPfS^z?zeVoA<;a4 z50RWQCEb$0f3R-MO7o7EX)*XF4W!6JyP>v(q2g z@iv`nbeJ#!RmB{6h3tGI!LlSu?q_f=Skqo))?D0g`D?vtdL;%9UF+Uxtug&7{rWvi zO$TiU{*rI;imXZf>DdLs@_3xxBL1_VN)ud7d8^i>+~ob#Qjk)FsELKr!ISJecIGxJ z|6%~z3{KjXIp#o>7DAmQIm z-Xe5uisBig2t(#^ykk*zBr|qx8JO{64pN3&1!6U=K z@l`D5ew0`PpvRL)uRAmc#a_>w!yEX4bwdA-FNUAT#T4)Y41r>2^*Z_FE`6_$7!P`# z%H4N)~va1L1q&ha<6F}X4Ppy=n=yQ0r)yz`{4rZ4@i- zz6*S?9m=}L!9v*(>*I!qnPBnxh(@_IkoS!I9&|zJIKY#VZ1w-@_DU19XnT`v?z1 z`j67b@kjyaZkC2ODuokfek6^wLwf#LUj40rV=1em_lM+P8VM)-2kES{4rSOs%pH(b zLM#LrKGq%DfAd~_2D=6kCFDhW;~OR!@v(8q384>Okq{buYev(!2&7v(s|64?eLw7L zrrdK>>XegRqZLM&rRw$TN}&@{?BJN?!!rq0%&J>ma{w`swUB5fKS&8)Qlh3dvzW-> z(CVpahxf%zrwblH;dE$Z*v!(fnb1OlVo<h_ElnJ*y`udjA4u=?6imAf zgJ8(QlAa{YwWMeIi%u7Oi1Y+LW)~+~S&rgntkdO)ORh36(;HjyKW+hfvbAy z;bpMnK;By`os}->nBe$VMd){m^bf)UTB;Kv){4OfZmO!myrpsOn>{9pHH2+@;Nufk z37fgzi$xWq)Si%@5O5u9z^1IHj;W{0p%QJd_ym>7QAz34r4B!)sIPjyUi?cN zABN+D2w(Nt$7GB;jk=l~c7vF4@FORxS(u zN8K-PAPR#nt^T^19U1yQEQh{^*#R7K!p)FG&)uY8uwwyyf|loAH3O4S$if0wb#ekM zx3&fu+0Ri&)jE(9TA3SMbA47j4$?d_76c4E0bK#hDeG|=>0X22O@|eRBB4ov{*?Nx zD@-FBSGNz_b)8#J4NqKeZTj@np=zzNb=7%R8geeQ?)2^que`VZ+a={+@@Vjy4DL87 zz&9iEBFyJ+JVOhGd(~x>M7FGeV3`h1q5F-N?9dr*LB-D!H2kMOkWkJFtj-vAm}cE{ zQ>npVzsVXE)u^N-;VL(HLCTxW81?9>W5N%JjqMF2j2|s3D%9NT`^VPet$K@>4K_W* zTt0CQ-8y9qbJQ_3Zgc<4n=~V!o=Q|yg9$A)H@~m&*a&zA%)|_rqs!$6hC8t|B3l}X zlCz4$T7SvYV*|dSAh3c5nkEWY8Q@i5m&CE<@MN&yYbQXCP`K)(WUO15qIo3~$7yRM zq!fJf)8Wg4OUb5&sISIcK$E-{`~0uhUxsO^Xn(-2k?H%=yWPy1g^|!^Xy$5DV~Nk# z90@O85?70nIwflPFNYHvL9YW%`kwY^^`>yXxGgAgm_PDXE$0nMQ>pe@gC)U3h}4-* z$S@)1f2}hJD#SrpVE|2JSQIVOOpy62b`F%|Vu&dD1RnF+*KeJ@c2R+&y9dG%gTf@< zyF*!WjJu6iO&=f!=_{?;5_t_i`-d z%qt%NJcf07VpSL{Ov#K?!S5fhqGlzT(k%k>wB<|qbX>|y%juGA9A$IQZKWx7GgYDy z(`&8$Yb8PTawzGCP_>{Z-~px5W9Mky`bI61Jr}CqvKAaVrn>|Jb< zulWKWZho+RWCE!8pr0E-D!HZSf>R-O0N(WgraC1>JRxhO(HeLh_$W3>Ic4cksjyS7 zZU`pHxVufnX!$C21jB^!qKJ0sOVnr}p88kp0%6r_#l+|{D6&N&wn&pac0bwV(WdB- zr27gOgMu@haR;f9s+TWhFsnS$7_Ms$^Ji=qMZ)FJ=HcaJ?0^;K&zm+vT7u%=m}ALn z1sxyZi>RKL@XU5O5xt}wi?~W4-^#JJ?uWEC%qF74wJlVJ%r(oovzPmBohuL(O9!E7 z;=jU!B)jAn6QHd z56+s_PfCMDF$@b$#nZ6C5ot*IX(dM$NoKLXQ7}w_;6BLYOkWJKe zb)R|1M3YG#a{5nVx;~&*CU&&=Uy2;9DqP^{a6cM6!N49)Sp4#OlE~Cu5p}MO9wpS_ z-3-C&*)pro%jdMgs&Nq) zKbGphLrWGC=|^QsjukkOqUy?Ah&3cLBSJ;iyg}R5y0~^v4#Z0PG>PtSNR1McFzul= zGsPwevfip17&t&jAx!5a=+Y?@3gwOkPt)N+M|Fo{r9V*(#XDX`<|4_;Hz}`0<(i$E z7N1U-iTK z3wW{5OOH*6K^9VX%e_?ZRNZa#&1b>mE$v$ymXQypIGJ) zC-zqhl*T14Mh{UIgM{h$4N2`7X4;P?F2$+RWGFx3FZxrUC=cP`p2ZDTR`?Y)s#!HhU0Zsz zNjW;s^R034&No&)%syN{l^X;lE&6u5b>{2FFV)_wWDk_!onlQo?x6G+qD%9x&*_{V zvN9G|a&#QOZ=DxiQ)iv(;#YmIP#zaMC1exU+s#P|E@g-DQ^lY-p^fnNbZ3O}W95#> z)ilN;t+M1DY>ltWu&{CYm{@iWnps3m^m+U`4Y4__x*9|PU{R!(1l%fDS5j;(610I5 z0d&@|kPMbbbZO}~>G&9v#Mtb7EQ@2&Jt2aW?>w*aO2!Y!tRA(Bl&^m4TNGNe7l#ct z)!k4hJPaM>r0Hz2Ku?k|G6Bg?T3{n&(Rm|#kM4_4@Q=tT6 zFUr^?dVdDf61v&SP9qK`fTwtKxb?8L-miZ#eWy&T#9davNq@ugT+iHY;8$_SGIZ8F z@ApO^n00C|Q`xlmova-UZl^sBj`nKVUJxE$Qq^I=2T6h0T#z@WM{e_+JsPy7q)>Oi zu+``vo_hIlm+|=RfzItQk}vPFOWV!+lpN%PlPjETZUkJ^U3Nd36~jJbLE5+=PMg5l zp^xFe?&|{im}ok84f_@;*3ewSR{N@=N(OJe2d;^XiWC6>W-=%2p6#4X3c42M+V32n zkZDk3s5!VANbF-n7tx?m8yz?tt;Iex@2DomdADimHXkVB;eTD@tE=v@F*`Y68=lRw z;F!gyPmdb8NNR61k*0O8`QH``w@Y7e9M?CfTVN~e(wGldH!$v^bhmf4nLanG?YyV` zQL&nIsNRodC;O{77aXoy`^&_vXqmAt?LOm%@N*u(6ulV*V%e!VaM8#jm>JnkQHZ4G ze_~m#RDqJ_uO|8Yt`sPllgqADz!(;MVM55Q@8Y}exIT)BNEkx;mjJA?YW*#K=rz0K zBD1!^h;5*7TF7~Qj`{M_WoKF{(+sg1X|~mCt5s9eOm;NX^|PM^6k9X&AWTmt4glwUi+b{t(Dk zA|dZyU9zCMoMxOGNK>*o@D-ONHnyZyl3YIq42ZrJQlb>_09QmbZIur`V~`~KrxJ$L zv|-|(7^qY0XbFRn<*YS?wB7-}7g+b*PUD@Pwy>zKhDO)Z?~<~k^#^+Y!qdUMJ39Q& zlM;o4%iz*IZlHi3NdsU`=Gfmc1F&v^{hVcN(>!vh89a^6LsI>vPOgTKMbHjnP3p#P zVxD*ESad4x2^ecb%M+IY4HFCZun}^re*rX;?w!2m1DMP_NM@LLr;Zq(QVtm4Or^FM z78swEf*7{>g6`{S?6Dv~Btw)hzU>&(@^DWxa6EjW$P_KS?vEq&`F9N81Y5l$ZqFaz zC1bWtY~)=OeD6Oj==cdc84ug8XPYuih)0Am@SgS$_l=R;bpazM1&%!^KHd7tNKSI&%F|@!^7*tAOi`9V?Gp#avi2MG_S<`@UVKr zi|Ts71sG%CmEOnMK-2mROg_IR*d{UYRPJyX>^kRns53s;^{%iiqUCzge0x%A@{ljp;4!vn0&S-5JK-UV!nji!BJ{l*?7^FgN#zSl+_0 z>2tVCSlyn(T{$+kV(#y_sH7ad>O#w93v=UL{>E*%+5PaUYaK}#T``HchNX%+&goyX zQjPK_)@NUe$1YpJsEZ^Ub+(&rjIx>)i>jNfi|Rs!MD3Ha`(I7vRmakGifoJcM zn{dL!LW%MWR@t~#94j9R9gr>86EB4d-O}BZE_W{dmCRBkM{ZmFY9CCdrkBS5s()wn zv!WmMxacnb;HXk$NhhflehTcwh|~a{F5rtbj2GCbU$RGg*R5GAPs`K1sOe74sG00- zu~GqSO^nrIy>b^}8%Jo1uV$jVJ>X*Mv#$V*Hp#V{HaE%~jX9s!Lla4FQ~aXx0nFladYlTNH|q zes;OH-1#z9)2nsWuWhKR*~Dj2E?z9zL-?^wG^D(XEP(4bnVfzf3l@B*oc7`^Sx-Ka z+47}w?L?-d53f)<6u4H`jn1!s@18ne87XSAEn!Aalft*zH$&ego}cBa;BK-c1sU)V zuWzn?opw6=;VCTfYZE|b!p%fjnliM0)}`m^bn6>d9~>1wJpDIE1)#m{2X(Isnc z+SD|4d28vr4hAZ|T(wr6LAqVFY3R~p4j0ZN(jCw?GJ~5BWKL!&ro{c5+F;&yZqA6+ z!Yi3*-{Pjj7{uihHW*cyHmg;uRc+O2OurY^UVcaF0SqDT5evdu9a{~S!KrQOKevjP zPCPt?u4LR2*<{?D`h-GKX)Ueel8bv7ci{4>6xFWq-s|IuAP>$Bb83{#z$C0eK;H?8 z6NqVCd0Zo0OMii`1d0JC7Tw|N+(ilf;0MBl_(k|=Y=)yJ{p7+~I_9=;$@{Iw5V1j3 z33ZGc@w{N4;=_j|Qr6IEu%13Wd29Xy?;(C4fsjl}n;~D_8oT1dB%k45EHf6?wB7JMh`v!OtA0M~XoW3bF<9pEp6T)P5Pz|L1k`H5 zpnV|qpsW-b#Q5PCVfXSsnLm-7GKlPjV@*=Lg9X$voZT_KsOlf;D0?MnT_A!zLZ|>N z*}*}L_d!DXCQW};vub2lS5prNv*%z9sQf;49Y1pIK&xaIhxyg1D{A#C*n1JbmXvtq zmMcjvNd%c$xd0bvrjS{!?8>+LC_<99sDtmt3mPMrQ;9Y=(2I*U$6?i1gxfB~lx;k$ zytt*_U)+E`%sKo7-w84jIz3|s6R}dLCxHKQAMv*Wbt}XRJ(-3#$q}~7V^`)S>^Or2EZ9L4 zmmPOD&(kzjg@T=03O(jhYsISr=oMB(Ouu#AWaX$whW|W5_9ke{Uo=a?atk6@ZTihm z*&Ml0!)i9<%R}DR6rewMUegppOBC6_z8m^Syh}j4fJ-*(NJN%T%plsugN&33H|j zbyKDhk-*8%ghwKDEx+37#=mxuq5Vye(a#+FQw_#rkGK`(M-P{MyYKH?0kn3b4zpQ` zCz}4Ji0Zy<`uFb%w>pVBBYr>6U2puV-Zidj)e?FiE*ll3c^exdb3)q3z^-_nC;??Z z)1m}IcSUnZT47DD`Xccr=sdhF?vU$hI`BZ41+P?X+@vk%Pw8!jQ(N4R?U#uar#@>uj$5&Jy2aSusB5pY0!Ky1loGK&DM zWVi!J9-%qV1f(m5Cyv|Am1D%n?*e<>bx*I06cXGvea{s|thW8?fG;E)8H1nmy8?T< zg_57Ew8Mp;#h(g;!Mse*-;tBO>fUJQg6P$P0jTxouH9#(#J@rYNP;{-C_w%?=fNPT@m!GTtDjs9aBp3cSj2GZ(>)dFGXppguHnKQ0?; znXVs;m^Tzo@>oQW`65tN20Fq5#lQFh!+)Lz7AZRX*-jY|r>Zs5R@5A?%4}j%X_Vc6 z3^!$%jI*uJ+ldF`QlZPag-a)cCm8h^&fXB{u^VJtA}N#edzqPv+RpD)i02O?jFPpa z#HZX)57Oq7#zWRdytPBvR3R&Gmt1L#()F>Tp&+fuZ$BfFc-TvW7Rx*@k(p9wqZ~p} z`1$=z^aIfo7He5c*)1N_Gn))nHIGC(wKq{Y4PYWrH5A+S)HLD9Lj0`9dhN%oC(t$H z=^{*=GZpW?Pev=7wMS>RXoI@vXp>`_#Wqp=t?s(q#!7eolZ8~bqgZ5?r7P#U{e_)e zC-4m346!PN&ri9lHep2Yux|QBL>N!)LK$(D>bAnSA#)v*XLF;$c_-+x59x;Zh*%Qw zK$5-FS@AA0m;m)T&;ONs%k`6W&oWqZpb-`r+w?px$mBjM#F*CJ)I?nsOOZSQQ4^ShH9;>7lMXLQ*mwTe`ibk%+?x{<{1rooFq zyfNyUt3e{ZgviTk)#MsT;|NH{F@8dj;YYk%(Hx`*1B^6&)wZhm%I32x$a}(q*ZOwJ z{1E*JKi>r-8ev_$tmq~&WrQ|uZXz6 zIPiymb^7l&L4a(27t%F=b2W#hxt&R0D1s0StgT}q6E{ub(eFFjc~v21Fp-KtkdPu& zGXk4=Rt_X7S2;ev>sr*+XF@NFf}!})>Q=FO?TMfjaBHM^!z`Ky#-j*%lG(C z2nd3pbT0@9Qp+wZE#2KAAtEKcbc1w=bazXObT@(^2uO!?Nq7Ht_3FLe`}sfL|L(q@ zojEh}o;hdEoY`ktUh_?LBk1(x#z@6vSQn{nBbu(wE>E=b>I0U24&Zt2Q*#@2ya)UJ z1u?#ZzLj`))ORU#-S>)y2Yf~66DgN;&rZ4O{R#RiG}^yO7|e<(VKz~*=n`#&&frkB z5Qbewf-mOVoQVShxt?)l(TE5mv~m^UI-)6m`H;XzVi-(M8XD<1O;RdThl)O1(W6)= z;7JfC(_HW%61iOG zS%s@wcg>WB(8d|clr2>(Rc;xMv=TO6xW%Y+_(}KrS*y+!Og_93JeN;+N8TD%&})U` zR!E@nK#dodAzyXT!2%~=i=`STF7-7V32L!|iwgH6sa)k0&87bP-@3BybDMKCg2;k+ z5>sZ;joTNmS@L_heTiF%mE!FVV)t9R0~cTN>GL9o`4puKxzj4_o!1||cXA!aPAf+o z^-Cmb@f>pOTP5P-NMK24A6j$y2>Y!riuakqiFCxR#fz0ETKuDDQI%9VSh8X|n5xLB zeyt|nO!QUn=<&v0O<=63l7&L0#a<_cT)FO!eh9qxiIi)9VMM9>!65+YL};?f?X#da z18aj%n{auW^`nThi==SI)4_%+u*djL@Ww{V%vW1c#@fk{mukln@$y>wT6H$_OWT&W z&ITuC_EfyF7Om+Emo;+D$D1qny7Nq!i$3=^T{Y`h2VUjcO6;Ty7{1VLwmr|<0GCdj zdz!R|pGNld@x>8eB&=?n)8CETiOyPbDjh6IpZZ8K{eraIze}1IpHy^g!^C@M-~|Gx zQ@*Wz9rmp>4?adzKuq*K|Hl3qv=UY=FC*F#WWPl-AkW*_ zJ$xjjPkeKRyxh)OwL@YwlMr5I;e1+?+wx*J5Zj8vD{`oMuXkJqP0#bfKf5+KbFJnK zDL08UpHI=X;z)0UHP?4(am3$jApUw4pR9eKa~>spAA!J?Xk8RQDR}t0Hgq(yF||?! zHPy$-HT9`xh^lPl<3m+Fr9A?7l~|P$&S*}RXOjan4oO>;;~S+*)+ck{8{!+|>vioK zP8?^qubSrEJTf72$#Ks$)qRQy?$KF5YPTI_xqBt>8&&dcUu8=RGzzYLm_R2D7EI9d z(fZu;1P>jVeL1Et0kQdAc{G8duBUeBHbL&|igRFSkl$B`cYeq#`6D}~jS({`$VC4G z>6|VJ98|Sc5t_D4!3#XoqO9%WLZ~Dp(4Iz5V9`3hx;fA(oT|DvxVE?tK~2h*1W!p@ zU1Gx^w$eX;oRY;N@`^v>jUa9B97S=vCUj^?mRQ^79GvpH;DV;UxRRz1(Vkh@m zFg=SA2~X&4ik2Zrmf7>mc8QJs;@wQzS0OziUf6bow~=IgO^$N%#P>gp=%Zp;(*n?sNtD za6O$1tmgM-eL0JtH?|3zu1||6^_R$>VffdDU+zQrR%g3n01+v43n2+)xrP&8aH@%- zcL+m6{$R0_yT2)1855LG_FSe{$d>5Mbbw3J9 z$!g{x_3Wc)Jm=A%#>}IhR6eeyXtk>1cfn(^OC=A?^N_c&2a2_9Tz9#9$5kjSf7NH$b6R}^ZVLNfNDQ#H+q@2#=l$BZ7oM;vMlSEJ&VU7 zE{74fM3gJtmB|)l7$%i$Q0b$Rcr>weq_>TS761uVOX=7_KBp4Wj~!Wv$Y4P(h|6qz zk{oF_rAj8k+c@k42}~V{9Vp7*jlSQz=&LZ_V_=1#fWy&jwM)lJ<;r&OqU^|xSpP!R zy3EhiEwrh6(CyRXw$BnDZn65hjT$i=wGiX6CA}qy3SY-+b_!)PESdEPSf1pmVlWd#uN5)Qj*O5P6)EF$dKhZi$@T zBf8DSXT0lxkGn=9`ccn>Xe2Lnh{*_@EDd)Y<`?QZyfm&pFY~|S1!22UycLLY=Q@0w z6Ckf0C7SXoV-x>a?f7d+$d|EjNw=@-n~5)39T=(-nnScpc1Copv@Dxus_ERp4!9n^ z$EACoPyq*T&+glXb%XgJDcmzPQNKOmkFI(I+) z_HMy2yW@4edrTem%E=*}d~i9aSDI8#lz^0fm1+3WUaLP>Rm+bN0Ib8(>c7OQ&{&x< zj=5T*JkJr8JTMohnY8F7ffW7I5}bj)EGWbJLm-uwTtS{U&QCj)f!C>D=w{= zv(_)hea#h655InX`k8QTtYqHda`*n#(O`7NI0|Gyt9qq->T!eh75ZcXS&PL9mN`p8 zm0e|p+2^D!G|%dbgE@=KfHjB}jLRfJx&|4bKa{mMjfnA#&J!;Z9armP{;og_W&02? z+pROG#MD#xpa;q>7KO~kpe?li0^_^!ee(x->wys@&{s6)xs^eWYWcO_EXVU)-Yc)* z?R%2CAN6u;5Amz}`JH5YKV0>k7WZ!ui8-|-8~)~OcB`Gy)#o3^<({N z`esUET19V^4%A5vs)&hm1IAvyMqG7#K4cvKM6&Wu6J#UCE5Z6u+O2d!akA^>$8@5n zOZt2e>e`pByqLu)RxQKct(dbUTzTcT@K~&jEYxmb2KIS!k!(xKThqv9MpeUxKoE z%i1#X-322L#Op9we<9?65A^}{JngPx3K@J9a6eCFy!UOja@C{`u;?XzUvYcilh{21J6Xg+DT6nO+3$65glo<1 zw2W9xKa2_N{lAbIrcX-1fo7LviE2iU8D0 zsfV#=wGjjLi`g@3_()d0u)q2FO!lvv;$u>I6glKS+bUsb(tn0~dzg9Asd>Oc z7=*GErn;3gsu|iLSg)hXb1*m@g3i#sLVY*6ZQ}bU?zKDekNKsulWgl$eZ<`n@5`UE zv1l$~iC9NA2$jB4A|uCZ5UBC6x}7?yO5L=Pvnz8bb+ELxvYq`jztPxH73u{!5&zER z#g`}d-Z6QA;y5xPNA09sPP%*{_(PQ@ueiCPQ>R&Sz+A|YCaa4|bYY2-)G94*hkz+@ zj3*W3s-yfsDCL1S&kON8ei$fa4+I-+qrwdB?Fot=O))8VPcW(P6@ORgS_=!-PAu-+ zgE}GT4w7rcmOlhnoM91X9S2HF+aAWbY^mR@56!DHPoMQwNW_FrmF;L(L}G{QD&o#N z*zW*pv=o!`vnYLs0Fxpk6NaTkfRUY+7eq-tI3zikecljI3R zyb^2ze5wK#idzTICZ}>b2k}%yHx6<4+99-r%y;be2z2Oo#xlg6nx`zhl-zYniWYLB z>E3@erYpAfsCTopkhUd%zsyv2#J~<@#D@Dk-@n~Lwjvqpgt!y$OHJ=-)Z3%4s!%q5 zRs%}2CE4z$yD<*I?)LTHWpuUplpM`s6lPNSWw(nY&wSNM+ij@;G{tN{58qBz9RnHp zu8Fd=kk2DD2UM@LtW}?H1d=A&NfZ>l`%o{!Bj(XO$RQCkcRrq3Ijf|p?tZ?>W>`u` z($aS0f38;3c(T8ufJcbKTBYl@hVnKvO`}`yd^DQWCitUkhwRAafz~0K=S@dxE#uy| z60hV$x|>brnbR<$O4ZmxsmZcCwOec%9GcK|tM@BT5WbG)k2jH2}`~y|M1|>zpoQH6GQA0`1sxZ7ikp(MBHAQ*mi#OOkZe8cfx&&MOG+4zDm3T@`h@`A#K-g^?^N)>>) zD$4vzNO^U8^XT}J*)=XT76o*kQaR_9_0=>k(|Qt*9bNg&EDlbgFN6v59XofI;oUjz zPtBjtSWQ1)G9+%%e(I-?K{FwNjd?lY7;N}tf^T}q^i)Nl{0bmjj*0NuukF=`3QSzE zpKu#ajOK>q5QN9{p39>I&Zq|_vTyH}ecCWCN%5&-%Y4pG;6)%Si+oe_@lAMLc6GvI z5_gJQ(l_Ettx@Td*@ zQ#UJ9+zvC_pqIQ1i}3k=qU>O{GNpt`6kn3OkL13TT*QzWCgN@8Qjd*pT9WXIp$$;O zXeg~r6(RSL)}8Etv#y;IO-g{7h#7KCULA(vw$a!#K#wP^Ddp;}M8WxzeM^~AS{Uvm9Y78x|X_l=|A6J&Ef2Y*+@VU8d zM<3m14(NU1egCWEr1;LR^h-8mWB+y|4J}}eq&#u50xFj{0_BG5ho4r+!l+JI5MWpOGqyELKu6TK zJ(m^@2G-aQIw-PVZ8@5eDSIULW{b47)qVEN=+mJ1p&*l9cUl%}wY&MZQnpCb_22vZ z@a6h!G$%coT~0UDMvK8MQFTROP)VBW9yE@uAaooz9Bf+c$_H3JsHvf4t)zRFokg92 zPuny$ica}AuraZuZbK2bTch{M3iJhZto<&oCNFL;(K>jacAhR??jzf56E*AkZ*g2r zomOfHz0Fa$E4Iu9_#~QJ$%;(iNRlf^xY2z01|tShD%0O#H|~&xTQ-BNPzdmZiu}%8 zD{z&jIFYOGriYY4G+X+mFlM0`!N=r<6KWJFlF|3!cgmW!6y;x*(~q;BEMHLeT;7gg zH=#agjkc<_^v?9z6iILAzk3=_Th5Oa&f~ixX$cT0dyIB+5x1BcW+5n3(5Jt_57@hMLuO(qFqoG zM|-SKX2xe06Y%?>4sinAtVX?!TUD&YPcg~Gd4~wsw=z>j^xKo_5Vae5k0dlzk~8AG zzv2g&um~~QL}`L6Q8?N!cf<#?-o7^~c%UwZ^&|sgkFM<(m-%VvSn(9emGGKCW{V1) zu>kP`NIvUlCE=9mdGzFDv1sotgO%x*p@-~PuH|={ok+u0nU5YH>1)2#ZhJylDJ(8sur?8i`2-?u6 zb&rIimP~46;M+LC+-at8$zK}Sg z=+fvP8@?KTt*pPXIeaLhE8>L3&uxF#bt!O8(rzlayVdk@CIiryFq_dx+d6ve;nA8| zC1ok{P|@1Z;X2XLHugGRaUEC?O+L>Ti(V=CuofXA1EppW!Y6)1e2kZnzTu4eahevO z!1--Uh-dDtSC~^f*GZcLjzHjir}e^oy8}|X-&Xn^IiTO0yAP459_rf21)8(4rE7{Z z(ZxNeX+6ICK6yd{Ga|@>hWBHg&2e;KYt}XMx!b{fjIXwcuGn=7k2rb0yrNfrbEZpu zRGPGc$^@Q^So$JW*GRweD#I$*)IIha;;@aYLHEk=+UPR^OMp0Xy3Y*V9Dv7wZfq%k zUqtX-puy}|>oJuMwT_w%!$LiQsU{-f!$-ngc$jA%dT*y!>?bUTyQ98jtT|}E(Vm(& z#$y+INJKm3OK#_W-Jaqpeb>>EF4x_L1+SmK?74gkb_h@NblyCtgw^V$mCOTey(>!Q zE~w1Dg-rh?MnQz^*_3bdjeaGH2eR{O4sk?tF7w3F7G=!H(#nw|cZpBsJhuK`)igoX z`Nck&zMGfCe3s?5-PAW*G%-LDDABtMaa2(Xdq<+gZk)A3h^ESP*Xhpm)a7;?q%It@ zW>9x%p5IK|EqP>jSBmb!cI)a}qbHul#&}m?3ya4fn%v_-Z>Pt&p}9BN$)opP-?JjY z`O?U({Ax!Ge9>FSf89y8L4M)f!Z9&s-E;t+uKO-oc)fb~^U2uluoJqI* zDDNB5x^atj^Hmh!s7fA#U@X(}a4Un@-4z%HwG|lWF(K8*p5M&xa38AKHot?5PsVpX z8&%gq8&X~=Vy{d>DVQ3Gk9gd%fruw%j|C`o>!t|v8UlLBlrTbaJ&nyw{5B6_(lRlI zOyhHGSKuaoOO^3L0lQKo{lj&+G%lfWBrDd{R zawpo#6@vJ!7T`W1Cg2>gTorXM&#LZ~%Fu2M#_O95%KEP(sAYwID;%IEI1Zo$yKp-nN4-0teU4=gy6*OZPa& zK0t5su?YM2cUhc8nFhG+8dmjkj|3)bBTtlz1!*Ns!(&!sR!w*KpMekFWxu5sIA(w< z-6j5Z5?zzQ5=2b>wml+T*aLZ)yVfm8*OXvc7w0l}S137FiVi9@YZt$!&$WdKMDv+MvGTYs2+*Og>6`ma;I3n+B zz2vh=&V|+u-evaX#qf|7A&W^v+* zVzk)343so)tY$5eO(@NGopipFZOtr5*J14-r^)bpo!+!coH@p9+)ps2#krMFz(Oj1 zMDYeG%QMp%g^3W83>U2qkI-SJEbsX&-pr9YrT`a8=m3d3NwW?^;8X796&$Ix%-pPP z%(>E5FY`3XR=Xj6^j;9(9TFm6NiyN<2-o1}h^N~DqgIj+)`f)Yb4SH9w#9`*wCovk zto@JZUI!$g995D@$BFbp>9y|D;w53#SvhxDoCo7lJ#KQyN-6Tw!Cii`qC+wl7oem4 z*#+H^)ws)K-^7_OtxN(+|zU~8+!KW3#aa(&WJ9?10vT7%FmxEk%Vv|q+s4&*E!`2aV%tt;la3vFBAPZQ;>HGLqC?+x)Ex@pAjsb~1 z|5QjK@C7o_?r~i8eVjAzQ+wBn)8tVE6k7d!RL!6p98y5q#MU)ER;1~%XGGe{weFJU zu7Ptqql&z5VF|^ zzU|0!qzi0CD#*@Ldb@>TN2sw*41BgyS)X_*Lw4~U=2WTIngG`+PRg#aPA|^o45yY0 zz}LlmDPBQI#x*tE+b0nAn|9tpEb)r*F)Kj01di3YKd{ppS!4kD%7I=RDluq!eF){&nHu%v$nI54uw?= zLmGpDdjMBiGR7sjl?hQsX4wAvj6g;|x}Q73MYHGwbzO^87}3C++4H z1KaY>#^#`O>o(v9_olcB_NEi!3fS%OdX>%;e>v^yYN30*RBwX$ZE%_pTd?azYnSrM znj*p(Hi`YQLUg+C3&l}K9Jxqp=le>bFNW=&_m1@qSTS+Rbf{!#CF4mA$Y)f}Fv+Dv zBwq`^sx~n%Zn9KhqT|d|F)f;T$(S0IgwXbhzs#?!dRr=gMZM2chvBqAd6HG&BeMW~ zv=7}I;&;7io0#kq(eL7lM%D^(S2lZLFX*xVTA|9yCOPb-c-_Q)70q#nm*_LsqbXBajW~ouC~jkQ@-y68wQNIPL@`; zX`7DkTt6I@I&SE04>v$UlUJOi49)f3g+6WWo)_0$9cUG43<}?(Z6gXA{g=G}|F{3Y z*b8hB5I6TP_yHRnVel_R0NdZJga5?{fKdm2L-Tc28p5Z6IN#6lnOM7oKPE3sO;xvb|aEb%O3OPkNSGa9lS zLcb`q=neAm%-3uyG_M+sm+(*=C*&vX$h3HDmuYcQdp>=0>^Vm{sCM#p|M0z$JoMP$Med!h{e zJNO7(__ka}v6k=HAXOnw;RHW&uP6&@rao6X`%ardNSYw<&3*a&?o&JQec5p2#})HI zo*jZW-h3(fU3|=2+M`uR77LSyGfOizpHb~jj=nEUzSj@*#JVOr+b`Zy8h^msR=lM+ zZg)d*=+wVU1H+k})huh;Fu_`4^%F;cqj3E@xHS`zuX)d$+-2@t_eL)n-4x?1e){5t zi9hC4{;cG66^p(m}2t|dN+V$s&PeCjbfhV|t98fArMFZRDa^usUyaw2w4&fhNd zUw{T2$RTQEX9zX3vA2f8Q58QJ9r6a2FuI1Ax`wut7Ne?}rI8)8vbCjw)$a=829{

hT7}!V}nVFcvC?Bxf{HUX1Z)B+s;QHABo{{{O zf$Iia7DgZdoUZXt+6J6B@@pymWPHHu{=A*T3;Q2v5mgw^177w+Dr{h91h4Y{Z4)!7 zoxO;u0rZyvWDWkxvw?n&^G{2|#{XkXaD$6k!H&2vvoZm&YM8;`h<0Yb1V6ggFneil zYWEky1Reu^J;7iw0Di&qF#G&YbHI%J|K|d6!YM0%KRH1l00aX0as5ccA`S-!+*E(x z8v>JYad89S`q+h2B$aQP;H9ZA#bXKoj9@jleGYx8xA2ARSOL0-}L$O>v zaA2B%knJOD0V%Nm$MXJld z76fu%Wc>fp@2_E#hF z%u8mv$j;+OXrmKLLV$jxu3@FhR^3E;c{pdn&t!cqL+Ors-uC5wOxwA)tc=d&!!Y)9 zKoY^w^ws*NrAf3O(_T4q;_A~{`uh9JCJ*BKNp;fL!jEVW1e?JRFM(|ZR?5ll?&;Kp|g5cQbEPx~dS0-SgDoc9VFZw4YXOR^rVEw0)n?vAGG3g=zXt2)3L5 zow6Us`D-Ttfqs*m{ySy=BLKpJANZ$PVUh1=Fb4vdfh-URkPRLeSRmZoAU4>H{NyRY z?;vMj4>g1Hmf#;uV3mKq{Vf0G6tHdJ_k_VCrXtkZ&<^HLzlGwzW9iSJ{&y(-S3qQe z1sgU9tRV}C<7Xeg0ZXuxh2Sm*bBaIW0o;B5@F!UQPuGPLrR;w6BV+aw9(I4k>EFmG z2iP9K_7CR;!8QDK2bd-=9SmVd7ttFUm_e-pY%FXL79fD$)ZX64j)xV-!-7dopawRk zW`=ew)=(3MpF5`r>|i5%GixhRI7^FOlm`R^u>rZjY;2tDoa`_h7RO^Ckl~-5{&yc2 zF@Wu*)+Rp&{zHYoFjz1f`~}Z)h8h`Tz@jP`1Ni#^fN*etIRM6hpE3}HlM}Y$;17V+ zUos#kCp*k)|B^xAdjBZ{!kpsYGENR|*zEjK55xfi!(8J}8H5A=iRBL&kdqrevwz4y z>|h8?^?%E_V7~Y-88`cX>v6-#U;nDd!3op;-!g9ap8DtgIJn{d{-+EA|FoR7sAEZ5Wo!-j;jBO0-_G6uYX8F{K%77}AO + + + + + + + + + + + + + + + + + + +

+
Node Range: :
+
+ + +
+
+
+
+
+
+ + diff --git a/examples/testbench/decent_band/js/timeline.js b/examples/testbench/decent_band/js/timeline.js new file mode 100644 index 000000000..ba3db5e30 --- /dev/null +++ b/examples/testbench/decent_band/js/timeline.js @@ -0,0 +1,2734 @@ +// Some of the constants are read in from load_scale_json +var constants = { + margin_left: 350, + margin_right: 75, + margin_bottom: 50, + margin_top: 50, + min_feature_width: 3, + min_gap_width: 1, + util_height: 100, + util_levels: 4, + elem_separation: 2, +} + +var op_dependencies = {}; +var base_map = {}; +var prof_uid_map = {}; + +// Contains the children for each util file +var util_files = {}; + +var state = {}; +var mouseX = 0; +var utilline = d3.svg.line() + .interpolate("step-after") + .x(function(d) { return state.x(+d.time); }) + .y(function(d) { return state.y(+d.count); }); +var timeBisector = d3.bisector(function(d) { return d.time; }).left; +// const num_colors = 20; +// var color = d3.scale.linear() +// .domain([0, num_colors]) +// .range(["green", "blue", "red", "yellow"]); + +String.prototype.hashCode = function() { + var hash = 0; + if (this.length == 0) return hash; + for (i = 0; i < this.length; i++) { + var c = this.charCodeAt(i); + var b = this.charCodeAt(c % this.length); + hash = ((hash<<5)-hash)^c^b; + hash = hash & hash; + } + return Math.abs(hash); +} + +function parseURLParameters() { + var match, + pl = /\+/g, // Regex for replacing addition symbol with a space + search = /([^&=]+)=?([^&]*)/g, + decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, + query = window.location.search.substring(1); + + var urlParams = {}; + while (match = search.exec(query)) + urlParams[decode(match[1])] = decode(match[2]); + + if ("collapseAll" in urlParams) + state.collapseAll = (urlParams["collapseAll"].toLowerCase() === "true"); + + if ("resolution" in urlParams) + state.resolution = Math.max(1, parseFloat(urlParams["resolution"])); + // adjust zoom + var zstart = constants.start; + if ("start" in urlParams) + zstart = Math.max(constants.start, parseFloat(urlParams["start"])); + + var zend = constants.end; + if ("end" in urlParams) + zend = Math.min(constants.end, parseFloat(urlParams["end"])); + + if(zstart < zend) { + // set zoom to get: (zend - start) * zoom * scale = $("#timeline").width() + var newZoom = $("#timeline").width() / state.scale / (zend - zstart); + adjustZoom(newZoom, false); + + // set scrollLeft to get: zstart * zoom * state.scale = scrollLeft() + $("#timeline").scrollLeft(convertToPos(state, zstart)); + } + + if ("search" in urlParams) { + state.searchEnabled = true; + searchRegex = new Array(sizeHistory); + currentPos = 0; + nextPos = 1; + searchRegex[currentPos] = new RegExp(urlParams["search"]); + } +} + +function makeTimelineTransparent() { + state.timelineSvg.select("g#timeline").style("opacity", "0.1"); + $("#timeline").css("overflow-x", "hidden"); + state.timelineSvg.select("g#lines").style("opacity", "0.1"); + state.timelineSvg.select("g.locator").style("opacity", "0.1"); + state.timelineSvg.selectAll("path.util").style("opacity", "0.1"); +} + +function makeTimelineOpaque() { + state.timelineSvg.select("g#timeline").style("opacity", "1.0"); + $("#timeline").css("overflow-x", "scroll"); + state.timelineSvg.select("g#lines").style("opacity", "1.0"); + state.timelineSvg.select("g.locator").style("opacity", "1.0"); + state.timelineSvg.selectAll("path.util").style("opacity", "1.0"); +} + +function mouseMoveHandlerWhenDown() { + var p = d3.mouse(this); + var select_block = state.timelineSvg.select("rect.select-block"); + var select_text = state.timelineSvg.select("text.select-block"); + var newWidth = Math.abs(p[0] - mouseX); + select_block.attr("width", newWidth); + if (p[0] >= mouseX) { + select_block.attr("x", mouseX); + select_text.attr("x", mouseX + (p[0] - mouseX) / 2); + } else { + select_block.attr("x", p[0]); + select_text.attr("x", p[0] + (mouseX - p[0]) / 2); + } + var time = convertToTime(state, newWidth); + select_text.text(getTimeString(time, time)); +} + +function mouseMoveHandlerWhenUp() { + var p = d3.mouse(this); + var x = parseFloat(p[0]); + var scrollLeft = $("#timeline").scrollLeft(); + var paneWidth = $("#timeline").width(); + var currentTime = convertToTime(state, x); + + state.timelineSvg.select("g.locator").remove(); + var locator = state.timelineSvg.append("g").attr("class", "locator"); + locator.insert("line") + .attr({ + x1: p[0], + y1: 0, + x2: p[0], + y2: p[1] - state.thickness / 2, + class: "locator", + }); + locator.append("line") + .attr({ + x1: p[0], + y1: p[1] + state.thickness / 2, + x2: p[0], + y2: state.height, + class: "locator", + }); + var locatorText = locator.append("text"); + var text = getTimeString(currentTime, convertToTime(state, paneWidth)); + locatorText.attr("class", "locator").text(text) + if ((x - scrollLeft) < paneWidth - 100) { + locatorText.attr({x: x + 2, y: $(window).scrollTop() + 10}); + locatorText.attr("anchor", "start"); + } + else { + locatorText.attr({x: x - 2 - text.length * 7, y: $(window).scrollTop() + 10}); + locatorText.attr("anchor", "end"); + } +} + +function mouseDownHandler() { + state.timelineSvg.select("g.locator").remove(); + var p = d3.mouse(this); + state.timelineSvg.append("rect") + .attr({ + x : p[0], + y : 0, + class : "select-block", + width : 0, + height : state.height + }); + state.timelineSvg.append("text") + .attr({ + x : p[0], + y : p[1], + class : "select-block", + anchor : "middle", + "text-anchor" : "middle", + }).text("0 us"); + mouseX = p[0]; + state.timelineSvg.on("mousemove", null); + state.timelineSvg.on("mousemove", mouseMoveHandlerWhenDown); + $(document).off("keydown"); +} + +function get_kind(name) { + var util_regex = /\((.*?)\)/; + var kind_match = util_regex.exec(name); + if (kind_match) { + return kind_match[1]; + } +} + +function getLineColor(elem) { + var kind = get_kind(elem.text); + const colorMap = { + "CPU": "steelblue", + "GPU": "olivedrab", + "Utility": "crimson", + "IO": "orangered", + "Proc Group": "orangered", + "Proc Set": "orangered", + "OpenMP": "orangered", + "Python": "olivedrab", + "System Memory": "olivedrab", + "GASNet Global Memory": "crimson", + "Registered Memory": "darkmagenta", + "Socket Memory": "orangered", + "Zero-Copy Memory": "crimson", + "Framebuffer Memory": "blue", + "Disk Memory": "darkgoldenrod", + "HDF5 Memory": "olivedrab", + "File Memory": "orangered", + "L3 Cache Memory": "crimson", + "L2 Cache Memory": "darkmagenta", + "L1 Cache Memory": "olivedrab", + "Channel": "orangered" + }; + return colorMap[kind]; +} + +function drawUtil() { + // TODO: Add to state + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + var start_time = convertToTime(state, windowStart); + var end_time = convertToTime(state, windowEnd); + var filteredUtilData = []; + for (var i = 0; i < state.flattenedLayoutData.length; i++) { + var elem = state.flattenedLayoutData[i]; + if (elem.type == "util" && elem.enabled && elem.loaded && elem.visible) { + filteredUtilData.push(filterUtilData(elem)); + } + } + + state.x = d3.scale.linear().range([0, convertToPos(state, end_time)]); + state.x.domain([0, end_time]); + state.timelineSvg.selectAll("rect.util").remove(); + state.timelineSvg.selectAll("path.util").remove(); + var paths = state.timelineSvg.selectAll("path") + .data(filteredUtilData); + var totalWidth = windowStart + $("#timeline").width(); + paths.enter().append("rect") + .attr("class", "util") + .attr("base_y", lineLevelCalculator) + .attr("y", lineLevelCalculator) + .attr("x", 0) + .attr("fill", "transparent") + .attr("width", totalWidth) + .attr("height", constants.util_levels * state.thickness) + .on("mouseover", mouseover) + .on("mousemove", mousemove) + .on("mouseout", function() { + state.timelineSvg.select("g.focus").remove(); + state.timelineSvg.select("g.utilDesc").remove(); + }); + paths.enter().append("path") + .attr("base_y", lineLevelCalculator) + .attr("class", "util") + .attr("id", function(d, i) { return "util" + i}) + .attr("d", function (d) { return utilline(d.data); }) + .attr("stroke", getLineColor) + .on("mouseover", mouseover) + .on("mousemove", mousemove) + .on("mouseout", function() { + state.timelineSvg.select("g.focus").remove(); + state.timelineSvg.select("g.utilDesc").remove(); + }) + .attr("transform", + function(d) { + var y = lineLevelCalculator(d); + return "translate(0," + y + ")" + }); +} + + +function mouseUpHandler() { + var p = d3.mouse(this); + var select_block = state.timelineSvg.select("rect.select-block"); + var prevZoom = state.zoom; + var selectWidth = parseInt(select_block.attr("width")); + var svgWidth = state.timelineSvg.attr("width"); + if (state.rangeZoom && selectWidth > 10) { + var x = select_block.attr("x"); + state.zoomHistory.push({zoom: prevZoom, start: $("#timeline").scrollLeft()}); + adjustZoom(svgWidth / selectWidth, false); + $("#timeline").scrollLeft(x / prevZoom * state.zoom); + } + + state.timelineSvg.selectAll("rect.select-block").remove(); + state.timelineSvg.selectAll("text.select-block").remove(); + mouseX = 0; + state.timelineSvg.on("mousemove", null); + state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); + $(document).on("keydown", defaultKeydown); +} + +function turnOffMouseHandlers() { + state.timelineSvg.on("mousedown", null); + state.timelineSvg.on("mouseup", null); + state.timelineSvg.on("mousemove", null); + state.timelineSvg.on("mousemove", null); + // prevent right-click menu + state.timelineSvg.on("contextmenu", function () { + d3.event.preventDefault(); + }); +} + +function turnOnMouseHandlers() { + state.timelineSvg.on("mousedown", mouseDownHandler); + state.timelineSvg.on("mouseup", mouseUpHandler); + state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); + // prevent right-click menu + state.timelineSvg.on("contextmenu", function () { + d3.event.preventDefault(); + }); +} + +function drawLoaderIcon() { + var loaderGroup = state.loaderSvg.append("g") + .attr({ + id: "loader-icon", + }); + loaderGroup.append("path") + .attr({ + opacity: 0.2, + stroke: "steelblue", + fill: "#000", + d: "M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z" + }); + var path = loaderGroup.append("path") + .attr({ + stroke: "steelblue", + fill: "#000", + d: "M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0C22.32,8.481,24.301,9.057,26.013,10.047z" + }); + path.append("animateTransform") + .attr({ + attributeType: "xml", + attributeName: "transform", + type: "rotate", + from: "0 20 20", + to: "360 20 20", + dur: "0.5s", + repeatCount: "indefinite" + }); + state.loaderSvg.select("g").attr("visibility", "hidden"); + state.loaderSvg.attr("width", "0px") + .attr("height", "0px"); +} + +function showLoaderIcon() { + state.numLoading++; + state.loaderSvg.select("g").attr("visibility", "visible"); + state.loaderSvg.attr("width", "40px") + .attr("height", "40px"); +} + +function hideLoaderIcon() { + state.numLoading--; + if (state.numLoading == 0) { + state.loaderSvg.select("g").attr("visibility", "hidden"); + state.loaderSvg.attr("width", "0px") + .attr("height", "0px"); +; + } +} + +function get_time_str(time_val, convert) +{ + if (convert) { + if (time_val >= 1000000) { + var val = time_val/1000000; + val = parseFloat(val.toFixed(3)) + return val.toString() + " sec"; + } + if (time_val >= 1000) { + var val = time_val/1000; + val = parseFloat(val.toFixed(3)) + return val.toString() + " ms"; + } + } + return time_val.toString() + " us"; +} + +function getMouseOver() { + var paneWidth = $("#timeline").width(); + var left = paneWidth / 3; + var right = paneWidth * 2 / 3; + return function(d, i) { + var p = d3.mouse(this); + var x = parseFloat(p[0]); + var y = timelineLevelCalculator(d) - 5; + var descView = state.timelineSvg.append("g") + .attr("id", "desc"); + var text = descView.append("text") + .attr("x", x) + .attr("y", y) + .attr("class", "desc"); + var depElem = prof_uid_map[d.prof_uid][0]; + if ((depElem.in.length != 0) || (depElem.out.length != 0) || + (depElem.children.length !== 0) || (depElem.parents.length !==0 )) { + d3.select(this).style("cursor", "pointer"); + } + // descTexts is an array of Texts we will store in the desc view + var descTexts = []; + var total = d.end - d.start; + var delay = d.start - d.ready; + total = parseFloat(total.toFixed(3)) + delay = parseFloat(delay.toFixed(3)) + var initiation = ""; + // Insert texts in reverse order + if ((d.ready != undefined) && (d.ready != "") && (delay != 0)) { + descTexts.push("Ready State: " + get_time_str(delay,false)); + } + descTexts.push("End: " + get_time_str(d.end, false)); + descTexts.push("Start: " + get_time_str(d.start, false)); + descTexts.push("Total: " + get_time_str(total, true)); + if ((d.initiation != undefined) && d.initiation != "") { + descTexts.push("Initiator: " + state.operations[d.initiation].desc); + } + + // split d.title + var titles = d.title.split("$"); + if (titles.length > 0) { + for (var i = titles.length-1; i >= 0; --i) { + descTexts.push(titles[i]); + } + } + var title = text.append("tspan") + .attr("x", x) + .attr("dy", -12) + .attr("class", "desc") + .text(descTexts[0].replace(/ /g, "\u00A0")); // preserve spacing + + for (var i = 1; i < descTexts.length; ++i) { + var elem = text.append("tspan") + .attr("x", x) + .attr("dy", -12) + .attr("class", "desc") + .text(descTexts[i].replace(/ /g, "\u00A0")); // preserve spacing + } + + var bbox = descView.node().getBBox(); + var padding = 2; + var rect = descView.insert("rect", "text") + .attr("x", bbox.x - 2*padding) + .attr("y", bbox.y - padding) + .attr("width", bbox.width + (padding*4)) + .attr("height", bbox.height + (padding*2)) + .style("fill", "#222") + .style("opacity", "0.7"); + + var bboxRight = bbox.x + bbox.width; + var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); + + // If the box moves off the screen, nudge it back + if (bboxRight > timelineRight) { + var translation = -(bboxRight - timelineRight + 20); + descView.attr("transform", "translate(" + translation + ",0)"); + } + }; +} + +var sizeHistory = 10; +var currentPos; +var nextPos; +var searchRegex = null; + +function showSlider() { + $('#lowerLimit').text($('#node_slider').slider("values", 0)); + $('#upperLimit').text($('#node_slider').slider("values", 1)); +} + +function createMenuList1() { + var memory_kinds = []; + var num_nodes = state.num_nodes; + var num_mems = 0; + var dropdown_options = [ + { value: "ready", + id: "ready_all", + text: "View", + count: 1, + low_range: 0, + high_range: 1 + }, + { value: "memories", + id: "memories_all", + text: "Memories", + count: num_mems, + low_range: 0, + high_range: num_mems -1 + } + ]; + + // memories list + dropdown_options_memories = []; + + // misc items list + var pkind = { + id: "rr", + value: "rdy", + count: 1, + low_range: 0, + high_range: 1, + text: "Ready State" + }; + + dropdown_options_misc = []; + dropdown_options_misc.push(pkind); + + // create the remaining entries + function appendKind(elem) { + var value = state.processor_kinds[elem]; + if (elem.includes("Memory") && (value.count >= 0)) + { + num_mems = num_mems+1; + dropdown_options_memories.push(value); + } + if ((value.count >= 0) && (value.low_range != -1)) { + dropdown_options.push(value); + } + } + Object.keys(state.processor_kinds).forEach(appendKind); + + // main menu + d3.select("#dropdown").selectAll("optgroup") + .data(dropdown_options) + .enter() + .append("optgroup") + .attr('label', function(d) { return d.text;}) + .attr("id", function(d) { return d.id;}) + .attr("value", function(d) { return d.value;}); + + for (var j=0; j val)) + kind_proc.low_range = val; + if (kind_proc.high_range < val) + kind_proc.high_range = val; + } + } + } + + // Util graphs will have processors as their children as well. + if (type == "util") { + // get the children for the util view + var proc_children = getProcessors(text); + var count = 1; + var node_id = get_node_id(text); + var kind = get_kind(text); + // add to processor kinds: union of all processor kinds + if (!(kind in state.processor_kinds)) { + var pkind = { + id: kind, + value: kind, + count: proc_children.length, + low_range: -1, + high_range: -1, + text: kind + }; + state.processor_kinds[kind] = pkind; + } + if (state.processor_kinds[kind].count < proc_children.length) + state.processor_kinds[kind].count = proc_children.length; + + proc_children.forEach(function(proc_child) { + var child_element = getElement(depth + 1, proc_child.text, + proc_child.full_text, "proc", + proc_child.height, load_proc_timeline, + proc_child.tsv, element, undefined, + true, false); + element.children.push(child_element); + }); + } + + return element; +} + + +function calculateLayout() { + + // First element in the layout will be the all_util. All first-level + // elements will start off not enabled, and will be uncollapsed later + // programmatically + var num_nodes = Object.keys(util_files).length; + if (num_nodes > 1) { + var proc_kinds = util_files["all"]; + proc_kinds.forEach(function(name) { + var kind = "(" + get_kind(name) + ")"; + var util_name = "all nodes " + kind; + var kind_element = getElement(0, util_name, undefined, "util", + constants.util_levels, load_util, + "tsv/" + name + "_util.tsv", + undefined, util_files[kind], false, true); + state.layoutData.push(kind_element); + }); + } + + var seen_nodes = []; + state.processors.forEach(function(proc) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + var proc_regex = /(Processor|Memory) 0x1(e|d)([a-fA-f0-9]{4})[a-fA-f0-9]{10}$/; + // Memory Channel + var proc_channel_regex = /(Memory) 0x1(e)([a-fA-f0-9]{4})[a-fA-f0-9]{10}.*Channel/; + var proc_channel_match = proc_channel_regex.exec(proc.full_text); + var proc_match = proc_regex.exec(proc.full_text); + proc_match = proc_match || proc_channel_match; + if (proc_match) { + var node_id = parseInt(proc_match[3], 16); + if (!(node_id in seen_nodes)) { + seen_nodes[node_id] = 1; + if (node_id in util_files) { + var proc_kinds = util_files[node_id]; + proc_kinds.forEach(function(kind) { + var util_name = "node " + kind; + var kind_element = getElement(0, util_name, undefined, "util", + constants.util_levels, load_util, + "tsv/" + kind + "_util.tsv", + undefined, util_files[kind], + false, true); + state.layoutData.push(kind_element); + }); + } + } + } + else { + state.layoutData.push(getElement(0, proc.text, proc.full_text, "proc", + proc.height, load_proc_timeline, + proc.tsv, undefined, undefined, + false, true)); + } + }); + state.num_nodes = seen_nodes.length; +} + +function getElemCoords(elems) { + var proc = elems[0].proc; + var level = elems[0].level; + var startX = convertToPos(state, elems[0].start); + var endX = convertToPos(state, elems[elems.length-1].end); + var endBase = +proc.base; + var endLevel = endBase + level; + var y = dependencyLineLevelCalculator(endLevel); + return {startX: startX, endX: endX, y: y}; +} + + +function addLine(group, x1, x2, y1, y2, color, dashed) { + var line; + if (dashed) { + line = group.append("line") + .attr("x1", x1) + .attr("y1", y1) + .attr("x2", x2) + .attr("y2", y2) + .style("stroke", color) + .style("stroke-dasharray", "3,3") + .style("stroke-width", "1px"); + } else { + line = group.append("line") + .attr("x1", x1) + .attr("y1", y1) + .attr("x2", x2) + .attr("y2", y2) + .style("stroke", color) + .style("stroke-width", "1px"); + } + + var slope = (y2 - y1) / (x2 - x1); + var intercept = y1 - (slope * x1); + var triangleRotation = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI - 90; + + group.append("line") + .attr("x1", x1) + .attr("y1", y1) + .attr("x2", x2) + .attr("y2", y2) + .style("stroke", "transparent") + .style("stroke-width", "20px") + .on("mouseover", function() { + group.append("g") + .attr("class", "marker") + .append("path") + .attr("d", d3.svg.symbol().type("triangle-down").size(20)) + .style("stroke", color) + .style("fill", color); + }) + .on("mousemove", function() { + var marker = group.select("g.marker"); + var px = d3.mouse(this)[0] - 10; + var py = d3.mouse(this)[1] - ((slope > 0 ? 1 : -1) * 20); + if (px < Math.min(x1, x2)) { + px += 20; + } + if (py < Math.min(y1, y2)) { + py += 40; + } + + // some linear algebra here + var cx = (slope * py + px - slope * intercept) / (slope * slope + 1); + var cy = (slope * slope * py + slope * px + intercept) / (slope * slope + 1); + + marker.attr("transform", "translate(" + cx + "," + cy + ") rotate(" + triangleRotation + ")"); + }) + .on("mouseout", function() { + group.select("g.marker").remove(); + }); + + group.append("circle") + .attr("cx", x1) + .attr("cy", y1) + .attr("fill", "white") + .attr("stroke", "black") + .attr("r", 2.5) + .style("stroke-width", "1px"); + + group.append("circle") + .attr("cx", x2) + .attr("cy", y2) + .attr("fill", "white") + .attr("stroke", "black") + .attr("r", 2.5) + .style("stroke-width", "1px"); +} + + +function drawCriticalPath() { + state.timelineSvg.selectAll("g.critical_path_lines").remove(); + if (state.critical_path == undefined || !state.display_critical_path) { + return; + } + var depGroup = state.timelineSvg.append("g") + .attr("class", "critical_path_lines"); + state.critical_path.forEach(function(op) { + var proc = base_map[op[0] + "," + op[1]]; // set in calculateBases + if (proc != undefined && proc.visible && proc.enabled && proc.loaded && proc.selected) { + var elems = prof_uid_map[op[2]]; + if (elems != undefined) { + var coords = getElemCoords(elems) + var startX = coords.startX; + var endX = coords.endX; + var y = coords.y; + elems[0].out.forEach(function(dep) { + if (dep[2] in state.critical_path_prof_uids) { + var depElems = prof_uid_map[dep[2]]; + if (depElems != undefined) { + var depProc = depElems[0].proc; + // is the proc visible? + if (depProc.visible && depProc.enabled && depProc.loaded) { + var depCoords = getElemCoords(depElems); + var depX = depCoords.endX; + var depY = depCoords.y; + addLine(depGroup, depX, startX, depY, y, "grey", false); + } + } + } + }); + // Draw parent-child lines + var lastChildCoords = undefined; + var firstChildCoords = undefined; + elems[0].children.forEach(function(child) { + if (child[2] in state.critical_path_prof_uids) { + var childElems = prof_uid_map[child[2]]; + var childCoords = getElemCoords(childElems); + if (childElems !== undefined) { + if (lastChildCoords === undefined || + childCoords.startX > lastChildCoords.startX) { + lastChildCoords = childCoords; + } + if (firstChildCoords === undefined || + childCoords.endX < firstChildCoords.endX) { + firstChildCoords = childCoords; + } + } + } + }); + if (firstChildCoords !== undefined) { + addLine(depGroup, startX, firstChildCoords.startX, + y, firstChildCoords.y, "grey", true); + } + if (lastChildCoords !== undefined) { + addLine(depGroup, lastChildCoords.endX, endX, + lastChildCoords.y, y, "grey", true); + } + } + } + }); +} + +function drawDependencies() { + state.timelineSvg.select("g.dependencies").remove(); + var timelineEvent = state.dependencyEvent; + if (timelineEvent == undefined || + !timelineEvent.proc.visible || !timelineEvent.proc.enabled) { + return; // don't draw in this case, the src isn't present + } + var srcElems = prof_uid_map[timelineEvent.prof_uid]; + timelineEvent = srcElems[0]; // only the first elem will have deps and children + var srcCoords = getElemCoords(srcElems); + var srcStartX = srcCoords.startX; + var srcEndX = srcCoords.endX; + var srcY = srcCoords.y; + var depGroup = state.timelineSvg.append("g") + .attr("class", "dependencies"); + + var addDependency = function(dep, dir, dashed) { + var depProc = base_map[dep[0] + "," + dep[1]]; // set in calculateBases + if (depProc.visible && depProc.enabled && depProc.selected) { + var depElems = prof_uid_map[dep[2]]; + if (depElems != undefined) { + console.log(dir); + var depCoords = getElemCoords(depElems); + var dstY = depCoords.y; + if (dir === "in") { + addLine(depGroup, srcEndX, depCoords.startX, srcY, dstY, "black", dashed); + } else if (dir === "out") { + addLine(depGroup, depCoords.endX, srcStartX, dstY, srcY, "black", dashed); + } else if (dir === "parent") { + addLine(depGroup, depCoords.startX, srcStartX, dstY, srcY, "black", dashed); + addLine(depGroup, srcEndX, depCoords.endX, srcY, dstY, "black", dashed); + } else if (dir === "child") { + addLine(depGroup, srcStartX, depCoords.startX, srcY, dstY, "black", dashed); + addLine(depGroup, depCoords.endX, srcEndX, dstY, srcY, "black", dashed); + } + + } + } + } + + if (state.drawDeps) { + timelineEvent.in.forEach(function(dep) {addDependency(dep, "in", false)}); + timelineEvent.out.forEach(function(dep) {addDependency(dep, "out", false)}); + } + if (state.drawChildren) { + timelineEvent.parents.forEach(function(dep) {addDependency(dep, "parent", true)}); + timelineEvent.children.forEach(function(dep) {addDependency(dep, "child", true)}); + } +} + +function timelineEventsExistAndEqual(a, b) { + if (a == undefined || b == undefined) { + return false; + } + return (a.proc.base == b.proc.base) && (a.prof_uid == b.prof_uid); +} + +function timelineElementStrokeCalculator(elem) { + if (timelineEventsExistAndEqual(elem, state.dependencyEvent)) { + return true; + } else if (state.display_critical_path && + elem.prof_uid in state.critical_path_prof_uids) { + return true; + } + return false; +} + +function timelineEventMouseDown(_timelineEvent) { + // only the first event of this uid will have information + var timelineEvent = prof_uid_map[_timelineEvent.prof_uid][0]; + var hasDependencies = ((timelineEvent.in.length != 0) || + (timelineEvent.out.length != 0)); + + if (hasDependencies) { + if (timelineEventsExistAndEqual(timelineEvent, state.dependencyEvent)) { + if (d3.event.button === 0) { + state.drawDeps = !state.drawDeps; + } else if (d3.event.button === 2) { + state.drawChildren = !state.drawChildren; + } + if (state.drawDeps === false && state.drawChildren === false) { + state.dependencyEvent = undefined; + } + } else { + timelineEvent.in.concat(timelineEvent.out).forEach(function(dep) { + expandByNodeProc(dep[0], dep[1]) + }); + state.dependencyEvent = timelineEvent; + if (d3.event.button === 0) { + state.drawDeps = true; + } else if (d3.event.button === 2) { + state.drawChildren = true; + } + } + redraw(); + } +} + +function drawTimeline() { + showLoaderIcon() + + updateURL(state.zoom, state.scale); + var timelineGroup = state.timelineSvg.select("g#timeline"); + timelineGroup.selectAll("rect").remove(); + timelineGroup.selectAll("text").remove(); + var timeline = timelineGroup.selectAll("rect") + .data(state.dataToDraw, function(d) { return d.proc.base + "-" + d.id; }); + var timelineText = timelineGroup.selectAll("text") + .data(state.memoryTexts); + var mouseOver = getMouseOver(); + + timeline.enter().append("rect"); + + timeline + .attr("id", function(d) { return "block-" + d.proc.base + "-" + d.id; }) + .attr("x", function(d) { return convertToPos(state, d.start); }) + .attr("y", timelineLevelCalculator) + .style("fill", function(d) { + if (!state.searchEnabled || + searchRegex[currentPos].exec(d.title) == null) + return d.color; + else return "#ff0000"; + }) + .attr("width", function(d) { + return Math.max(constants.min_feature_width, convertToPos(state, d.end - d.start)); + }) + .attr("stroke", function(d) { + if (timelineElementStrokeCalculator(d)) { + return "red"; + } else { + return "black"; + } + }) + .attr("stroke-width", function(d) { + if (timelineElementStrokeCalculator(d)) { + return "1.5"; + } else { + return "0.5"; + } + }) + .attr("height", state.thickness) + .style("opacity", function(d) { + if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) != null || searchRegex[currentPos].exec(d.initiation) != null) { + return d.opacity; + } + else return 0.05; + }) + .on("mouseout", function(d, i) { + if ((d.in.length != 0) || (d.out.length != 0)) { + d3.select(this).style("cursor", "default"); + } + state.timelineSvg.selectAll("#desc").remove(); + }) + .on("mousedown", timelineEventMouseDown) + + + timelineText.enter().append("text"); + + timelineText + .attr("class", "timeline") + .attr("y", timelineTextLevelCalculator) + .attr("text-anchor", "start") + .text(function(d) { + var sizeRegex = /Size=(.*)/; + var match = sizeRegex.exec(d.title); + return match[1]; + }) + .attr("visibility", function(d) { + var textWidth = this.getComputedTextLength(); + var startX = convertToPos(state, d.start); + var endX = convertToPos(state, d.end); + var boxWidth = endX - startX; + return boxWidth > textWidth ? "visible" : "hidden"; + }) + .attr("x", function(d) { + var textWidth = this.getComputedTextLength(); + var midPoint = convertToPos(state, d.start + (d.end - d.start) / 2); + midPoint -= textWidth / 2; + return midPoint + }); + + drawUtil(); + timeline.on("mouseover", mouseOver); + timeline.exit().remove(); + hideLoaderIcon(); +} + +function redraw() { + if (state.numLoading == 0) { + calculateBases(); + filterAndMergeBlocks(state); + constants.max_level = calculateVisibileLevels(); + recalculateHeight(); + drawTimeline(); + drawDependencies(); + drawCriticalPath(); + drawLayout(); + } +} + +function calculateVisibileLevels() { + var levels = 0; + state.flattenedLayoutData.forEach(function(elem) { + if (elem.visible) { + if (elem.enabled) { + if (state.ready_selected && elem.num_levels_ready != undefined) + levels += elem.num_levels_ready; + else + levels += elem.num_levels; + } + levels += constants.elem_separation; + } + }); + return levels; +} + +function is_proc(proc) { + // the full text of this proc should start with 0x1d to be a processor + return /0x1d/.exec(proc.full_text) !== undefined; +} + +function is_proc_string(text) +{ + return /0x1d/.exec(text) != undefined; +} + +function is_mem_string(text) { + return /0x1e/.exec(text) != undefined; +} + +function get_node_val(text) { + var match = /\d+/.exec(text); + if (match) { + var val = parseInt(text.match(/\d+/)); + return val; + } + return match; +} + +function get_node_id(text) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + var proc_regex = /(Memory|Processor) 0x1(e|d)([a-fA-f0-9]{4})/; + var proc_match = proc_regex.exec(text); + // if there's only one node, then per-node graphs are redundant + if (proc_match) { + var node_id = parseInt(proc_match[3], 16); + return node_id + } +} + +function get_proc_in_node(text) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + var proc_regex = /Processor 0x1d[a-fA-f0-9]{11}([a-fA-f0-9]{3})/; + var proc_match = proc_regex.exec(text); + // if there's only one node, then per-node graphs are redundant + if (proc_match) { + var proc_in_node = parseInt(proc_match[1], 16); + return proc_in_node; + } +} + +function calculateBases() { + var base = 0; + state.flattenedLayoutData.forEach(function(elem) { + elem.base = base; + var node_id = get_node_id(elem.full_text); + var proc_in_node = get_proc_in_node(elem.full_text); + if (node_id != undefined && proc_in_node != undefined) { + base_map[(+node_id) + "," + (+proc_in_node)] = elem; + } + if (elem.visible) { + if (elem.enabled) { + if (state.ready_selected && elem.num_levels_ready != undefined) + base += elem.num_levels_ready; + else + base += elem.num_levels; + } + base += constants.elem_separation; + } + }); +} + +function expandHandler(elem, index) { + elem.expanded = !elem.expanded; + + if (elem.expanded) { + function expandChild(child) { + child.visible = true; + //child.enabled = true; + if(!child.loaded) { + showLoaderIcon(); + child.loader(child); // will redraw the timeline once loaded + } else if (child.expanded) { + child.children.forEach(expandChild); + } + } + elem.children.forEach(expandChild); + } else { + function collapseChildren(child) { + child.visible = false; + child.children.forEach(collapseChildren); + } + elem.children.forEach(collapseChildren); + } + redraw(); +} + +// This handler is called when you collapse/uncollapse a row in the +// timeline +function collapseHandler(d, index) { + d.enabled = !d.enabled; + + if (!d.loaded) { + // should always be expanding here + showLoaderIcon(); + //var elem = state.flattenedLayoutData[index]; + d.loader(d); // will redraw the timeline once loaded + } else { + redraw(); + } +} + +// This expands a particular element and its parents if necessary +function expandElementAndParents(elem) { + if (elem !== undefined) { + var elemPath = []; // path up to parent + var curElem = elem; + while (curElem != undefined) { + elemPath.push(curElem); + curElem = curElem.parent; + } + + for (var i = elemPath.length - 1; i >= 0; --i) { + var elem = elemPath[i]; + if (!elem.expanded) { + expandHandler(elem); + } + // uncollapse if necessary + if ((i == 0) && !elem.enabled) { + collapseHandler(elem); + } + } + } +} + + +function expandByNodeProc(node, proc) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + // ugh why isn't there string formatting + var nodeHex = ("0000" + node.toString(16)).slice(-4); + var procHex = ("000" + proc.toString(16)).slice(-3); + var expectedTitle = "0x1d" + nodeHex + "0000000" + procHex; + var matchedElement = undefined; + for (var i = 0; i < state.flattenedLayoutData.length; i++) { + var timelineElement = state.flattenedLayoutData[i]; + if ((timelineElement.full_text != undefined) && + (timelineElement.full_text.indexOf(expectedTitle) !=-1)) { + matchedElement = timelineElement; + break; + } + } + expandElementAndParents(matchedElement) +} + + +function lineLevelCalculator(timelineElement) { + var level = timelineElement.base + 1; + if (timelineElement.enabled) { + if (state.ready_selected && timelineElement.num_levels_ready != undefined) + level += timelineElement.num_levels_ready; + else + level += timelineElement.num_levels; + } + return constants.margin_top + level * state.thickness; +}; + +function utilLevelCalculator(timelineElement) { + var level = timelineElement.base; + if (timelineElement.enabled) { + if (state.ready_selected && timelineElement.num_levels_ready != undefined) + level += timeLineElement.num_levels_ready; + else + level += timeLineElement.num_levels; + } + return constants.margin_top + level * state.thickness; +}; + + +function timelineLevelCalculator(timelineEvent) { + return constants.margin_top + + (timelineEvent.proc.base + timelineEvent.level) * state.thickness; +}; + +function timelineTextLevelCalculator(timelineEvent) { + return constants.margin_top + + (timelineEvent.proc.base + timelineEvent.level + 0.75) * state.thickness; +}; + +function dependencyLineLevelCalculator(level) { + return constants.margin_top + ((level+0.5) * state.thickness); +} + +function drawLayout() { + d3.select("#processors").select("svg").remove(); + state.timelineSvg.select("g#lines").remove(); + + var data = state.flattenedLayoutData; + var svg = d3.select("#processors").append("svg") + .attr("width", constants.margin_left) + .attr("height", state.height); + + var namesGroup = svg.selectAll(".processors") + .data(data) + .enter().append("g"); + + var names = namesGroup.append("text"); + + var thickness = state.thickness; + var xCalculator = function(d) { return (d.depth + 1) * 15; }; + names.attr("text-anchor", "start") + .attr("class", "processor") + .text(function(d) { return d.text; }) + .attr("x", xCalculator) + .attr("y", lineLevelCalculator) + .attr("visibility", function(elem) { + return (elem.visible) ? "visible" : "hidden" + }) + .style("fill", "#000000") + .style("opacity", function(proc) { + return (proc.enabled) ? 1 : 0.5; + }); + + + // names.each(function(d) { + // var elem = d3.select(this); + // var text = d.text; + // var tokens = d.text.split(" to "); + // if (tokens.length == 1) + // elem.append("tspan").text(d.text); + // else { + // var source = tokens[0]; + // var target = tokens[1].replace(" Channel", ""); + // elem.append("tspan").text(source) + // .attr("x", xCalculator) + // .attr("dy", -10); + // elem.append("tspan").text("==> " + target) + // .attr("x", xCalculator) + // .attr("dy", 10); + // } + // }); + names.on({ + "mouseover": function(d) { + d3.select(this).style("cursor", "pointer") + if (d.full_text != undefined) { + var x = xCalculator(d); + var y = lineLevelCalculator(d) - state.thickness; + + var overlaySvg = d3.select("#overlay").append("svg"); + var descView = overlaySvg.append("g").attr("id", "desc"); + + var text = descView.append("text") + .attr("x", x) + .attr("y", y) + .attr("text-anchor", "start") + .attr("class", "desc") + .text(unescape(escape(d.full_text))); + + var bbox = text.node().getBBox(); + var padding = 2; + var rect = descView.insert("rect", "text") + .attr("x", bbox.x - padding) + .attr("y", bbox.y - padding) + .attr("width", bbox.width + (padding*2)) + .attr("height", bbox.height + (padding*2)) + .style("fill", "#222") + .style("opacity", "0.7"); + + overlaySvg.attr("width", bbox.x + bbox.width + (padding*2)) + .attr("height", bbox.y + bbox.height + (padding*2)); + } + }, + "mouseout": function(d) { + d3.select(this).style("cursor", "default") + if (d.full_text != undefined) { + d3.select("#overlay").selectAll("svg").remove(); + } + }, + "click": collapseHandler + }); + + var expandableNodes = namesGroup.filter(function(elem) { + return elem.children.length > 0; + }); + + var expand_group = expandableNodes.append("g"); + + var expand_clickable = expand_group.append("circle") + .attr("fill", "transparent") + .attr("stroke", "transparent") + .attr("r", 8); + var expand_icons = expand_group.append("path"); + var arc = d3.svg.symbol().type('triangle-down') + .size(12); + + + //.attr("transform", function(elem) { + // var x = constants.margin_left - 10; + // var y = lineLevelCalculator(elem); + // return "translate(" + x + "," + y + ")"; + //}) + expand_icons.attr("class", "processor") + .attr("d", arc) + .attr("visibility", function(elem) { + return (elem.visible) ? "visible" : "hidden" + }) + .style("fill", "#000000") + .style("stroke", "#000000") + .style("opacity", function(proc) { + return (proc.enabled) ? 1 : 0.5; + }); + + expand_group.each(function(elem) { + var path = d3.select(this); + var x = elem.depth * 15 + 5; + var y = lineLevelCalculator(elem) - 3; + + if (elem.expanded) { + path.attr("transform", "translate(" + x + ", " + y + ") rotate(0)"); + } else { + path.attr("transform", "translate(" + x + ", " + y + ") rotate(30)"); + } + + }); + + + expand_group.on({ + "mouseover": function(d) { + d3.select(this).style("cursor", "pointer") + }, + "mouseout": function(d) { + d3.select(this).style("cursor", "default") + }, + "click": expandHandler + }); + + + var lines = state.timelineSvg + .append("g") + .attr("id", "lines"); + + var thickness = state.thickness; + lines.selectAll(".lines") + .data(data) + .enter().append("line") + .attr("x1", 0) + .attr("y1", lineLevelCalculator) + .attr("x2", state.zoom * state.width) + .attr("y2", lineLevelCalculator) + .attr("visibility", function(elem) { + return (elem.visible) ? "visible" : "hidden" + }) + .style("stroke", "#000000") + .style("stroke-width", "2px") + .style("opacity", function(proc) { + return (proc.enabled) ? 1 : 0.5; + }); +} + +function drawHelpBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + + var helpBoxGroup = popUpSvg.append("g"); + var helpBoxWidth = Math.min(450, width - 100); + var helpTextOffset = 20; + var helpBoxHeight = Math.min(helpMessage.length * helpTextOffset + 100, + height - 100); + + var boxStartX = (width - helpBoxWidth) / 2; + var boxStartY = (height - helpBoxHeight) / 2; + + helpBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: helpBoxWidth, + height: helpBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var helpText = helpBoxGroup.append("text") + .attr("class", "help-box") + .style("width", helpBoxWidth); + var helpTitle = "Keyboard Shortcuts"; + helpText.append("tspan") + .attr({ x: boxStartX + helpBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text(helpTitle); + var off = 15; + for (var i = 0; i < helpMessage.length; ++i) { + helpText.append("tspan") + .style("font-size", "12pt") + .attr("text-anchor", "start") + .attr({ x: boxStartX + 30, dy: off + helpTextOffset}) + .text(helpMessage[i]); + off = 0; + } +} + +function evalExpandRequest(re) { + var re = new RegExp(re); + state.flattenedLayoutData.forEach(function(elem) { + if (re.exec(elem.text)) { + expandElementAndParents(elem); + } + }); + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); +} + +function drawExpandBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + var expandBoxGroup = popUpSvg.append("g"); + var expandBoxWidth = Math.min(450, width - 100); + var expandBoxHeight = Math.min(220, height - 100); + + var thicknessRatio = state.thickness / state.baseThickness; + var boxStartX = (width - expandBoxWidth) / 2; + var boxStartY = (height - expandBoxHeight) / 2; + + expandBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: expandBoxWidth, + height: expandBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var expandText = expandBoxGroup.append("text") + .attr("class", "expand-box") + .style("width", expandBoxWidth); + expandText.append("tspan") + .attr({ x: boxStartX + expandBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text("expand"); + var expandInputWidth = expandBoxWidth - 40; + var expandInputHeight = 50; + var expandInputStartY = 65; + + + expandBoxGroup.append("foreignObject") + .attr({ x: boxStartX + 20, y: boxStartY + expandInputStartY, + width: expandInputWidth, height: expandBoxHeight - expandInputStartY}) + .attr("text-anchor", "middle") + .html( + "" + + "
" + + "" + + "Presets" + + "" + + "
" + + "
" + + "" + + "" + + "" + + "" + + "" + + "" + + "
" + ); + $("input.expand-box").focus(); +} + +function drawSearchBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + var searchBoxGroup = popUpSvg.append("g"); + var searchBoxWidth = Math.min(450, width - 100); + var searchBoxHeight = Math.min(250, height - 100); + + var thicknessRatio = state.thickness / state.baseThickness; + var boxStartX = (width - searchBoxWidth) / 2; + var boxStartY = (height - searchBoxHeight) / 2; + + searchBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: searchBoxWidth, + height: searchBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var searchText = searchBoxGroup.append("text") + .attr("class", "search-box") + .style("width", searchBoxWidth); + searchText.append("tspan") + .attr({ x: boxStartX + searchBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text("Search"); + var searchInputWidth = searchBoxWidth - 40; + var searchInputHeight = 50; + searchBoxGroup.append("foreignObject") + .attr({ x: boxStartX + 20, y: boxStartY + 150, + width: searchInputWidth, height: searchInputHeight}) + .attr("text-anchor", "middle") + .html(""); + $("input.search-box").focus(); +} + +function drawSearchHistoryBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + + var historyBoxGroup = popUpSvg.append("g"); + var historyBoxWidth = Math.min(450, width - 100); + var historyBoxHeight = Math.min(350, height - 100); + + var boxStartX = (width - historyBoxWidth) / 2; + var boxStartY = (height - historyBoxHeight) / 2; + + historyBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: historyBoxWidth, + height: historyBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var historyText = historyBoxGroup.append("text") + .attr("class", "history-box") + .style("width", historyBoxWidth); + var historyTitle = "Search History"; + historyText.append("tspan") + .attr({ x: boxStartX + historyBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text(historyTitle); + if (searchRegex != null) { + var off = 15; + var id = 1; + for (var i = 0; i < sizeHistory; ++i) { + var pos = (nextPos + i) % sizeHistory; + var regex = searchRegex[pos]; + if (regex != null) { + if (pos == currentPos) prefix = ">>> "; + else prefix = id + " : "; + historyText.append("tspan") + .attr("text-anchor", "start") + .attr({ x: boxStartX + 30, dy: off + 25}) + .text(prefix + regex.source); + off = 0; + id++; + } + } + } +} + +function updateURL() { + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + var start_time = convertToTime(state, windowStart); + var end_time = convertToTime(state, windowEnd); + var url = window.location.href.split('?')[0]; + url += "?start=" + start_time; + url += "&end=" + end_time; + url += "&collapseAll=" + state.collapseAll; + url += "&resolution=" + state.resolution; + if (state.searchEnabled) + url += "&search=" + searchRegex[currentPos].source; + window.history.replaceState("", "", url); +} + +function adjustZoom(newZoom, scroll) { + var prevZoom = state.zoom; + state.zoom = Math.round(newZoom * 10) / 10; + + var svg = d3.select("#timeline").select("svg"); + + svg.attr("width", state.zoom * state.width) + .attr("height", state.height); + + var timelineGroup = svg.select("g#timeline"); + //timelineGroup.selectAll("rect").remove(); + + svg.select("g#lines").selectAll("line") + .attr("x2", state.zoom * state.width); + svg.selectAll("#desc").remove(); + svg.selectAll("g.locator").remove(); + d3.select("#overlay").selectAll("svg").remove(); + + if (scroll) { + var paneWidth = $("#timeline").width(); + var pos = ($("#timeline").scrollLeft() + paneWidth / 2) / prevZoom; + // this will trigger a scroll event which in turn redraws the timeline + $("#timeline").scrollLeft(pos * state.zoom - state.width / 2); + } else { + filterAndMergeBlocks(state); + drawTimeline(); + } + drawDependencies(); + drawCriticalPath(); +} + +function recalculateHeight() { + // adjust the height based on the new thickness and max level + state.height = constants.margin_top + constants.margin_bottom + + (state.thickness * constants.max_level); + var util_height = constants.util_levels * state.thickness; + state.y = d3.scale.linear().range([util_height, 0]); + state.y.domain([0, 1]); + + d3.select("#processors").select("svg").remove(); + var svg = d3.select("#timeline").select("svg"); + svg.attr("width", state.zoom * state.width) + .attr("height", state.height); + var lines = state.timelineSvg.select("g#lines"); + lines.remove(); + + svg.selectAll("#desc").remove(); + svg.selectAll("g.locator").remove(); + d3.select("#overlay").selectAll("svg").remove(); + +} + +function adjustThickness(newThickness) { + state.thickness = newThickness; + recalculateHeight(); + drawTimeline(); + drawLayout(); +} + +function suppressdefault(e) { + if (e.preventDefault) e.preventDefault(); + if (e.stopPropagation) e.stopPropagation(); +} + +function setKeyHandler(handler) { + $(document).off("keydown"); + $(document).on("keydown", handler); +} + +function makeModalKeyHandler(validKeys, callback) { + return function(e) { + if (!e) e = event; + var code = e.keyCode || e.charCode; + if (!(e.ctrlKey || e.metaKey || e.altKey)) { + for (var i = 0; i < validKeys.length; ++i) { + if (keys[code] == validKeys[i]) { + callback(keys[code]); + return false; + } + } + } + return true; + } +} + +function displayPopUp() { + d3.select("#pop-up").append("svg") + .attr("width", $(window).width()) + .attr("height", $(window).height()); +} + +function removePopUp() { + var popUpSvg = d3.select("#pop-up").selectAll("svg").remove(); +} + + +function defaultKeydown(e) { + if (!e) e = event; + + var code = e.keyCode || e.charCode; + var commandType = Command.none; + var modifier = e.ctrlKey || e.metaKey || e.altKey; + var multiFnKeys = e.metaKey && e.ctrlKey || e.altKey && e.ctrlKey; + + var translatedCode = keys[code]; + + if (!modifier) { + commandType = noModifierCommands[translatedCode]; + } else if (!multiFnKeys) { + commandType = modifierCommands[translatedCode]; + } else { + commandType = multipleModifierCommands[translatedCode]; + } + + if (commandType == undefined) { + if (e.metaKey || e.altKey) + state.rangeZoom = false; + return true; + } + + suppressdefault(e); + if (commandType == Command.help) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + // make help box visible + displayPopUp(); + drawHelpBox(); + setKeyHandler(makeModalKeyHandler(['/', 'esc'], function(key) { + // make help box invisible + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + else if (commandType == Command.search) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + displayPopUp(); + drawSearchBox(); + setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { + if (key == 'enter') { + var re = $("input.search-box").val(); + if (re.trim() != "") { + if (searchRegex == null) { + searchRegex = new Array(sizeHistory); + currentPos = -1; + nextPos = 0; + } + currentPos = nextPos; + nextPos = (nextPos + 1) % sizeHistory; + searchRegex[currentPos] = new RegExp(re); + state.searchEnabled = true; + } + } + removePopUp(); + if (state.searchEnabled) { + filterAndMergeBlocks(state); + drawTimeline(); + } + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + else if (commandType == Command.expand) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + displayPopUp(); + drawExpandBox(); + setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { + if (key == 'enter') { + var re = $("input.expand-box").val(); + if (re.trim() != "") { + re = new RegExp(re); + state.flattenedLayoutData.forEach(function(elem) { + if (re.exec(elem.text)) { + expandElementAndParents(elem); + } + }); + } + } + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + else if (commandType == Command.search_history) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + displayPopUp(); + drawSearchHistoryBox(); + setKeyHandler(makeModalKeyHandler(['h', 'esc'], function(key) { + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + + if (commandType == Command.zix) { + var inc = 4.0; + adjustZoom(state.zoom + inc, true); + } else if (commandType == Command.zox) { + var dec = 4.0; + if (state.zoom - dec > 0) + adjustZoom(state.zoom - dec, true); + } else if (commandType == Command.zrx) { + state.zoomHistory = Array(); + adjustZoom(1.0, false); + $("#timeline").scrollLeft(0); + } else if (commandType == Command.zux) { + if (state.zoomHistory.length > 0) { + var previousZoomHistory = state.zoomHistory.pop(); + adjustZoom(previousZoomHistory.zoom, false); + $("#timeline").scrollLeft(previousZoomHistory.start); + } + } else if (commandType == Command.ziy) + adjustThickness(state.thickness * 2); + else if (commandType == Command.zoy) + adjustThickness(state.thickness / 2); + else if (commandType == Command.zry) { + state.height = $(window).height() - constants.margin_bottom - constants.margin_top; + state.thickness = state.height / constants.max_level; + adjustThickness(state.thickness); + } + else if (commandType == Command.clear_search) { + state.searchEnabled = false; + searchRegex = null; + filterAndMergeBlocks(state); + drawTimeline(); + } + else if (commandType == Command.toggle_search) { + if (searchRegex != null) { + state.searchEnabled = !state.searchEnabled; + filterAndMergeBlocks(state); + drawTimeline(); + } + } + else if (commandType == Command.previous_search || + commandType == Command.next_search) { + if (state.searchEnabled) { + var pos = commandType == Command.previous_search ? + (currentPos - 1 + sizeHistory) % sizeHistory : + (currentPos + 1) % sizeHistory; + var sentinel = commandType == Command.previous_search ? + (nextPos - 1 + sizeHistory) % sizeHistory : nextPos; + if (pos != sentinel && searchRegex[pos] != null) { + currentPos = pos; + filterAndMergeBlocks(state); + drawTimeline(); + } + } + } + else if (commandType == Command.toggle_critical_path) { + state.display_critical_path = !state.display_critical_path; + if (state.display_critical_path) { + state.critical_path.forEach(function(op) { + expandByNodeProc(op[0], op[1]); + }); + } + redraw(); + } + return false; +} + +function defaultKeyUp(e) { + if (!e) e = event; + if (!(e.metaKey || e.altKey)) { + state.rangeZoom = true; + } + return true; +} + +function load_proc_timeline(proc) { + var proc_name = proc.full_text; + state.processorData[proc_name] = {}; + var num_levels_ready = proc.num_levels; + if (state.ready_selected) { + proc.num_levels_ready = proc.num_levels; + } + d3.tsv(proc.tsv, + function(d, i) { + var level = +d.level; + var ready = +d.ready; + var start = +d.start; + var end = +d.end; + var level_ready = +d.level_ready; + var total = end - start; + var _in = d.in === "" ? [] : JSON.parse(d.in) + var out = d.out === "" ? [] : JSON.parse(d.out) + var children = d.children === "" ? [] : JSON.parse(d.children) + var parents = d.parents === "" ? [] : JSON.parse(d.parents) + if (total > state.resolution) { + return { + id: i, + level: level, + level_ready: level_ready, + ready: ready, + start: start, + end: end, + color: d.color, + opacity: d.opacity, + initiation: d.initiation, + title: d.title, + in: _in, + out: out, + children: children, + parents: parents, + prof_uid: d.prof_uid, + proc: proc + }; + } + }, + function(data) { + var num_levels_ready=0 + // split profiling items by which level they're on + for(var i = 0; i < data.length; i++) { + var d = data[i]; + var level_sel=d.level; + if (level_sel in state.processorData[proc_name]) { + state.processorData[proc_name][level_sel].push(d); + } else { + state.processorData[proc_name][level_sel] = [d]; + } + if ((d.level_ready != undefined) && (d.level_ready != 0) && + num_levels_ready < d.level_ready) + num_levels_ready = d.level_ready; + + if (d.prof_uid != undefined && d.prof_uid !== "") { + if (d.prof_uid in prof_uid_map) { + prof_uid_map[d.prof_uid].push(d); + } else { + prof_uid_map[d.prof_uid] = [d]; + } + } + } + if (num_levels_ready > proc.num_levels) + proc.num_levels_ready = num_levels_ready; + else + proc.num_levels_ready = proc.num_levels; + proc.loaded = true; + hideLoaderIcon(); + redraw(); + } + ); +} + +function initTimelineElements() { + var timelineGroup = state.timelineSvg.append("g") + .attr("id", "timeline"); + + $("#timeline").scrollLeft(0); + parseURLParameters(); + + var windowCenterY = $(window).height() / 2; + $(window).scroll(function() { + $("#loader-icon").css("top", $(window).scrollTop() + windowCenterY); + $("#pop-up").css("top", $(window).scrollTop()); + }); + + // set scroll callback + var timer = null; + $("#timeline").scroll(function() { + if (timer !== null) { + clearTimeout(timer); + } + timer = setTimeout(function() { + filterAndMergeBlocks(state); + drawTimeline(); + }, 100); + }); + if (!state.collapseAll) { + // initially load in all the cpu processors and the "all util" + var util_regex = /node/; + for (var i = 0; i < state.flattenedLayoutData.length; i++) { + var timelineElement = state.flattenedLayoutData[i]; + if (timelineElement.type == "util" && + util_regex.exec(timelineElement.text) && + timelineElement.depth == 0) { + collapseHandler(timelineElement, i); + } + } + } + turnOnMouseHandlers(); +} + + +function load_ops_and_timeline() { + d3.tsv("legion_prof_ops.tsv", // TODO: move to tsv folder + function(d) { + return d; + }, + function(data) { + data.forEach(function(d) { + state.operations[parseInt(d.op_id)] = d; + }); + // initTimelineElements depends on the ops to be loaded + initTimelineElements(); + } + ); +} + +function load_procs(callback) { + d3.tsv('legion_prof_processor.tsv', + function(d) { + return { + full_text: d.full_text, + text: d.text, + height: +d.levels, + tsv: d.tsv + }; + }, + function(data) { + var prevEnd = 0; + var base = 0; + data.forEach(function(proc) { + proc.enabled = false; + proc.loaded = false; + proc.base = base; + + base += 2; + }); + state.processors = data; + calculateLayout(); + + // flatten the layout and get the new calculated max num levels + flattenLayout(); + calculateBases(); + drawLayout(); + createMenuList1(); + callback(); + + // TODO: fix + load_critical_path(); + } + ); +} + +function getMinElement(arr, mapF) { + if (arr.length === undefined || arr.length == 0) { + throw "invalid array: " + arr; + } + var minElement = arr[0]; + if (mapF === undefined) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] < minElement) { + minElement = arr[i]; + } + } + } else { + minValue = mapF(minElement); + for (var i = 1; i < arr.length; i++) { + var elem = arr[i]; + var value = mapF(elem); + if (value < minValue) { + minElement = elem; + minValue = value; + } + } + } + return minElement; +} + +function filterUtilData(timelineElem) { + var data = state.utilData[timelineElem.tsv]; // TODO: attach to object + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + var start_time = convertToTime(state, windowStart - 100); + var end_time = convertToTime(state, windowEnd + 100); + + var startIndex = timeBisector(data, start_time); + var endIndex = timeBisector(data, end_time); + + startIndex = Math.max(0, startIndex - 1); + endIndex = Math.min(data.length, endIndex + 2); + var length = endIndex - startIndex; + var newData = Array(); + // we will average points together if they are too close together + var resolution = 1; // 3 pixel resolution + var elem = {time: 0, count: 0}; + var startTime = data[startIndex].time; + var startX = convertToPos(state, startTime); + var endTime = 0; + + for (var i = startIndex; i < endIndex - 1; i++) { + endTime = data[i+1].time; + elem.count += data[i].count * (endTime - data[i].time); + //elem.time += data[i].time; + var endX = convertToPos(state, endTime); + if ((endX - startX) >= resolution || i == (endIndex - 2)) { + var totalTime = endTime - startTime; + elem.count /= totalTime; + //avgElem.time /= windowSize; + elem.time = startTime; + newData.push(elem); + elem = {time: 0, count: 0}; + startX = endX; + startTime = endTime; + } + } + + newData.push({time: endTime, count:0}); + + return { + text: timelineElem.text, + base: timelineElem.base, + num_levels: timelineElem.num_levels, + num_levels_ready: timelineElem.num_levels_ready, + data: newData + }; +} + +function mouseover() { + var focus = state.timelineSvg.append("g") + .attr("class", "focus"); + + focus.append("circle") + .attr("fill", "none") + .attr("stroke", "black") + .attr("r", 4.5); + + var utilDescView = state.timelineSvg.append("g") + .attr("class", "utilDesc"); + utilDescView.append("text") + .attr("x", 7) + .attr("y", -4.5) + .attr("class", "desc") + .attr("dy", ".35em"); + utilDescView.insert("rect", "text") + .style("fill", "#222") + .style("opacity", "0.7"); +} + +function mousemove(d, i) { + var line = document.getElementById("util" + i); + + // offset for this particular line grapgh + var base_y = +line.getAttribute("base_y"); + var px = d3.mouse(line)[0]; + var py = d3.mouse(line)[1] + base_y; + + var start = 0; + var end = line.getTotalLength(); + var target = undefined; + var pos = undefined; + + // https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91 + while (true){ + target = Math.floor((start + end) / 2); + pos = line.getPointAtLength(target); + if ((target === end || target === start) && pos.x !== px) { + break; + } + if (pos.x > px) end = target; + else if (pos.x < px) start = target; + else break; //position found + } + + + var cx = pos.x; + var cy = pos.y + base_y; + + var focus = state.timelineSvg.select("g.focus"); + focus.attr("transform", "translate(" + cx + "," + cy + ")"); + + var utilDescView = state.timelineSvg.select("g.utilDesc"); + utilDescView.attr("transform", "translate(" + (px + 10) + "," + (py - 10) + ")"); + var text = utilDescView.select("text") + + text.text(Math.round(state.y.invert(pos.y) * 100) + "% utilization"); + + var bbox = text.node().getBBox(); + var padding = 2; + var rect = utilDescView.select("rect", "text"); + rect.attr("x", bbox.x - padding) + .attr("y", bbox.y - padding) + .attr("width", bbox.width + (padding*2)) + .attr("height", bbox.height + (padding*2)); + + var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); + var bboxRight = px + bbox.x + bbox.width; + // If the box moves off the screen, nudge it back + if (bboxRight > timelineRight) { + var translation = -(bboxRight - timelineRight + 20); + text.attr("transform", "translate(" + translation + ",0)"); + rect.attr("transform", "translate(" + translation + ",0)"); + } +} + +// Get the data +function load_util(elem) { + var util_file = elem.tsv; + + // exit early if we already loaded it + if(state.utilData[util_file]) { + elem.loaded = true; + hideLoaderIcon(); + redraw(); + return; + } + + d3.tsv(util_file, + function(d) { + return { + time: +d.time, + count: +d.count + }; + }, + function(error, data) { + state.utilData[util_file] = data; + elem.loaded = true; + hideLoaderIcon(); + redraw(); + } + ); +} + +function load_critical_path() { + $.getJSON("json/critical_path.json", function(json) { + state.critical_path = json.map(function(p) {return p.tuple}); + state.critical_path_prof_uids = {}; + state.critical_path.forEach(function(p) { + state.critical_path_prof_uids[p[2]] = 1; + }); + }); +} + +function load_data() { + load_procs(load_ops_and_timeline); +} + +function initializeState() { + var margin = constants.margin_left + constants.margin_right; + state.width = $(window).width() - margin; + state.height = $(window).height() - constants.margin_bottom; + state.scale = state.width / (constants.end - constants.start); + state.zoom = 1.0; + state.zoomHistory = Array(); + state.numLoading = 0; + state.dependencyEvent = undefined; + state.drawDeps = false; + state.drawChildren = false; + + state.layoutData = []; + state.flattenedLayoutData = []; + + state.profilingData = {}; + state.processorData = {}; + state.utilData = []; + + state.operations = {}; + state.thickness = 20; //Math.max(state.height / constants.max_level, 20); + state.baseThickness = state.height / constants.max_level; + state.height = constants.max_level * state.thickness; + state.resolution = 10; // time (in us) of the smallest feature we want to load + state.searchEnabled = false; + state.rangeZoom = true; + state.collapseAll = false; + state.display_critical_path = false; + state.processor_kinds = {}; + + // display task ready state? + state.ready_selected = false; + // TODO: change this + state.x = d3.scale.linear().range([0, state.width]); + state.y = d3.scale.linear().range([constants.util_levels * state.thickness, 0]); + state.y.domain([0, 1]); + + setKeyHandler(defaultKeydown); + $(document).on("keyup", defaultKeyUp); + state.timelineSvg = d3.select("#timeline").select("svg").remove(); + state.timelineSvg = d3.select("#timeline").append("svg") + .attr("width", state.zoom * state.width) + .attr("height", state.height); + + state.loaderSvg = d3.select("#loader-icon").select("svg").remove(); + state.loaderSvg = d3.select("#loader-icon").append("svg") + .attr("width", "40px") + .attr("height", "40px"); + + d3.select("#processors").select("svg").remove(); + + drawLoaderIcon(); + drawHelpBox(); + load_data(); +} + +function load_util_json(callback) { + $.getJSON("json/utils.json", function(json) { + util_files = json; + callback(); + }); +} + +// Loads constants such as max_level, start/end time, and number of levels +// of a util view +function load_scale_json(callback) { + $.getJSON("json/scale.json", function(json) { + // add the read-in constants + $.each(json, function(key, val) { + constants[key] = val; + }); + load_util_json(callback); + }); +} + +function load_op_deps_json(callback) { + $.getJSON("json/op_dependencies.json", function(json) { + op_dependencies = json; + load_scale_json(callback); + }); +} + +function load_jsons(callback) { + load_scale_json(callback); +} + +function main() { + load_jsons(initializeState); +} + +main(); diff --git a/examples/testbench/decent_band/js/util.js b/examples/testbench/decent_band/js/util.js new file mode 100644 index 000000000..16ea770f2 --- /dev/null +++ b/examples/testbench/decent_band/js/util.js @@ -0,0 +1,378 @@ +//----------------------------------------------------------------------------- +// UTILS +//----------------------------------------------------------------------------- + +var helpMessage = [ + "Zoom-in (x-axis) : Ctrl + / 4", + "Zoom-out (x-axis) : Ctrl - / 3", + "Reset zoom (x-axis): Ctrl 0 / 0", + "Undo zoom (x-axis) : u / U", + "Zoom-in (y-axis) : Ctrl-Alt + / 2", + "Zoom-out (y-axis) : Ctrl-Alt - / 1", + "Reset zoom (y-axis): Ctrl-Alt 0 / `", + "Range Zoom-in : drag-select", + "Measure duration : Alt + drag-select", + "Expand : e / E", + "Draw Critical Path : a / A", + "Search : s / S", + "Search History : h / H", + "Previous Search : p / P", + "Next Search : n / N", + "Clear Search : c / C", + "Toggle Search : t / T", +]; + +var Command = { + none : 0, + help : 1, + zox : 2, + zix : 3, + zrx : 4, + zux : 5, + zoy : 6, + ziy : 7, + zry : 8, + search : 9, + clear_search : 10, + toggle_search : 11, + expand: 12, + toggle_critical_path: 13, + search_history : 14, + previous_search : 15, + next_search : 16 +}; + +// commands without a modifier key pressed +var noModifierCommands = { + '0': Command.zrx, + '1': Command.zoy, + '2': Command.ziy, + '3': Command.zox, + '4': Command.zix, + 'c': Command.clear_search, + 'e': Command.expand, + 'h': Command.search_history, + 'n': Command.next_search, + 'p': Command.previous_search, + 's': Command.search, + 'a': Command.toggle_critical_path, + 't': Command.toggle_search, + 'u': Command.zux, + '/': Command.help +}; + +var modifierCommands = { + '+': Command.zix, + '-': Command.zox, + '0': Command.zrx +} + +var multipleModifierCommands = { + '+': Command.ziy, + '-': Command.zoy, + '0': Command.zry +} + +var keys = { + 13 : 'enter', + 27 : 'esc', + 48 : '0', + 49 : '1', + 50 : '2', + 51 : '3', + 52 : '4', + 61 : '+', // Firefox + 65 : 'a', + 67 : 'c', + 69 : 'e', + 72 : 'h', + 78 : 'n', + 80 : 'p', + 83 : 's', + 84 : 't', + 85 : 'u', + 173 : '-', // Firefox + 187 : '+', + 189 : '-', + 191 : '/', + 192 : '`' +}; + +/** + * Function: convertToTime + * + * Description: + * Takes a value and converts it to time. The input 'x' can either be + * a single position on the timeline, or it can be a width. + */ +function convertToTime(state, x) { + return x / state.zoom / state.scale; +} + +/** + * Function: convertToPos + * + * Description: + * Takes a time and converts it to a position in the window. + * The 'time' parameter MUST BE IN us + */ +function convertToPos(state, time) { + return time * state.zoom * state.scale; +} + +/** + * Function: getTimeString + * + * Description: + * This function takes a time (in us) as well as a 'width' + * field. The 'width' field determines over what interval + * the time is being considered. + * + * If the width is too large, the time will be converted + * to either ms or sec. + * + * The function will return a string representation of the + * (possibly) scaled time at the end of the method + */ +function getTimeString(time, timeWidth) { + var unit = "us"; + var scaledTime = Math.floor(time); + if (timeWidth >= 100000) { + var scaledTime = Math.floor(time / 1000); + unit = "ms"; + } else if (timeWidth >= 100000000) { + var scaledTime = Math.floor(time / 1000000); + unit = "s"; + } + return scaledTime + " " + unit; +} + +// timeField should be 'end' for the left hand side and +// 'start' for the right hand side +function binarySearch(data, level, time, useStart) { + var low = 0; + var high = data[level].length; + while (true) { + // ugh is there a way to do integer division in javascrtipt? + var mid = Math.floor((high - low) / 2) + low; + + // In this case, we haven't found it. This is as close + // as we were able to get. + if (low == high || low == mid) { + return low; + } else if (high == mid) { + return high; + } + var midTime; + if (useStart) { + midTime = data[level][mid].start; + } else { + midTime = data[level][mid].end; + } + + if (midTime > time) { + // need to look below + high = mid; + } else if (midTime < time) { + // need to look above + low = mid; + } else { + // Exact Match + return mid; + } + } +} + +dataReady = {}; +function redoData(proc) { + dataReady = {}; + var items = state.processorData[proc.full_text]; + for (var level in items) { + for (var j = 0; j< items[level].length; j++) { + d = items[level][j]; + // ready state items + if (d.level_ready != undefined && d.level_ready != "" && + d.ready != undefined && d.ready != "") { + // if the level has already been switched, then don't do anything + var level_to_set = d.level_ready; + if (d.level_ready_set != undefined && d.level_ready_set == true) + level_to_set = d.level; + var d_ready = { + id: d.id+items[level].length+1, // unique id + level: level_to_set, + level_ready: d.level, + ready: d.ready, + start: d.ready, + end: d.start, + color: d.color, + opacity: "0.45", + initiation: d.initiation, + title: d.title + " (ready)", + in: d.in, + out: d.out, + children: d.children, + parents: d.parents, + prof_uid: d.prof_uid, + proc: d.proc + }; + // switch levels if we need to + if (d.level_ready_set == undefined || d.level_ready_set == false) + { + var level_tmp = d.level; + d.level = d.level_ready; + d.level_ready = level_tmp; + d.level_ready_set = true; + } + if (d.level_ready in dataReady){ + dataReady[d.level_ready].push(d_ready); + dataReady[d.level_ready].push(d); + } + else { + dataReady[d.level_ready] = [d_ready]; + dataReady[d.level_ready].push(d); + } + } + // add items to the level + else { + if (d.level in dataReady) + dataReady[d.level].push(d); + else + dataReady[d.level] = [d]; + } + } + } +} + +function readyData(proc) { + redoData(proc); +} + +function filterAndMergeBlocks(state) { + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + state.dataToDraw = Array(); + state.memoryTexts = Array(); + var startTime = convertToTime(state, windowStart); + var endTime = convertToTime(state, windowEnd); + var min_feature_time = convertToTime(state, constants.min_feature_width); + var min_gap_time = convertToTime(state, constants.min_gap_width); + for (var index in state.flattenedLayoutData) { + var timelineElement = state.flattenedLayoutData[index]; + if (timelineElement.type == "proc" && timelineElement.enabled && timelineElement.visible) { + var items = state.processorData[timelineElement.full_text]; + var memoryRegex = /Memory/; + var isMemory = memoryRegex.exec(timelineElement.text); + if (state.ready_selected) { + readyData(timelineElement); + items = dataReady; + } + + for (var level in items) { + // gap merging below assumes intervals are sorted - do that first + //items[level].sort(function(a,b) { return a.start - b.start; }); + + // We will use binary search to limit the following section + var startIndex = binarySearch(items, level, startTime, false); + var endIndex = binarySearch(items, level, endTime, true); + for (var i = startIndex; i <= endIndex; ++i) { + var d = items[level][i]; + var start = d.start; + var end = d.end; + // fix the level here + if (state.ready_selected == false && d.level_ready_set != undefined + && d.level_ready_set == true) + { + // switch levels + var level_tmp = d.level; + d.level = d.level_ready; + d.level_ready = level_tmp; + d.level_ready_set = false; + } + // is this block too narrow? + if ((end - start) < min_feature_time) { + // see how many more after this are also too narrow and too close to us + var count = 1; + // don't do this if we're the subject of the current search and don't merge with + // something that is + if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) == null) { + while (((i + count) < items[level].length) && + ((items[level][i + count].start - end) < min_gap_time) && + ((items[level][i + count].end - items[level][i + count].start) < min_feature_time) && + (!state.searchEnabled || searchRegex[currentPos].exec(items[level][i + count].title) == null)) { + end = items[level][i + count].end; + count++; + } + } + // are we still too narrow? if so, bloat, but make sure we don't overlap something later + if ((end - start) < min_feature_time) { + end = start + min_feature_time; + if (((i + count) < items[level].length) && (items[level][i + count].start < end)) + end = items[level][i + count].start; + } + if (count > 1) { + state.dataToDraw.push({ + id: d.id, + prof_uid: d.prof_uid, + proc: timelineElement, + level: d.level, + ready: d.ready, + start: d.start, + end: Math.round(end), + color: "#808080", + title: count + " merged tasks", + in: [], + out: [], + children: [], + parents: [] + }); + i += (count - 1); + } else { + var elem = { + id: d.id, + prof_uid: d.prof_uid, + proc: timelineElement, + level: d.level, + ready: d.ready, + start: d.start, + end: d.end, + color: d.color, + initiation: d.initiation, + title: d.title + " (expanded for visibility)", + in: d.in, + out: d.out, + children: d.children, + parents: d.parents + } + state.dataToDraw.push(elem); + if (isMemory) { + state.memoryTexts.push(elem); + } + } + } else { + var elem = { + id: d.id, + prof_uid: d.prof_uid, + proc: timelineElement, + level: d.level, + ready: d.ready, + start: d.start, + end: d.end, + opacity: d.opacity, + color: d.color, + initiation: d.initiation, + title: d.title, + in: d.in, + out: d.out, + children: d.children, + parents: d.parents + } + state.dataToDraw.push(elem); + if (isMemory) { + state.memoryTexts.push(elem); + } + } + } + } + } + } +} diff --git a/examples/testbench/decent_band/legion_prof_ops.tsv b/examples/testbench/decent_band/legion_prof_ops.tsv new file mode 100644 index 000000000..281f0c6be --- /dev/null +++ b/examples/testbench/decent_band/legion_prof_ops.tsv @@ -0,0 +1,90 @@ +op_id desc proc level +1 legion_python_main <1> Python Processor 0x1d00000000000004 2 +47 legate::numpy::BinaryOpTask [CPU] <47> CPU Processor 0x1d00000000000002 2 +71 legate::numpy::BinaryOpTask [CPU] <71> CPU Processor 0x1d00000000000002 2 +76 legate::numpy::BinaryOpTask [CPU] <76> CPU Processor 0x1d00000000000002 2 +5 Tunable Operation <5> +6 Pending Partition Operation <6> +8 Refinement Operation <8> +7 legate::numpy::FillTask <7> +9 legate::numpy::FillTask <9> +0 Operation <0> +10 legate::numpy::FillTask <10> +12 legate::numpy::FillTask <12> +14 Refinement Operation <14> +15 legate::numpy::FillTask [CPU] <15> CPU Processor 0x1d00000000000003 2 +18 Refinement Operation <18> +17 legate::numpy::FillTask <17> +20 legate::numpy::FillTask <20> +16 legate::numpy::FillTask <16> +19 legate::numpy::FillTask <19> +54 legate::numpy::BinaryOpTask <54> +55 legate::numpy::BinaryOpTask <55> +56 legate::numpy::BinaryOpTask <56> +59 legate::numpy::BinaryOpTask [CPU] <59> CPU Processor 0x1d00000000000003 2 +60 legate::numpy::BinaryOpTask <60> +65 legate::numpy::BinaryOpTask [CPU] <65> CPU Processor 0x1d00000000000002 2 +63 legate::numpy::BinaryOpTask <63> +68 legate::numpy::BinaryOpTask <68> +77 legate::numpy::BinaryOpTask [CPU] <77> CPU Processor 0x1d00000000000003 2 +79 legate::numpy::BinaryOpTask <79> +80 legate::numpy::BinaryOpTask <80> +82 legate::numpy::BinaryOpTask [CPU] <82> CPU Processor 0x1d00000000000002 2 +84 Merge Close Operation <84> +85 legate::numpy::BinaryOpTask [CPU] <85> CPU Processor 0x1d00000000000003 2 +83 Mapping Operation <83> +89 Deletion Operation <89> +87 Deletion Operation <87> +88 Deletion Operation <88> +13 legate::numpy::FillTask [CPU] <13> CPU Processor 0x1d00000000000002 2 +48 legate::numpy::BinaryOpTask [CPU] <48> CPU Processor 0x1d00000000000003 2 +29 legate::numpy::FillTask [CPU] <29> CPU Processor 0x1d00000000000002 2 +38 legate::numpy::FillTask [CPU] <38> CPU Processor 0x1d00000000000002 2 +52 legate::numpy::BinaryOpTask [CPU] <52> CPU Processor 0x1d00000000000002 2 +11 legate::numpy::FillTask <11> +21 legate::numpy::FillTask <21> +25 legate::numpy::FillTask [CPU] <25> CPU Processor 0x1d00000000000003 2 +33 Refinement Operation <33> +34 Refinement Operation <34> +35 legate::numpy::FillTask [CPU] <35> CPU Processor 0x1d00000000000002 2 +36 legate::numpy::FillTask [CPU] <36> CPU Processor 0x1d00000000000003 2 +42 legate::numpy::FillTask [CPU] <42> CPU Processor 0x1d00000000000002 2 +44 legate::numpy::BinaryOpTask <44> +45 legate::numpy::BinaryOpTask <45> +46 legate::numpy::BinaryOpTask <46> +50 legate::numpy::BinaryOpTask <50> +51 legate::numpy::BinaryOpTask <51> +53 legate::numpy::BinaryOpTask [CPU] <53> CPU Processor 0x1d00000000000003 2 +49 legate::numpy::BinaryOpTask <49> +32 legate::numpy::FillTask <32> +31 legate::numpy::FillTask <31> +28 legate::numpy::BinaryOpTask <28> +39 legate::numpy::FillTask [CPU] <39> CPU Processor 0x1d00000000000003 2 +3 Tunable Operation <3> +4 Tunable Operation <4> +22 legate::numpy::FillTask <22> +30 legate::numpy::BinaryOpTask <30> +23 legate::numpy::FillTask <23> +24 legate::numpy::FillTask <24> +26 legate::numpy::FillTask <26> +27 legate::numpy::FillTask <27> +41 legate::numpy::FillTask <41> +40 legate::numpy::FillTask <40> +43 legate::numpy::FillTask [CPU] <43> CPU Processor 0x1d00000000000003 2 +37 legate::numpy::FillTask <37> +64 legate::numpy::BinaryOpTask <64> +70 legate::numpy::BinaryOpTask <70> +78 legate::numpy::BinaryOpTask <78> +86 Fence Operation <86> +58 legate::numpy::BinaryOpTask [CPU] <58> CPU Processor 0x1d00000000000002 2 +57 legate::numpy::BinaryOpTask <57> +66 legate::numpy::BinaryOpTask [CPU] <66> CPU Processor 0x1d00000000000003 2 +72 legate::numpy::BinaryOpTask [CPU] <72> CPU Processor 0x1d00000000000003 2 +81 legate::numpy::BinaryOpTask <81> +62 legate::numpy::BinaryOpTask <62> +73 legate::numpy::BinaryOpTask <73> +74 legate::numpy::BinaryOpTask <74> +75 legate::numpy::BinaryOpTask <75> +61 legate::numpy::BinaryOpTask <61> +67 legate::numpy::BinaryOpTask <67> +69 legate::numpy::BinaryOpTask <69> diff --git a/examples/testbench/decent_band/legion_prof_processor.tsv b/examples/testbench/decent_band/legion_prof_processor.tsv new file mode 100644 index 000000000..1f9a1fa94 --- /dev/null +++ b/examples/testbench/decent_band/legion_prof_processor.tsv @@ -0,0 +1,9 @@ +full_text text tsv levels +Utility Processor 0x1d00000000000000 Utility Proc 0 tsv/Proc_0x1d00000000000000.tsv 4 +Utility Processor 0x1d00000000000001 Utility Proc 1 tsv/Proc_0x1d00000000000001.tsv 5 +CPU Processor 0x1d00000000000002 CPU Proc 2 tsv/Proc_0x1d00000000000002.tsv 1 +CPU Processor 0x1d00000000000003 CPU Proc 3 tsv/Proc_0x1d00000000000003.tsv 1 +Python Processor 0x1d00000000000004 Python Proc 4 tsv/Proc_0x1d00000000000004.tsv 1 +Dependent Partition Channel Dependent Partition Channel tsv/None.tsv 3 +System Memory 0x1e00000000000000 to System Memory 0x1e00000000000000 Channel [n0] sys to [n0] sys tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv 3 +System Memory 0x1e00000000000000 [n0] sys tsv/Mem_0x1e00000000000000.tsv 11 diff --git a/examples/testbench/decent_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv b/examples/testbench/decent_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv new file mode 100644 index 000000000..55e3f448b --- /dev/null +++ b/examples/testbench/decent_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv @@ -0,0 +1,3 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +3 1048681.945 1050273.272 #ff6e00 1.0 size=1.907 MiB, num reqs=1$req[0]: src_inst=0x4000000000000007, dst_inst=0x400000000000000b, fields=1, type=copy, hops=1 83 686 +2 1048752.497 1050266.685 #ff6e00 1.0 size=1.907 MiB, num reqs=1$req[0]: src_inst=0x4000000000000008, dst_inst=0x400000000000000b, fields=1, type=copy, hops=1 83 702 diff --git a/examples/testbench/decent_band/tsv/0 (CPU)_util.tsv b/examples/testbench/decent_band/tsv/0 (CPU)_util.tsv new file mode 100644 index 000000000..8d75fcdb6 --- /dev/null +++ b/examples/testbench/decent_band/tsv/0 (CPU)_util.tsv @@ -0,0 +1,288 @@ +time count +0.000 0.00 +962689.824 0.50 +962698.725 0.00 +999427.832 0.50 +999433.367 0.00 +999530.605 0.50 +999537.468 0.00 +999566.582 0.50 +999574.512 0.00 +1019563.499 0.50 +1019569.168 0.00 +1019723.664 0.50 +1019734.354 0.00 +1019976.547 0.50 +1019982.927 0.00 +1020029.859 0.50 +1020035.992 0.00 +1020081.621 0.50 +1020088.315 0.00 +1020133.393 0.50 +1020140.003 0.00 +1020170.226 0.50 +1020176.043 0.00 +1020320.009 0.50 +1020320.096 1.00 +1020326.182 0.50 +1020326.371 0.00 +1020336.073 0.50 +1020344.812 0.00 +1020409.676 0.50 +1020415.356 0.00 +1020465.741 0.50 +1020471.704 0.00 +1020538.912 0.50 +1020544.913 0.00 +1020607.485 0.50 +1020618.851 0.00 +1020683.611 0.50 +1020698.885 1.00 +1020708.696 0.50 +1020718.044 1.00 +1020723.315 0.50 +1020728.635 1.00 +1020732.653 0.50 +1020812.834 1.00 +1020820.679 0.50 +1020841.769 1.00 +1020849.994 0.50 +1020859.100 1.00 +1022061.790 0.50 +1022107.376 1.00 +1022115.335 0.50 +1022125.977 1.00 +1022132.984 0.50 +1022141.854 1.00 +1022148.613 0.50 +1022155.102 1.00 +1022158.592 0.50 +1022164.775 1.00 +1022169.154 0.50 +1022175.085 1.00 +1022178.496 0.50 +1022184.906 1.00 +1022191.677 0.50 +1022198.572 1.00 +1022204.310 0.50 +1022210.953 1.00 +1022211.911 0.50 +1022214.923 0.00 +1022222.553 0.50 +1022227.962 0.00 +1022237.249 0.50 +1022245.039 0.00 +1022245.345 0.50 +1022259.076 1.00 +1023674.045 0.50 +1023674.774 0.00 +1023700.501 0.50 +1023714.788 1.00 +1024165.613 0.50 +1024175.988 0.00 +1024191.329 0.50 +1024212.470 1.00 +1025513.689 0.50 +1025523.689 0.00 +1025541.836 0.50 +1025553.734 1.00 +1025784.682 0.50 +1025793.359 0.00 +1025817.215 0.50 +1025825.619 1.00 +1025838.009 0.50 +1025857.809 1.00 +1027264.327 0.50 +1027267.987 0.00 +1027290.352 0.50 +1027298.588 1.00 +1027310.850 0.50 +1027340.279 1.00 +1028673.325 0.50 +1028683.215 0.00 +1028696.363 0.50 +1028702.589 0.00 +1043099.467 0.50 +1043105.925 0.00 +1043152.725 0.50 +1043162.570 0.00 +1043172.134 0.50 +1043175.780 0.00 +1043313.696 0.50 +1043321.599 0.00 +1043381.693 0.50 +1043389.858 0.00 +1043463.226 0.50 +1043469.407 0.00 +1043478.703 0.50 +1043483.955 0.00 +1043544.444 0.50 +1043550.837 0.00 +1043559.025 0.50 +1043565.584 0.00 +1043780.003 0.50 +1043793.581 0.00 +1043815.587 0.50 +1043823.752 0.00 +1043840.550 0.50 +1043845.419 0.00 +1043885.917 0.50 +1043891.674 1.00 +1043893.078 0.50 +1043899.319 1.00 +1043902.688 0.50 +1043932.016 1.00 +1044741.669 0.50 +1044772.977 1.00 +1044785.500 0.50 +1044786.018 0.00 +1044798.568 0.50 +1044804.821 0.00 +1044816.976 0.50 +1044818.895 1.00 +1044826.305 0.50 +1044832.900 1.00 +1044836.390 0.50 +1044841.026 1.00 +1044846.632 0.50 +1044853.660 1.00 +1044856.914 0.50 +1044903.140 1.00 +1045600.715 0.50 +1045633.063 1.00 +1045640.501 0.50 +1045658.078 1.00 +1045664.840 0.50 +1045674.697 1.00 +1045716.824 0.50 +1045749.414 1.00 +1045757.154 0.50 +1045767.502 1.00 +1045774.232 0.50 +1045783.097 1.00 +1046429.291 0.50 +1046459.143 1.00 +1046466.393 0.50 +1046474.283 1.00 +1046481.896 0.50 +1046509.517 1.00 +1046540.037 0.50 +1046615.744 1.00 +1047234.439 0.50 +1047255.694 1.00 +1047261.622 0.50 +1047267.900 1.00 +1047274.343 0.50 +1047281.641 1.00 +1047298.270 0.50 +1047306.163 1.00 +1047311.434 0.50 +1047316.397 1.00 +1047328.915 0.50 +1047333.748 1.00 +1047336.991 0.50 +1047402.303 0.00 +1047408.539 0.50 +1047414.776 0.00 +1047425.444 0.50 +1047428.177 1.00 +1047430.972 0.50 +1047435.591 0.00 +1047463.197 0.50 +1047485.607 1.00 +1047499.472 0.50 +1047509.224 1.00 +1047515.337 0.50 +1047551.395 1.00 +1047558.273 0.50 +1047583.009 1.00 +1047588.140 0.50 +1047610.844 1.00 +1047614.303 0.50 +1047619.993 1.00 +1047623.284 0.50 +1047656.279 1.00 +1048083.927 0.50 +1048208.167 1.00 +1048215.606 0.50 +1048245.381 1.00 +1048260.714 0.50 +1048281.052 0.00 +1048360.624 0.50 +1048368.336 0.00 +1048392.151 0.50 +1048397.420 0.00 +1048858.236 0.50 +1048865.054 0.00 +1048914.304 0.50 +1048919.582 0.00 +1048927.422 0.50 +1048933.418 0.00 +1183514.868 0.50 +1183526.003 0.00 +1183564.060 0.50 +1183571.389 0.00 +1183586.336 0.50 +1183593.882 0.00 +1183618.998 0.50 +1183627.204 0.00 +1183656.435 0.50 +1183662.395 0.00 +1183716.981 0.50 +1183722.963 0.00 +1183789.778 0.50 +1183796.240 0.00 +1183844.266 0.50 +1183850.453 0.00 +1183876.008 0.50 +1183881.779 0.00 +1183932.594 0.50 +1183961.777 0.00 +1183962.273 0.50 +1183969.461 0.00 +1183990.520 0.50 +1183995.478 0.00 +1184022.320 0.50 +1184027.253 0.00 +1184378.314 0.50 +1184386.071 0.00 +1184410.125 0.50 +1184416.531 0.00 +1184438.252 0.50 +1184446.042 0.00 +1184452.860 0.50 +1184456.362 0.00 +1184482.915 0.50 +1184489.625 0.00 +1184514.238 0.50 +1184519.942 0.00 +1184528.822 0.50 +1184533.676 0.00 +1184557.808 0.50 +1184562.356 0.00 +1184575.260 0.50 +1184578.768 0.00 +1184612.280 0.50 +1184619.851 0.00 +1184649.833 0.50 +1184656.431 0.00 +1184676.751 0.50 +1184683.603 0.00 +1184686.919 0.50 +1184705.292 0.00 +1184711.881 0.50 +1184716.235 1.00 +1184720.164 0.50 +1184722.729 0.00 +1184751.168 0.50 +1184757.069 0.00 +1184788.335 0.50 +1184793.531 0.00 +1184825.080 0.50 +1184831.298 0.00 +1184838.998 0.50 +1184845.978 0.00 +1184846.419 0.50 +1184853.601 0.00 +1184862.211 0.50 +1184865.981 0.00 diff --git a/examples/testbench/decent_band/tsv/0 (Channel)_util.tsv b/examples/testbench/decent_band/tsv/0 (Channel)_util.tsv new file mode 100644 index 000000000..308fc3280 --- /dev/null +++ b/examples/testbench/decent_band/tsv/0 (Channel)_util.tsv @@ -0,0 +1,4 @@ +time count +0.000 0.00 +1048681.945 1.00 +1050273.272 0.00 diff --git a/examples/testbench/decent_band/tsv/0 (Python)_util.tsv b/examples/testbench/decent_band/tsv/0 (Python)_util.tsv new file mode 100644 index 000000000..eb57e7853 --- /dev/null +++ b/examples/testbench/decent_band/tsv/0 (Python)_util.tsv @@ -0,0 +1,14 @@ +time count +0.000 0.00 +478641.174 1.00 +922239.137 0.00 +922497.427 1.00 +922606.850 0.00 +922815.999 1.00 +962519.280 0.00 +962723.661 1.00 +1047360.569 0.00 +1048908.961 1.00 +1048924.893 0.00 +1050359.631 1.00 +1183469.202 0.00 diff --git a/examples/testbench/decent_band/tsv/0 (System Memory)_util.tsv b/examples/testbench/decent_band/tsv/0 (System Memory)_util.tsv new file mode 100644 index 000000000..d2d9245bc --- /dev/null +++ b/examples/testbench/decent_band/tsv/0 (System Memory)_util.tsv @@ -0,0 +1,24 @@ +time count +0.000 0.00 +1020277.868 0.00 +1020517.864 0.00 +1021638.640 0.00 +1021896.476 0.00 +1022852.940 0.00 +1023094.891 0.00 +1024127.778 0.00 +1024326.370 0.00 +1025091.417 0.00 +1025243.869 0.00 +1048334.454 0.01 +1183909.479 0.01 +1183973.835 0.00 +1184355.765 0.00 +1184412.082 0.00 +1184466.441 0.00 +1184520.480 0.00 +1184563.664 0.00 +1184616.464 0.00 +1184671.451 0.00 +1184732.637 0.00 +1184825.486 0.00 diff --git a/examples/testbench/decent_band/tsv/0 (Utility)_util.tsv b/examples/testbench/decent_band/tsv/0 (Utility)_util.tsv new file mode 100644 index 000000000..eb2ceb069 --- /dev/null +++ b/examples/testbench/decent_band/tsv/0 (Utility)_util.tsv @@ -0,0 +1,924 @@ +time count +0.000 0.00 +478125.062 0.50 +478182.035 0.00 +478215.611 0.50 +478215.750 1.00 +478227.571 0.50 +478293.256 0.00 +478321.896 0.50 +478322.038 1.00 +478327.141 0.50 +478364.450 0.00 +478393.250 0.50 +478397.534 1.00 +478398.019 0.50 +478455.013 0.00 +478487.003 0.50 +478488.917 1.00 +478491.783 0.50 +478610.233 0.00 +478651.813 0.50 +478657.222 0.00 +922202.362 0.50 +922257.734 0.00 +922271.051 0.50 +922282.907 1.00 +922293.697 0.50 +922313.422 0.00 +922320.369 0.50 +922352.823 1.00 +922360.236 0.50 +922430.159 0.00 +922485.054 0.50 +922500.295 0.00 +922615.976 0.50 +922651.888 0.00 +922678.906 0.50 +922683.753 0.00 +922685.337 0.50 +922723.942 0.00 +922748.730 0.50 +922752.172 1.00 +922757.292 0.50 +922781.292 0.00 +922821.002 0.50 +922824.608 0.00 +962526.481 0.50 +962567.952 0.00 +962598.963 0.50 +962603.564 0.00 +962606.098 0.50 +962647.123 0.00 +962678.949 0.50 +962723.015 0.00 +962756.169 0.50 +962760.737 0.00 +999297.143 0.50 +999351.129 0.00 +999365.982 0.50 +999372.250 1.00 +999376.414 0.50 +999398.360 0.00 +999406.012 0.50 +999503.615 0.00 +999507.767 0.50 +999524.730 1.00 +999529.853 0.50 +999537.920 0.00 +999551.347 0.50 +999554.898 0.00 +1019311.922 0.50 +1019495.678 1.00 +1019495.815 0.50 +1019516.941 1.00 +1019521.801 0.50 +1019527.822 1.00 +1019531.556 0.50 +1019576.947 1.00 +1019579.130 0.50 +1019594.838 1.00 +1019598.189 0.50 +1019620.039 0.00 +1019628.570 0.50 +1019636.957 1.00 +1019640.979 0.50 +1019699.933 0.00 +1019714.252 0.50 +1019811.952 0.00 +1019827.080 0.50 +1019830.493 1.00 +1019834.164 0.50 +1019933.635 1.00 +1019950.329 0.50 +1019974.821 1.00 +1020004.219 0.50 +1020027.498 1.00 +1020060.964 0.50 +1020081.461 1.00 +1020099.613 0.50 +1020115.715 1.00 +1020149.907 0.50 +1020169.732 1.00 +1020198.015 0.50 +1020215.638 1.00 +1020251.160 0.50 +1020263.069 1.00 +1020281.769 0.50 +1020365.103 1.00 +1020389.610 0.50 +1020411.660 1.00 +1020446.324 0.50 +1020465.390 1.00 +1020580.691 0.50 +1020602.314 1.00 +1020623.469 0.50 +1020634.362 1.00 +1020671.314 0.50 +1020676.289 0.00 +1020691.218 0.50 +1020713.369 0.00 +1020722.173 0.50 +1020750.432 1.00 +1020787.419 0.50 +1020808.922 0.00 +1020810.229 0.50 +1020839.392 1.00 +1020846.307 0.50 +1020864.411 1.00 +1020874.211 0.50 +1020894.975 1.00 +1020913.363 0.50 +1020928.632 1.00 +1020930.984 0.50 +1020952.149 1.00 +1020985.345 0.50 +1020996.549 0.00 +1021013.914 0.50 +1021015.936 1.00 +1021039.622 0.50 +1021048.610 0.00 +1021058.657 0.50 +1021061.000 1.00 +1021089.194 0.50 +1021095.392 0.00 +1021103.473 0.50 +1021113.857 1.00 +1021142.700 0.50 +1021159.797 1.00 +1021175.820 0.50 +1021181.610 0.00 +1021196.702 0.50 +1021219.821 1.00 +1021266.724 0.50 +1021284.322 1.00 +1021292.380 0.50 +1021312.878 1.00 +1021325.094 0.50 +1021339.701 1.00 +1021358.196 0.50 +1021375.545 1.00 +1021396.717 0.50 +1021396.820 0.00 +1021416.548 0.50 +1021427.029 1.00 +1021465.556 0.50 +1021477.105 0.00 +1021485.938 0.50 +1021492.376 1.00 +1021517.858 0.50 +1021535.050 1.00 +1021563.059 0.50 +1021570.371 0.00 +1021585.593 0.50 +1021598.522 1.00 +1021633.743 0.50 +1021650.015 1.00 +1021708.350 0.50 +1021729.660 1.00 +1021748.943 0.50 +1021776.980 0.00 +1021799.332 0.50 +1021800.527 1.00 +1021831.515 0.50 +1021836.851 0.00 +1021856.216 0.50 +1021869.553 1.00 +1021890.510 0.50 +1021906.979 1.00 +1021935.187 0.50 +1021994.272 0.00 +1022016.171 0.50 +1022033.123 1.00 +1022036.573 0.50 +1022059.820 1.00 +1022077.471 0.50 +1022096.587 1.00 +1022115.674 0.50 +1022147.738 0.00 +1022149.566 0.50 +1022163.230 1.00 +1022191.124 0.50 +1022202.817 0.00 +1022220.315 0.50 +1022226.791 1.00 +1022257.425 0.50 +1022276.351 1.00 +1022306.819 0.50 +1022330.425 1.00 +1022345.941 0.50 +1022359.294 1.00 +1022392.149 0.50 +1022402.911 1.00 +1022420.902 0.50 +1022466.782 1.00 +1022494.632 0.50 +1022519.257 1.00 +1022522.165 0.50 +1022536.070 1.00 +1022545.038 0.50 +1022565.474 1.00 +1022572.262 0.50 +1022586.450 1.00 +1022614.121 0.50 +1022625.358 1.00 +1022643.447 0.50 +1022672.695 1.00 +1022681.509 0.50 +1022694.589 1.00 +1022708.855 0.50 +1022721.685 0.00 +1022729.096 0.50 +1022732.564 1.00 +1022761.644 0.50 +1022770.283 0.00 +1022792.567 0.50 +1022795.202 1.00 +1022828.127 0.50 +1022853.928 1.00 +1022898.698 0.50 +1022915.164 1.00 +1022928.362 0.50 +1022953.932 1.00 +1022971.622 0.50 +1022987.959 1.00 +1023010.260 0.50 +1023030.646 0.00 +1023050.877 0.50 +1023051.263 1.00 +1023065.156 0.50 +1023086.962 1.00 +1023113.349 0.50 +1023128.018 1.00 +1023140.111 0.50 +1023152.278 1.00 +1023157.689 0.50 +1023163.973 1.00 +1023168.055 0.50 +1023180.849 0.00 +1023197.049 0.50 +1023208.594 0.00 +1023217.702 0.50 +1023219.200 1.00 +1023224.712 0.50 +1023231.705 1.00 +1023236.361 0.50 +1023243.711 1.00 +1023248.462 0.50 +1023255.017 1.00 +1023259.870 0.50 +1023266.635 1.00 +1023271.371 0.50 +1023278.427 1.00 +1023287.444 0.50 +1023296.822 1.00 +1023297.512 0.50 +1023334.341 0.00 +1023345.970 0.50 +1023357.571 1.00 +1023364.867 0.50 +1023374.111 1.00 +1023376.256 0.50 +1023398.373 1.00 +1023403.459 0.50 +1023435.265 1.00 +1023447.377 0.50 +1023468.882 1.00 +1023524.215 0.50 +1023544.753 1.00 +1023551.388 0.50 +1023567.314 1.00 +1023593.726 0.50 +1023606.937 0.00 +1023608.446 0.50 +1023620.187 1.00 +1023665.627 0.50 +1023676.616 0.00 +1023685.236 0.50 +1023692.044 1.00 +1023718.305 0.50 +1023726.876 0.00 +1023741.592 0.50 +1023746.877 1.00 +1023765.560 0.50 +1023777.870 1.00 +1023800.215 0.50 +1023810.031 0.00 +1023813.667 0.50 +1023824.143 1.00 +1023831.242 0.50 +1023837.657 1.00 +1023842.050 0.50 +1023848.474 1.00 +1023855.887 0.50 +1023864.845 1.00 +1023869.083 0.50 +1023874.606 1.00 +1023879.071 0.50 +1023885.288 1.00 +1023886.789 0.50 +1023900.795 1.00 +1023904.789 0.50 +1023911.051 1.00 +1023919.322 0.50 +1023924.498 1.00 +1023978.079 0.50 +1023982.068 0.00 +1023994.093 0.50 +1024023.781 1.00 +1024050.003 0.50 +1024066.601 1.00 +1024067.567 0.50 +1024083.242 1.00 +1024112.260 0.50 +1024125.702 1.00 +1024142.386 0.50 +1024176.449 1.00 +1024187.245 0.50 +1024197.413 1.00 +1024204.799 0.50 +1024214.037 1.00 +1024298.425 0.50 +1024316.465 1.00 +1024327.960 0.50 +1024336.179 1.00 +1024341.424 0.50 +1024350.467 1.00 +1024359.821 0.50 +1024367.407 1.00 +1024372.548 0.50 +1024380.168 1.00 +1024385.425 0.50 +1024393.264 1.00 +1024397.528 0.50 +1024403.247 1.00 +1024409.951 0.50 +1024415.079 1.00 +1024418.409 0.50 +1024422.747 1.00 +1024425.896 0.50 +1024430.164 1.00 +1024433.324 0.50 +1024437.680 1.00 +1024440.818 0.50 +1024445.675 1.00 +1024450.251 0.50 +1024457.169 1.00 +1024462.152 0.50 +1024468.852 1.00 +1024473.600 0.50 +1024481.925 1.00 +1024488.279 0.50 +1024497.214 1.00 +1024532.506 0.50 +1024551.826 1.00 +1024557.161 0.50 +1024557.310 0.00 +1024564.753 0.50 +1024569.824 0.00 +1024577.086 0.50 +1024582.272 0.00 +1024585.057 0.50 +1024590.350 0.00 +1024597.545 0.50 +1024601.896 0.00 +1024604.599 0.50 +1024607.410 1.00 +1024610.839 0.50 +1024615.132 1.00 +1024619.071 0.50 +1024623.671 1.00 +1024626.791 0.50 +1024631.171 1.00 +1024634.661 0.50 +1024639.219 1.00 +1024642.520 0.50 +1024647.137 1.00 +1024653.786 0.50 +1024658.361 1.00 +1024661.720 0.50 +1024666.000 1.00 +1024669.305 0.50 +1024674.022 1.00 +1024677.281 0.50 +1024682.524 1.00 +1024686.570 0.50 +1024691.334 1.00 +1024694.870 0.50 +1024701.141 1.00 +1024710.027 0.50 +1024725.666 0.00 +1024736.750 0.50 +1024738.342 1.00 +1024762.023 0.50 +1024774.483 1.00 +1024779.744 0.50 +1024804.740 1.00 +1024816.493 0.50 +1024826.612 1.00 +1024833.728 0.50 +1024836.925 0.00 +1024843.783 0.50 +1024849.380 1.00 +1024856.773 0.50 +1024862.364 1.00 +1024865.775 0.50 +1024870.158 1.00 +1024873.470 0.50 +1024878.042 1.00 +1024882.017 0.50 +1024887.041 1.00 +1024891.672 0.50 +1024896.902 1.00 +1024934.671 0.50 +1024954.495 0.00 +1024959.693 0.50 +1024968.486 1.00 +1025006.101 0.50 +1025019.490 1.00 +1025036.615 0.50 +1025052.455 1.00 +1025062.406 0.50 +1025084.356 1.00 +1025136.235 0.50 +1025163.800 1.00 +1025193.188 0.50 +1025214.680 1.00 +1025220.882 0.50 +1025229.189 1.00 +1025233.988 0.50 +1025241.497 1.00 +1025247.221 0.50 +1025257.689 1.00 +1025263.857 0.50 +1025270.770 1.00 +1025275.650 0.50 +1025283.515 1.00 +1025288.725 0.50 +1025296.185 1.00 +1025301.041 0.50 +1025308.726 1.00 +1025315.060 0.50 +1025322.404 1.00 +1025328.213 0.50 +1025336.959 1.00 +1025342.196 0.50 +1025359.303 1.00 +1025364.244 0.50 +1025370.767 1.00 +1025375.170 0.50 +1025381.120 1.00 +1025382.984 0.50 +1025385.474 0.00 +1025391.182 0.50 +1025394.660 0.00 +1025399.314 0.50 +1025402.789 0.00 +1025408.650 0.50 +1025411.987 0.00 +1025424.161 0.50 +1025425.162 1.00 +1025483.181 0.50 +1025498.175 1.00 +1025513.498 0.50 +1025527.688 0.00 +1025539.025 0.50 +1025543.882 1.00 +1025548.382 0.50 +1025558.764 1.00 +1025586.146 0.50 +1025602.869 0.00 +1025611.427 0.50 +1025614.838 1.00 +1025619.617 0.50 +1025622.226 0.00 +1025625.266 0.50 +1025628.726 0.00 +1025633.859 0.50 +1025638.213 1.00 +1025642.194 0.50 +1025647.842 1.00 +1025647.947 0.50 +1025652.082 0.00 +1025656.285 0.50 +1025662.911 0.00 +1025663.084 0.50 +1025668.053 1.00 +1025672.011 0.50 +1025676.517 0.00 +1025677.535 0.50 +1025681.288 0.00 +1025685.439 0.50 +1025689.447 0.00 +1025693.048 0.50 +1025695.077 1.00 +1025699.308 0.50 +1025703.809 0.00 +1025704.517 0.50 +1025708.414 0.00 +1025714.241 0.50 +1025718.680 0.00 +1025721.602 0.50 +1025724.009 1.00 +1025728.305 0.50 +1025731.260 0.00 +1025733.660 0.50 +1025737.322 0.00 +1025743.220 0.50 +1025746.411 1.00 +1025749.866 0.50 +1025755.473 1.00 +1025757.279 0.50 +1025761.694 0.00 +1025766.641 0.50 +1025770.104 1.00 +1025773.447 0.50 +1025779.732 1.00 +1025781.733 0.50 +1025784.983 0.00 +1025792.915 0.50 +1025793.659 1.00 +1025799.588 0.50 +1025800.787 0.00 +1025805.808 0.50 +1025809.659 1.00 +1025811.421 0.50 +1025816.652 0.00 +1025817.749 0.50 +1025826.110 0.00 +1025827.856 0.50 +1025879.400 0.00 +1025906.153 0.50 +1025912.069 0.00 +1027308.633 0.50 +1027310.719 1.00 +1027329.152 0.50 +1027395.869 0.00 +1027416.270 0.50 +1027421.057 0.00 +1028703.178 0.50 +1028712.514 0.00 +1028717.674 0.50 +1028780.475 0.00 +1028818.229 0.50 +1028823.793 0.00 +1042970.205 0.50 +1043065.662 0.00 +1043079.828 0.50 +1043116.150 0.00 +1043117.747 0.50 +1043158.329 0.00 +1043182.818 0.50 +1043276.396 0.00 +1043292.115 0.50 +1043357.314 0.00 +1043363.999 0.50 +1043380.714 1.00 +1043439.363 0.50 +1043456.611 0.00 +1043462.537 0.50 +1043480.043 1.00 +1043521.460 0.50 +1043527.246 0.00 +1043539.388 0.50 +1043543.456 1.00 +1043569.949 0.50 +1043608.194 1.00 +1043755.669 0.50 +1043775.142 0.00 +1043798.301 0.50 +1043801.712 1.00 +1043819.547 0.50 +1043843.446 1.00 +1043856.144 0.50 +1043873.303 0.00 +1043892.005 0.50 +1043895.364 1.00 +1043927.706 0.50 +1043943.742 1.00 +1043944.189 0.50 +1043966.030 0.00 +1043975.777 0.50 +1043979.505 1.00 +1043984.049 0.50 +1043989.105 1.00 +1043993.343 0.50 +1043997.722 1.00 +1044001.005 0.50 +1044064.430 0.00 +1044073.642 0.50 +1044089.069 1.00 +1044098.310 0.50 +1044226.567 0.00 +1044226.872 0.50 +1044247.954 1.00 +1044259.135 0.50 +1044300.172 1.00 +1044329.824 0.50 +1044354.406 1.00 +1044386.707 0.50 +1044410.934 1.00 +1044445.597 0.50 +1044466.872 1.00 +1044480.531 0.50 +1044499.704 1.00 +1044567.279 0.50 +1044587.570 0.00 +1044589.211 0.50 +1044610.308 1.00 +1044652.525 0.50 +1044661.375 0.00 +1044673.215 0.50 +1044681.828 1.00 +1044694.814 0.50 +1044708.340 1.00 +1044713.469 0.50 +1044720.801 1.00 +1044725.565 0.50 +1044733.154 1.00 +1044739.424 0.50 +1044748.470 1.00 +1044753.463 0.50 +1044761.516 1.00 +1044767.193 0.50 +1044780.080 1.00 +1044784.929 0.50 +1044820.621 1.00 +1044825.226 0.50 +1044846.453 1.00 +1044894.401 0.50 +1044900.995 0.00 +1044914.641 0.50 +1044917.922 1.00 +1044921.456 0.50 +1044926.303 1.00 +1044929.620 0.50 +1044956.768 1.00 +1044957.622 0.50 +1044977.578 1.00 +1044983.228 0.50 +1045043.456 0.00 +1045056.568 0.50 +1045063.383 1.00 +1045069.759 0.50 +1045129.604 1.00 +1045161.665 0.50 +1045193.135 1.00 +1045222.693 0.50 +1045244.778 1.00 +1045294.673 0.50 +1045307.601 0.00 +1045319.687 0.50 +1045327.219 1.00 +1045373.960 0.50 +1045394.111 1.00 +1045447.100 0.50 +1045477.587 1.00 +1045506.945 0.50 +1045516.256 0.00 +1045530.483 0.50 +1045538.802 1.00 +1045572.715 0.50 +1045590.083 1.00 +1045596.571 0.50 +1045606.996 1.00 +1045613.389 0.50 +1045623.192 1.00 +1045627.364 0.50 +1045656.151 1.00 +1045675.044 0.50 +1045696.208 1.00 +1045698.593 0.50 +1045723.770 1.00 +1045730.321 0.50 +1045738.104 0.00 +1045740.255 0.50 +1045762.330 1.00 +1045816.314 0.50 +1045829.832 1.00 +1045834.051 0.50 +1045840.224 1.00 +1045845.981 0.50 +1045884.019 1.00 +1045890.352 0.50 +1045899.719 1.00 +1045917.954 0.50 +1045933.357 1.00 +1045982.091 0.50 +1045999.345 0.00 +1046021.175 0.50 +1046041.662 0.00 +1046056.676 0.50 +1046076.892 1.00 +1046091.530 0.50 +1046099.419 1.00 +1046104.230 0.50 +1046111.528 1.00 +1046117.513 0.50 +1046126.367 1.00 +1046135.932 0.50 +1046171.137 1.00 +1046202.563 0.50 +1046217.381 1.00 +1046250.716 0.50 +1046253.709 0.00 +1046267.074 0.50 +1046278.030 1.00 +1046314.988 0.50 +1046339.475 1.00 +1046346.238 0.50 +1046347.300 0.00 +1046356.442 0.50 +1046361.479 1.00 +1046366.368 0.50 +1046371.169 1.00 +1046376.461 0.50 +1046382.603 1.00 +1046386.495 0.50 +1046392.676 1.00 +1046393.607 0.50 +1046397.357 0.00 +1046403.160 0.50 +1046406.375 0.00 +1046413.126 0.50 +1046413.696 1.00 +1046417.530 0.50 +1046420.873 0.00 +1046424.509 0.50 +1046430.009 0.00 +1046432.425 0.50 +1046436.284 1.00 +1046440.982 0.50 +1046441.751 0.00 +1046446.383 0.50 +1046451.457 0.00 +1046452.072 0.50 +1046458.827 0.00 +1046460.896 0.50 +1046470.788 1.00 +1046477.290 0.50 +1046505.755 0.00 +1046529.968 0.50 +1046535.783 0.00 +1046561.498 0.50 +1046574.575 0.00 +1046575.458 0.50 +1046629.117 1.00 +1046632.653 0.50 +1046651.407 1.00 +1046656.178 0.50 +1046661.879 1.00 +1046686.301 0.50 +1046714.430 1.00 +1046725.278 0.50 +1046731.836 0.00 +1046740.944 0.50 +1046745.147 1.00 +1046745.264 0.50 +1046777.346 0.00 +1046791.619 0.50 +1046792.290 1.00 +1046796.714 0.50 +1046847.610 0.00 +1046858.968 0.50 +1046861.463 1.00 +1046865.754 0.50 +1046953.784 0.00 +1046963.523 0.50 +1046968.448 1.00 +1046972.915 0.50 +1047041.315 1.00 +1047045.904 0.50 +1047060.705 1.00 +1047095.389 0.50 +1047157.403 1.00 +1047168.964 0.50 +1047183.873 0.00 +1047197.484 0.50 +1047219.317 1.00 +1047280.431 0.50 +1047296.481 0.00 +1047308.491 0.50 +1047326.874 1.00 +1047380.812 0.50 +1047384.780 0.00 +1047402.395 0.50 +1047409.220 1.00 +1047457.574 0.50 +1047465.051 0.00 +1047478.032 0.50 +1047485.106 1.00 +1047513.167 0.50 +1047531.411 1.00 +1047559.608 0.50 +1047579.867 1.00 +1047591.084 0.50 +1047600.351 0.00 +1047606.599 0.50 +1047617.954 1.00 +1047648.258 0.50 +1047652.121 0.00 +1047667.464 0.50 +1047704.246 1.00 +1047714.252 0.50 +1047727.631 1.00 +1047733.357 0.50 +1047743.823 1.00 +1047767.970 0.50 +1047866.075 1.00 +1047885.816 0.50 +1047892.303 0.00 +1048028.782 0.50 +1048046.924 0.00 +1048073.019 0.50 +1048079.943 0.00 +1048089.840 0.50 +1048102.683 0.00 +1048111.659 0.50 +1048120.678 0.00 +1048129.055 0.50 +1048135.725 1.00 +1048178.094 0.50 +1048202.620 1.00 +1048208.721 0.50 +1048233.751 0.00 +1048240.244 0.50 +1048253.255 1.00 +1048259.273 0.50 +1048303.934 1.00 +1048310.306 0.50 +1048319.181 1.00 +1048367.651 0.50 +1048535.478 1.00 +1048541.225 0.50 +1048570.806 1.00 +1048584.206 0.50 +1048804.548 0.00 +1048841.090 0.50 +1048854.074 1.00 +1048881.903 0.50 +1048904.134 0.00 +1050297.761 0.50 +1050298.787 1.00 +1050315.697 0.50 +1050316.398 0.00 +1144670.598 0.50 +1144703.476 0.00 +1144732.332 0.50 +1144738.433 0.00 +1144879.567 0.50 +1144915.226 0.00 +1144943.824 0.50 +1144961.684 0.00 +1144974.220 0.50 +1144991.831 0.00 +1145003.814 0.50 +1145008.939 0.00 +1145013.909 0.50 +1145017.309 0.00 +1145021.935 0.50 +1145025.293 0.00 +1183447.115 0.50 +1183505.306 1.00 +1183539.347 0.50 +1183556.775 0.00 +1183567.025 0.50 +1183584.044 1.00 +1183592.790 0.50 +1183620.810 1.00 +1183632.883 0.50 +1183682.119 1.00 +1183686.977 0.50 +1183740.807 1.00 +1183767.389 0.50 +1183786.910 1.00 +1183824.028 0.50 +1183846.435 1.00 +1183856.010 0.50 +1183875.602 1.00 +1183938.722 0.50 +1183966.177 1.00 +1183997.470 0.50 +1184344.122 1.00 +1184386.204 0.50 +1184404.214 1.00 +1184437.440 0.50 +1184459.636 1.00 +1184492.880 0.50 +1184513.128 1.00 +1184539.716 0.50 +1184556.087 1.00 +1184588.795 0.50 +1184610.581 1.00 +1184645.091 0.50 +1184665.321 1.00 +1184688.358 0.50 +1184692.744 0.00 +1184717.064 0.50 +1184721.421 1.00 +1184764.287 0.50 +1184788.784 1.00 +1184801.507 0.50 +1184810.844 0.00 +1184818.629 0.50 +1184847.345 0.00 diff --git a/examples/testbench/decent_band/tsv/Mem_0x1e00000000000000.tsv b/examples/testbench/decent_band/tsv/Mem_0x1e00000000000000.tsv new file mode 100644 index 000000000..f432bcea2 --- /dev/null +++ b/examples/testbench/decent_band/tsv/Mem_0x1e00000000000000.tsv @@ -0,0 +1,12 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +11 1020277.868 1184412.082 #00fff6 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000001 $Size: 1.907 MiB 13 108 +10 1020517.864 1184732.637 #00fff6 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000002 $Size: 1.907 MiB 15 109 +9 1021638.640 1184825.486 #00fff6 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000003 $Size: 1.907 MiB 25 222 +8 1021896.476 1184466.441 #00fff6 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000004 $Size: 1.907 MiB 29 115 +7 1022852.940 1184520.480 #00fff6 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000005 $Size: 1.907 MiB 38 117 +6 1023094.891 1184616.464 #00fff6 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000006 $Size: 1.907 MiB 39 343 +5 1024127.778 1183973.835 #ff0038 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000007 $Size: 1.907 MiB 47 113 +4 1024326.370 1183909.479 #ff0038 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000008 $Size: 1.907 MiB 48 112 +3 1025091.417 1184563.664 #ff0038 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048581]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000009 $Size: 1.907 MiB 52 119 +2 1025243.869 1184671.451 #ff0038 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048581]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000a $Size: 1.907 MiB 53 344 +1 1048334.454 1184355.765 #ff6e00 1.0 Region: ispace:1[0:499999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000b $Size: 3.815 MiB 83 110 diff --git a/examples/testbench/decent_band/tsv/None.tsv b/examples/testbench/decent_band/tsv/None.tsv new file mode 100644 index 000000000..fd1ca0fb2 --- /dev/null +++ b/examples/testbench/decent_band/tsv/None.tsv @@ -0,0 +1,5 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +3 1047709.207 1047718.548 #ffa700 1.0 Intersection Reduction 84 653 +3 1047764.499 1047773.404 #ffa700 1.0 Intersection Reduction 84 687 +3 1047878.425 1047958.736 #ffa700 1.0 Union Reduction 84 688 +3 1048512.192 1048517.590 #ff6e00 1.0 Difference 83 689 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000000.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000000.tsv new file mode 100644 index 000000000..b13b85e05 --- /dev/null +++ b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000000.tsv @@ -0,0 +1,297 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +4 6 478089.159 478125.062 478182.035 #f100ff 1.0 Deferred Enqueue Task 1 [[0, 4, 8]] 223 +4 6 478215.750 478215.750 478227.571 #ffc0cb 1.0 ProfTask <1> 262 +4 6 478280.038 478321.896 478364.450 #3dff00 1.0 Task Physical Dependence Analysis 1 [[0, 4, 8]] 224 +4 6 478393.250 478393.250 478398.019 #ffc0cb 1.0 ProfTask <1> 263 +4 6 478443.497 478488.917 478610.233 #3dff00 1.0 Task Physical Dependence Analysis 1 [[0, 4, 8]] 312 +4 6 922125.469 922202.362 922257.734 #00ff12 1.0 Logical Dependence Analysis 3 226 +4 6 922282.907 922282.907 922293.697 #ffc0cb 1.0 ProfTask <3> 264 +4 6 922301.230 922320.369 922430.159 #007bff 1.0 Operation Physical Dependence Analysis 3 314 +4 6 922573.150 922615.976 922651.888 #00ff12 1.0 Logical Dependence Analysis 4 228 +4 6 922678.906 922678.906 922683.753 #ffc0cb 1.0 ProfTask <4> 265 +4 6 922701.693 922748.730 922781.292 #007bff 1.0 Operation Physical Dependence Analysis 4 229 +4 6 922821.002 922821.002 922824.608 #ffc0cb 1.0 ProfTask <4> 266 +4 6 962476.345 962526.481 962567.952 #00ff12 1.0 Logical Dependence Analysis 5 230 +4 6 962598.963 962598.963 962603.564 #ffc0cb 1.0 ProfTask <5> 267 +4 6 962626.749 962678.949 962723.015 #007bff 1.0 Operation Physical Dependence Analysis 5 316 +4 6 999247.591 999297.143 999351.129 #00ff12 1.0 Logical Dependence Analysis 6 231 +4 6 999372.250 999372.250 999376.414 #ffc0cb 1.0 ProfTask <6> 268 +4 6 999386.903 999406.012 999503.615 #007bff 1.0 Operation Physical Dependence Analysis 6 13 +4 5 999477.933 999524.730 999537.920 #ff00c5 1.0 Tighten Index Space 6 232 +4 6 999551.347 999551.347 999554.898 #ffc0cb 1.0 ProfTask <6> 269 +4 6 1019264.111 1019311.922 1019495.815 #00ff12 1.0 Logical Dependence Analysis 7 233 +4 6 1019516.941 1019516.941 1019521.801 #ffc0cb 1.0 ProfTask <7> 270 +4 5 1019518.805 1019527.822 1019579.130 #007bff 1.0 Operation Physical Dependence Analysis 8 234 +4 6 1019594.838 1019594.838 1019598.189 #ffc0cb 1.0 ProfTask <8> 271 +4 6 1019608.309 1019628.570 1019699.933 #007bff 1.0 Operation Physical Dependence Analysis 7 17 +4 6 1019789.476 1019827.080 1019950.329 #3dff00 1.0 Task Physical Dependence Analysis 9 19 +4 5 1019924.320 1019974.821 1020060.964 #ff7a00 1.0 Scheduler 0 22 +4 6 1020028.245 1020081.461 1020149.907 #00ff12 1.0 Logical Dependence Analysis 12 26 +4 5 1020132.251 1020169.732 1020198.015 #333399 1.0 Deferred Ready Trigger 14 28 +4 4 1020052.647 1020215.638 1020251.160 #3dff00 1.0 Task Physical Dependence Analysis 11 396 +4 5 1020263.069 1020263.069 1020281.769 #cd00ff 1.0 Defer Task Perform Mapping 15 [[0, 3, 470]] 401 +4 5 1020281.769 1020281.769 1020697.773 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 15 401 +4 5 1020697.773 1020697.773 1020722.173 #cd00ff 0.45 Defer Task Perform Mapping (ready) 15 401 +4 5 1020722.173 1020722.173 1020787.419 #cd00ff 1.0 Defer Task Perform Mapping 15 401 +3 6 1020186.739 1020365.103 1020389.610 #007bff 1.0 Operation Physical Dependence Analysis 14 29 +3 4 1020379.795 1020411.660 1020446.324 #333399 1.0 Deferred Ready Trigger 12 30 +3 6 1020465.390 1020465.390 1020545.104 #00b1ff 1.0 Mapper Continuation 15 [[0, 3, 470]] 398 +3 6 1020545.104 1020545.104 1020588.179 #00b1ff 0.15 Mapper Continuation (waiting) 15 398 +3 6 1020588.179 1020588.179 1020618.504 #00b1ff 0.45 Mapper Continuation (ready) 15 398 +3 6 1020618.504 1020618.504 1020671.314 #00b1ff 1.0 Mapper Continuation 15 398 +2 4 1020471.639 1020471.639 1020652.461 #ff3200 1.0 Mapper Call map_task for 15 15 [[0, 3, 470]] 505 +4 6 1020778.521 1020810.229 1020846.307 #ff0098 1.0 Defer Task Launch 15 [[0, 3, 470]] 32 +4 5 1020830.907 1020864.411 1020913.363 #00ff12 1.0 Logical Dependence Analysis 17 36 +4 6 1020916.574 1020928.632 1020996.549 #ff7a00 1.0 Scheduler 0 39 +4 5 1020933.799 1021015.936 1021048.610 #00ff12 1.0 Logical Dependence Analysis 20 42 +4 4 1020973.416 1021061.000 1021089.194 #007bff 1.0 Operation Physical Dependence Analysis 17 43 +4 6 1021103.473 1021103.473 1021142.700 #ff7a00 1.0 Scheduler 0 543 +4 6 1021142.700 1021142.700 1021199.633 #ff7a00 0.15 Scheduler (waiting) 0 543 +4 6 1021199.633 1021199.633 1021219.821 #ff7a00 0.45 Scheduler (ready) 0 543 +4 6 1021219.821 1021219.821 1021266.724 #ff7a00 1.0 Scheduler 0 543 +3 5 1021138.184 1021159.797 1021181.610 #00b1ff 1.0 Mapper Continuation 0 566 +4 5 1021258.764 1021284.322 1021396.717 #ff7a00 1.0 Scheduler 0 547 +4 6 1021278.556 1021416.548 1021465.556 #3dff00 1.0 Task Physical Dependence Analysis 23 548 +4 4 1021453.870 1021485.938 1021570.371 #ff7a00 1.0 Scheduler 0 235 +4 5 1021585.593 1021585.593 1021662.844 #cd00ff 1.0 Defer Task Perform Mapping 25 [[0, 3, 472]] 238 +4 5 1021662.844 1021662.844 1021677.939 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 25 238 +4 5 1021677.939 1021677.939 1021692.768 #cd00ff 0.45 Defer Task Perform Mapping (ready) 25 238 +4 5 1021692.768 1021692.768 1021776.980 #cd00ff 1.0 Defer Task Perform Mapping 25 238 +3 4 1021593.456 1021593.456 1021724.585 #ff3200 1.0 Mapper Call map_task for 25 25 [[0, 3, 472]] 260 +4 4 1021769.429 1021799.332 1021836.851 #ff0098 1.0 Defer Task Launch 25 [[0, 3, 472]] 240 +4 5 1021856.216 1021856.216 1021922.476 #00b1ff 1.0 Mapper Continuation 29 [[0, 2, 471]] 551 +4 5 1021922.476 1021922.476 1021939.770 #00b1ff 0.15 Mapper Continuation (waiting) 29 551 +4 5 1021939.770 1021939.770 1021956.185 #00b1ff 0.45 Mapper Continuation (ready) 29 551 +4 5 1021956.185 1021956.185 1021994.272 #00b1ff 1.0 Mapper Continuation 29 551 +3 4 1021861.823 1021861.823 1021981.244 #ff3200 1.0 Mapper Call map_task for 29 29 [[0, 2, 471]] 261 +4 4 1021986.768 1022016.171 1022036.573 #00b1ff 1.0 Mapper Continuation 0 319 +4 5 1022028.232 1022059.820 1022077.471 #00b1ff 1.0 Mapper Continuation 24 473 +4 5 1022089.923 1022096.587 1022147.738 #006600 1.0 Post-Task Execution 13 [[0, 2, 469]] 475 +4 4 1022093.137 1022163.230 1022202.817 #333399 1.0 Deferred Ready Trigger 20 477 +4 2 1022102.921 1022220.315 1022257.425 #ff0098 1.0 Defer Task Launch 29 [[0, 2, 471]] 478 +4 2 1022266.613 1022276.351 1022345.941 #ff7a00 1.0 Scheduler 0 480 +4 4 1022231.497 1022359.294 1022392.149 #006600 1.0 Post-Task Execution 15 [[0, 3, 470]] 481 +4 6 1021493.653 1022402.911 1022522.165 #00ff12 1.0 Logical Dependence Analysis 28 484 +4 3 1021560.614 1022536.070 1022572.262 #3dff00 1.0 Task Physical Dependence Analysis 26 486 +4 5 1022172.158 1022586.450 1022614.121 #3dff00 1.0 Task Physical Dependence Analysis 27 487 +4 3 1022601.302 1022625.358 1022681.509 #cd00ff 1.0 Defer Task Perform Mapping 36 [[0, 3, 308]] 489 +4 5 1022674.088 1022694.589 1022721.685 #ff0098 1.0 Defer Task Launch 36 [[0, 3, 308]] 320 +4 1 1022335.879 1022732.564 1022770.283 #3dff00 1.0 Task Physical Dependence Analysis 31 322 +4 5 1022792.567 1022792.567 1022828.127 #ff7a00 1.0 Scheduler 0 331 +4 5 1022828.127 1022828.127 1023024.785 #ff7a00 0.15 Scheduler (waiting) 0 331 +4 5 1023024.785 1023024.785 1023051.263 #ff7a00 0.45 Scheduler (ready) 0 331 +4 5 1023051.263 1023051.263 1023065.156 #ff7a00 1.0 Scheduler 0 331 +4 5 1023065.156 1023065.156 1023193.642 #ff7a00 0.15 Scheduler (waiting) 0 331 +4 5 1023193.642 1023193.642 1023345.970 #ff7a00 0.45 Scheduler (ready) 0 331 +4 5 1023345.970 1023345.970 1023376.256 #ff7a00 1.0 Scheduler 0 331 +3 4 1022406.884 1022853.928 1022898.698 #3dff00 1.0 Task Physical Dependence Analysis 32 323 +3 3 1022915.164 1022915.164 1022928.362 #cd00ff 1.0 Defer Task Perform Mapping 39 [[0, 3, 309]] 241 +3 3 1022928.362 1022928.362 1023188.811 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 39 241 +3 3 1023188.811 1023188.811 1023217.702 #cd00ff 0.45 Defer Task Perform Mapping (ready) 39 241 +3 3 1023217.702 1023217.702 1023297.512 #cd00ff 1.0 Defer Task Perform Mapping 39 241 +2 2 1022483.024 1022953.932 1022971.622 #007bff 1.0 Operation Physical Dependence Analysis 33 324 +2 4 1022966.877 1022987.959 1023010.260 #00b1ff 1.0 Mapper Continuation 0 325 +2 4 1023018.399 1023086.962 1023113.349 #ff0098 1.0 Defer Task Launch 38 [[0, 2, 220]] 327 +2 6 1022533.687 1023128.018 1023140.111 #007bff 1.0 Operation Physical Dependence Analysis 34 328 +2 6 1023152.278 1023152.278 1023157.689 #ffc0cb 1.0 ProfTask <0> 569 +2 4 1023155.463 1023163.973 1023180.849 #00b1ff 1.0 Mapper Continuation 0 330 +4 6 1023398.373 1023398.373 1023403.459 #ffc0cb 1.0 ProfTask <0> 272 +4 6 1023415.606 1023435.265 1023524.215 #ff7a00 1.0 Scheduler 0 334 +4 5 1023510.174 1023544.753 1023593.726 #3dff00 1.0 Task Physical Dependence Analysis 40 336 +4 6 1023575.485 1023608.446 1023665.627 #cd00ff 1.0 Defer Task Perform Mapping 42 [[0, 2, 221]] 492 +4 5 1023652.822 1023685.236 1023718.305 #ff0098 1.0 Defer Task Launch 42 [[0, 2, 221]] 494 +4 4 1023664.096 1023741.592 1023765.560 #ff0098 1.0 Defer Task Launch 43 [[0, 3, 389]] 496 +4 6 1023709.363 1023777.870 1023810.031 #007bff 1.0 Operation Physical Dependence Analysis 28 498 +4 6 1023824.143 1023824.143 1023831.242 #ffc0cb 1.0 ProfTask <25> 273 +4 6 1023837.657 1023837.657 1023842.050 #ffc0cb 1.0 ProfTask <22> 274 +4 6 1023848.474 1023848.474 1023855.887 #ffc0cb 1.0 ProfTask <25> 275 +4 6 1023864.845 1023864.845 1023869.083 #ffc0cb 1.0 ProfTask <0> 276 +4 6 1023874.606 1023874.606 1023879.071 #ffc0cb 1.0 ProfTask <25> 277 +4 5 1023876.726 1023885.288 1023978.079 #3dff00 1.0 Task Physical Dependence Analysis 44 501 +4 6 1023971.542 1024023.781 1024067.567 #3dff00 1.0 Task Physical Dependence Analysis 45 503 +4 5 1024040.964 1024083.242 1024112.260 #3dff00 1.0 Task Physical Dependence Analysis 46 504 +4 6 1024125.702 1024125.702 1024142.386 #cd00ff 1.0 Defer Task Perform Mapping 48 [[0, 3, 573]] 337 +4 6 1024142.386 1024142.386 1024577.294 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 48 337 +4 6 1024577.294 1024577.294 1024604.599 #cd00ff 0.45 Defer Task Perform Mapping (ready) 48 337 +4 6 1024604.599 1024604.599 1024710.027 #cd00ff 1.0 Defer Task Perform Mapping 48 337 +3 5 1024176.449 1024176.449 1024187.245 #ffc0cb 1.0 ProfTask <13> 506 +3 4 1024197.413 1024197.413 1024204.799 #ffc0cb 1.0 ProfTask <24> 507 +3 5 1024197.316 1024214.037 1024298.425 #006600 1.0 Post-Task Execution 35 [[0, 2, 219]] 243 +3 5 1024316.465 1024316.465 1024327.960 #ffc0cb 1.0 ProfTask <29> 508 +3 5 1024336.179 1024336.179 1024341.424 #ffc0cb 1.0 ProfTask <13> 509 +3 5 1024350.467 1024350.467 1024359.821 #ffc0cb 1.0 ProfTask <0> 510 +3 5 1024367.407 1024367.407 1024372.548 #ffc0cb 1.0 ProfTask <20> 511 +3 5 1024380.168 1024380.168 1024385.425 #ffc0cb 1.0 ProfTask <15> 512 +3 5 1024393.264 1024393.264 1024397.528 #ffc0cb 1.0 ProfTask <29> 513 +3 5 1024403.247 1024403.247 1024409.951 #ffc0cb 1.0 ProfTask <24> 514 +3 5 1024415.079 1024415.079 1024418.409 #ffc0cb 1.0 ProfTask <0> 515 +3 5 1024422.747 1024422.747 1024425.896 #ffc0cb 1.0 ProfTask <15> 516 +3 5 1024430.164 1024430.164 1024433.324 #ffc0cb 1.0 ProfTask <0> 517 +3 5 1024437.680 1024437.680 1024440.818 #ffc0cb 1.0 ProfTask <33> 518 +3 5 1024445.675 1024445.675 1024450.251 #ffc0cb 1.0 ProfTask <28> 519 +3 5 1024457.169 1024457.169 1024462.152 #ffc0cb 1.0 ProfTask <34> 520 +3 5 1024468.852 1024468.852 1024473.600 #ffc0cb 1.0 ProfTask <26> 521 +3 5 1024481.925 1024481.925 1024488.279 #ffc0cb 1.0 ProfTask <27> 522 +3 4 1024486.316 1024497.214 1024532.506 #ff0098 1.0 Defer Task Launch 47 [[0, 2, 3]] 245 +3 5 1024551.826 1024551.826 1024557.310 #ffc0cb 1.0 ProfTask <35> 523 +3 5 1024564.753 1024564.753 1024569.824 #ffc0cb 1.0 ProfTask <36> 524 +3 5 1024577.086 1024577.086 1024582.272 #ffc0cb 1.0 ProfTask <35> 525 +4 5 1024697.301 1024736.750 1024779.744 #ff0098 1.0 Defer Task Launch 48 [[0, 3, 573]] 250 +4 6 1024804.740 1024804.740 1024816.493 #ffc0cb 1.0 ProfTask <39> 278 +4 6 1024826.612 1024826.612 1024833.728 #ffc0cb 1.0 ProfTask <39> 279 +4 5 1024827.055 1024843.783 1024934.671 #3dff00 1.0 Task Physical Dependence Analysis 49 251 +4 6 1024914.668 1024959.693 1025062.406 #ff7a00 1.0 Scheduler 0 339 +4 5 1025046.686 1025084.356 1025136.235 #3dff00 1.0 Task Physical Dependence Analysis 51 254 +4 6 1025163.800 1025163.800 1025193.188 #cd00ff 1.0 Defer Task Perform Mapping 53 [[0, 3, 390]] 340 +4 6 1025193.188 1025193.188 1025405.718 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 53 340 +4 6 1025405.718 1025405.718 1025425.162 #cd00ff 0.45 Defer Task Perform Mapping (ready) 53 340 +4 6 1025425.162 1025425.162 1025483.181 #cd00ff 1.0 Defer Task Perform Mapping 53 340 +3 5 1025214.680 1025214.680 1025220.882 #ffc0cb 1.0 ProfTask <41> 526 +3 5 1025229.189 1025229.189 1025233.988 #ffc0cb 1.0 ProfTask <42> 527 +3 5 1025241.497 1025241.497 1025247.221 #ffc0cb 1.0 ProfTask <43> 528 +3 5 1025257.689 1025257.689 1025263.857 #ffc0cb 1.0 ProfTask <29> 529 +3 5 1025270.770 1025270.770 1025275.650 #ffc0cb 1.0 ProfTask <25> 530 +3 5 1025283.515 1025283.515 1025288.725 #ffc0cb 1.0 ProfTask <42> 531 +3 5 1025296.185 1025296.185 1025301.041 #ffc0cb 1.0 ProfTask <28> 532 +3 5 1025308.726 1025308.726 1025315.060 #ffc0cb 1.0 ProfTask <43> 533 +3 5 1025322.404 1025322.404 1025328.213 #ffc0cb 1.0 ProfTask <25> 534 +3 5 1025336.959 1025336.959 1025342.196 #ffc0cb 1.0 ProfTask <28> 535 +3 5 1025359.303 1025359.303 1025364.244 #ffc0cb 1.0 ProfTask <0> 536 +3 5 1025370.767 1025370.767 1025375.170 #ffc0cb 1.0 ProfTask <0> 537 +3 5 1025381.120 1025381.120 1025385.474 #ffc0cb 1.0 ProfTask <44> 538 +3 5 1025391.182 1025391.182 1025394.660 #ffc0cb 1.0 ProfTask <0> 539 +3 5 1025399.314 1025399.314 1025402.789 #ffc0cb 1.0 ProfTask <45> 540 +3 5 1025408.650 1025408.650 1025411.987 #ffc0cb 1.0 ProfTask <46> 541 +4 5 1025475.654 1025498.175 1025527.688 #ff0098 1.0 Defer Task Launch 53 [[0, 3, 390]] 258 +4 5 1025543.882 1025543.882 1025548.382 #ffc0cb 1.0 ProfTask <47> 280 +4 6 1025540.699 1025558.764 1025602.869 #006600 1.0 Post-Task Execution 39 [[0, 3, 309]] 341 +4 6 1025614.838 1025614.838 1025619.617 #ffc0cb 1.0 ProfTask <35> 281 +4 6 1025625.266 1025625.266 1025628.726 #ffc0cb 1.0 ProfTask <35> 282 +4 6 1025633.859 1025633.859 1025642.194 #ffc0cb 1.0 ProfTask <47> 283 +4 6 1025647.842 1025647.842 1025652.082 #ffc0cb 1.0 ProfTask <47> 284 +4 6 1025656.285 1025656.285 1025662.911 #ffc0cb 1.0 ProfTask <48> 285 +4 6 1025668.053 1025668.053 1025672.011 #ffc0cb 1.0 ProfTask <30> 286 +4 6 1025677.535 1025677.535 1025681.288 #ffc0cb 1.0 ProfTask <30> 287 +4 6 1025685.439 1025685.439 1025689.447 #ffc0cb 1.0 ProfTask <48> 288 +4 6 1025695.077 1025695.077 1025699.308 #ffc0cb 1.0 ProfTask <49> 289 +4 6 1025704.517 1025704.517 1025708.414 #ffc0cb 1.0 ProfTask <0> 290 +4 6 1025714.241 1025714.241 1025718.680 #ffc0cb 1.0 ProfTask <50> 291 +4 6 1025724.009 1025724.009 1025728.305 #ffc0cb 1.0 ProfTask <52> 292 +4 6 1025733.660 1025733.660 1025737.322 #ffc0cb 1.0 ProfTask <51> 293 +4 6 1025743.220 1025743.220 1025749.866 #ffc0cb 1.0 ProfTask <52> 294 +4 6 1025755.473 1025755.473 1025761.694 #ffc0cb 1.0 ProfTask <53> 295 +4 6 1025766.641 1025766.641 1025773.447 #ffc0cb 1.0 ProfTask <52> 296 +4 6 1025779.732 1025779.732 1025784.983 #ffc0cb 1.0 ProfTask <38> 297 +4 6 1025793.659 1025793.659 1025799.588 #ffc0cb 1.0 ProfTask <53> 298 +4 6 1025805.808 1025805.808 1025811.421 #ffc0cb 1.0 ProfTask <52> 299 +4 6 1025817.749 1025817.749 1025826.110 #ffc0cb 1.0 ProfTask <42> 300 +4 6 1027287.711 1027308.633 1027395.869 #006600 1.0 Post-Task Execution 47 [[0, 2, 3]] 567 +4 6 1027416.270 1027416.270 1027421.057 #ffc0cb 1.0 ProfTask <47> 570 +4 6 1028703.178 1028703.178 1028712.514 #ffc0cb 1.0 ProfTask <52> 571 +4 6 1028818.229 1028818.229 1028823.793 #ffc0cb 1.0 ProfTask <52> 572 +4 6 1042928.225 1042970.205 1043065.662 #00ff12 1.0 Logical Dependence Analysis 54 49 +4 6 1043102.875 1043117.747 1043158.329 #007bff 1.0 Operation Physical Dependence Analysis 54 404 +4 6 1043253.807 1043292.115 1043357.314 #3dff00 1.0 Task Physical Dependence Analysis 55 52 +4 5 1043345.875 1043380.714 1043456.611 #ff7a00 1.0 Scheduler 0 405 +4 6 1043447.447 1043480.043 1043527.246 #3dff00 1.0 Task Physical Dependence Analysis 57 407 +4 5 1043543.456 1043543.456 1043569.949 #cd00ff 1.0 Defer Task Perform Mapping 59 [[0, 3, 393]] 409 +4 5 1043569.949 1043569.949 1043777.305 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 59 409 +4 5 1043777.305 1043777.305 1043798.301 #cd00ff 0.45 Defer Task Perform Mapping (ready) 59 409 +4 5 1043798.301 1043798.301 1043856.144 #cd00ff 1.0 Defer Task Perform Mapping 59 409 +3 6 1043608.194 1043608.194 1043660.704 #00b1ff 1.0 Mapper Continuation 59 [[0, 3, 393]] 57 +3 6 1043660.704 1043660.704 1043708.485 #00b1ff 0.15 Mapper Continuation (waiting) 59 57 +3 6 1043708.485 1043708.485 1043734.260 #00b1ff 0.45 Mapper Continuation (ready) 59 57 +3 6 1043734.260 1043734.260 1043755.669 #00b1ff 1.0 Mapper Continuation 59 57 +2 4 1043613.020 1043613.020 1043738.538 #ff3200 1.0 Mapper Call map_task for 59 59 [[0, 3, 393]] 610 +1 3 1043692.331 1043692.331 1043723.512 #00ff12 1.0 Logical Dependence Analysis 60 575 +1 3 1043723.512 1043723.512 1043836.856 #00ff12 0.15 Logical Dependence Analysis (waiting) 60 575 +1 3 1043836.856 1043836.856 1043895.364 #00ff12 0.45 Logical Dependence Analysis (ready) 60 575 +1 3 1043895.364 1043895.364 1043944.189 #00ff12 1.0 Logical Dependence Analysis 60 575 +4 6 1043959.063 1043975.777 1044064.430 #007bff 1.0 Operation Physical Dependence Analysis 60 633 +4 6 1044089.069 1044089.069 1044098.310 #ffc0cb 1.0 ProfTask <60> 634 +4 6 1044209.907 1044226.872 1044329.824 #3dff00 1.0 Task Physical Dependence Analysis 61 588 +4 5 1044305.651 1044354.406 1044445.597 #ff7a00 1.0 Scheduler 0 590 +4 5 1044452.596 1044466.872 1044587.570 #cd00ff 1.0 Defer Task Perform Mapping 65 [[0, 2, 636]] 593 +4 6 1044433.035 1044610.308 1044661.375 #3dff00 1.0 Task Physical Dependence Analysis 63 63 +4 6 1044681.828 1044681.828 1044694.814 #ffc0cb 1.0 ProfTask <61> 611 +4 6 1044708.340 1044708.340 1044713.469 #ffc0cb 1.0 ProfTask <0> 612 +4 6 1044720.801 1044720.801 1044725.565 #ffc0cb 1.0 ProfTask <0> 613 +4 6 1044733.154 1044733.154 1044739.424 #ffc0cb 1.0 ProfTask <62> 614 +4 6 1044748.470 1044748.470 1044753.463 #ffc0cb 1.0 ProfTask <64> 615 +4 5 1044761.516 1044761.516 1044767.193 #ffc0cb 1.0 ProfTask <65> 616 +4 6 1044756.504 1044780.080 1044825.226 #333399 1.0 Deferred Ready Trigger 64 413 +4 4 1044765.339 1044846.453 1044900.995 #ff0098 1.0 Defer Task Launch 66 [[0, 3, 587]] 595 +4 6 1044917.922 1044917.922 1044921.456 #ffc0cb 1.0 ProfTask <58> 617 +4 6 1044926.303 1044926.303 1044929.620 #ffc0cb 1.0 ProfTask <66> 618 +4 6 1044941.139 1044956.768 1045043.456 #ff7a00 1.0 Scheduler 0 596 +4 6 1045063.383 1045063.383 1045069.759 #ffc0cb 1.0 ProfTask <0> 619 +4 6 1045111.054 1045129.604 1045222.693 #ff7a00 1.0 Scheduler 0 599 +4 5 1045208.449 1045244.778 1045307.601 #3dff00 1.0 Task Physical Dependence Analysis 68 66 +4 6 1045278.958 1045327.219 1045373.960 #3dff00 1.0 Task Physical Dependence Analysis 69 639 +4 5 1045353.422 1045394.111 1045506.945 #cd00ff 1.0 Defer Task Perform Mapping 72 [[0, 3, 672]] 416 +4 6 1045493.944 1045530.483 1045572.715 #ff0098 1.0 Defer Task Launch 72 [[0, 3, 672]] 640 +4 6 1045590.083 1045590.083 1045596.571 #ffc0cb 1.0 ProfTask <67> 620 +4 6 1045606.996 1045606.996 1045613.389 #ffc0cb 1.0 ProfTask <0> 621 +4 5 1045609.591 1045623.192 1045675.044 #333399 1.0 Deferred Ready Trigger 70 642 +4 6 1045660.379 1045696.208 1045738.104 #007bff 1.0 Operation Physical Dependence Analysis 70 601 +4 5 1045736.249 1045762.330 1045816.314 #006600 1.0 Post-Task Execution 66 [[0, 3, 587]] 602 +4 6 1045829.832 1045829.832 1045834.051 #ffc0cb 1.0 ProfTask <71> 622 +4 5 1045830.765 1045840.224 1045917.954 #3dff00 1.0 Task Physical Dependence Analysis 73 604 +4 6 1045933.357 1045933.357 1045982.091 #ff7a00 1.0 Scheduler 0 645 +4 6 1045982.091 1045982.091 1046059.946 #ff7a00 0.15 Scheduler (waiting) 0 645 +4 6 1046059.946 1046059.946 1046171.137 #ff7a00 0.45 Scheduler (ready) 0 645 +4 6 1046171.137 1046171.137 1046202.563 #ff7a00 1.0 Scheduler 0 645 +3 5 1045987.208 1046056.676 1046135.932 #3dff00 1.0 Task Physical Dependence Analysis 74 606 +4 5 1046194.419 1046217.381 1046253.709 #3dff00 1.0 Task Physical Dependence Analysis 75 607 +4 6 1046236.282 1046267.074 1046346.238 #cd00ff 1.0 Defer Task Perform Mapping 77 [[0, 3, 394]] 68 +4 6 1046361.479 1046361.479 1046366.368 #ffc0cb 1.0 ProfTask <66> 623 +4 6 1046371.169 1046371.169 1046376.461 #ffc0cb 1.0 ProfTask <70> 624 +4 6 1046382.603 1046382.603 1046386.495 #ffc0cb 1.0 ProfTask <66> 625 +4 6 1046392.676 1046392.676 1046397.357 #ffc0cb 1.0 ProfTask <0> 626 +4 6 1046403.160 1046403.160 1046406.375 #ffc0cb 1.0 ProfTask <73> 627 +4 6 1046413.126 1046413.126 1046417.530 #ffc0cb 1.0 ProfTask <0> 628 +4 6 1046424.509 1046424.509 1046430.009 #ffc0cb 1.0 ProfTask <74> 629 +4 6 1046436.284 1046436.284 1046440.982 #ffc0cb 1.0 ProfTask <75> 630 +4 6 1046446.383 1046446.383 1046451.457 #ffc0cb 1.0 ProfTask <76> 631 +4 5 1046446.973 1046460.896 1046505.755 #006600 1.0 Post-Task Execution 71 [[0, 2, 5]] 609 +4 6 1046529.968 1046529.968 1046535.783 #ffc0cb 1.0 ProfTask <71> 632 +4 6 1046561.498 1046561.498 1046574.575 #ffc0cb 1.0 ProfTask <72> 677 +4 6 1046612.262 1046629.117 1046686.301 #009900 1.0 Deferred Commit 64 673 +4 6 1046714.430 1046714.430 1046731.836 #ffc0cb 1.0 ProfTask <64> 678 +4 5 1046716.432 1046745.147 1046777.346 #333399 1.0 Deferred Ready Trigger 78 674 +4 6 1046792.290 1046792.290 1046796.714 #ffc0cb 1.0 ProfTask <78> 679 +4 6 1046836.830 1046858.968 1046953.784 #ff7a00 1.0 Scheduler 0 675 +4 6 1046968.448 1046968.448 1046972.915 #ffc0cb 1.0 ProfTask <0> 680 +4 6 1047020.284 1047041.315 1047168.964 #ff7a00 1.0 Scheduler 0 71 +4 5 1047150.882 1047197.484 1047296.481 #3dff00 1.0 Task Physical Dependence Analysis 80 75 +4 6 1047249.015 1047326.874 1047384.780 #006600 1.0 Post-Task Execution 76 [[0, 2, 7]] 78 +4 5 1047302.855 1047402.395 1047465.051 #00ff12 1.0 Logical Dependence Analysis 83 418 +4 6 1047419.961 1047478.032 1047513.167 #006600 1.0 Post-Task Execution 77 [[0, 3, 394]] 419 +4 6 1047523.890 1047531.411 1047600.351 #cd00ff 1.0 Defer Task Perform Mapping 85 [[0, 3, 682]] 423 +4 5 1047592.783 1047617.954 1047652.121 #ff0098 1.0 Defer Task Launch 85 [[0, 3, 682]] 651 +4 6 1047667.464 1047667.464 1047892.303 #007bff 1.0 Operation Physical Dependence Analysis 84 81 +4 6 1047892.303 1047892.303 1048064.832 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 84 81 +4 6 1048064.832 1048064.832 1048135.725 #007bff 0.45 Operation Physical Dependence Analysis (ready) 84 81 +4 6 1048135.725 1048135.725 1048208.721 #007bff 1.0 Operation Physical Dependence Analysis 84 81 +3 5 1047984.153 1048028.782 1048046.924 #ff00c5 1.0 Tighten Index Space 84 683 +4 6 1048240.244 1048240.244 1048371.600 #007bff 1.0 Operation Physical Dependence Analysis 83 86 +4 6 1048371.600 1048371.600 1048388.500 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 83 86 +4 6 1048388.500 1048388.500 1048411.149 #007bff 0.45 Operation Physical Dependence Analysis (ready) 83 86 +4 6 1048411.149 1048411.149 1048584.206 #007bff 1.0 Operation Physical Dependence Analysis 83 86 +4 6 1048584.206 1048584.206 1048783.844 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 83 86 +4 6 1048783.844 1048783.844 1048841.090 #007bff 0.45 Operation Physical Dependence Analysis (ready) 83 86 +4 6 1048841.090 1048841.090 1048904.134 #007bff 1.0 Operation Physical Dependence Analysis 83 86 +3 5 1048253.631 1048253.631 1048443.184 #ff5f00 1.0 Mapper Call map_inline for 83 83 676 +4 6 1050297.761 1050297.761 1050315.697 #ffc0cb 1.0 ProfTask <83> 703 +4 6 1144625.320 1144670.598 1144703.476 #009900 1.0 Deferred Commit 83 685 +4 6 1144860.898 1144879.567 1144915.226 #00ff12 1.0 Logical Dependence Analysis 86 699 +4 5 1144902.125 1144943.824 1144961.684 #333399 1.0 Deferred Ready Trigger 86 700 +4 6 1144954.368 1144974.220 1144991.831 #007bff 1.0 Operation Physical Dependence Analysis 86 701 +4 6 1145003.814 1145003.814 1145008.939 #ffc0cb 1.0 ProfTask <86> 704 +4 6 1145013.909 1145013.909 1145017.309 #ffc0cb 1.0 ProfTask <86> 705 +4 6 1145021.935 1145021.935 1145025.293 #ffc0cb 1.0 ProfTask <86> 706 +4 6 1183406.282 1183447.115 1183556.775 #00ff12 1.0 Logical Dependence Analysis 89 425 +4 5 1183528.104 1183584.044 1183632.883 #007bff 1.0 Operation Physical Dependence Analysis 89 90 +4 6 1183652.384 1183682.119 1184688.358 #007bff 1.0 Operation Physical Dependence Analysis 87 428 +4 5 1184569.758 1184721.421 1184764.287 #009900 1.0 Garbage Collection 87 104 +4 6 1184770.795 1184788.784 1184810.844 #ff8c00 1.0 Top Finish 0 106 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000001.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000001.tsv new file mode 100644 index 000000000..e021bb2f9 --- /dev/null +++ b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000001.tsv @@ -0,0 +1,266 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +5 5 478172.693 478215.611 478293.256 #ff7a00 1.0 Scheduler 0 310 +5 5 478322.038 478322.038 478327.141 #ffc0cb 1.0 ProfTask <0> 347 +5 5 478343.946 478397.534 478455.013 #ff7a00 1.0 Scheduler 0 311 +5 5 478487.003 478487.003 478491.783 #ffc0cb 1.0 ProfTask <0> 348 +5 5 478651.813 478651.813 478657.222 #ffc0cb 1.0 ProfTask <1> 349 +5 5 922233.314 922271.051 922313.422 #333399 1.0 Deferred Ready Trigger 3 313 +5 5 922352.823 922352.823 922360.236 #ffc0cb 1.0 ProfTask <3> 350 +5 5 922485.054 922485.054 922500.295 #ffc0cb 1.0 ProfTask <3> 351 +5 5 922630.835 922685.337 922723.942 #333399 1.0 Deferred Ready Trigger 4 315 +5 5 922752.172 922752.172 922757.292 #ffc0cb 1.0 ProfTask <4> 352 +5 5 962545.217 962606.098 962647.123 #333399 1.0 Deferred Ready Trigger 5 10 +5 5 962756.169 962756.169 962760.737 #ffc0cb 1.0 ProfTask <5> 353 +5 5 999327.424 999365.982 999398.360 #333399 1.0 Deferred Ready Trigger 6 12 +5 5 999472.194 999507.767 999529.853 #ff00c5 1.0 Tighten Index Space 6 395 +5 5 1019457.047 1019495.678 1019531.556 #333399 1.0 Deferred Ready Trigger 8 15 +5 5 1019557.401 1019576.947 1019620.039 #333399 1.0 Deferred Ready Trigger 7 317 +5 5 1019636.957 1019636.957 1019640.979 #ffc0cb 1.0 ProfTask <7> 354 +5 5 1019678.408 1019714.252 1019811.952 #ff7a00 1.0 Scheduler 0 318 +5 5 1019830.493 1019830.493 1019834.164 #ffc0cb 1.0 ProfTask <0> 355 +5 5 1019897.852 1019933.635 1020004.219 #ff7a00 1.0 Scheduler 0 21 +5 4 1019992.992 1020027.498 1020099.613 #3dff00 1.0 Task Physical Dependence Analysis 10 24 +5 5 1020115.715 1020115.715 1020307.025 #cd00ff 1.0 Defer Task Perform Mapping 13 [[0, 2, 469]] 397 +5 5 1020307.025 1020307.025 1020352.321 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 13 397 +5 5 1020352.321 1020352.321 1020384.622 #cd00ff 0.45 Defer Task Perform Mapping (ready) 13 397 +5 5 1020384.622 1020384.622 1020580.691 #cd00ff 1.0 Defer Task Perform Mapping 13 397 +4 4 1020128.964 1020128.964 1020436.997 #ff3200 1.0 Mapper Call map_task for 13 13 [[0, 2, 469]] 345 +5 3 1020602.314 1020602.314 1020623.469 #00ff12 1.0 Logical Dependence Analysis 16 402 +5 3 1020623.469 1020623.469 1020734.315 #00ff12 0.15 Logical Dependence Analysis (waiting) 16 402 +5 3 1020734.315 1020734.315 1020750.432 #00ff12 0.45 Logical Dependence Analysis (ready) 16 402 +5 3 1020750.432 1020750.432 1020808.922 #00ff12 1.0 Logical Dependence Analysis 16 402 +4 2 1020573.676 1020634.362 1020676.289 #ff0098 1.0 Defer Task Launch 13 [[0, 2, 469]] 399 +4 5 1020660.088 1020691.218 1020713.369 #00b1ff 1.0 Mapper Continuation 16 400 +5 5 1020789.298 1020839.392 1020874.211 #333399 1.0 Deferred Ready Trigger 18 34 +5 4 1020437.396 1020894.975 1020930.984 #007bff 1.0 Operation Physical Dependence Analysis 12 37 +5 5 1020903.439 1020952.149 1020985.345 #333399 1.0 Deferred Ready Trigger 17 38 +5 3 1020861.093 1021013.914 1021039.622 #007bff 1.0 Operation Physical Dependence Analysis 18 40 +5 4 1021026.234 1021058.657 1021095.392 #333399 1.0 Deferred Ready Trigger 16 45 +5 5 1020987.324 1021113.857 1021175.820 #3dff00 1.0 Task Physical Dependence Analysis 19 47 +5 4 1021158.455 1021196.702 1021292.380 #ff7a00 1.0 Scheduler 0 544 +5 3 1021081.721 1021312.878 1021325.094 #007bff 1.0 Operation Physical Dependence Analysis 16 545 +5 5 1021339.701 1021339.701 1021358.196 #3dff00 1.0 Task Physical Dependence Analysis 21 549 +5 5 1021358.196 1021358.196 1021411.587 #3dff00 0.15 Task Physical Dependence Analysis (waiting) 21 549 +5 5 1021411.587 1021411.587 1021427.029 #3dff00 0.45 Task Physical Dependence Analysis (ready) 21 549 +5 5 1021427.029 1021427.029 1021477.105 #3dff00 1.0 Task Physical Dependence Analysis 21 549 +4 4 1021352.856 1021375.545 1021396.820 #00b1ff 1.0 Mapper Continuation 21 546 +5 4 1021492.376 1021492.376 1021517.858 #ff7a00 1.0 Scheduler 0 476 +5 4 1021517.858 1021517.858 1021580.405 #ff7a00 0.15 Scheduler (waiting) 0 476 +5 4 1021580.405 1021580.405 1021598.522 #ff7a00 0.45 Scheduler (ready) 0 476 +5 4 1021598.522 1021598.522 1021633.743 #ff7a00 1.0 Scheduler 0 476 +5 4 1021633.743 1021633.743 1021852.513 #ff7a00 0.15 Scheduler (waiting) 0 476 +5 4 1021852.513 1021852.513 1021869.553 #ff7a00 0.45 Scheduler (ready) 0 476 +5 4 1021869.553 1021869.553 1021890.510 #ff7a00 1.0 Scheduler 0 476 +5 4 1021890.510 1021890.510 1022054.060 #ff7a00 0.15 Scheduler (waiting) 0 476 +5 4 1022054.060 1022054.060 1022149.566 #ff7a00 0.45 Scheduler (ready) 0 476 +5 4 1022149.566 1022149.566 1022191.124 #ff7a00 1.0 Scheduler 0 476 +4 5 1021519.896 1021535.050 1021563.059 #00b1ff 1.0 Mapper Continuation 0 550 +4 3 1021361.126 1021650.015 1021708.350 #3dff00 1.0 Task Physical Dependence Analysis 22 237 +4 5 1021729.660 1021729.660 1021748.943 #cd00ff 1.0 Defer Task Perform Mapping 29 [[0, 2, 471]] 474 +4 5 1021748.943 1021748.943 1022010.605 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 29 474 +4 5 1022010.605 1022010.605 1022033.123 #cd00ff 0.45 Defer Task Perform Mapping (ready) 29 474 +4 5 1022033.123 1022033.123 1022115.674 #cd00ff 1.0 Defer Task Perform Mapping 29 474 +3 3 1021729.839 1021800.527 1021831.515 #00b1ff 1.0 Mapper Continuation 0 239 +3 2 1021906.979 1021906.979 1021935.187 #3dff00 1.0 Task Physical Dependence Analysis 24 479 +3 2 1021935.187 1021935.187 1022091.376 #3dff00 0.15 Task Physical Dependence Analysis (waiting) 24 479 +3 2 1022091.376 1022091.376 1022226.791 #3dff00 0.45 Task Physical Dependence Analysis (ready) 24 479 +3 2 1022226.791 1022226.791 1022306.819 #3dff00 1.0 Task Physical Dependence Analysis 24 479 +5 4 1022285.594 1022330.425 1022420.902 #ff7a00 1.0 Scheduler 0 482 +5 4 1022452.838 1022466.782 1022494.632 #333399 1.0 Deferred Ready Trigger 33 483 +5 4 1022500.553 1022519.257 1022545.038 #333399 1.0 Deferred Ready Trigger 34 485 +5 4 1022553.538 1022565.474 1022643.447 #cd00ff 1.0 Defer Task Perform Mapping 35 [[0, 2, 219]] 488 +5 3 1022631.033 1022672.695 1022708.855 #ff0098 1.0 Defer Task Launch 35 [[0, 2, 219]] 490 +5 5 1022190.077 1022729.096 1022761.644 #007bff 1.0 Operation Physical Dependence Analysis 20 321 +5 4 1022795.202 1022795.202 1022883.517 #cd00ff 1.0 Defer Task Perform Mapping 38 [[0, 2, 220]] 326 +5 4 1022883.517 1022883.517 1022901.333 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 38 326 +5 4 1022901.333 1022901.333 1022920.608 #cd00ff 0.45 Defer Task Perform Mapping (ready) 38 326 +5 4 1022920.608 1022920.608 1023030.646 #cd00ff 1.0 Defer Task Perform Mapping 38 326 +4 5 1022804.277 1022804.277 1022960.652 #ff3200 1.0 Mapper Call map_task for 38 38 [[0, 2, 220]] 552 +5 5 1023003.439 1023050.877 1023168.055 #00b1ff 1.0 Mapper Continuation 39 [[0, 3, 309]] 329 +5 5 1023197.049 1023197.049 1023208.594 #ffc0cb 1.0 ProfTask <0> 555 +5 5 1023219.200 1023219.200 1023224.712 #ffc0cb 1.0 ProfTask <0> 556 +5 5 1023231.705 1023231.705 1023236.361 #ffc0cb 1.0 ProfTask <16> 557 +5 5 1023243.711 1023243.711 1023248.462 #ffc0cb 1.0 ProfTask <21> 558 +5 5 1023255.017 1023255.017 1023259.870 #ffc0cb 1.0 ProfTask <0> 559 +5 5 1023266.635 1023266.635 1023271.371 #ffc0cb 1.0 ProfTask <23> 560 +5 5 1023278.427 1023278.427 1023287.444 #ffc0cb 1.0 ProfTask <21> 561 +5 4 1023283.147 1023296.822 1023334.341 #ff0098 1.0 Defer Task Launch 39 [[0, 3, 309]] 242 +5 5 1023357.571 1023357.571 1023364.867 #ffc0cb 1.0 ProfTask <0> 562 +5 4 1023364.341 1023374.111 1023447.377 #3dff00 1.0 Task Physical Dependence Analysis 37 333 +5 5 1023430.096 1023468.882 1023551.388 #ff7a00 1.0 Scheduler 0 335 +5 4 1023539.745 1023567.314 1023606.937 #3dff00 1.0 Task Physical Dependence Analysis 41 491 +5 5 1023588.530 1023620.187 1023676.616 #cd00ff 1.0 Defer Task Perform Mapping 43 [[0, 3, 389]] 493 +5 4 1023656.170 1023692.044 1023726.876 #333399 1.0 Deferred Ready Trigger 28 495 +5 5 1023699.394 1023746.877 1023800.215 #006600 1.0 Post-Task Execution 25 [[0, 3, 472]] 497 +5 5 1023801.370 1023813.667 1023886.789 #ff7a00 1.0 Scheduler 0 499 +5 5 1023900.795 1023900.795 1023904.789 #ffc0cb 1.0 ProfTask <29> 563 +5 5 1023911.051 1023911.051 1023919.322 #ffc0cb 1.0 ProfTask <29> 564 +5 4 1023916.347 1023924.498 1023982.068 #ff7a00 1.0 Scheduler 0 500 +5 5 1023952.187 1023994.093 1024050.003 #ff7a00 1.0 Scheduler 0 502 +5 4 1024066.601 1024066.601 1024150.109 #cd00ff 1.0 Defer Task Perform Mapping 47 [[0, 2, 3]] 244 +5 4 1024150.109 1024150.109 1024163.098 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 47 244 +5 4 1024163.098 1024163.098 1024201.405 #cd00ff 0.45 Defer Task Perform Mapping (ready) 47 244 +5 4 1024201.405 1024201.405 1024250.833 #cd00ff 1.0 Defer Task Perform Mapping 47 244 +5 4 1024250.833 1024250.833 1024366.581 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 47 244 +5 4 1024366.581 1024366.581 1024393.117 #cd00ff 0.45 Defer Task Perform Mapping (ready) 47 244 +5 4 1024393.117 1024393.117 1024495.054 #cd00ff 1.0 Defer Task Perform Mapping 47 244 +4 5 1024073.354 1024073.354 1024401.185 #ff3200 1.0 Mapper Call map_task for 47 47 [[0, 2, 3]] 553 +3 3 1024168.921 1024168.921 1024174.931 #ffc0cb 1.0 ProfTask <0> 356 +3 3 1024279.064 1024279.064 1024375.510 #00b1ff 1.0 Mapper Continuation 48 [[0, 3, 573]] 246 +3 3 1024375.510 1024375.510 1024408.679 #00b1ff 0.15 Mapper Continuation (waiting) 48 246 +3 3 1024408.679 1024408.679 1024522.111 #00b1ff 0.45 Mapper Continuation (ready) 48 246 +3 3 1024522.111 1024522.111 1024557.161 #00b1ff 1.0 Mapper Continuation 48 246 +2 2 1024285.192 1024285.192 1024543.162 #ff3200 1.0 Mapper Call map_task for 48 48 [[0, 3, 573]] 346 +5 5 1024585.057 1024585.057 1024590.350 #ffc0cb 1.0 ProfTask <36> 357 +5 5 1024597.545 1024597.545 1024601.896 #ffc0cb 1.0 ProfTask <20> 358 +5 5 1024607.410 1024607.410 1024610.839 #ffc0cb 1.0 ProfTask <31> 359 +5 5 1024615.132 1024615.132 1024619.071 #ffc0cb 1.0 ProfTask <38> 360 +5 5 1024623.671 1024623.671 1024626.791 #ffc0cb 1.0 ProfTask <32> 361 +5 5 1024631.171 1024631.171 1024634.661 #ffc0cb 1.0 ProfTask <33> 362 +5 5 1024639.219 1024639.219 1024642.520 #ffc0cb 1.0 ProfTask <0> 363 +5 5 1024647.137 1024647.137 1024653.786 #ffc0cb 1.0 ProfTask <38> 364 +5 5 1024658.361 1024658.361 1024661.720 #ffc0cb 1.0 ProfTask <39> 365 +5 5 1024666.000 1024666.000 1024669.305 #ffc0cb 1.0 ProfTask <38> 366 +5 5 1024674.022 1024674.022 1024677.281 #ffc0cb 1.0 ProfTask <34> 367 +5 5 1024682.524 1024682.524 1024686.570 #ffc0cb 1.0 ProfTask <39> 368 +5 5 1024691.334 1024691.334 1024694.870 #ffc0cb 1.0 ProfTask <0> 369 +5 4 1024686.172 1024701.141 1024725.666 #333399 1.0 Deferred Ready Trigger 30 248 +5 5 1024717.995 1024738.342 1024762.023 #007bff 1.0 Operation Physical Dependence Analysis 30 249 +5 4 1024753.354 1024774.483 1024836.925 #ff7a00 1.0 Scheduler 0 338 +5 5 1024849.380 1024849.380 1024856.773 #ffc0cb 1.0 ProfTask <0> 370 +5 5 1024862.364 1024862.364 1024865.775 #ffc0cb 1.0 ProfTask <37> 371 +5 5 1024870.158 1024870.158 1024873.470 #ffc0cb 1.0 ProfTask <0> 372 +5 5 1024878.042 1024878.042 1024882.017 #ffc0cb 1.0 ProfTask <0> 373 +5 5 1024887.041 1024887.041 1024891.672 #ffc0cb 1.0 ProfTask <40> 374 +5 4 1024890.447 1024896.902 1024954.495 #ff7a00 1.0 Scheduler 0 252 +5 5 1024946.696 1024968.486 1025006.101 #3dff00 1.0 Task Physical Dependence Analysis 50 253 +5 4 1025019.490 1025019.490 1025036.615 #cd00ff 1.0 Defer Task Perform Mapping 52 [[0, 2, 565]] 257 +5 4 1025036.615 1025036.615 1025346.362 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 52 257 +5 4 1025346.362 1025346.362 1025424.161 #cd00ff 0.45 Defer Task Perform Mapping (ready) 52 257 +5 4 1025424.161 1025424.161 1025513.498 #cd00ff 1.0 Defer Task Perform Mapping 52 257 +4 5 1025052.455 1025052.455 1025110.284 #00b1ff 1.0 Mapper Continuation 52 [[0, 2, 565]] 255 +4 5 1025110.284 1025110.284 1025138.358 #00b1ff 0.15 Mapper Continuation (waiting) 52 255 +4 5 1025138.358 1025138.358 1025163.253 #00b1ff 0.45 Mapper Continuation (ready) 52 255 +4 5 1025163.253 1025163.253 1025184.599 #00b1ff 1.0 Mapper Continuation 52 255 +4 5 1025184.599 1025184.599 1025281.634 #00b1ff 0.15 Mapper Continuation (waiting) 52 255 +4 5 1025281.634 1025281.634 1025305.541 #00b1ff 0.45 Mapper Continuation (ready) 52 255 +4 5 1025305.541 1025305.541 1025331.812 #00b1ff 1.0 Mapper Continuation 52 255 +3 3 1025057.887 1025057.887 1025311.567 #ff3200 1.0 Mapper Call map_task for 52 52 [[0, 2, 565]] 554 +2 2 1025208.469 1025208.469 1025290.866 #00b1ff 1.0 Mapper Continuation 53 [[0, 3, 390]] 256 +2 2 1025290.866 1025290.866 1025317.599 #00b1ff 0.15 Mapper Continuation (waiting) 53 256 +2 2 1025317.599 1025317.599 1025361.797 #00b1ff 0.45 Mapper Continuation (ready) 53 256 +2 2 1025361.797 1025361.797 1025382.984 #00b1ff 1.0 Mapper Continuation 53 256 +1 1 1025213.340 1025213.340 1025369.380 #ff3200 1.0 Mapper Call map_task for 53 53 [[0, 3, 390]] 542 +5 5 1025500.433 1025539.025 1025586.146 #ff0098 1.0 Defer Task Launch 52 [[0, 2, 565]] 259 +5 5 1025611.427 1025611.427 1025622.226 #ffc0cb 1.0 ProfTask <36> 375 +5 5 1025638.213 1025638.213 1025647.947 #ffc0cb 1.0 ProfTask <48> 376 +5 5 1025663.084 1025663.084 1025676.517 #ffc0cb 1.0 ProfTask <48> 377 +5 5 1025693.048 1025693.048 1025703.809 #ffc0cb 1.0 ProfTask <0> 378 +5 5 1025721.602 1025721.602 1025731.260 #ffc0cb 1.0 ProfTask <0> 379 +5 5 1025746.411 1025746.411 1025757.279 #ffc0cb 1.0 ProfTask <53> 380 +5 5 1025770.104 1025770.104 1025781.733 #ffc0cb 1.0 ProfTask <53> 381 +5 5 1025792.915 1025792.915 1025800.787 #ffc0cb 1.0 ProfTask <39> 382 +5 5 1025809.659 1025809.659 1025816.652 #ffc0cb 1.0 ProfTask <39> 383 +5 4 1025812.390 1025827.856 1025879.400 #006600 1.0 Post-Task Execution 43 [[0, 3, 389]] 342 +5 5 1025906.153 1025906.153 1025912.069 #ffc0cb 1.0 ProfTask <43> 384 +5 5 1027310.719 1027310.719 1027329.152 #ffc0cb 1.0 ProfTask <48> 578 +5 5 1028698.765 1028717.674 1028780.475 #006600 1.0 Post-Task Execution 52 [[0, 2, 565]] 568 +5 5 1043041.583 1043079.828 1043116.150 #333399 1.0 Deferred Ready Trigger 54 403 +5 5 1043147.303 1043182.818 1043276.396 #ff7a00 1.0 Scheduler 0 50 +5 5 1043331.296 1043363.999 1043439.363 #ff7a00 1.0 Scheduler 0 53 +5 4 1043429.649 1043462.537 1043521.460 #3dff00 1.0 Task Physical Dependence Analysis 56 55 +5 5 1043539.388 1043539.388 1043563.409 #cd00ff 1.0 Defer Task Perform Mapping 58 [[0, 2, 392]] 408 +5 5 1043563.409 1043563.409 1043637.676 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 58 408 +5 5 1043637.676 1043637.676 1043696.865 #cd00ff 0.45 Defer Task Perform Mapping (ready) 58 408 +5 5 1043696.865 1043696.865 1043775.142 #cd00ff 1.0 Defer Task Perform Mapping 58 408 +4 4 1043548.690 1043548.690 1043702.771 #ff3200 1.0 Mapper Call map_task for 58 58 [[0, 2, 392]] 577 +5 4 1043748.490 1043801.712 1043819.547 #00b1ff 1.0 Mapper Continuation 60 59 +5 3 1043767.658 1043843.446 1043873.303 #ff0098 1.0 Defer Task Launch 58 [[0, 2, 392]] 410 +5 5 1043848.600 1043892.005 1043927.706 #ff0098 1.0 Defer Task Launch 59 [[0, 3, 393]] 574 +5 5 1043929.230 1043943.742 1043966.030 #333399 1.0 Deferred Ready Trigger 60 576 +5 5 1043979.505 1043979.505 1043984.049 #ffc0cb 1.0 ProfTask <59> 579 +5 5 1043989.105 1043989.105 1043993.343 #ffc0cb 1.0 ProfTask <60> 580 +5 5 1043997.722 1043997.722 1044001.005 #ffc0cb 1.0 ProfTask <60> 581 +5 5 1044036.712 1044073.642 1044226.567 #ff7a00 1.0 Scheduler 0 637 +5 5 1044247.954 1044247.954 1044259.135 #ffc0cb 1.0 ProfTask <0> 654 +5 5 1044285.773 1044300.172 1044386.707 #ff7a00 1.0 Scheduler 0 589 +5 4 1044372.250 1044410.934 1044480.531 #3dff00 1.0 Task Physical Dependence Analysis 62 591 +5 5 1044392.301 1044499.704 1044567.279 #00ff12 1.0 Logical Dependence Analysis 64 592 +5 5 1044576.433 1044589.211 1044652.525 #ff0098 1.0 Defer Task Launch 65 [[0, 2, 636]] 61 +5 4 1044637.918 1044673.215 1044784.929 #cd00ff 1.0 Defer Task Perform Mapping 66 [[0, 3, 587]] 412 +5 5 1044758.443 1044820.621 1044894.401 #006600 1.0 Post-Task Execution 58 [[0, 2, 392]] 594 +5 4 1044808.320 1044914.641 1044957.622 #007bff 1.0 Operation Physical Dependence Analysis 64 638 +5 5 1044977.578 1044977.578 1044983.228 #ffc0cb 1.0 ProfTask <64> 655 +5 5 1045027.536 1045056.568 1045161.665 #3dff00 1.0 Task Physical Dependence Analysis 67 598 +5 4 1045139.449 1045193.135 1045294.673 #ff7a00 1.0 Scheduler 0 64 +5 5 1045276.168 1045319.687 1045447.100 #cd00ff 1.0 Defer Task Perform Mapping 71 [[0, 2, 5]] 414 +5 4 1045436.237 1045477.587 1045516.256 #ff0098 1.0 Defer Task Launch 71 [[0, 2, 5]] 600 +5 3 1045283.908 1045538.802 1045627.364 #00ff12 1.0 Logical Dependence Analysis 70 641 +5 5 1045619.478 1045656.151 1045698.593 #006600 1.0 Post-Task Execution 65 [[0, 2, 636]] 643 +5 4 1045723.770 1045723.770 1045730.321 #ffc0cb 1.0 ProfTask <69> 656 +5 5 1045721.386 1045740.255 1045845.981 #ff7a00 1.0 Scheduler 0 603 +5 5 1045884.019 1045884.019 1045890.352 #ffc0cb 1.0 ProfTask <72> 657 +5 4 1045885.201 1045899.719 1045999.345 #ff7a00 1.0 Scheduler 0 644 +5 5 1045976.234 1046021.175 1046041.662 #00b1ff 1.0 Mapper Continuation 0 605 +5 5 1046076.892 1046076.892 1046091.530 #ffc0cb 1.0 ProfTask <65> 658 +5 5 1046099.419 1046099.419 1046104.230 #ffc0cb 1.0 ProfTask <70> 659 +5 5 1046111.528 1046111.528 1046117.513 #ffc0cb 1.0 ProfTask <70> 660 +5 4 1046113.992 1046126.367 1046250.716 #cd00ff 1.0 Defer Task Perform Mapping 76 [[0, 2, 7]] 608 +5 5 1046237.537 1046278.030 1046314.988 #ff0098 1.0 Defer Task Launch 76 [[0, 2, 7]] 646 +5 4 1046339.475 1046339.475 1046347.300 #ffc0cb 1.0 ProfTask <65> 661 +5 5 1046337.015 1046356.442 1046393.607 #ff0098 1.0 Defer Task Launch 77 [[0, 3, 394]] 647 +5 5 1046413.696 1046413.696 1046420.873 #ffc0cb 1.0 ProfTask <0> 662 +5 5 1046432.425 1046432.425 1046441.751 #ffc0cb 1.0 ProfTask <0> 663 +5 5 1046452.072 1046452.072 1046458.827 #ffc0cb 1.0 ProfTask <76> 664 +5 5 1046470.788 1046470.788 1046477.290 #ffc0cb 1.0 ProfTask <77> 665 +5 5 1046560.606 1046575.458 1046632.653 #006600 1.0 Post-Task Execution 72 [[0, 3, 672]] 648 +5 5 1046651.407 1046651.407 1046656.178 #ffc0cb 1.0 ProfTask <72> 666 +5 4 1046653.371 1046661.879 1046725.278 #00ff12 1.0 Logical Dependence Analysis 78 649 +5 5 1046740.944 1046740.944 1046745.264 #ffc0cb 1.0 ProfTask <78> 667 +5 5 1046766.391 1046791.619 1046847.610 #007bff 1.0 Operation Physical Dependence Analysis 78 650 +5 5 1046861.463 1046861.463 1046865.754 #ffc0cb 1.0 ProfTask <78> 668 +5 5 1046943.149 1046963.523 1047045.904 #3dff00 1.0 Task Physical Dependence Analysis 79 70 +5 4 1047060.705 1047060.705 1047095.389 #ff7a00 1.0 Scheduler 0 73 +5 4 1047095.389 1047095.389 1047197.337 #ff7a00 0.15 Scheduler (waiting) 0 73 +5 4 1047197.337 1047197.337 1047219.317 #ff7a00 0.45 Scheduler (ready) 0 73 +5 4 1047219.317 1047219.317 1047280.431 #ff7a00 1.0 Scheduler 0 73 +4 5 1047090.004 1047157.403 1047183.873 #00b1ff 1.0 Mapper Continuation 0 72 +5 5 1047242.202 1047308.491 1047380.812 #cd00ff 1.0 Defer Task Perform Mapping 82 [[0, 2, 681]] 77 +5 4 1047372.876 1047409.220 1047457.574 #ff0098 1.0 Defer Task Launch 82 [[0, 2, 681]] 417 +5 3 1047265.656 1047485.106 1047559.608 #3dff00 1.0 Task Physical Dependence Analysis 81 421 +5 2 1047276.966 1047579.867 1047591.084 #2500ff 1.0 Prepipeline Stage 83 422 +5 5 1047585.357 1047606.599 1047648.258 #333399 1.0 Deferred Ready Trigger 84 652 +5 5 1047704.246 1047704.246 1047714.252 #ffc0cb 1.0 ProfTask <85> 669 +5 5 1047727.631 1047727.631 1047733.357 #ffc0cb 1.0 ProfTask <84> 670 +5 5 1047743.823 1047743.823 1047767.970 #ffc0cb 1.0 ProfTask <84> 671 +5 5 1047866.075 1047866.075 1047885.816 #ffc0cb 1.0 ProfTask <84> 690 +5 5 1048073.019 1048073.019 1048079.943 #ffc0cb 1.0 ProfTask <84> 691 +5 5 1048089.840 1048089.840 1048102.683 #ffc0cb 1.0 ProfTask <84> 692 +5 4 1048111.659 1048111.659 1048120.678 #ffc0cb 1.0 ProfTask <82> 693 +5 5 1048106.806 1048129.055 1048178.094 #006600 1.0 Post-Task Execution 82 [[0, 2, 681]] 79 +5 4 1048177.813 1048202.620 1048233.751 #333399 1.0 Deferred Ready Trigger 83 684 +5 5 1048253.255 1048253.255 1048259.273 #ffc0cb 1.0 ProfTask <83> 694 +5 5 1048303.934 1048303.934 1048310.306 #ffc0cb 1.0 ProfTask <85> 695 +5 4 1048304.146 1048319.181 1048367.651 #006600 1.0 Post-Task Execution 85 [[0, 3, 682]] 83 +5 5 1048535.478 1048535.478 1048541.225 #ffc0cb 1.0 ProfTask <83> 696 +5 5 1048557.987 1048570.806 1048804.548 #1f00ff 1.0 Copy Fill Aggregation 83 424 +5 4 1048794.518 1048854.074 1048881.903 #00ff0f 1.0 Copy Fill Deletion 83 85 +5 5 1050298.787 1050298.787 1050316.398 #ffc0cb 1.0 ProfTask <83> 697 +5 5 1144732.332 1144732.332 1144738.433 #ffc0cb 1.0 ProfTask <83> 698 +5 5 1183469.750 1183505.306 1183539.347 #333399 1.0 Deferred Ready Trigger 89 88 +5 4 1183509.249 1183567.025 1183592.790 #006600 1.0 Post-Task Execution 1 [[0, 4, 8]] 89 +5 5 1183591.689 1183620.810 1183686.977 #333399 1.0 Deferred Ready Trigger 87 92 +5 5 1183723.784 1183740.807 1183767.389 #333399 1.0 Deferred Ready Trigger 88 94 +5 4 1183759.243 1183786.910 1183824.028 #007bff 1.0 Operation Physical Dependence Analysis 88 95 +5 4 1183795.438 1183846.435 1183856.010 #f7ff00 1.0 Trigger Complete 1 [[0, 4, 8]] 96 +5 5 1183790.134 1183875.602 1183938.722 #009900 1.0 Garbage Collection 87 426 +5 3 1183810.754 1183966.177 1183997.470 #009900 1.0 Garbage Collection 87 97 +5 5 1184311.353 1184344.122 1184386.204 #009900 1.0 Garbage Collection 87 427 +5 4 1184377.864 1184404.214 1184437.440 #009900 1.0 Garbage Collection 87 98 +5 5 1184398.593 1184459.636 1184492.880 #009900 1.0 Garbage Collection 87 99 +5 3 1184418.693 1184513.128 1184539.716 #009900 1.0 Garbage Collection 87 100 +5 4 1184443.049 1184556.087 1184588.795 #009900 1.0 Garbage Collection 87 101 +5 5 1184537.181 1184610.581 1184645.091 #009900 1.0 Garbage Collection 87 102 +5 3 1184552.029 1184665.321 1184692.744 #009900 1.0 Garbage Collection 87 103 +5 5 1184670.914 1184717.064 1184801.507 #990000 1.0 Deferred Execute 88 105 +5 4 1184592.607 1184818.629 1184847.345 #009900 1.0 Garbage Collection 87 429 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000002.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000002.tsv new file mode 100644 index 000000000..b43bebebf --- /dev/null +++ b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000002.tsv @@ -0,0 +1,93 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +1 3 962689.824 962689.824 962698.725 #ffc0cb 1.0 ProfTask <5> 120 +1 3 999427.832 999427.832 999433.367 #ffc0cb 1.0 ProfTask <6> 121 +1 3 999530.605 999530.605 999537.468 #ffc0cb 1.0 ProfTask <6> 122 +1 3 1019563.499 1019563.499 1019569.168 #ffc0cb 1.0 ProfTask <8> 123 +1 3 1019723.664 1019723.664 1019734.354 #ffc0cb 1.0 ProfTask <7> 124 +1 3 1019976.547 1019976.547 1019982.927 #ffc0cb 1.0 ProfTask <9> 125 +1 3 1020029.859 1020029.859 1020035.992 #ffc0cb 1.0 ProfTask <0> 126 +1 3 1020081.621 1020081.621 1020088.315 #ffc0cb 1.0 ProfTask <0> 127 +1 3 1020133.393 1020133.393 1020140.003 #ffc0cb 1.0 ProfTask <10> 128 +1 3 1020170.226 1020170.226 1020176.043 #ffc0cb 1.0 ProfTask <12> 129 +1 3 1020320.009 1020320.009 1020326.182 #ffc0cb 1.0 ProfTask <14> 130 +1 3 1020336.073 1020336.073 1020344.812 #ffc0cb 1.0 ProfTask <13> 131 +1 3 1020409.676 1020409.676 1020415.356 #ffc0cb 1.0 ProfTask <14> 132 +1 3 1020465.741 1020465.741 1020471.704 #ffc0cb 1.0 ProfTask <12> 133 +1 3 1020538.912 1020538.912 1020544.913 #ffc0cb 1.0 ProfTask <15> 134 +1 3 1020662.935 1020683.611 1022061.790 #00fff6 1.0 legate::numpy::FillTask [CPU] <13> [[0, 3, 308], [0, 0, 475]] [[0, 1, 345], [0, 1, 397], [0, 1, 399]] [[0, 4, 8]] 469 +1 3 1022107.376 1022107.376 1022115.335 #ffc0cb 1.0 ProfTask <15> 135 +1 3 1022125.977 1022125.977 1022132.984 #ffc0cb 1.0 ProfTask <18> 136 +1 3 1022141.854 1022141.854 1022148.613 #ffc0cb 1.0 ProfTask <17> 137 +1 3 1022155.102 1022155.102 1022158.592 #ffc0cb 1.0 ProfTask <12> 138 +1 3 1022164.775 1022164.775 1022169.154 #ffc0cb 1.0 ProfTask <17> 139 +1 3 1022175.085 1022175.085 1022178.496 #ffc0cb 1.0 ProfTask <0> 140 +1 3 1022184.906 1022184.906 1022191.677 #ffc0cb 1.0 ProfTask <18> 141 +1 3 1022198.572 1022198.572 1022204.310 #ffc0cb 1.0 ProfTask <20> 142 +1 3 1022210.953 1022210.953 1022214.923 #ffc0cb 1.0 ProfTask <17> 143 +1 3 1022222.553 1022222.553 1022227.962 #ffc0cb 1.0 ProfTask <16> 144 +1 3 1022237.249 1022237.249 1022245.039 #ffc0cb 1.0 ProfTask <19> 145 +1 2 1022238.538 1022259.076 1023674.045 #00fff6 1.0 legate::numpy::FillTask [CPU] <29> [[0, 1, 474], [0, 0, 551], [0, 0, 478], [0, 0, 261]] 471 +1 3 1022696.533 1023700.501 1024175.988 #00fff6 1.0 legate::numpy::FillTask [CPU] <35> [[0, 0, 243]] [[0, 2, 565], [0, 1, 488], [0, 3, 390], [0, 1, 490]] [[0, 4, 8]] 219 +1 1 1023104.640 1024212.470 1025513.689 #00fff6 1.0 legate::numpy::FillTask [CPU] <38> [[0, 2, 221], [0, 1, 326], [0, 0, 327], [0, 1, 552], [0, 3, 389]] 220 +1 2 1023703.011 1025541.836 1025784.682 #00fff6 1.0 legate::numpy::FillTask [CPU] <42> [[0, 2, 220], [0, 3, 573]] [[0, 0, 494], [0, 3, 472], [0, 0, 492]] [[0, 4, 8]] 221 +1 3 1025808.403 1025817.215 1027264.327 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <47> [[0, 0, 567], [0, 2, 565]] [[0, 3, 308], [0, 1, 553], [0, 1, 244], [0, 3, 389], [0, 0, 245]] [[0, 4, 8]] 3 +1 3 1027298.588 1027298.588 1027310.850 #ffc0cb 1.0 ProfTask <47> 146 +1 3 1027323.700 1027340.279 1028683.215 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <52> [[0, 3, 393], [0, 1, 568], [0, 2, 219]] [[0, 1, 255], [0, 1, 554], [0, 1, 259], [0, 1, 257], [0, 2, 3]] [[0, 4, 8]] 565 +1 3 1043099.467 1043099.467 1043105.925 #ffc0cb 1.0 ProfTask <54> 147 +1 3 1043313.696 1043313.696 1043321.599 #ffc0cb 1.0 ProfTask <0> 148 +1 3 1043381.693 1043381.693 1043389.858 #ffc0cb 1.0 ProfTask <55> 149 +1 3 1043463.226 1043463.226 1043469.407 #ffc0cb 1.0 ProfTask <0> 150 +1 3 1043544.444 1043544.444 1043550.837 #ffc0cb 1.0 ProfTask <56> 151 +1 3 1043780.003 1043780.003 1043793.581 #ffc0cb 1.0 ProfTask <59> 152 +1 3 1043840.550 1043840.550 1043845.419 #ffc0cb 1.0 ProfTask <60> 153 +1 3 1043865.362 1043891.674 1044741.669 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <58> [[0, 2, 636], [0, 1, 594]] [[0, 1, 408], [0, 1, 410], [0, 1, 577], [0, 3, 390]] [[0, 4, 8]] 392 +1 3 1044772.977 1044772.977 1044785.500 #ffc0cb 1.0 ProfTask <65> 154 +1 3 1044798.568 1044798.568 1044804.821 #ffc0cb 1.0 ProfTask <63> 155 +1 2 1044801.631 1044816.976 1045600.715 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <65> [[0, 1, 643], [0, 2, 5]] [[0, 1, 61], [0, 2, 392], [0, 0, 593]] [[0, 4, 8]] 636 +1 3 1045633.063 1045633.063 1045640.501 #ffc0cb 1.0 ProfTask <0> 156 +1 2 1045658.078 1045658.078 1045664.840 #ffc0cb 1.0 ProfTask <68> 157 +1 3 1045655.819 1045674.697 1046429.291 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <71> [[0, 0, 609], [0, 2, 7], [0, 3, 587]] [[0, 2, 636], [0, 1, 414], [0, 1, 600]] [[0, 4, 8]] 5 +1 3 1046459.143 1046459.143 1046466.393 #ffc0cb 1.0 ProfTask <77> 158 +1 3 1046474.283 1046474.283 1046481.896 #ffc0cb 1.0 ProfTask <71> 159 +1 3 1046483.645 1046509.517 1047234.439 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <76> [[0, 0, 78], [0, 3, 672]] [[0, 1, 646], [0, 1, 608], [0, 2, 5]] [[0, 4, 8]] 7 +1 3 1047255.694 1047255.694 1047261.622 #ffc0cb 1.0 ProfTask <79> 160 +1 3 1047267.900 1047267.900 1047274.343 #ffc0cb 1.0 ProfTask <0> 161 +1 3 1047281.641 1047281.641 1047298.270 #ffc0cb 1.0 ProfTask <0> 162 +1 3 1047306.163 1047306.163 1047311.434 #ffc0cb 1.0 ProfTask <76> 163 +1 3 1047316.397 1047316.397 1047328.915 #ffc0cb 1.0 ProfTask <0> 164 +1 3 1047333.748 1047333.748 1047336.991 #ffc0cb 1.0 ProfTask <80> 165 +1 3 1047408.539 1047408.539 1047414.776 #ffc0cb 1.0 ProfTask <82> 166 +1 3 1047425.444 1047425.444 1047430.972 #ffc0cb 1.0 ProfTask <76> 167 +1 3 1047440.173 1047463.197 1048083.927 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <82> [[0, 1, 79]] [[0, 3, 394], [0, 1, 417], [0, 1, 77]] [[0, 4, 8]] 681 +1 3 1048208.167 1048208.167 1048215.606 #ffc0cb 1.0 ProfTask <82> 168 +1 3 1048245.381 1048245.381 1048260.714 #ffc0cb 1.0 ProfTask <84> 169 +1 3 1048360.624 1048360.624 1048368.336 #ffc0cb 1.0 ProfTask <83> 170 +1 3 1048392.151 1048392.151 1048397.420 #ffc0cb 1.0 ProfTask <85> 171 +1 3 1048914.304 1048914.304 1048919.582 #ffc0cb 1.0 ProfTask <83> 172 +1 3 1048927.422 1048927.422 1048933.418 #ffc0cb 1.0 ProfTask <83> 173 +1 3 1183514.868 1183514.868 1183526.003 #ffc0cb 1.0 ProfTask <1> 174 +1 3 1183564.060 1183564.060 1183571.389 #ffc0cb 1.0 ProfTask <89> 175 +1 3 1183618.998 1183618.998 1183627.204 #ffc0cb 1.0 ProfTask <1> 176 +1 3 1183656.435 1183656.435 1183662.395 #ffc0cb 1.0 ProfTask <89> 177 +1 3 1183716.981 1183716.981 1183722.963 #ffc0cb 1.0 ProfTask <87> 178 +1 3 1183789.778 1183789.778 1183796.240 #ffc0cb 1.0 ProfTask <88> 179 +1 3 1183844.266 1183844.266 1183850.453 #ffc0cb 1.0 ProfTask <88> 180 +1 3 1183876.008 1183876.008 1183881.779 #ffc0cb 1.0 ProfTask <1> 181 +1 3 1183932.594 1183932.594 1183961.777 #ffc0cb 1.0 ProfTask <48> 182 +1 3 1183990.520 1183990.520 1183995.478 #ffc0cb 1.0 ProfTask <47> 183 +1 3 1184022.320 1184022.320 1184027.253 #ffc0cb 1.0 ProfTask <87> 184 +1 3 1184378.314 1184378.314 1184386.071 #ffc0cb 1.0 ProfTask <83> 185 +1 3 1184438.252 1184438.252 1184446.042 #ffc0cb 1.0 ProfTask <13> 186 +1 3 1184452.860 1184452.860 1184456.362 #ffc0cb 1.0 ProfTask <87> 187 +1 3 1184482.915 1184482.915 1184489.625 #ffc0cb 1.0 ProfTask <29> 188 +1 3 1184514.238 1184514.238 1184519.942 #ffc0cb 1.0 ProfTask <87> 189 +1 3 1184528.822 1184528.822 1184533.676 #ffc0cb 1.0 ProfTask <38> 190 +1 3 1184557.808 1184557.808 1184562.356 #ffc0cb 1.0 ProfTask <87> 191 +1 3 1184575.260 1184575.260 1184578.768 #ffc0cb 1.0 ProfTask <52> 192 +1 3 1184612.280 1184612.280 1184619.851 #ffc0cb 1.0 ProfTask <87> 193 +1 3 1184676.751 1184676.751 1184683.603 #ffc0cb 1.0 ProfTask <87> 194 +1 3 1184711.881 1184711.881 1184720.164 #ffc0cb 1.0 ProfTask <87> 195 +1 3 1184751.168 1184751.168 1184757.069 #ffc0cb 1.0 ProfTask <15> 196 +1 3 1184788.335 1184788.335 1184793.531 #ffc0cb 1.0 ProfTask <87> 197 +1 3 1184825.080 1184825.080 1184831.298 #ffc0cb 1.0 ProfTask <88> 198 +1 3 1184838.998 1184838.998 1184845.978 #ffc0cb 1.0 ProfTask <0> 199 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000003.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000003.tsv new file mode 100644 index 000000000..3224fd8ff --- /dev/null +++ b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000003.tsv @@ -0,0 +1,52 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +1 3 999566.582 999566.582 999574.512 #ffc0cb 1.0 ProfTask <6> 430 +1 3 1020320.096 1020320.096 1020326.371 #ffc0cb 1.0 ProfTask <11> 431 +1 3 1020607.485 1020607.485 1020618.851 #ffc0cb 1.0 ProfTask <13> 432 +1 3 1020698.885 1020698.885 1020708.696 #ffc0cb 1.0 ProfTask <15> 433 +1 3 1020718.044 1020718.044 1020723.315 #ffc0cb 1.0 ProfTask <13> 434 +1 3 1020728.635 1020728.635 1020732.653 #ffc0cb 1.0 ProfTask <16> 435 +1 3 1020812.834 1020812.834 1020820.679 #ffc0cb 1.0 ProfTask <15> 436 +1 2 1020841.769 1020841.769 1020849.994 #ffc0cb 1.0 ProfTask <16> 437 +1 3 1020836.247 1020859.100 1022211.911 #00fff6 1.0 legate::numpy::FillTask [CPU] <15> [[0, 0, 481]] [[0, 0, 32], [0, 0, 398], [0, 0, 401], [0, 0, 505]] [[0, 4, 8]] 470 +1 2 1021824.225 1022245.345 1023674.774 #00fff6 1.0 legate::numpy::FillTask [CPU] <25> [[0, 1, 497], [0, 2, 221]] [[0, 0, 240], [0, 0, 260], [0, 0, 238]] [[0, 4, 8]] 472 +1 3 1022713.176 1023714.788 1024165.613 #00fff6 1.0 legate::numpy::FillTask [CPU] <36> [[0, 2, 3]] [[0, 0, 320], [0, 2, 469], [0, 0, 489]] [[0, 4, 8]] 308 +1 1 1023323.068 1024191.329 1025523.689 #00fff6 1.0 legate::numpy::FillTask [CPU] <39> [[0, 0, 341]] [[0, 0, 241], [0, 1, 329], [0, 1, 242]] [[0, 4, 8]] 309 +1 2 1023757.906 1025553.734 1025793.359 #00fff6 1.0 legate::numpy::FillTask [CPU] <43> [[0, 2, 220], [0, 2, 3], [0, 1, 342]] [[0, 1, 493], [0, 0, 496]] [[0, 4, 8]] 389 +1 3 1025825.619 1025825.619 1025838.009 #ffc0cb 1.0 ProfTask <43> 438 +1 3 1025842.865 1025857.809 1027267.987 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <48> [[0, 3, 390]] [[0, 2, 221], [0, 1, 346], [0, 0, 337], [0, 1, 246], [0, 0, 250]] [[0, 4, 8]] 573 +1 3 1027284.385 1027290.352 1028673.325 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <53> [[0, 2, 392], [0, 2, 219]] [[0, 0, 258], [0, 3, 573], [0, 1, 256], [0, 1, 542], [0, 0, 340]] [[0, 4, 8]] 390 +1 3 1028696.363 1028696.363 1028702.589 #ffc0cb 1.0 ProfTask <53> 439 +1 3 1043152.725 1043152.725 1043162.570 #ffc0cb 1.0 ProfTask <54> 440 +1 3 1043172.134 1043172.134 1043175.780 #ffc0cb 1.0 ProfTask <54> 441 +1 3 1043478.703 1043478.703 1043483.955 #ffc0cb 1.0 ProfTask <0> 442 +1 3 1043559.025 1043559.025 1043565.584 #ffc0cb 1.0 ProfTask <57> 443 +1 3 1043815.587 1043815.587 1043823.752 #ffc0cb 1.0 ProfTask <58> 444 +1 3 1043885.917 1043885.917 1043893.078 #ffc0cb 1.0 ProfTask <59> 445 +1 3 1043899.319 1043899.319 1043902.688 #ffc0cb 1.0 ProfTask <58> 446 +1 3 1043915.164 1043932.016 1044786.018 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <59> [[0, 3, 394], [0, 3, 587]] [[0, 0, 409], [0, 2, 565], [0, 1, 574], [0, 0, 57], [0, 0, 610]] [[0, 4, 8]] 393 +1 3 1044818.895 1044818.895 1044826.305 #ffc0cb 1.0 ProfTask <58> 447 +1 3 1044832.900 1044832.900 1044836.390 #ffc0cb 1.0 ProfTask <59> 448 +1 3 1044841.026 1044841.026 1044846.632 #ffc0cb 1.0 ProfTask <66> 449 +1 3 1044853.660 1044853.660 1044856.914 #ffc0cb 1.0 ProfTask <64> 450 +1 3 1044886.088 1044903.140 1045716.824 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <66> [[0, 0, 602]] [[0, 0, 595], [0, 3, 393], [0, 1, 412], [0, 2, 5]] [[0, 4, 8]] 587 +1 3 1045749.414 1045749.414 1045757.154 #ffc0cb 1.0 ProfTask <71> 451 +1 3 1045767.502 1045767.502 1045774.232 #ffc0cb 1.0 ProfTask <72> 452 +1 2 1045769.705 1045783.097 1046540.037 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <72> [[0, 1, 648]] [[0, 0, 640], [0, 0, 416], [0, 3, 394], [0, 2, 7]] [[0, 4, 8]] 672 +1 3 1046599.653 1046615.744 1047402.303 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <77> [[0, 2, 681], [0, 0, 419], [0, 3, 672]] [[0, 3, 393], [0, 0, 68], [0, 1, 647]] [[0, 4, 8]] 394 +1 3 1047428.177 1047428.177 1047435.591 #ffc0cb 1.0 ProfTask <77> 453 +1 3 1047485.607 1047485.607 1047499.472 #ffc0cb 1.0 ProfTask <82> 454 +1 3 1047509.224 1047509.224 1047515.337 #ffc0cb 1.0 ProfTask <83> 455 +1 3 1047551.395 1047551.395 1047558.273 #ffc0cb 1.0 ProfTask <77> 456 +1 3 1047583.009 1047583.009 1047588.140 #ffc0cb 1.0 ProfTask <81> 457 +1 3 1047610.844 1047610.844 1047614.303 #ffc0cb 1.0 ProfTask <83> 458 +1 3 1047619.993 1047619.993 1047623.284 #ffc0cb 1.0 ProfTask <85> 459 +1 3 1047638.420 1047656.279 1048281.052 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <85> [[0, 1, 83]] [[0, 0, 651], [0, 0, 423]] [[0, 4, 8]] 682 +1 3 1048858.236 1048858.236 1048865.054 #ffc0cb 1.0 ProfTask <83> 460 +1 3 1183586.336 1183586.336 1183593.882 #ffc0cb 1.0 ProfTask <89> 461 +1 3 1183962.273 1183962.273 1183969.461 #ffc0cb 1.0 ProfTask <87> 462 +1 3 1184410.125 1184410.125 1184416.531 #ffc0cb 1.0 ProfTask <87> 463 +1 3 1184649.833 1184649.833 1184656.431 #ffc0cb 1.0 ProfTask <39> 464 +1 3 1184686.919 1184686.919 1184705.292 #ffc0cb 1.0 ProfTask <53> 465 +1 3 1184716.235 1184716.235 1184722.729 #ffc0cb 1.0 ProfTask <87> 466 +1 3 1184846.419 1184846.419 1184853.601 #ffc0cb 1.0 ProfTask <25> 467 +1 3 1184862.211 1184862.211 1184865.981 #ffc0cb 1.0 ProfTask <87> 468 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000004.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000004.tsv new file mode 100644 index 000000000..6c823e943 --- /dev/null +++ b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000004.tsv @@ -0,0 +1,17 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +1 1 478641.174 478641.174 922239.137 #eb00ff 1.0 legion_python_main <1> [[0, 1, 89], [0, 1, 96]] [[0, 0, 223], [0, 0, 224], [0, 0, 312]] [[0, 3, 682], [0, 3, 470], [0, 3, 389], [0, 2, 392], [0, 2, 3], [0, 2, 636], [0, 3, 308], [0, 2, 221], [0, 3, 587], [0, 3, 573], [0, 3, 393], [0, 2, 7], [0, 3, 390], [0, 2, 219], [0, 3, 309], [0, 2, 469], [0, 3, 672], [0, 2, 681], [0, 3, 472], [0, 2, 565], [0, 2, 5], [0, 3, 394]] 8 +1 1 922239.137 922239.137 922397.410 #eb00ff 0.15 legion_python_main <1> (waiting) 8 +1 1 922397.410 922397.410 922497.427 #eb00ff 0.45 legion_python_main <1> (ready) 8 +1 1 922497.427 922497.427 922606.850 #eb00ff 1.0 legion_python_main <1> 8 +1 1 922606.850 922606.850 922766.603 #eb00ff 0.15 legion_python_main <1> (waiting) 8 +1 1 922766.603 922766.603 922815.999 #eb00ff 0.45 legion_python_main <1> (ready) 8 +1 1 922815.999 922815.999 962519.280 #eb00ff 1.0 legion_python_main <1> 8 +1 1 962519.280 962519.280 962704.926 #eb00ff 0.15 legion_python_main <1> (waiting) 8 +1 1 962704.926 962704.926 962723.661 #eb00ff 0.45 legion_python_main <1> (ready) 8 +1 1 962723.661 962723.661 1047360.569 #eb00ff 1.0 legion_python_main <1> 8 +1 1 1047360.569 1047360.569 1048868.455 #eb00ff 0.15 legion_python_main <1> (waiting) 8 +1 1 1048868.455 1048868.455 1048908.961 #eb00ff 0.45 legion_python_main <1> (ready) 8 +1 1 1048908.961 1048908.961 1048924.893 #eb00ff 1.0 legion_python_main <1> 8 +1 1 1048924.893 1048924.893 1050325.359 #eb00ff 0.15 legion_python_main <1> (waiting) 8 +1 1 1050325.359 1050325.359 1050359.631 #eb00ff 0.45 legion_python_main <1> (ready) 8 +1 1 1050359.631 1050359.631 1183469.202 #eb00ff 1.0 legion_python_main <1> 8 diff --git a/examples/testbench/decent_band/tsv/all (CPU)_util.tsv b/examples/testbench/decent_band/tsv/all (CPU)_util.tsv new file mode 100644 index 000000000..8d75fcdb6 --- /dev/null +++ b/examples/testbench/decent_band/tsv/all (CPU)_util.tsv @@ -0,0 +1,288 @@ +time count +0.000 0.00 +962689.824 0.50 +962698.725 0.00 +999427.832 0.50 +999433.367 0.00 +999530.605 0.50 +999537.468 0.00 +999566.582 0.50 +999574.512 0.00 +1019563.499 0.50 +1019569.168 0.00 +1019723.664 0.50 +1019734.354 0.00 +1019976.547 0.50 +1019982.927 0.00 +1020029.859 0.50 +1020035.992 0.00 +1020081.621 0.50 +1020088.315 0.00 +1020133.393 0.50 +1020140.003 0.00 +1020170.226 0.50 +1020176.043 0.00 +1020320.009 0.50 +1020320.096 1.00 +1020326.182 0.50 +1020326.371 0.00 +1020336.073 0.50 +1020344.812 0.00 +1020409.676 0.50 +1020415.356 0.00 +1020465.741 0.50 +1020471.704 0.00 +1020538.912 0.50 +1020544.913 0.00 +1020607.485 0.50 +1020618.851 0.00 +1020683.611 0.50 +1020698.885 1.00 +1020708.696 0.50 +1020718.044 1.00 +1020723.315 0.50 +1020728.635 1.00 +1020732.653 0.50 +1020812.834 1.00 +1020820.679 0.50 +1020841.769 1.00 +1020849.994 0.50 +1020859.100 1.00 +1022061.790 0.50 +1022107.376 1.00 +1022115.335 0.50 +1022125.977 1.00 +1022132.984 0.50 +1022141.854 1.00 +1022148.613 0.50 +1022155.102 1.00 +1022158.592 0.50 +1022164.775 1.00 +1022169.154 0.50 +1022175.085 1.00 +1022178.496 0.50 +1022184.906 1.00 +1022191.677 0.50 +1022198.572 1.00 +1022204.310 0.50 +1022210.953 1.00 +1022211.911 0.50 +1022214.923 0.00 +1022222.553 0.50 +1022227.962 0.00 +1022237.249 0.50 +1022245.039 0.00 +1022245.345 0.50 +1022259.076 1.00 +1023674.045 0.50 +1023674.774 0.00 +1023700.501 0.50 +1023714.788 1.00 +1024165.613 0.50 +1024175.988 0.00 +1024191.329 0.50 +1024212.470 1.00 +1025513.689 0.50 +1025523.689 0.00 +1025541.836 0.50 +1025553.734 1.00 +1025784.682 0.50 +1025793.359 0.00 +1025817.215 0.50 +1025825.619 1.00 +1025838.009 0.50 +1025857.809 1.00 +1027264.327 0.50 +1027267.987 0.00 +1027290.352 0.50 +1027298.588 1.00 +1027310.850 0.50 +1027340.279 1.00 +1028673.325 0.50 +1028683.215 0.00 +1028696.363 0.50 +1028702.589 0.00 +1043099.467 0.50 +1043105.925 0.00 +1043152.725 0.50 +1043162.570 0.00 +1043172.134 0.50 +1043175.780 0.00 +1043313.696 0.50 +1043321.599 0.00 +1043381.693 0.50 +1043389.858 0.00 +1043463.226 0.50 +1043469.407 0.00 +1043478.703 0.50 +1043483.955 0.00 +1043544.444 0.50 +1043550.837 0.00 +1043559.025 0.50 +1043565.584 0.00 +1043780.003 0.50 +1043793.581 0.00 +1043815.587 0.50 +1043823.752 0.00 +1043840.550 0.50 +1043845.419 0.00 +1043885.917 0.50 +1043891.674 1.00 +1043893.078 0.50 +1043899.319 1.00 +1043902.688 0.50 +1043932.016 1.00 +1044741.669 0.50 +1044772.977 1.00 +1044785.500 0.50 +1044786.018 0.00 +1044798.568 0.50 +1044804.821 0.00 +1044816.976 0.50 +1044818.895 1.00 +1044826.305 0.50 +1044832.900 1.00 +1044836.390 0.50 +1044841.026 1.00 +1044846.632 0.50 +1044853.660 1.00 +1044856.914 0.50 +1044903.140 1.00 +1045600.715 0.50 +1045633.063 1.00 +1045640.501 0.50 +1045658.078 1.00 +1045664.840 0.50 +1045674.697 1.00 +1045716.824 0.50 +1045749.414 1.00 +1045757.154 0.50 +1045767.502 1.00 +1045774.232 0.50 +1045783.097 1.00 +1046429.291 0.50 +1046459.143 1.00 +1046466.393 0.50 +1046474.283 1.00 +1046481.896 0.50 +1046509.517 1.00 +1046540.037 0.50 +1046615.744 1.00 +1047234.439 0.50 +1047255.694 1.00 +1047261.622 0.50 +1047267.900 1.00 +1047274.343 0.50 +1047281.641 1.00 +1047298.270 0.50 +1047306.163 1.00 +1047311.434 0.50 +1047316.397 1.00 +1047328.915 0.50 +1047333.748 1.00 +1047336.991 0.50 +1047402.303 0.00 +1047408.539 0.50 +1047414.776 0.00 +1047425.444 0.50 +1047428.177 1.00 +1047430.972 0.50 +1047435.591 0.00 +1047463.197 0.50 +1047485.607 1.00 +1047499.472 0.50 +1047509.224 1.00 +1047515.337 0.50 +1047551.395 1.00 +1047558.273 0.50 +1047583.009 1.00 +1047588.140 0.50 +1047610.844 1.00 +1047614.303 0.50 +1047619.993 1.00 +1047623.284 0.50 +1047656.279 1.00 +1048083.927 0.50 +1048208.167 1.00 +1048215.606 0.50 +1048245.381 1.00 +1048260.714 0.50 +1048281.052 0.00 +1048360.624 0.50 +1048368.336 0.00 +1048392.151 0.50 +1048397.420 0.00 +1048858.236 0.50 +1048865.054 0.00 +1048914.304 0.50 +1048919.582 0.00 +1048927.422 0.50 +1048933.418 0.00 +1183514.868 0.50 +1183526.003 0.00 +1183564.060 0.50 +1183571.389 0.00 +1183586.336 0.50 +1183593.882 0.00 +1183618.998 0.50 +1183627.204 0.00 +1183656.435 0.50 +1183662.395 0.00 +1183716.981 0.50 +1183722.963 0.00 +1183789.778 0.50 +1183796.240 0.00 +1183844.266 0.50 +1183850.453 0.00 +1183876.008 0.50 +1183881.779 0.00 +1183932.594 0.50 +1183961.777 0.00 +1183962.273 0.50 +1183969.461 0.00 +1183990.520 0.50 +1183995.478 0.00 +1184022.320 0.50 +1184027.253 0.00 +1184378.314 0.50 +1184386.071 0.00 +1184410.125 0.50 +1184416.531 0.00 +1184438.252 0.50 +1184446.042 0.00 +1184452.860 0.50 +1184456.362 0.00 +1184482.915 0.50 +1184489.625 0.00 +1184514.238 0.50 +1184519.942 0.00 +1184528.822 0.50 +1184533.676 0.00 +1184557.808 0.50 +1184562.356 0.00 +1184575.260 0.50 +1184578.768 0.00 +1184612.280 0.50 +1184619.851 0.00 +1184649.833 0.50 +1184656.431 0.00 +1184676.751 0.50 +1184683.603 0.00 +1184686.919 0.50 +1184705.292 0.00 +1184711.881 0.50 +1184716.235 1.00 +1184720.164 0.50 +1184722.729 0.00 +1184751.168 0.50 +1184757.069 0.00 +1184788.335 0.50 +1184793.531 0.00 +1184825.080 0.50 +1184831.298 0.00 +1184838.998 0.50 +1184845.978 0.00 +1184846.419 0.50 +1184853.601 0.00 +1184862.211 0.50 +1184865.981 0.00 diff --git a/examples/testbench/decent_band/tsv/all (Channel)_util.tsv b/examples/testbench/decent_band/tsv/all (Channel)_util.tsv new file mode 100644 index 000000000..308fc3280 --- /dev/null +++ b/examples/testbench/decent_band/tsv/all (Channel)_util.tsv @@ -0,0 +1,4 @@ +time count +0.000 0.00 +1048681.945 1.00 +1050273.272 0.00 diff --git a/examples/testbench/decent_band/tsv/all (Python)_util.tsv b/examples/testbench/decent_band/tsv/all (Python)_util.tsv new file mode 100644 index 000000000..eb57e7853 --- /dev/null +++ b/examples/testbench/decent_band/tsv/all (Python)_util.tsv @@ -0,0 +1,14 @@ +time count +0.000 0.00 +478641.174 1.00 +922239.137 0.00 +922497.427 1.00 +922606.850 0.00 +922815.999 1.00 +962519.280 0.00 +962723.661 1.00 +1047360.569 0.00 +1048908.961 1.00 +1048924.893 0.00 +1050359.631 1.00 +1183469.202 0.00 diff --git a/examples/testbench/decent_band/tsv/all (System Memory)_util.tsv b/examples/testbench/decent_band/tsv/all (System Memory)_util.tsv new file mode 100644 index 000000000..d2d9245bc --- /dev/null +++ b/examples/testbench/decent_band/tsv/all (System Memory)_util.tsv @@ -0,0 +1,24 @@ +time count +0.000 0.00 +1020277.868 0.00 +1020517.864 0.00 +1021638.640 0.00 +1021896.476 0.00 +1022852.940 0.00 +1023094.891 0.00 +1024127.778 0.00 +1024326.370 0.00 +1025091.417 0.00 +1025243.869 0.00 +1048334.454 0.01 +1183909.479 0.01 +1183973.835 0.00 +1184355.765 0.00 +1184412.082 0.00 +1184466.441 0.00 +1184520.480 0.00 +1184563.664 0.00 +1184616.464 0.00 +1184671.451 0.00 +1184732.637 0.00 +1184825.486 0.00 diff --git a/examples/testbench/decent_band/tsv/all (Utility)_util.tsv b/examples/testbench/decent_band/tsv/all (Utility)_util.tsv new file mode 100644 index 000000000..eb2ceb069 --- /dev/null +++ b/examples/testbench/decent_band/tsv/all (Utility)_util.tsv @@ -0,0 +1,924 @@ +time count +0.000 0.00 +478125.062 0.50 +478182.035 0.00 +478215.611 0.50 +478215.750 1.00 +478227.571 0.50 +478293.256 0.00 +478321.896 0.50 +478322.038 1.00 +478327.141 0.50 +478364.450 0.00 +478393.250 0.50 +478397.534 1.00 +478398.019 0.50 +478455.013 0.00 +478487.003 0.50 +478488.917 1.00 +478491.783 0.50 +478610.233 0.00 +478651.813 0.50 +478657.222 0.00 +922202.362 0.50 +922257.734 0.00 +922271.051 0.50 +922282.907 1.00 +922293.697 0.50 +922313.422 0.00 +922320.369 0.50 +922352.823 1.00 +922360.236 0.50 +922430.159 0.00 +922485.054 0.50 +922500.295 0.00 +922615.976 0.50 +922651.888 0.00 +922678.906 0.50 +922683.753 0.00 +922685.337 0.50 +922723.942 0.00 +922748.730 0.50 +922752.172 1.00 +922757.292 0.50 +922781.292 0.00 +922821.002 0.50 +922824.608 0.00 +962526.481 0.50 +962567.952 0.00 +962598.963 0.50 +962603.564 0.00 +962606.098 0.50 +962647.123 0.00 +962678.949 0.50 +962723.015 0.00 +962756.169 0.50 +962760.737 0.00 +999297.143 0.50 +999351.129 0.00 +999365.982 0.50 +999372.250 1.00 +999376.414 0.50 +999398.360 0.00 +999406.012 0.50 +999503.615 0.00 +999507.767 0.50 +999524.730 1.00 +999529.853 0.50 +999537.920 0.00 +999551.347 0.50 +999554.898 0.00 +1019311.922 0.50 +1019495.678 1.00 +1019495.815 0.50 +1019516.941 1.00 +1019521.801 0.50 +1019527.822 1.00 +1019531.556 0.50 +1019576.947 1.00 +1019579.130 0.50 +1019594.838 1.00 +1019598.189 0.50 +1019620.039 0.00 +1019628.570 0.50 +1019636.957 1.00 +1019640.979 0.50 +1019699.933 0.00 +1019714.252 0.50 +1019811.952 0.00 +1019827.080 0.50 +1019830.493 1.00 +1019834.164 0.50 +1019933.635 1.00 +1019950.329 0.50 +1019974.821 1.00 +1020004.219 0.50 +1020027.498 1.00 +1020060.964 0.50 +1020081.461 1.00 +1020099.613 0.50 +1020115.715 1.00 +1020149.907 0.50 +1020169.732 1.00 +1020198.015 0.50 +1020215.638 1.00 +1020251.160 0.50 +1020263.069 1.00 +1020281.769 0.50 +1020365.103 1.00 +1020389.610 0.50 +1020411.660 1.00 +1020446.324 0.50 +1020465.390 1.00 +1020580.691 0.50 +1020602.314 1.00 +1020623.469 0.50 +1020634.362 1.00 +1020671.314 0.50 +1020676.289 0.00 +1020691.218 0.50 +1020713.369 0.00 +1020722.173 0.50 +1020750.432 1.00 +1020787.419 0.50 +1020808.922 0.00 +1020810.229 0.50 +1020839.392 1.00 +1020846.307 0.50 +1020864.411 1.00 +1020874.211 0.50 +1020894.975 1.00 +1020913.363 0.50 +1020928.632 1.00 +1020930.984 0.50 +1020952.149 1.00 +1020985.345 0.50 +1020996.549 0.00 +1021013.914 0.50 +1021015.936 1.00 +1021039.622 0.50 +1021048.610 0.00 +1021058.657 0.50 +1021061.000 1.00 +1021089.194 0.50 +1021095.392 0.00 +1021103.473 0.50 +1021113.857 1.00 +1021142.700 0.50 +1021159.797 1.00 +1021175.820 0.50 +1021181.610 0.00 +1021196.702 0.50 +1021219.821 1.00 +1021266.724 0.50 +1021284.322 1.00 +1021292.380 0.50 +1021312.878 1.00 +1021325.094 0.50 +1021339.701 1.00 +1021358.196 0.50 +1021375.545 1.00 +1021396.717 0.50 +1021396.820 0.00 +1021416.548 0.50 +1021427.029 1.00 +1021465.556 0.50 +1021477.105 0.00 +1021485.938 0.50 +1021492.376 1.00 +1021517.858 0.50 +1021535.050 1.00 +1021563.059 0.50 +1021570.371 0.00 +1021585.593 0.50 +1021598.522 1.00 +1021633.743 0.50 +1021650.015 1.00 +1021708.350 0.50 +1021729.660 1.00 +1021748.943 0.50 +1021776.980 0.00 +1021799.332 0.50 +1021800.527 1.00 +1021831.515 0.50 +1021836.851 0.00 +1021856.216 0.50 +1021869.553 1.00 +1021890.510 0.50 +1021906.979 1.00 +1021935.187 0.50 +1021994.272 0.00 +1022016.171 0.50 +1022033.123 1.00 +1022036.573 0.50 +1022059.820 1.00 +1022077.471 0.50 +1022096.587 1.00 +1022115.674 0.50 +1022147.738 0.00 +1022149.566 0.50 +1022163.230 1.00 +1022191.124 0.50 +1022202.817 0.00 +1022220.315 0.50 +1022226.791 1.00 +1022257.425 0.50 +1022276.351 1.00 +1022306.819 0.50 +1022330.425 1.00 +1022345.941 0.50 +1022359.294 1.00 +1022392.149 0.50 +1022402.911 1.00 +1022420.902 0.50 +1022466.782 1.00 +1022494.632 0.50 +1022519.257 1.00 +1022522.165 0.50 +1022536.070 1.00 +1022545.038 0.50 +1022565.474 1.00 +1022572.262 0.50 +1022586.450 1.00 +1022614.121 0.50 +1022625.358 1.00 +1022643.447 0.50 +1022672.695 1.00 +1022681.509 0.50 +1022694.589 1.00 +1022708.855 0.50 +1022721.685 0.00 +1022729.096 0.50 +1022732.564 1.00 +1022761.644 0.50 +1022770.283 0.00 +1022792.567 0.50 +1022795.202 1.00 +1022828.127 0.50 +1022853.928 1.00 +1022898.698 0.50 +1022915.164 1.00 +1022928.362 0.50 +1022953.932 1.00 +1022971.622 0.50 +1022987.959 1.00 +1023010.260 0.50 +1023030.646 0.00 +1023050.877 0.50 +1023051.263 1.00 +1023065.156 0.50 +1023086.962 1.00 +1023113.349 0.50 +1023128.018 1.00 +1023140.111 0.50 +1023152.278 1.00 +1023157.689 0.50 +1023163.973 1.00 +1023168.055 0.50 +1023180.849 0.00 +1023197.049 0.50 +1023208.594 0.00 +1023217.702 0.50 +1023219.200 1.00 +1023224.712 0.50 +1023231.705 1.00 +1023236.361 0.50 +1023243.711 1.00 +1023248.462 0.50 +1023255.017 1.00 +1023259.870 0.50 +1023266.635 1.00 +1023271.371 0.50 +1023278.427 1.00 +1023287.444 0.50 +1023296.822 1.00 +1023297.512 0.50 +1023334.341 0.00 +1023345.970 0.50 +1023357.571 1.00 +1023364.867 0.50 +1023374.111 1.00 +1023376.256 0.50 +1023398.373 1.00 +1023403.459 0.50 +1023435.265 1.00 +1023447.377 0.50 +1023468.882 1.00 +1023524.215 0.50 +1023544.753 1.00 +1023551.388 0.50 +1023567.314 1.00 +1023593.726 0.50 +1023606.937 0.00 +1023608.446 0.50 +1023620.187 1.00 +1023665.627 0.50 +1023676.616 0.00 +1023685.236 0.50 +1023692.044 1.00 +1023718.305 0.50 +1023726.876 0.00 +1023741.592 0.50 +1023746.877 1.00 +1023765.560 0.50 +1023777.870 1.00 +1023800.215 0.50 +1023810.031 0.00 +1023813.667 0.50 +1023824.143 1.00 +1023831.242 0.50 +1023837.657 1.00 +1023842.050 0.50 +1023848.474 1.00 +1023855.887 0.50 +1023864.845 1.00 +1023869.083 0.50 +1023874.606 1.00 +1023879.071 0.50 +1023885.288 1.00 +1023886.789 0.50 +1023900.795 1.00 +1023904.789 0.50 +1023911.051 1.00 +1023919.322 0.50 +1023924.498 1.00 +1023978.079 0.50 +1023982.068 0.00 +1023994.093 0.50 +1024023.781 1.00 +1024050.003 0.50 +1024066.601 1.00 +1024067.567 0.50 +1024083.242 1.00 +1024112.260 0.50 +1024125.702 1.00 +1024142.386 0.50 +1024176.449 1.00 +1024187.245 0.50 +1024197.413 1.00 +1024204.799 0.50 +1024214.037 1.00 +1024298.425 0.50 +1024316.465 1.00 +1024327.960 0.50 +1024336.179 1.00 +1024341.424 0.50 +1024350.467 1.00 +1024359.821 0.50 +1024367.407 1.00 +1024372.548 0.50 +1024380.168 1.00 +1024385.425 0.50 +1024393.264 1.00 +1024397.528 0.50 +1024403.247 1.00 +1024409.951 0.50 +1024415.079 1.00 +1024418.409 0.50 +1024422.747 1.00 +1024425.896 0.50 +1024430.164 1.00 +1024433.324 0.50 +1024437.680 1.00 +1024440.818 0.50 +1024445.675 1.00 +1024450.251 0.50 +1024457.169 1.00 +1024462.152 0.50 +1024468.852 1.00 +1024473.600 0.50 +1024481.925 1.00 +1024488.279 0.50 +1024497.214 1.00 +1024532.506 0.50 +1024551.826 1.00 +1024557.161 0.50 +1024557.310 0.00 +1024564.753 0.50 +1024569.824 0.00 +1024577.086 0.50 +1024582.272 0.00 +1024585.057 0.50 +1024590.350 0.00 +1024597.545 0.50 +1024601.896 0.00 +1024604.599 0.50 +1024607.410 1.00 +1024610.839 0.50 +1024615.132 1.00 +1024619.071 0.50 +1024623.671 1.00 +1024626.791 0.50 +1024631.171 1.00 +1024634.661 0.50 +1024639.219 1.00 +1024642.520 0.50 +1024647.137 1.00 +1024653.786 0.50 +1024658.361 1.00 +1024661.720 0.50 +1024666.000 1.00 +1024669.305 0.50 +1024674.022 1.00 +1024677.281 0.50 +1024682.524 1.00 +1024686.570 0.50 +1024691.334 1.00 +1024694.870 0.50 +1024701.141 1.00 +1024710.027 0.50 +1024725.666 0.00 +1024736.750 0.50 +1024738.342 1.00 +1024762.023 0.50 +1024774.483 1.00 +1024779.744 0.50 +1024804.740 1.00 +1024816.493 0.50 +1024826.612 1.00 +1024833.728 0.50 +1024836.925 0.00 +1024843.783 0.50 +1024849.380 1.00 +1024856.773 0.50 +1024862.364 1.00 +1024865.775 0.50 +1024870.158 1.00 +1024873.470 0.50 +1024878.042 1.00 +1024882.017 0.50 +1024887.041 1.00 +1024891.672 0.50 +1024896.902 1.00 +1024934.671 0.50 +1024954.495 0.00 +1024959.693 0.50 +1024968.486 1.00 +1025006.101 0.50 +1025019.490 1.00 +1025036.615 0.50 +1025052.455 1.00 +1025062.406 0.50 +1025084.356 1.00 +1025136.235 0.50 +1025163.800 1.00 +1025193.188 0.50 +1025214.680 1.00 +1025220.882 0.50 +1025229.189 1.00 +1025233.988 0.50 +1025241.497 1.00 +1025247.221 0.50 +1025257.689 1.00 +1025263.857 0.50 +1025270.770 1.00 +1025275.650 0.50 +1025283.515 1.00 +1025288.725 0.50 +1025296.185 1.00 +1025301.041 0.50 +1025308.726 1.00 +1025315.060 0.50 +1025322.404 1.00 +1025328.213 0.50 +1025336.959 1.00 +1025342.196 0.50 +1025359.303 1.00 +1025364.244 0.50 +1025370.767 1.00 +1025375.170 0.50 +1025381.120 1.00 +1025382.984 0.50 +1025385.474 0.00 +1025391.182 0.50 +1025394.660 0.00 +1025399.314 0.50 +1025402.789 0.00 +1025408.650 0.50 +1025411.987 0.00 +1025424.161 0.50 +1025425.162 1.00 +1025483.181 0.50 +1025498.175 1.00 +1025513.498 0.50 +1025527.688 0.00 +1025539.025 0.50 +1025543.882 1.00 +1025548.382 0.50 +1025558.764 1.00 +1025586.146 0.50 +1025602.869 0.00 +1025611.427 0.50 +1025614.838 1.00 +1025619.617 0.50 +1025622.226 0.00 +1025625.266 0.50 +1025628.726 0.00 +1025633.859 0.50 +1025638.213 1.00 +1025642.194 0.50 +1025647.842 1.00 +1025647.947 0.50 +1025652.082 0.00 +1025656.285 0.50 +1025662.911 0.00 +1025663.084 0.50 +1025668.053 1.00 +1025672.011 0.50 +1025676.517 0.00 +1025677.535 0.50 +1025681.288 0.00 +1025685.439 0.50 +1025689.447 0.00 +1025693.048 0.50 +1025695.077 1.00 +1025699.308 0.50 +1025703.809 0.00 +1025704.517 0.50 +1025708.414 0.00 +1025714.241 0.50 +1025718.680 0.00 +1025721.602 0.50 +1025724.009 1.00 +1025728.305 0.50 +1025731.260 0.00 +1025733.660 0.50 +1025737.322 0.00 +1025743.220 0.50 +1025746.411 1.00 +1025749.866 0.50 +1025755.473 1.00 +1025757.279 0.50 +1025761.694 0.00 +1025766.641 0.50 +1025770.104 1.00 +1025773.447 0.50 +1025779.732 1.00 +1025781.733 0.50 +1025784.983 0.00 +1025792.915 0.50 +1025793.659 1.00 +1025799.588 0.50 +1025800.787 0.00 +1025805.808 0.50 +1025809.659 1.00 +1025811.421 0.50 +1025816.652 0.00 +1025817.749 0.50 +1025826.110 0.00 +1025827.856 0.50 +1025879.400 0.00 +1025906.153 0.50 +1025912.069 0.00 +1027308.633 0.50 +1027310.719 1.00 +1027329.152 0.50 +1027395.869 0.00 +1027416.270 0.50 +1027421.057 0.00 +1028703.178 0.50 +1028712.514 0.00 +1028717.674 0.50 +1028780.475 0.00 +1028818.229 0.50 +1028823.793 0.00 +1042970.205 0.50 +1043065.662 0.00 +1043079.828 0.50 +1043116.150 0.00 +1043117.747 0.50 +1043158.329 0.00 +1043182.818 0.50 +1043276.396 0.00 +1043292.115 0.50 +1043357.314 0.00 +1043363.999 0.50 +1043380.714 1.00 +1043439.363 0.50 +1043456.611 0.00 +1043462.537 0.50 +1043480.043 1.00 +1043521.460 0.50 +1043527.246 0.00 +1043539.388 0.50 +1043543.456 1.00 +1043569.949 0.50 +1043608.194 1.00 +1043755.669 0.50 +1043775.142 0.00 +1043798.301 0.50 +1043801.712 1.00 +1043819.547 0.50 +1043843.446 1.00 +1043856.144 0.50 +1043873.303 0.00 +1043892.005 0.50 +1043895.364 1.00 +1043927.706 0.50 +1043943.742 1.00 +1043944.189 0.50 +1043966.030 0.00 +1043975.777 0.50 +1043979.505 1.00 +1043984.049 0.50 +1043989.105 1.00 +1043993.343 0.50 +1043997.722 1.00 +1044001.005 0.50 +1044064.430 0.00 +1044073.642 0.50 +1044089.069 1.00 +1044098.310 0.50 +1044226.567 0.00 +1044226.872 0.50 +1044247.954 1.00 +1044259.135 0.50 +1044300.172 1.00 +1044329.824 0.50 +1044354.406 1.00 +1044386.707 0.50 +1044410.934 1.00 +1044445.597 0.50 +1044466.872 1.00 +1044480.531 0.50 +1044499.704 1.00 +1044567.279 0.50 +1044587.570 0.00 +1044589.211 0.50 +1044610.308 1.00 +1044652.525 0.50 +1044661.375 0.00 +1044673.215 0.50 +1044681.828 1.00 +1044694.814 0.50 +1044708.340 1.00 +1044713.469 0.50 +1044720.801 1.00 +1044725.565 0.50 +1044733.154 1.00 +1044739.424 0.50 +1044748.470 1.00 +1044753.463 0.50 +1044761.516 1.00 +1044767.193 0.50 +1044780.080 1.00 +1044784.929 0.50 +1044820.621 1.00 +1044825.226 0.50 +1044846.453 1.00 +1044894.401 0.50 +1044900.995 0.00 +1044914.641 0.50 +1044917.922 1.00 +1044921.456 0.50 +1044926.303 1.00 +1044929.620 0.50 +1044956.768 1.00 +1044957.622 0.50 +1044977.578 1.00 +1044983.228 0.50 +1045043.456 0.00 +1045056.568 0.50 +1045063.383 1.00 +1045069.759 0.50 +1045129.604 1.00 +1045161.665 0.50 +1045193.135 1.00 +1045222.693 0.50 +1045244.778 1.00 +1045294.673 0.50 +1045307.601 0.00 +1045319.687 0.50 +1045327.219 1.00 +1045373.960 0.50 +1045394.111 1.00 +1045447.100 0.50 +1045477.587 1.00 +1045506.945 0.50 +1045516.256 0.00 +1045530.483 0.50 +1045538.802 1.00 +1045572.715 0.50 +1045590.083 1.00 +1045596.571 0.50 +1045606.996 1.00 +1045613.389 0.50 +1045623.192 1.00 +1045627.364 0.50 +1045656.151 1.00 +1045675.044 0.50 +1045696.208 1.00 +1045698.593 0.50 +1045723.770 1.00 +1045730.321 0.50 +1045738.104 0.00 +1045740.255 0.50 +1045762.330 1.00 +1045816.314 0.50 +1045829.832 1.00 +1045834.051 0.50 +1045840.224 1.00 +1045845.981 0.50 +1045884.019 1.00 +1045890.352 0.50 +1045899.719 1.00 +1045917.954 0.50 +1045933.357 1.00 +1045982.091 0.50 +1045999.345 0.00 +1046021.175 0.50 +1046041.662 0.00 +1046056.676 0.50 +1046076.892 1.00 +1046091.530 0.50 +1046099.419 1.00 +1046104.230 0.50 +1046111.528 1.00 +1046117.513 0.50 +1046126.367 1.00 +1046135.932 0.50 +1046171.137 1.00 +1046202.563 0.50 +1046217.381 1.00 +1046250.716 0.50 +1046253.709 0.00 +1046267.074 0.50 +1046278.030 1.00 +1046314.988 0.50 +1046339.475 1.00 +1046346.238 0.50 +1046347.300 0.00 +1046356.442 0.50 +1046361.479 1.00 +1046366.368 0.50 +1046371.169 1.00 +1046376.461 0.50 +1046382.603 1.00 +1046386.495 0.50 +1046392.676 1.00 +1046393.607 0.50 +1046397.357 0.00 +1046403.160 0.50 +1046406.375 0.00 +1046413.126 0.50 +1046413.696 1.00 +1046417.530 0.50 +1046420.873 0.00 +1046424.509 0.50 +1046430.009 0.00 +1046432.425 0.50 +1046436.284 1.00 +1046440.982 0.50 +1046441.751 0.00 +1046446.383 0.50 +1046451.457 0.00 +1046452.072 0.50 +1046458.827 0.00 +1046460.896 0.50 +1046470.788 1.00 +1046477.290 0.50 +1046505.755 0.00 +1046529.968 0.50 +1046535.783 0.00 +1046561.498 0.50 +1046574.575 0.00 +1046575.458 0.50 +1046629.117 1.00 +1046632.653 0.50 +1046651.407 1.00 +1046656.178 0.50 +1046661.879 1.00 +1046686.301 0.50 +1046714.430 1.00 +1046725.278 0.50 +1046731.836 0.00 +1046740.944 0.50 +1046745.147 1.00 +1046745.264 0.50 +1046777.346 0.00 +1046791.619 0.50 +1046792.290 1.00 +1046796.714 0.50 +1046847.610 0.00 +1046858.968 0.50 +1046861.463 1.00 +1046865.754 0.50 +1046953.784 0.00 +1046963.523 0.50 +1046968.448 1.00 +1046972.915 0.50 +1047041.315 1.00 +1047045.904 0.50 +1047060.705 1.00 +1047095.389 0.50 +1047157.403 1.00 +1047168.964 0.50 +1047183.873 0.00 +1047197.484 0.50 +1047219.317 1.00 +1047280.431 0.50 +1047296.481 0.00 +1047308.491 0.50 +1047326.874 1.00 +1047380.812 0.50 +1047384.780 0.00 +1047402.395 0.50 +1047409.220 1.00 +1047457.574 0.50 +1047465.051 0.00 +1047478.032 0.50 +1047485.106 1.00 +1047513.167 0.50 +1047531.411 1.00 +1047559.608 0.50 +1047579.867 1.00 +1047591.084 0.50 +1047600.351 0.00 +1047606.599 0.50 +1047617.954 1.00 +1047648.258 0.50 +1047652.121 0.00 +1047667.464 0.50 +1047704.246 1.00 +1047714.252 0.50 +1047727.631 1.00 +1047733.357 0.50 +1047743.823 1.00 +1047767.970 0.50 +1047866.075 1.00 +1047885.816 0.50 +1047892.303 0.00 +1048028.782 0.50 +1048046.924 0.00 +1048073.019 0.50 +1048079.943 0.00 +1048089.840 0.50 +1048102.683 0.00 +1048111.659 0.50 +1048120.678 0.00 +1048129.055 0.50 +1048135.725 1.00 +1048178.094 0.50 +1048202.620 1.00 +1048208.721 0.50 +1048233.751 0.00 +1048240.244 0.50 +1048253.255 1.00 +1048259.273 0.50 +1048303.934 1.00 +1048310.306 0.50 +1048319.181 1.00 +1048367.651 0.50 +1048535.478 1.00 +1048541.225 0.50 +1048570.806 1.00 +1048584.206 0.50 +1048804.548 0.00 +1048841.090 0.50 +1048854.074 1.00 +1048881.903 0.50 +1048904.134 0.00 +1050297.761 0.50 +1050298.787 1.00 +1050315.697 0.50 +1050316.398 0.00 +1144670.598 0.50 +1144703.476 0.00 +1144732.332 0.50 +1144738.433 0.00 +1144879.567 0.50 +1144915.226 0.00 +1144943.824 0.50 +1144961.684 0.00 +1144974.220 0.50 +1144991.831 0.00 +1145003.814 0.50 +1145008.939 0.00 +1145013.909 0.50 +1145017.309 0.00 +1145021.935 0.50 +1145025.293 0.00 +1183447.115 0.50 +1183505.306 1.00 +1183539.347 0.50 +1183556.775 0.00 +1183567.025 0.50 +1183584.044 1.00 +1183592.790 0.50 +1183620.810 1.00 +1183632.883 0.50 +1183682.119 1.00 +1183686.977 0.50 +1183740.807 1.00 +1183767.389 0.50 +1183786.910 1.00 +1183824.028 0.50 +1183846.435 1.00 +1183856.010 0.50 +1183875.602 1.00 +1183938.722 0.50 +1183966.177 1.00 +1183997.470 0.50 +1184344.122 1.00 +1184386.204 0.50 +1184404.214 1.00 +1184437.440 0.50 +1184459.636 1.00 +1184492.880 0.50 +1184513.128 1.00 +1184539.716 0.50 +1184556.087 1.00 +1184588.795 0.50 +1184610.581 1.00 +1184645.091 0.50 +1184665.321 1.00 +1184688.358 0.50 +1184692.744 0.00 +1184717.064 0.50 +1184721.421 1.00 +1184764.287 0.50 +1184788.784 1.00 +1184801.507 0.50 +1184810.844 0.00 +1184818.629 0.50 +1184847.345 0.00 diff --git a/examples/testbench/event_graph_legion_python_main_1.pdf b/examples/testbench/event_graph_legion_python_main_1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d90eedb33ee10433f47317a54fa9ae92f6148cf0 GIT binary patch literal 25345 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 WjUAoOEdm1N<>w=0Vv<&oA^bnr2%($+ literal 0 HcmV?d00001 diff --git a/examples/testbench/go.sh b/examples/testbench/go.sh new file mode 100644 index 000000000..e851f13d0 --- /dev/null +++ b/examples/testbench/go.sh @@ -0,0 +1,15 @@ +rm -rf prof* +rm -rf spy* +rm -rf legion_prof* +#prof +../../../legate.core/install/bin/legate --cpus 1 test.py -lg:prof 1 -lg:prof_logfile prof_%.gz + +#spy +../../../legate.core/install/bin/legate --cpus 1 test.py -lg:spy -logfile spy_%.log +../../../legate.core/legion/tools/legion_spy.py -dez spy_*.log + +#both +../../../legate.core/legion/tools/legion_prof.py prof_*.gz spy_*.log +cp dataflow_legion_python* legion_prof/ +cp event_graph_legion_python* legion_prof/ +echo "done" diff --git a/examples/testbench/good_band/dataflow_legion_python_main_1.pdf b/examples/testbench/good_band/dataflow_legion_python_main_1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..26c905f13c9399024e89ed427c01a5865fa7f38f GIT binary patch literal 31522 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 literal 0 HcmV?d00001 diff --git a/examples/testbench/good_band/event_graph_legion_python_main_1.pdf b/examples/testbench/good_band/event_graph_legion_python_main_1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..08c5b7d64537c700fd23892164e97f23506cc063 GIT binary patch literal 27545 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 + + + + + + + + + + + + + + + + + + +
+
Node Range: :
+
+ + +
+
+
+
+
+
+ + diff --git a/examples/testbench/good_band/js/timeline.js b/examples/testbench/good_band/js/timeline.js new file mode 100644 index 000000000..ba3db5e30 --- /dev/null +++ b/examples/testbench/good_band/js/timeline.js @@ -0,0 +1,2734 @@ +// Some of the constants are read in from load_scale_json +var constants = { + margin_left: 350, + margin_right: 75, + margin_bottom: 50, + margin_top: 50, + min_feature_width: 3, + min_gap_width: 1, + util_height: 100, + util_levels: 4, + elem_separation: 2, +} + +var op_dependencies = {}; +var base_map = {}; +var prof_uid_map = {}; + +// Contains the children for each util file +var util_files = {}; + +var state = {}; +var mouseX = 0; +var utilline = d3.svg.line() + .interpolate("step-after") + .x(function(d) { return state.x(+d.time); }) + .y(function(d) { return state.y(+d.count); }); +var timeBisector = d3.bisector(function(d) { return d.time; }).left; +// const num_colors = 20; +// var color = d3.scale.linear() +// .domain([0, num_colors]) +// .range(["green", "blue", "red", "yellow"]); + +String.prototype.hashCode = function() { + var hash = 0; + if (this.length == 0) return hash; + for (i = 0; i < this.length; i++) { + var c = this.charCodeAt(i); + var b = this.charCodeAt(c % this.length); + hash = ((hash<<5)-hash)^c^b; + hash = hash & hash; + } + return Math.abs(hash); +} + +function parseURLParameters() { + var match, + pl = /\+/g, // Regex for replacing addition symbol with a space + search = /([^&=]+)=?([^&]*)/g, + decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, + query = window.location.search.substring(1); + + var urlParams = {}; + while (match = search.exec(query)) + urlParams[decode(match[1])] = decode(match[2]); + + if ("collapseAll" in urlParams) + state.collapseAll = (urlParams["collapseAll"].toLowerCase() === "true"); + + if ("resolution" in urlParams) + state.resolution = Math.max(1, parseFloat(urlParams["resolution"])); + // adjust zoom + var zstart = constants.start; + if ("start" in urlParams) + zstart = Math.max(constants.start, parseFloat(urlParams["start"])); + + var zend = constants.end; + if ("end" in urlParams) + zend = Math.min(constants.end, parseFloat(urlParams["end"])); + + if(zstart < zend) { + // set zoom to get: (zend - start) * zoom * scale = $("#timeline").width() + var newZoom = $("#timeline").width() / state.scale / (zend - zstart); + adjustZoom(newZoom, false); + + // set scrollLeft to get: zstart * zoom * state.scale = scrollLeft() + $("#timeline").scrollLeft(convertToPos(state, zstart)); + } + + if ("search" in urlParams) { + state.searchEnabled = true; + searchRegex = new Array(sizeHistory); + currentPos = 0; + nextPos = 1; + searchRegex[currentPos] = new RegExp(urlParams["search"]); + } +} + +function makeTimelineTransparent() { + state.timelineSvg.select("g#timeline").style("opacity", "0.1"); + $("#timeline").css("overflow-x", "hidden"); + state.timelineSvg.select("g#lines").style("opacity", "0.1"); + state.timelineSvg.select("g.locator").style("opacity", "0.1"); + state.timelineSvg.selectAll("path.util").style("opacity", "0.1"); +} + +function makeTimelineOpaque() { + state.timelineSvg.select("g#timeline").style("opacity", "1.0"); + $("#timeline").css("overflow-x", "scroll"); + state.timelineSvg.select("g#lines").style("opacity", "1.0"); + state.timelineSvg.select("g.locator").style("opacity", "1.0"); + state.timelineSvg.selectAll("path.util").style("opacity", "1.0"); +} + +function mouseMoveHandlerWhenDown() { + var p = d3.mouse(this); + var select_block = state.timelineSvg.select("rect.select-block"); + var select_text = state.timelineSvg.select("text.select-block"); + var newWidth = Math.abs(p[0] - mouseX); + select_block.attr("width", newWidth); + if (p[0] >= mouseX) { + select_block.attr("x", mouseX); + select_text.attr("x", mouseX + (p[0] - mouseX) / 2); + } else { + select_block.attr("x", p[0]); + select_text.attr("x", p[0] + (mouseX - p[0]) / 2); + } + var time = convertToTime(state, newWidth); + select_text.text(getTimeString(time, time)); +} + +function mouseMoveHandlerWhenUp() { + var p = d3.mouse(this); + var x = parseFloat(p[0]); + var scrollLeft = $("#timeline").scrollLeft(); + var paneWidth = $("#timeline").width(); + var currentTime = convertToTime(state, x); + + state.timelineSvg.select("g.locator").remove(); + var locator = state.timelineSvg.append("g").attr("class", "locator"); + locator.insert("line") + .attr({ + x1: p[0], + y1: 0, + x2: p[0], + y2: p[1] - state.thickness / 2, + class: "locator", + }); + locator.append("line") + .attr({ + x1: p[0], + y1: p[1] + state.thickness / 2, + x2: p[0], + y2: state.height, + class: "locator", + }); + var locatorText = locator.append("text"); + var text = getTimeString(currentTime, convertToTime(state, paneWidth)); + locatorText.attr("class", "locator").text(text) + if ((x - scrollLeft) < paneWidth - 100) { + locatorText.attr({x: x + 2, y: $(window).scrollTop() + 10}); + locatorText.attr("anchor", "start"); + } + else { + locatorText.attr({x: x - 2 - text.length * 7, y: $(window).scrollTop() + 10}); + locatorText.attr("anchor", "end"); + } +} + +function mouseDownHandler() { + state.timelineSvg.select("g.locator").remove(); + var p = d3.mouse(this); + state.timelineSvg.append("rect") + .attr({ + x : p[0], + y : 0, + class : "select-block", + width : 0, + height : state.height + }); + state.timelineSvg.append("text") + .attr({ + x : p[0], + y : p[1], + class : "select-block", + anchor : "middle", + "text-anchor" : "middle", + }).text("0 us"); + mouseX = p[0]; + state.timelineSvg.on("mousemove", null); + state.timelineSvg.on("mousemove", mouseMoveHandlerWhenDown); + $(document).off("keydown"); +} + +function get_kind(name) { + var util_regex = /\((.*?)\)/; + var kind_match = util_regex.exec(name); + if (kind_match) { + return kind_match[1]; + } +} + +function getLineColor(elem) { + var kind = get_kind(elem.text); + const colorMap = { + "CPU": "steelblue", + "GPU": "olivedrab", + "Utility": "crimson", + "IO": "orangered", + "Proc Group": "orangered", + "Proc Set": "orangered", + "OpenMP": "orangered", + "Python": "olivedrab", + "System Memory": "olivedrab", + "GASNet Global Memory": "crimson", + "Registered Memory": "darkmagenta", + "Socket Memory": "orangered", + "Zero-Copy Memory": "crimson", + "Framebuffer Memory": "blue", + "Disk Memory": "darkgoldenrod", + "HDF5 Memory": "olivedrab", + "File Memory": "orangered", + "L3 Cache Memory": "crimson", + "L2 Cache Memory": "darkmagenta", + "L1 Cache Memory": "olivedrab", + "Channel": "orangered" + }; + return colorMap[kind]; +} + +function drawUtil() { + // TODO: Add to state + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + var start_time = convertToTime(state, windowStart); + var end_time = convertToTime(state, windowEnd); + var filteredUtilData = []; + for (var i = 0; i < state.flattenedLayoutData.length; i++) { + var elem = state.flattenedLayoutData[i]; + if (elem.type == "util" && elem.enabled && elem.loaded && elem.visible) { + filteredUtilData.push(filterUtilData(elem)); + } + } + + state.x = d3.scale.linear().range([0, convertToPos(state, end_time)]); + state.x.domain([0, end_time]); + state.timelineSvg.selectAll("rect.util").remove(); + state.timelineSvg.selectAll("path.util").remove(); + var paths = state.timelineSvg.selectAll("path") + .data(filteredUtilData); + var totalWidth = windowStart + $("#timeline").width(); + paths.enter().append("rect") + .attr("class", "util") + .attr("base_y", lineLevelCalculator) + .attr("y", lineLevelCalculator) + .attr("x", 0) + .attr("fill", "transparent") + .attr("width", totalWidth) + .attr("height", constants.util_levels * state.thickness) + .on("mouseover", mouseover) + .on("mousemove", mousemove) + .on("mouseout", function() { + state.timelineSvg.select("g.focus").remove(); + state.timelineSvg.select("g.utilDesc").remove(); + }); + paths.enter().append("path") + .attr("base_y", lineLevelCalculator) + .attr("class", "util") + .attr("id", function(d, i) { return "util" + i}) + .attr("d", function (d) { return utilline(d.data); }) + .attr("stroke", getLineColor) + .on("mouseover", mouseover) + .on("mousemove", mousemove) + .on("mouseout", function() { + state.timelineSvg.select("g.focus").remove(); + state.timelineSvg.select("g.utilDesc").remove(); + }) + .attr("transform", + function(d) { + var y = lineLevelCalculator(d); + return "translate(0," + y + ")" + }); +} + + +function mouseUpHandler() { + var p = d3.mouse(this); + var select_block = state.timelineSvg.select("rect.select-block"); + var prevZoom = state.zoom; + var selectWidth = parseInt(select_block.attr("width")); + var svgWidth = state.timelineSvg.attr("width"); + if (state.rangeZoom && selectWidth > 10) { + var x = select_block.attr("x"); + state.zoomHistory.push({zoom: prevZoom, start: $("#timeline").scrollLeft()}); + adjustZoom(svgWidth / selectWidth, false); + $("#timeline").scrollLeft(x / prevZoom * state.zoom); + } + + state.timelineSvg.selectAll("rect.select-block").remove(); + state.timelineSvg.selectAll("text.select-block").remove(); + mouseX = 0; + state.timelineSvg.on("mousemove", null); + state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); + $(document).on("keydown", defaultKeydown); +} + +function turnOffMouseHandlers() { + state.timelineSvg.on("mousedown", null); + state.timelineSvg.on("mouseup", null); + state.timelineSvg.on("mousemove", null); + state.timelineSvg.on("mousemove", null); + // prevent right-click menu + state.timelineSvg.on("contextmenu", function () { + d3.event.preventDefault(); + }); +} + +function turnOnMouseHandlers() { + state.timelineSvg.on("mousedown", mouseDownHandler); + state.timelineSvg.on("mouseup", mouseUpHandler); + state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); + // prevent right-click menu + state.timelineSvg.on("contextmenu", function () { + d3.event.preventDefault(); + }); +} + +function drawLoaderIcon() { + var loaderGroup = state.loaderSvg.append("g") + .attr({ + id: "loader-icon", + }); + loaderGroup.append("path") + .attr({ + opacity: 0.2, + stroke: "steelblue", + fill: "#000", + d: "M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z" + }); + var path = loaderGroup.append("path") + .attr({ + stroke: "steelblue", + fill: "#000", + d: "M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0C22.32,8.481,24.301,9.057,26.013,10.047z" + }); + path.append("animateTransform") + .attr({ + attributeType: "xml", + attributeName: "transform", + type: "rotate", + from: "0 20 20", + to: "360 20 20", + dur: "0.5s", + repeatCount: "indefinite" + }); + state.loaderSvg.select("g").attr("visibility", "hidden"); + state.loaderSvg.attr("width", "0px") + .attr("height", "0px"); +} + +function showLoaderIcon() { + state.numLoading++; + state.loaderSvg.select("g").attr("visibility", "visible"); + state.loaderSvg.attr("width", "40px") + .attr("height", "40px"); +} + +function hideLoaderIcon() { + state.numLoading--; + if (state.numLoading == 0) { + state.loaderSvg.select("g").attr("visibility", "hidden"); + state.loaderSvg.attr("width", "0px") + .attr("height", "0px"); +; + } +} + +function get_time_str(time_val, convert) +{ + if (convert) { + if (time_val >= 1000000) { + var val = time_val/1000000; + val = parseFloat(val.toFixed(3)) + return val.toString() + " sec"; + } + if (time_val >= 1000) { + var val = time_val/1000; + val = parseFloat(val.toFixed(3)) + return val.toString() + " ms"; + } + } + return time_val.toString() + " us"; +} + +function getMouseOver() { + var paneWidth = $("#timeline").width(); + var left = paneWidth / 3; + var right = paneWidth * 2 / 3; + return function(d, i) { + var p = d3.mouse(this); + var x = parseFloat(p[0]); + var y = timelineLevelCalculator(d) - 5; + var descView = state.timelineSvg.append("g") + .attr("id", "desc"); + var text = descView.append("text") + .attr("x", x) + .attr("y", y) + .attr("class", "desc"); + var depElem = prof_uid_map[d.prof_uid][0]; + if ((depElem.in.length != 0) || (depElem.out.length != 0) || + (depElem.children.length !== 0) || (depElem.parents.length !==0 )) { + d3.select(this).style("cursor", "pointer"); + } + // descTexts is an array of Texts we will store in the desc view + var descTexts = []; + var total = d.end - d.start; + var delay = d.start - d.ready; + total = parseFloat(total.toFixed(3)) + delay = parseFloat(delay.toFixed(3)) + var initiation = ""; + // Insert texts in reverse order + if ((d.ready != undefined) && (d.ready != "") && (delay != 0)) { + descTexts.push("Ready State: " + get_time_str(delay,false)); + } + descTexts.push("End: " + get_time_str(d.end, false)); + descTexts.push("Start: " + get_time_str(d.start, false)); + descTexts.push("Total: " + get_time_str(total, true)); + if ((d.initiation != undefined) && d.initiation != "") { + descTexts.push("Initiator: " + state.operations[d.initiation].desc); + } + + // split d.title + var titles = d.title.split("$"); + if (titles.length > 0) { + for (var i = titles.length-1; i >= 0; --i) { + descTexts.push(titles[i]); + } + } + var title = text.append("tspan") + .attr("x", x) + .attr("dy", -12) + .attr("class", "desc") + .text(descTexts[0].replace(/ /g, "\u00A0")); // preserve spacing + + for (var i = 1; i < descTexts.length; ++i) { + var elem = text.append("tspan") + .attr("x", x) + .attr("dy", -12) + .attr("class", "desc") + .text(descTexts[i].replace(/ /g, "\u00A0")); // preserve spacing + } + + var bbox = descView.node().getBBox(); + var padding = 2; + var rect = descView.insert("rect", "text") + .attr("x", bbox.x - 2*padding) + .attr("y", bbox.y - padding) + .attr("width", bbox.width + (padding*4)) + .attr("height", bbox.height + (padding*2)) + .style("fill", "#222") + .style("opacity", "0.7"); + + var bboxRight = bbox.x + bbox.width; + var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); + + // If the box moves off the screen, nudge it back + if (bboxRight > timelineRight) { + var translation = -(bboxRight - timelineRight + 20); + descView.attr("transform", "translate(" + translation + ",0)"); + } + }; +} + +var sizeHistory = 10; +var currentPos; +var nextPos; +var searchRegex = null; + +function showSlider() { + $('#lowerLimit').text($('#node_slider').slider("values", 0)); + $('#upperLimit').text($('#node_slider').slider("values", 1)); +} + +function createMenuList1() { + var memory_kinds = []; + var num_nodes = state.num_nodes; + var num_mems = 0; + var dropdown_options = [ + { value: "ready", + id: "ready_all", + text: "View", + count: 1, + low_range: 0, + high_range: 1 + }, + { value: "memories", + id: "memories_all", + text: "Memories", + count: num_mems, + low_range: 0, + high_range: num_mems -1 + } + ]; + + // memories list + dropdown_options_memories = []; + + // misc items list + var pkind = { + id: "rr", + value: "rdy", + count: 1, + low_range: 0, + high_range: 1, + text: "Ready State" + }; + + dropdown_options_misc = []; + dropdown_options_misc.push(pkind); + + // create the remaining entries + function appendKind(elem) { + var value = state.processor_kinds[elem]; + if (elem.includes("Memory") && (value.count >= 0)) + { + num_mems = num_mems+1; + dropdown_options_memories.push(value); + } + if ((value.count >= 0) && (value.low_range != -1)) { + dropdown_options.push(value); + } + } + Object.keys(state.processor_kinds).forEach(appendKind); + + // main menu + d3.select("#dropdown").selectAll("optgroup") + .data(dropdown_options) + .enter() + .append("optgroup") + .attr('label', function(d) { return d.text;}) + .attr("id", function(d) { return d.id;}) + .attr("value", function(d) { return d.value;}); + + for (var j=0; j val)) + kind_proc.low_range = val; + if (kind_proc.high_range < val) + kind_proc.high_range = val; + } + } + } + + // Util graphs will have processors as their children as well. + if (type == "util") { + // get the children for the util view + var proc_children = getProcessors(text); + var count = 1; + var node_id = get_node_id(text); + var kind = get_kind(text); + // add to processor kinds: union of all processor kinds + if (!(kind in state.processor_kinds)) { + var pkind = { + id: kind, + value: kind, + count: proc_children.length, + low_range: -1, + high_range: -1, + text: kind + }; + state.processor_kinds[kind] = pkind; + } + if (state.processor_kinds[kind].count < proc_children.length) + state.processor_kinds[kind].count = proc_children.length; + + proc_children.forEach(function(proc_child) { + var child_element = getElement(depth + 1, proc_child.text, + proc_child.full_text, "proc", + proc_child.height, load_proc_timeline, + proc_child.tsv, element, undefined, + true, false); + element.children.push(child_element); + }); + } + + return element; +} + + +function calculateLayout() { + + // First element in the layout will be the all_util. All first-level + // elements will start off not enabled, and will be uncollapsed later + // programmatically + var num_nodes = Object.keys(util_files).length; + if (num_nodes > 1) { + var proc_kinds = util_files["all"]; + proc_kinds.forEach(function(name) { + var kind = "(" + get_kind(name) + ")"; + var util_name = "all nodes " + kind; + var kind_element = getElement(0, util_name, undefined, "util", + constants.util_levels, load_util, + "tsv/" + name + "_util.tsv", + undefined, util_files[kind], false, true); + state.layoutData.push(kind_element); + }); + } + + var seen_nodes = []; + state.processors.forEach(function(proc) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + var proc_regex = /(Processor|Memory) 0x1(e|d)([a-fA-f0-9]{4})[a-fA-f0-9]{10}$/; + // Memory Channel + var proc_channel_regex = /(Memory) 0x1(e)([a-fA-f0-9]{4})[a-fA-f0-9]{10}.*Channel/; + var proc_channel_match = proc_channel_regex.exec(proc.full_text); + var proc_match = proc_regex.exec(proc.full_text); + proc_match = proc_match || proc_channel_match; + if (proc_match) { + var node_id = parseInt(proc_match[3], 16); + if (!(node_id in seen_nodes)) { + seen_nodes[node_id] = 1; + if (node_id in util_files) { + var proc_kinds = util_files[node_id]; + proc_kinds.forEach(function(kind) { + var util_name = "node " + kind; + var kind_element = getElement(0, util_name, undefined, "util", + constants.util_levels, load_util, + "tsv/" + kind + "_util.tsv", + undefined, util_files[kind], + false, true); + state.layoutData.push(kind_element); + }); + } + } + } + else { + state.layoutData.push(getElement(0, proc.text, proc.full_text, "proc", + proc.height, load_proc_timeline, + proc.tsv, undefined, undefined, + false, true)); + } + }); + state.num_nodes = seen_nodes.length; +} + +function getElemCoords(elems) { + var proc = elems[0].proc; + var level = elems[0].level; + var startX = convertToPos(state, elems[0].start); + var endX = convertToPos(state, elems[elems.length-1].end); + var endBase = +proc.base; + var endLevel = endBase + level; + var y = dependencyLineLevelCalculator(endLevel); + return {startX: startX, endX: endX, y: y}; +} + + +function addLine(group, x1, x2, y1, y2, color, dashed) { + var line; + if (dashed) { + line = group.append("line") + .attr("x1", x1) + .attr("y1", y1) + .attr("x2", x2) + .attr("y2", y2) + .style("stroke", color) + .style("stroke-dasharray", "3,3") + .style("stroke-width", "1px"); + } else { + line = group.append("line") + .attr("x1", x1) + .attr("y1", y1) + .attr("x2", x2) + .attr("y2", y2) + .style("stroke", color) + .style("stroke-width", "1px"); + } + + var slope = (y2 - y1) / (x2 - x1); + var intercept = y1 - (slope * x1); + var triangleRotation = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI - 90; + + group.append("line") + .attr("x1", x1) + .attr("y1", y1) + .attr("x2", x2) + .attr("y2", y2) + .style("stroke", "transparent") + .style("stroke-width", "20px") + .on("mouseover", function() { + group.append("g") + .attr("class", "marker") + .append("path") + .attr("d", d3.svg.symbol().type("triangle-down").size(20)) + .style("stroke", color) + .style("fill", color); + }) + .on("mousemove", function() { + var marker = group.select("g.marker"); + var px = d3.mouse(this)[0] - 10; + var py = d3.mouse(this)[1] - ((slope > 0 ? 1 : -1) * 20); + if (px < Math.min(x1, x2)) { + px += 20; + } + if (py < Math.min(y1, y2)) { + py += 40; + } + + // some linear algebra here + var cx = (slope * py + px - slope * intercept) / (slope * slope + 1); + var cy = (slope * slope * py + slope * px + intercept) / (slope * slope + 1); + + marker.attr("transform", "translate(" + cx + "," + cy + ") rotate(" + triangleRotation + ")"); + }) + .on("mouseout", function() { + group.select("g.marker").remove(); + }); + + group.append("circle") + .attr("cx", x1) + .attr("cy", y1) + .attr("fill", "white") + .attr("stroke", "black") + .attr("r", 2.5) + .style("stroke-width", "1px"); + + group.append("circle") + .attr("cx", x2) + .attr("cy", y2) + .attr("fill", "white") + .attr("stroke", "black") + .attr("r", 2.5) + .style("stroke-width", "1px"); +} + + +function drawCriticalPath() { + state.timelineSvg.selectAll("g.critical_path_lines").remove(); + if (state.critical_path == undefined || !state.display_critical_path) { + return; + } + var depGroup = state.timelineSvg.append("g") + .attr("class", "critical_path_lines"); + state.critical_path.forEach(function(op) { + var proc = base_map[op[0] + "," + op[1]]; // set in calculateBases + if (proc != undefined && proc.visible && proc.enabled && proc.loaded && proc.selected) { + var elems = prof_uid_map[op[2]]; + if (elems != undefined) { + var coords = getElemCoords(elems) + var startX = coords.startX; + var endX = coords.endX; + var y = coords.y; + elems[0].out.forEach(function(dep) { + if (dep[2] in state.critical_path_prof_uids) { + var depElems = prof_uid_map[dep[2]]; + if (depElems != undefined) { + var depProc = depElems[0].proc; + // is the proc visible? + if (depProc.visible && depProc.enabled && depProc.loaded) { + var depCoords = getElemCoords(depElems); + var depX = depCoords.endX; + var depY = depCoords.y; + addLine(depGroup, depX, startX, depY, y, "grey", false); + } + } + } + }); + // Draw parent-child lines + var lastChildCoords = undefined; + var firstChildCoords = undefined; + elems[0].children.forEach(function(child) { + if (child[2] in state.critical_path_prof_uids) { + var childElems = prof_uid_map[child[2]]; + var childCoords = getElemCoords(childElems); + if (childElems !== undefined) { + if (lastChildCoords === undefined || + childCoords.startX > lastChildCoords.startX) { + lastChildCoords = childCoords; + } + if (firstChildCoords === undefined || + childCoords.endX < firstChildCoords.endX) { + firstChildCoords = childCoords; + } + } + } + }); + if (firstChildCoords !== undefined) { + addLine(depGroup, startX, firstChildCoords.startX, + y, firstChildCoords.y, "grey", true); + } + if (lastChildCoords !== undefined) { + addLine(depGroup, lastChildCoords.endX, endX, + lastChildCoords.y, y, "grey", true); + } + } + } + }); +} + +function drawDependencies() { + state.timelineSvg.select("g.dependencies").remove(); + var timelineEvent = state.dependencyEvent; + if (timelineEvent == undefined || + !timelineEvent.proc.visible || !timelineEvent.proc.enabled) { + return; // don't draw in this case, the src isn't present + } + var srcElems = prof_uid_map[timelineEvent.prof_uid]; + timelineEvent = srcElems[0]; // only the first elem will have deps and children + var srcCoords = getElemCoords(srcElems); + var srcStartX = srcCoords.startX; + var srcEndX = srcCoords.endX; + var srcY = srcCoords.y; + var depGroup = state.timelineSvg.append("g") + .attr("class", "dependencies"); + + var addDependency = function(dep, dir, dashed) { + var depProc = base_map[dep[0] + "," + dep[1]]; // set in calculateBases + if (depProc.visible && depProc.enabled && depProc.selected) { + var depElems = prof_uid_map[dep[2]]; + if (depElems != undefined) { + console.log(dir); + var depCoords = getElemCoords(depElems); + var dstY = depCoords.y; + if (dir === "in") { + addLine(depGroup, srcEndX, depCoords.startX, srcY, dstY, "black", dashed); + } else if (dir === "out") { + addLine(depGroup, depCoords.endX, srcStartX, dstY, srcY, "black", dashed); + } else if (dir === "parent") { + addLine(depGroup, depCoords.startX, srcStartX, dstY, srcY, "black", dashed); + addLine(depGroup, srcEndX, depCoords.endX, srcY, dstY, "black", dashed); + } else if (dir === "child") { + addLine(depGroup, srcStartX, depCoords.startX, srcY, dstY, "black", dashed); + addLine(depGroup, depCoords.endX, srcEndX, dstY, srcY, "black", dashed); + } + + } + } + } + + if (state.drawDeps) { + timelineEvent.in.forEach(function(dep) {addDependency(dep, "in", false)}); + timelineEvent.out.forEach(function(dep) {addDependency(dep, "out", false)}); + } + if (state.drawChildren) { + timelineEvent.parents.forEach(function(dep) {addDependency(dep, "parent", true)}); + timelineEvent.children.forEach(function(dep) {addDependency(dep, "child", true)}); + } +} + +function timelineEventsExistAndEqual(a, b) { + if (a == undefined || b == undefined) { + return false; + } + return (a.proc.base == b.proc.base) && (a.prof_uid == b.prof_uid); +} + +function timelineElementStrokeCalculator(elem) { + if (timelineEventsExistAndEqual(elem, state.dependencyEvent)) { + return true; + } else if (state.display_critical_path && + elem.prof_uid in state.critical_path_prof_uids) { + return true; + } + return false; +} + +function timelineEventMouseDown(_timelineEvent) { + // only the first event of this uid will have information + var timelineEvent = prof_uid_map[_timelineEvent.prof_uid][0]; + var hasDependencies = ((timelineEvent.in.length != 0) || + (timelineEvent.out.length != 0)); + + if (hasDependencies) { + if (timelineEventsExistAndEqual(timelineEvent, state.dependencyEvent)) { + if (d3.event.button === 0) { + state.drawDeps = !state.drawDeps; + } else if (d3.event.button === 2) { + state.drawChildren = !state.drawChildren; + } + if (state.drawDeps === false && state.drawChildren === false) { + state.dependencyEvent = undefined; + } + } else { + timelineEvent.in.concat(timelineEvent.out).forEach(function(dep) { + expandByNodeProc(dep[0], dep[1]) + }); + state.dependencyEvent = timelineEvent; + if (d3.event.button === 0) { + state.drawDeps = true; + } else if (d3.event.button === 2) { + state.drawChildren = true; + } + } + redraw(); + } +} + +function drawTimeline() { + showLoaderIcon() + + updateURL(state.zoom, state.scale); + var timelineGroup = state.timelineSvg.select("g#timeline"); + timelineGroup.selectAll("rect").remove(); + timelineGroup.selectAll("text").remove(); + var timeline = timelineGroup.selectAll("rect") + .data(state.dataToDraw, function(d) { return d.proc.base + "-" + d.id; }); + var timelineText = timelineGroup.selectAll("text") + .data(state.memoryTexts); + var mouseOver = getMouseOver(); + + timeline.enter().append("rect"); + + timeline + .attr("id", function(d) { return "block-" + d.proc.base + "-" + d.id; }) + .attr("x", function(d) { return convertToPos(state, d.start); }) + .attr("y", timelineLevelCalculator) + .style("fill", function(d) { + if (!state.searchEnabled || + searchRegex[currentPos].exec(d.title) == null) + return d.color; + else return "#ff0000"; + }) + .attr("width", function(d) { + return Math.max(constants.min_feature_width, convertToPos(state, d.end - d.start)); + }) + .attr("stroke", function(d) { + if (timelineElementStrokeCalculator(d)) { + return "red"; + } else { + return "black"; + } + }) + .attr("stroke-width", function(d) { + if (timelineElementStrokeCalculator(d)) { + return "1.5"; + } else { + return "0.5"; + } + }) + .attr("height", state.thickness) + .style("opacity", function(d) { + if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) != null || searchRegex[currentPos].exec(d.initiation) != null) { + return d.opacity; + } + else return 0.05; + }) + .on("mouseout", function(d, i) { + if ((d.in.length != 0) || (d.out.length != 0)) { + d3.select(this).style("cursor", "default"); + } + state.timelineSvg.selectAll("#desc").remove(); + }) + .on("mousedown", timelineEventMouseDown) + + + timelineText.enter().append("text"); + + timelineText + .attr("class", "timeline") + .attr("y", timelineTextLevelCalculator) + .attr("text-anchor", "start") + .text(function(d) { + var sizeRegex = /Size=(.*)/; + var match = sizeRegex.exec(d.title); + return match[1]; + }) + .attr("visibility", function(d) { + var textWidth = this.getComputedTextLength(); + var startX = convertToPos(state, d.start); + var endX = convertToPos(state, d.end); + var boxWidth = endX - startX; + return boxWidth > textWidth ? "visible" : "hidden"; + }) + .attr("x", function(d) { + var textWidth = this.getComputedTextLength(); + var midPoint = convertToPos(state, d.start + (d.end - d.start) / 2); + midPoint -= textWidth / 2; + return midPoint + }); + + drawUtil(); + timeline.on("mouseover", mouseOver); + timeline.exit().remove(); + hideLoaderIcon(); +} + +function redraw() { + if (state.numLoading == 0) { + calculateBases(); + filterAndMergeBlocks(state); + constants.max_level = calculateVisibileLevels(); + recalculateHeight(); + drawTimeline(); + drawDependencies(); + drawCriticalPath(); + drawLayout(); + } +} + +function calculateVisibileLevels() { + var levels = 0; + state.flattenedLayoutData.forEach(function(elem) { + if (elem.visible) { + if (elem.enabled) { + if (state.ready_selected && elem.num_levels_ready != undefined) + levels += elem.num_levels_ready; + else + levels += elem.num_levels; + } + levels += constants.elem_separation; + } + }); + return levels; +} + +function is_proc(proc) { + // the full text of this proc should start with 0x1d to be a processor + return /0x1d/.exec(proc.full_text) !== undefined; +} + +function is_proc_string(text) +{ + return /0x1d/.exec(text) != undefined; +} + +function is_mem_string(text) { + return /0x1e/.exec(text) != undefined; +} + +function get_node_val(text) { + var match = /\d+/.exec(text); + if (match) { + var val = parseInt(text.match(/\d+/)); + return val; + } + return match; +} + +function get_node_id(text) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + var proc_regex = /(Memory|Processor) 0x1(e|d)([a-fA-f0-9]{4})/; + var proc_match = proc_regex.exec(text); + // if there's only one node, then per-node graphs are redundant + if (proc_match) { + var node_id = parseInt(proc_match[3], 16); + return node_id + } +} + +function get_proc_in_node(text) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + var proc_regex = /Processor 0x1d[a-fA-f0-9]{11}([a-fA-f0-9]{3})/; + var proc_match = proc_regex.exec(text); + // if there's only one node, then per-node graphs are redundant + if (proc_match) { + var proc_in_node = parseInt(proc_match[1], 16); + return proc_in_node; + } +} + +function calculateBases() { + var base = 0; + state.flattenedLayoutData.forEach(function(elem) { + elem.base = base; + var node_id = get_node_id(elem.full_text); + var proc_in_node = get_proc_in_node(elem.full_text); + if (node_id != undefined && proc_in_node != undefined) { + base_map[(+node_id) + "," + (+proc_in_node)] = elem; + } + if (elem.visible) { + if (elem.enabled) { + if (state.ready_selected && elem.num_levels_ready != undefined) + base += elem.num_levels_ready; + else + base += elem.num_levels; + } + base += constants.elem_separation; + } + }); +} + +function expandHandler(elem, index) { + elem.expanded = !elem.expanded; + + if (elem.expanded) { + function expandChild(child) { + child.visible = true; + //child.enabled = true; + if(!child.loaded) { + showLoaderIcon(); + child.loader(child); // will redraw the timeline once loaded + } else if (child.expanded) { + child.children.forEach(expandChild); + } + } + elem.children.forEach(expandChild); + } else { + function collapseChildren(child) { + child.visible = false; + child.children.forEach(collapseChildren); + } + elem.children.forEach(collapseChildren); + } + redraw(); +} + +// This handler is called when you collapse/uncollapse a row in the +// timeline +function collapseHandler(d, index) { + d.enabled = !d.enabled; + + if (!d.loaded) { + // should always be expanding here + showLoaderIcon(); + //var elem = state.flattenedLayoutData[index]; + d.loader(d); // will redraw the timeline once loaded + } else { + redraw(); + } +} + +// This expands a particular element and its parents if necessary +function expandElementAndParents(elem) { + if (elem !== undefined) { + var elemPath = []; // path up to parent + var curElem = elem; + while (curElem != undefined) { + elemPath.push(curElem); + curElem = curElem.parent; + } + + for (var i = elemPath.length - 1; i >= 0; --i) { + var elem = elemPath[i]; + if (!elem.expanded) { + expandHandler(elem); + } + // uncollapse if necessary + if ((i == 0) && !elem.enabled) { + collapseHandler(elem); + } + } + } +} + + +function expandByNodeProc(node, proc) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + // ugh why isn't there string formatting + var nodeHex = ("0000" + node.toString(16)).slice(-4); + var procHex = ("000" + proc.toString(16)).slice(-3); + var expectedTitle = "0x1d" + nodeHex + "0000000" + procHex; + var matchedElement = undefined; + for (var i = 0; i < state.flattenedLayoutData.length; i++) { + var timelineElement = state.flattenedLayoutData[i]; + if ((timelineElement.full_text != undefined) && + (timelineElement.full_text.indexOf(expectedTitle) !=-1)) { + matchedElement = timelineElement; + break; + } + } + expandElementAndParents(matchedElement) +} + + +function lineLevelCalculator(timelineElement) { + var level = timelineElement.base + 1; + if (timelineElement.enabled) { + if (state.ready_selected && timelineElement.num_levels_ready != undefined) + level += timelineElement.num_levels_ready; + else + level += timelineElement.num_levels; + } + return constants.margin_top + level * state.thickness; +}; + +function utilLevelCalculator(timelineElement) { + var level = timelineElement.base; + if (timelineElement.enabled) { + if (state.ready_selected && timelineElement.num_levels_ready != undefined) + level += timeLineElement.num_levels_ready; + else + level += timeLineElement.num_levels; + } + return constants.margin_top + level * state.thickness; +}; + + +function timelineLevelCalculator(timelineEvent) { + return constants.margin_top + + (timelineEvent.proc.base + timelineEvent.level) * state.thickness; +}; + +function timelineTextLevelCalculator(timelineEvent) { + return constants.margin_top + + (timelineEvent.proc.base + timelineEvent.level + 0.75) * state.thickness; +}; + +function dependencyLineLevelCalculator(level) { + return constants.margin_top + ((level+0.5) * state.thickness); +} + +function drawLayout() { + d3.select("#processors").select("svg").remove(); + state.timelineSvg.select("g#lines").remove(); + + var data = state.flattenedLayoutData; + var svg = d3.select("#processors").append("svg") + .attr("width", constants.margin_left) + .attr("height", state.height); + + var namesGroup = svg.selectAll(".processors") + .data(data) + .enter().append("g"); + + var names = namesGroup.append("text"); + + var thickness = state.thickness; + var xCalculator = function(d) { return (d.depth + 1) * 15; }; + names.attr("text-anchor", "start") + .attr("class", "processor") + .text(function(d) { return d.text; }) + .attr("x", xCalculator) + .attr("y", lineLevelCalculator) + .attr("visibility", function(elem) { + return (elem.visible) ? "visible" : "hidden" + }) + .style("fill", "#000000") + .style("opacity", function(proc) { + return (proc.enabled) ? 1 : 0.5; + }); + + + // names.each(function(d) { + // var elem = d3.select(this); + // var text = d.text; + // var tokens = d.text.split(" to "); + // if (tokens.length == 1) + // elem.append("tspan").text(d.text); + // else { + // var source = tokens[0]; + // var target = tokens[1].replace(" Channel", ""); + // elem.append("tspan").text(source) + // .attr("x", xCalculator) + // .attr("dy", -10); + // elem.append("tspan").text("==> " + target) + // .attr("x", xCalculator) + // .attr("dy", 10); + // } + // }); + names.on({ + "mouseover": function(d) { + d3.select(this).style("cursor", "pointer") + if (d.full_text != undefined) { + var x = xCalculator(d); + var y = lineLevelCalculator(d) - state.thickness; + + var overlaySvg = d3.select("#overlay").append("svg"); + var descView = overlaySvg.append("g").attr("id", "desc"); + + var text = descView.append("text") + .attr("x", x) + .attr("y", y) + .attr("text-anchor", "start") + .attr("class", "desc") + .text(unescape(escape(d.full_text))); + + var bbox = text.node().getBBox(); + var padding = 2; + var rect = descView.insert("rect", "text") + .attr("x", bbox.x - padding) + .attr("y", bbox.y - padding) + .attr("width", bbox.width + (padding*2)) + .attr("height", bbox.height + (padding*2)) + .style("fill", "#222") + .style("opacity", "0.7"); + + overlaySvg.attr("width", bbox.x + bbox.width + (padding*2)) + .attr("height", bbox.y + bbox.height + (padding*2)); + } + }, + "mouseout": function(d) { + d3.select(this).style("cursor", "default") + if (d.full_text != undefined) { + d3.select("#overlay").selectAll("svg").remove(); + } + }, + "click": collapseHandler + }); + + var expandableNodes = namesGroup.filter(function(elem) { + return elem.children.length > 0; + }); + + var expand_group = expandableNodes.append("g"); + + var expand_clickable = expand_group.append("circle") + .attr("fill", "transparent") + .attr("stroke", "transparent") + .attr("r", 8); + var expand_icons = expand_group.append("path"); + var arc = d3.svg.symbol().type('triangle-down') + .size(12); + + + //.attr("transform", function(elem) { + // var x = constants.margin_left - 10; + // var y = lineLevelCalculator(elem); + // return "translate(" + x + "," + y + ")"; + //}) + expand_icons.attr("class", "processor") + .attr("d", arc) + .attr("visibility", function(elem) { + return (elem.visible) ? "visible" : "hidden" + }) + .style("fill", "#000000") + .style("stroke", "#000000") + .style("opacity", function(proc) { + return (proc.enabled) ? 1 : 0.5; + }); + + expand_group.each(function(elem) { + var path = d3.select(this); + var x = elem.depth * 15 + 5; + var y = lineLevelCalculator(elem) - 3; + + if (elem.expanded) { + path.attr("transform", "translate(" + x + ", " + y + ") rotate(0)"); + } else { + path.attr("transform", "translate(" + x + ", " + y + ") rotate(30)"); + } + + }); + + + expand_group.on({ + "mouseover": function(d) { + d3.select(this).style("cursor", "pointer") + }, + "mouseout": function(d) { + d3.select(this).style("cursor", "default") + }, + "click": expandHandler + }); + + + var lines = state.timelineSvg + .append("g") + .attr("id", "lines"); + + var thickness = state.thickness; + lines.selectAll(".lines") + .data(data) + .enter().append("line") + .attr("x1", 0) + .attr("y1", lineLevelCalculator) + .attr("x2", state.zoom * state.width) + .attr("y2", lineLevelCalculator) + .attr("visibility", function(elem) { + return (elem.visible) ? "visible" : "hidden" + }) + .style("stroke", "#000000") + .style("stroke-width", "2px") + .style("opacity", function(proc) { + return (proc.enabled) ? 1 : 0.5; + }); +} + +function drawHelpBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + + var helpBoxGroup = popUpSvg.append("g"); + var helpBoxWidth = Math.min(450, width - 100); + var helpTextOffset = 20; + var helpBoxHeight = Math.min(helpMessage.length * helpTextOffset + 100, + height - 100); + + var boxStartX = (width - helpBoxWidth) / 2; + var boxStartY = (height - helpBoxHeight) / 2; + + helpBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: helpBoxWidth, + height: helpBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var helpText = helpBoxGroup.append("text") + .attr("class", "help-box") + .style("width", helpBoxWidth); + var helpTitle = "Keyboard Shortcuts"; + helpText.append("tspan") + .attr({ x: boxStartX + helpBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text(helpTitle); + var off = 15; + for (var i = 0; i < helpMessage.length; ++i) { + helpText.append("tspan") + .style("font-size", "12pt") + .attr("text-anchor", "start") + .attr({ x: boxStartX + 30, dy: off + helpTextOffset}) + .text(helpMessage[i]); + off = 0; + } +} + +function evalExpandRequest(re) { + var re = new RegExp(re); + state.flattenedLayoutData.forEach(function(elem) { + if (re.exec(elem.text)) { + expandElementAndParents(elem); + } + }); + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); +} + +function drawExpandBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + var expandBoxGroup = popUpSvg.append("g"); + var expandBoxWidth = Math.min(450, width - 100); + var expandBoxHeight = Math.min(220, height - 100); + + var thicknessRatio = state.thickness / state.baseThickness; + var boxStartX = (width - expandBoxWidth) / 2; + var boxStartY = (height - expandBoxHeight) / 2; + + expandBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: expandBoxWidth, + height: expandBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var expandText = expandBoxGroup.append("text") + .attr("class", "expand-box") + .style("width", expandBoxWidth); + expandText.append("tspan") + .attr({ x: boxStartX + expandBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text("expand"); + var expandInputWidth = expandBoxWidth - 40; + var expandInputHeight = 50; + var expandInputStartY = 65; + + + expandBoxGroup.append("foreignObject") + .attr({ x: boxStartX + 20, y: boxStartY + expandInputStartY, + width: expandInputWidth, height: expandBoxHeight - expandInputStartY}) + .attr("text-anchor", "middle") + .html( + "" + + "
" + + "" + + "Presets" + + "" + + "
" + + "
" + + "" + + "" + + "" + + "" + + "" + + "" + + "
" + ); + $("input.expand-box").focus(); +} + +function drawSearchBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + var searchBoxGroup = popUpSvg.append("g"); + var searchBoxWidth = Math.min(450, width - 100); + var searchBoxHeight = Math.min(250, height - 100); + + var thicknessRatio = state.thickness / state.baseThickness; + var boxStartX = (width - searchBoxWidth) / 2; + var boxStartY = (height - searchBoxHeight) / 2; + + searchBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: searchBoxWidth, + height: searchBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var searchText = searchBoxGroup.append("text") + .attr("class", "search-box") + .style("width", searchBoxWidth); + searchText.append("tspan") + .attr({ x: boxStartX + searchBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text("Search"); + var searchInputWidth = searchBoxWidth - 40; + var searchInputHeight = 50; + searchBoxGroup.append("foreignObject") + .attr({ x: boxStartX + 20, y: boxStartY + 150, + width: searchInputWidth, height: searchInputHeight}) + .attr("text-anchor", "middle") + .html(""); + $("input.search-box").focus(); +} + +function drawSearchHistoryBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + + var historyBoxGroup = popUpSvg.append("g"); + var historyBoxWidth = Math.min(450, width - 100); + var historyBoxHeight = Math.min(350, height - 100); + + var boxStartX = (width - historyBoxWidth) / 2; + var boxStartY = (height - historyBoxHeight) / 2; + + historyBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: historyBoxWidth, + height: historyBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var historyText = historyBoxGroup.append("text") + .attr("class", "history-box") + .style("width", historyBoxWidth); + var historyTitle = "Search History"; + historyText.append("tspan") + .attr({ x: boxStartX + historyBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text(historyTitle); + if (searchRegex != null) { + var off = 15; + var id = 1; + for (var i = 0; i < sizeHistory; ++i) { + var pos = (nextPos + i) % sizeHistory; + var regex = searchRegex[pos]; + if (regex != null) { + if (pos == currentPos) prefix = ">>> "; + else prefix = id + " : "; + historyText.append("tspan") + .attr("text-anchor", "start") + .attr({ x: boxStartX + 30, dy: off + 25}) + .text(prefix + regex.source); + off = 0; + id++; + } + } + } +} + +function updateURL() { + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + var start_time = convertToTime(state, windowStart); + var end_time = convertToTime(state, windowEnd); + var url = window.location.href.split('?')[0]; + url += "?start=" + start_time; + url += "&end=" + end_time; + url += "&collapseAll=" + state.collapseAll; + url += "&resolution=" + state.resolution; + if (state.searchEnabled) + url += "&search=" + searchRegex[currentPos].source; + window.history.replaceState("", "", url); +} + +function adjustZoom(newZoom, scroll) { + var prevZoom = state.zoom; + state.zoom = Math.round(newZoom * 10) / 10; + + var svg = d3.select("#timeline").select("svg"); + + svg.attr("width", state.zoom * state.width) + .attr("height", state.height); + + var timelineGroup = svg.select("g#timeline"); + //timelineGroup.selectAll("rect").remove(); + + svg.select("g#lines").selectAll("line") + .attr("x2", state.zoom * state.width); + svg.selectAll("#desc").remove(); + svg.selectAll("g.locator").remove(); + d3.select("#overlay").selectAll("svg").remove(); + + if (scroll) { + var paneWidth = $("#timeline").width(); + var pos = ($("#timeline").scrollLeft() + paneWidth / 2) / prevZoom; + // this will trigger a scroll event which in turn redraws the timeline + $("#timeline").scrollLeft(pos * state.zoom - state.width / 2); + } else { + filterAndMergeBlocks(state); + drawTimeline(); + } + drawDependencies(); + drawCriticalPath(); +} + +function recalculateHeight() { + // adjust the height based on the new thickness and max level + state.height = constants.margin_top + constants.margin_bottom + + (state.thickness * constants.max_level); + var util_height = constants.util_levels * state.thickness; + state.y = d3.scale.linear().range([util_height, 0]); + state.y.domain([0, 1]); + + d3.select("#processors").select("svg").remove(); + var svg = d3.select("#timeline").select("svg"); + svg.attr("width", state.zoom * state.width) + .attr("height", state.height); + var lines = state.timelineSvg.select("g#lines"); + lines.remove(); + + svg.selectAll("#desc").remove(); + svg.selectAll("g.locator").remove(); + d3.select("#overlay").selectAll("svg").remove(); + +} + +function adjustThickness(newThickness) { + state.thickness = newThickness; + recalculateHeight(); + drawTimeline(); + drawLayout(); +} + +function suppressdefault(e) { + if (e.preventDefault) e.preventDefault(); + if (e.stopPropagation) e.stopPropagation(); +} + +function setKeyHandler(handler) { + $(document).off("keydown"); + $(document).on("keydown", handler); +} + +function makeModalKeyHandler(validKeys, callback) { + return function(e) { + if (!e) e = event; + var code = e.keyCode || e.charCode; + if (!(e.ctrlKey || e.metaKey || e.altKey)) { + for (var i = 0; i < validKeys.length; ++i) { + if (keys[code] == validKeys[i]) { + callback(keys[code]); + return false; + } + } + } + return true; + } +} + +function displayPopUp() { + d3.select("#pop-up").append("svg") + .attr("width", $(window).width()) + .attr("height", $(window).height()); +} + +function removePopUp() { + var popUpSvg = d3.select("#pop-up").selectAll("svg").remove(); +} + + +function defaultKeydown(e) { + if (!e) e = event; + + var code = e.keyCode || e.charCode; + var commandType = Command.none; + var modifier = e.ctrlKey || e.metaKey || e.altKey; + var multiFnKeys = e.metaKey && e.ctrlKey || e.altKey && e.ctrlKey; + + var translatedCode = keys[code]; + + if (!modifier) { + commandType = noModifierCommands[translatedCode]; + } else if (!multiFnKeys) { + commandType = modifierCommands[translatedCode]; + } else { + commandType = multipleModifierCommands[translatedCode]; + } + + if (commandType == undefined) { + if (e.metaKey || e.altKey) + state.rangeZoom = false; + return true; + } + + suppressdefault(e); + if (commandType == Command.help) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + // make help box visible + displayPopUp(); + drawHelpBox(); + setKeyHandler(makeModalKeyHandler(['/', 'esc'], function(key) { + // make help box invisible + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + else if (commandType == Command.search) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + displayPopUp(); + drawSearchBox(); + setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { + if (key == 'enter') { + var re = $("input.search-box").val(); + if (re.trim() != "") { + if (searchRegex == null) { + searchRegex = new Array(sizeHistory); + currentPos = -1; + nextPos = 0; + } + currentPos = nextPos; + nextPos = (nextPos + 1) % sizeHistory; + searchRegex[currentPos] = new RegExp(re); + state.searchEnabled = true; + } + } + removePopUp(); + if (state.searchEnabled) { + filterAndMergeBlocks(state); + drawTimeline(); + } + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + else if (commandType == Command.expand) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + displayPopUp(); + drawExpandBox(); + setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { + if (key == 'enter') { + var re = $("input.expand-box").val(); + if (re.trim() != "") { + re = new RegExp(re); + state.flattenedLayoutData.forEach(function(elem) { + if (re.exec(elem.text)) { + expandElementAndParents(elem); + } + }); + } + } + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + else if (commandType == Command.search_history) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + displayPopUp(); + drawSearchHistoryBox(); + setKeyHandler(makeModalKeyHandler(['h', 'esc'], function(key) { + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + + if (commandType == Command.zix) { + var inc = 4.0; + adjustZoom(state.zoom + inc, true); + } else if (commandType == Command.zox) { + var dec = 4.0; + if (state.zoom - dec > 0) + adjustZoom(state.zoom - dec, true); + } else if (commandType == Command.zrx) { + state.zoomHistory = Array(); + adjustZoom(1.0, false); + $("#timeline").scrollLeft(0); + } else if (commandType == Command.zux) { + if (state.zoomHistory.length > 0) { + var previousZoomHistory = state.zoomHistory.pop(); + adjustZoom(previousZoomHistory.zoom, false); + $("#timeline").scrollLeft(previousZoomHistory.start); + } + } else if (commandType == Command.ziy) + adjustThickness(state.thickness * 2); + else if (commandType == Command.zoy) + adjustThickness(state.thickness / 2); + else if (commandType == Command.zry) { + state.height = $(window).height() - constants.margin_bottom - constants.margin_top; + state.thickness = state.height / constants.max_level; + adjustThickness(state.thickness); + } + else if (commandType == Command.clear_search) { + state.searchEnabled = false; + searchRegex = null; + filterAndMergeBlocks(state); + drawTimeline(); + } + else if (commandType == Command.toggle_search) { + if (searchRegex != null) { + state.searchEnabled = !state.searchEnabled; + filterAndMergeBlocks(state); + drawTimeline(); + } + } + else if (commandType == Command.previous_search || + commandType == Command.next_search) { + if (state.searchEnabled) { + var pos = commandType == Command.previous_search ? + (currentPos - 1 + sizeHistory) % sizeHistory : + (currentPos + 1) % sizeHistory; + var sentinel = commandType == Command.previous_search ? + (nextPos - 1 + sizeHistory) % sizeHistory : nextPos; + if (pos != sentinel && searchRegex[pos] != null) { + currentPos = pos; + filterAndMergeBlocks(state); + drawTimeline(); + } + } + } + else if (commandType == Command.toggle_critical_path) { + state.display_critical_path = !state.display_critical_path; + if (state.display_critical_path) { + state.critical_path.forEach(function(op) { + expandByNodeProc(op[0], op[1]); + }); + } + redraw(); + } + return false; +} + +function defaultKeyUp(e) { + if (!e) e = event; + if (!(e.metaKey || e.altKey)) { + state.rangeZoom = true; + } + return true; +} + +function load_proc_timeline(proc) { + var proc_name = proc.full_text; + state.processorData[proc_name] = {}; + var num_levels_ready = proc.num_levels; + if (state.ready_selected) { + proc.num_levels_ready = proc.num_levels; + } + d3.tsv(proc.tsv, + function(d, i) { + var level = +d.level; + var ready = +d.ready; + var start = +d.start; + var end = +d.end; + var level_ready = +d.level_ready; + var total = end - start; + var _in = d.in === "" ? [] : JSON.parse(d.in) + var out = d.out === "" ? [] : JSON.parse(d.out) + var children = d.children === "" ? [] : JSON.parse(d.children) + var parents = d.parents === "" ? [] : JSON.parse(d.parents) + if (total > state.resolution) { + return { + id: i, + level: level, + level_ready: level_ready, + ready: ready, + start: start, + end: end, + color: d.color, + opacity: d.opacity, + initiation: d.initiation, + title: d.title, + in: _in, + out: out, + children: children, + parents: parents, + prof_uid: d.prof_uid, + proc: proc + }; + } + }, + function(data) { + var num_levels_ready=0 + // split profiling items by which level they're on + for(var i = 0; i < data.length; i++) { + var d = data[i]; + var level_sel=d.level; + if (level_sel in state.processorData[proc_name]) { + state.processorData[proc_name][level_sel].push(d); + } else { + state.processorData[proc_name][level_sel] = [d]; + } + if ((d.level_ready != undefined) && (d.level_ready != 0) && + num_levels_ready < d.level_ready) + num_levels_ready = d.level_ready; + + if (d.prof_uid != undefined && d.prof_uid !== "") { + if (d.prof_uid in prof_uid_map) { + prof_uid_map[d.prof_uid].push(d); + } else { + prof_uid_map[d.prof_uid] = [d]; + } + } + } + if (num_levels_ready > proc.num_levels) + proc.num_levels_ready = num_levels_ready; + else + proc.num_levels_ready = proc.num_levels; + proc.loaded = true; + hideLoaderIcon(); + redraw(); + } + ); +} + +function initTimelineElements() { + var timelineGroup = state.timelineSvg.append("g") + .attr("id", "timeline"); + + $("#timeline").scrollLeft(0); + parseURLParameters(); + + var windowCenterY = $(window).height() / 2; + $(window).scroll(function() { + $("#loader-icon").css("top", $(window).scrollTop() + windowCenterY); + $("#pop-up").css("top", $(window).scrollTop()); + }); + + // set scroll callback + var timer = null; + $("#timeline").scroll(function() { + if (timer !== null) { + clearTimeout(timer); + } + timer = setTimeout(function() { + filterAndMergeBlocks(state); + drawTimeline(); + }, 100); + }); + if (!state.collapseAll) { + // initially load in all the cpu processors and the "all util" + var util_regex = /node/; + for (var i = 0; i < state.flattenedLayoutData.length; i++) { + var timelineElement = state.flattenedLayoutData[i]; + if (timelineElement.type == "util" && + util_regex.exec(timelineElement.text) && + timelineElement.depth == 0) { + collapseHandler(timelineElement, i); + } + } + } + turnOnMouseHandlers(); +} + + +function load_ops_and_timeline() { + d3.tsv("legion_prof_ops.tsv", // TODO: move to tsv folder + function(d) { + return d; + }, + function(data) { + data.forEach(function(d) { + state.operations[parseInt(d.op_id)] = d; + }); + // initTimelineElements depends on the ops to be loaded + initTimelineElements(); + } + ); +} + +function load_procs(callback) { + d3.tsv('legion_prof_processor.tsv', + function(d) { + return { + full_text: d.full_text, + text: d.text, + height: +d.levels, + tsv: d.tsv + }; + }, + function(data) { + var prevEnd = 0; + var base = 0; + data.forEach(function(proc) { + proc.enabled = false; + proc.loaded = false; + proc.base = base; + + base += 2; + }); + state.processors = data; + calculateLayout(); + + // flatten the layout and get the new calculated max num levels + flattenLayout(); + calculateBases(); + drawLayout(); + createMenuList1(); + callback(); + + // TODO: fix + load_critical_path(); + } + ); +} + +function getMinElement(arr, mapF) { + if (arr.length === undefined || arr.length == 0) { + throw "invalid array: " + arr; + } + var minElement = arr[0]; + if (mapF === undefined) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] < minElement) { + minElement = arr[i]; + } + } + } else { + minValue = mapF(minElement); + for (var i = 1; i < arr.length; i++) { + var elem = arr[i]; + var value = mapF(elem); + if (value < minValue) { + minElement = elem; + minValue = value; + } + } + } + return minElement; +} + +function filterUtilData(timelineElem) { + var data = state.utilData[timelineElem.tsv]; // TODO: attach to object + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + var start_time = convertToTime(state, windowStart - 100); + var end_time = convertToTime(state, windowEnd + 100); + + var startIndex = timeBisector(data, start_time); + var endIndex = timeBisector(data, end_time); + + startIndex = Math.max(0, startIndex - 1); + endIndex = Math.min(data.length, endIndex + 2); + var length = endIndex - startIndex; + var newData = Array(); + // we will average points together if they are too close together + var resolution = 1; // 3 pixel resolution + var elem = {time: 0, count: 0}; + var startTime = data[startIndex].time; + var startX = convertToPos(state, startTime); + var endTime = 0; + + for (var i = startIndex; i < endIndex - 1; i++) { + endTime = data[i+1].time; + elem.count += data[i].count * (endTime - data[i].time); + //elem.time += data[i].time; + var endX = convertToPos(state, endTime); + if ((endX - startX) >= resolution || i == (endIndex - 2)) { + var totalTime = endTime - startTime; + elem.count /= totalTime; + //avgElem.time /= windowSize; + elem.time = startTime; + newData.push(elem); + elem = {time: 0, count: 0}; + startX = endX; + startTime = endTime; + } + } + + newData.push({time: endTime, count:0}); + + return { + text: timelineElem.text, + base: timelineElem.base, + num_levels: timelineElem.num_levels, + num_levels_ready: timelineElem.num_levels_ready, + data: newData + }; +} + +function mouseover() { + var focus = state.timelineSvg.append("g") + .attr("class", "focus"); + + focus.append("circle") + .attr("fill", "none") + .attr("stroke", "black") + .attr("r", 4.5); + + var utilDescView = state.timelineSvg.append("g") + .attr("class", "utilDesc"); + utilDescView.append("text") + .attr("x", 7) + .attr("y", -4.5) + .attr("class", "desc") + .attr("dy", ".35em"); + utilDescView.insert("rect", "text") + .style("fill", "#222") + .style("opacity", "0.7"); +} + +function mousemove(d, i) { + var line = document.getElementById("util" + i); + + // offset for this particular line grapgh + var base_y = +line.getAttribute("base_y"); + var px = d3.mouse(line)[0]; + var py = d3.mouse(line)[1] + base_y; + + var start = 0; + var end = line.getTotalLength(); + var target = undefined; + var pos = undefined; + + // https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91 + while (true){ + target = Math.floor((start + end) / 2); + pos = line.getPointAtLength(target); + if ((target === end || target === start) && pos.x !== px) { + break; + } + if (pos.x > px) end = target; + else if (pos.x < px) start = target; + else break; //position found + } + + + var cx = pos.x; + var cy = pos.y + base_y; + + var focus = state.timelineSvg.select("g.focus"); + focus.attr("transform", "translate(" + cx + "," + cy + ")"); + + var utilDescView = state.timelineSvg.select("g.utilDesc"); + utilDescView.attr("transform", "translate(" + (px + 10) + "," + (py - 10) + ")"); + var text = utilDescView.select("text") + + text.text(Math.round(state.y.invert(pos.y) * 100) + "% utilization"); + + var bbox = text.node().getBBox(); + var padding = 2; + var rect = utilDescView.select("rect", "text"); + rect.attr("x", bbox.x - padding) + .attr("y", bbox.y - padding) + .attr("width", bbox.width + (padding*2)) + .attr("height", bbox.height + (padding*2)); + + var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); + var bboxRight = px + bbox.x + bbox.width; + // If the box moves off the screen, nudge it back + if (bboxRight > timelineRight) { + var translation = -(bboxRight - timelineRight + 20); + text.attr("transform", "translate(" + translation + ",0)"); + rect.attr("transform", "translate(" + translation + ",0)"); + } +} + +// Get the data +function load_util(elem) { + var util_file = elem.tsv; + + // exit early if we already loaded it + if(state.utilData[util_file]) { + elem.loaded = true; + hideLoaderIcon(); + redraw(); + return; + } + + d3.tsv(util_file, + function(d) { + return { + time: +d.time, + count: +d.count + }; + }, + function(error, data) { + state.utilData[util_file] = data; + elem.loaded = true; + hideLoaderIcon(); + redraw(); + } + ); +} + +function load_critical_path() { + $.getJSON("json/critical_path.json", function(json) { + state.critical_path = json.map(function(p) {return p.tuple}); + state.critical_path_prof_uids = {}; + state.critical_path.forEach(function(p) { + state.critical_path_prof_uids[p[2]] = 1; + }); + }); +} + +function load_data() { + load_procs(load_ops_and_timeline); +} + +function initializeState() { + var margin = constants.margin_left + constants.margin_right; + state.width = $(window).width() - margin; + state.height = $(window).height() - constants.margin_bottom; + state.scale = state.width / (constants.end - constants.start); + state.zoom = 1.0; + state.zoomHistory = Array(); + state.numLoading = 0; + state.dependencyEvent = undefined; + state.drawDeps = false; + state.drawChildren = false; + + state.layoutData = []; + state.flattenedLayoutData = []; + + state.profilingData = {}; + state.processorData = {}; + state.utilData = []; + + state.operations = {}; + state.thickness = 20; //Math.max(state.height / constants.max_level, 20); + state.baseThickness = state.height / constants.max_level; + state.height = constants.max_level * state.thickness; + state.resolution = 10; // time (in us) of the smallest feature we want to load + state.searchEnabled = false; + state.rangeZoom = true; + state.collapseAll = false; + state.display_critical_path = false; + state.processor_kinds = {}; + + // display task ready state? + state.ready_selected = false; + // TODO: change this + state.x = d3.scale.linear().range([0, state.width]); + state.y = d3.scale.linear().range([constants.util_levels * state.thickness, 0]); + state.y.domain([0, 1]); + + setKeyHandler(defaultKeydown); + $(document).on("keyup", defaultKeyUp); + state.timelineSvg = d3.select("#timeline").select("svg").remove(); + state.timelineSvg = d3.select("#timeline").append("svg") + .attr("width", state.zoom * state.width) + .attr("height", state.height); + + state.loaderSvg = d3.select("#loader-icon").select("svg").remove(); + state.loaderSvg = d3.select("#loader-icon").append("svg") + .attr("width", "40px") + .attr("height", "40px"); + + d3.select("#processors").select("svg").remove(); + + drawLoaderIcon(); + drawHelpBox(); + load_data(); +} + +function load_util_json(callback) { + $.getJSON("json/utils.json", function(json) { + util_files = json; + callback(); + }); +} + +// Loads constants such as max_level, start/end time, and number of levels +// of a util view +function load_scale_json(callback) { + $.getJSON("json/scale.json", function(json) { + // add the read-in constants + $.each(json, function(key, val) { + constants[key] = val; + }); + load_util_json(callback); + }); +} + +function load_op_deps_json(callback) { + $.getJSON("json/op_dependencies.json", function(json) { + op_dependencies = json; + load_scale_json(callback); + }); +} + +function load_jsons(callback) { + load_scale_json(callback); +} + +function main() { + load_jsons(initializeState); +} + +main(); diff --git a/examples/testbench/good_band/js/util.js b/examples/testbench/good_band/js/util.js new file mode 100644 index 000000000..16ea770f2 --- /dev/null +++ b/examples/testbench/good_band/js/util.js @@ -0,0 +1,378 @@ +//----------------------------------------------------------------------------- +// UTILS +//----------------------------------------------------------------------------- + +var helpMessage = [ + "Zoom-in (x-axis) : Ctrl + / 4", + "Zoom-out (x-axis) : Ctrl - / 3", + "Reset zoom (x-axis): Ctrl 0 / 0", + "Undo zoom (x-axis) : u / U", + "Zoom-in (y-axis) : Ctrl-Alt + / 2", + "Zoom-out (y-axis) : Ctrl-Alt - / 1", + "Reset zoom (y-axis): Ctrl-Alt 0 / `", + "Range Zoom-in : drag-select", + "Measure duration : Alt + drag-select", + "Expand : e / E", + "Draw Critical Path : a / A", + "Search : s / S", + "Search History : h / H", + "Previous Search : p / P", + "Next Search : n / N", + "Clear Search : c / C", + "Toggle Search : t / T", +]; + +var Command = { + none : 0, + help : 1, + zox : 2, + zix : 3, + zrx : 4, + zux : 5, + zoy : 6, + ziy : 7, + zry : 8, + search : 9, + clear_search : 10, + toggle_search : 11, + expand: 12, + toggle_critical_path: 13, + search_history : 14, + previous_search : 15, + next_search : 16 +}; + +// commands without a modifier key pressed +var noModifierCommands = { + '0': Command.zrx, + '1': Command.zoy, + '2': Command.ziy, + '3': Command.zox, + '4': Command.zix, + 'c': Command.clear_search, + 'e': Command.expand, + 'h': Command.search_history, + 'n': Command.next_search, + 'p': Command.previous_search, + 's': Command.search, + 'a': Command.toggle_critical_path, + 't': Command.toggle_search, + 'u': Command.zux, + '/': Command.help +}; + +var modifierCommands = { + '+': Command.zix, + '-': Command.zox, + '0': Command.zrx +} + +var multipleModifierCommands = { + '+': Command.ziy, + '-': Command.zoy, + '0': Command.zry +} + +var keys = { + 13 : 'enter', + 27 : 'esc', + 48 : '0', + 49 : '1', + 50 : '2', + 51 : '3', + 52 : '4', + 61 : '+', // Firefox + 65 : 'a', + 67 : 'c', + 69 : 'e', + 72 : 'h', + 78 : 'n', + 80 : 'p', + 83 : 's', + 84 : 't', + 85 : 'u', + 173 : '-', // Firefox + 187 : '+', + 189 : '-', + 191 : '/', + 192 : '`' +}; + +/** + * Function: convertToTime + * + * Description: + * Takes a value and converts it to time. The input 'x' can either be + * a single position on the timeline, or it can be a width. + */ +function convertToTime(state, x) { + return x / state.zoom / state.scale; +} + +/** + * Function: convertToPos + * + * Description: + * Takes a time and converts it to a position in the window. + * The 'time' parameter MUST BE IN us + */ +function convertToPos(state, time) { + return time * state.zoom * state.scale; +} + +/** + * Function: getTimeString + * + * Description: + * This function takes a time (in us) as well as a 'width' + * field. The 'width' field determines over what interval + * the time is being considered. + * + * If the width is too large, the time will be converted + * to either ms or sec. + * + * The function will return a string representation of the + * (possibly) scaled time at the end of the method + */ +function getTimeString(time, timeWidth) { + var unit = "us"; + var scaledTime = Math.floor(time); + if (timeWidth >= 100000) { + var scaledTime = Math.floor(time / 1000); + unit = "ms"; + } else if (timeWidth >= 100000000) { + var scaledTime = Math.floor(time / 1000000); + unit = "s"; + } + return scaledTime + " " + unit; +} + +// timeField should be 'end' for the left hand side and +// 'start' for the right hand side +function binarySearch(data, level, time, useStart) { + var low = 0; + var high = data[level].length; + while (true) { + // ugh is there a way to do integer division in javascrtipt? + var mid = Math.floor((high - low) / 2) + low; + + // In this case, we haven't found it. This is as close + // as we were able to get. + if (low == high || low == mid) { + return low; + } else if (high == mid) { + return high; + } + var midTime; + if (useStart) { + midTime = data[level][mid].start; + } else { + midTime = data[level][mid].end; + } + + if (midTime > time) { + // need to look below + high = mid; + } else if (midTime < time) { + // need to look above + low = mid; + } else { + // Exact Match + return mid; + } + } +} + +dataReady = {}; +function redoData(proc) { + dataReady = {}; + var items = state.processorData[proc.full_text]; + for (var level in items) { + for (var j = 0; j< items[level].length; j++) { + d = items[level][j]; + // ready state items + if (d.level_ready != undefined && d.level_ready != "" && + d.ready != undefined && d.ready != "") { + // if the level has already been switched, then don't do anything + var level_to_set = d.level_ready; + if (d.level_ready_set != undefined && d.level_ready_set == true) + level_to_set = d.level; + var d_ready = { + id: d.id+items[level].length+1, // unique id + level: level_to_set, + level_ready: d.level, + ready: d.ready, + start: d.ready, + end: d.start, + color: d.color, + opacity: "0.45", + initiation: d.initiation, + title: d.title + " (ready)", + in: d.in, + out: d.out, + children: d.children, + parents: d.parents, + prof_uid: d.prof_uid, + proc: d.proc + }; + // switch levels if we need to + if (d.level_ready_set == undefined || d.level_ready_set == false) + { + var level_tmp = d.level; + d.level = d.level_ready; + d.level_ready = level_tmp; + d.level_ready_set = true; + } + if (d.level_ready in dataReady){ + dataReady[d.level_ready].push(d_ready); + dataReady[d.level_ready].push(d); + } + else { + dataReady[d.level_ready] = [d_ready]; + dataReady[d.level_ready].push(d); + } + } + // add items to the level + else { + if (d.level in dataReady) + dataReady[d.level].push(d); + else + dataReady[d.level] = [d]; + } + } + } +} + +function readyData(proc) { + redoData(proc); +} + +function filterAndMergeBlocks(state) { + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + state.dataToDraw = Array(); + state.memoryTexts = Array(); + var startTime = convertToTime(state, windowStart); + var endTime = convertToTime(state, windowEnd); + var min_feature_time = convertToTime(state, constants.min_feature_width); + var min_gap_time = convertToTime(state, constants.min_gap_width); + for (var index in state.flattenedLayoutData) { + var timelineElement = state.flattenedLayoutData[index]; + if (timelineElement.type == "proc" && timelineElement.enabled && timelineElement.visible) { + var items = state.processorData[timelineElement.full_text]; + var memoryRegex = /Memory/; + var isMemory = memoryRegex.exec(timelineElement.text); + if (state.ready_selected) { + readyData(timelineElement); + items = dataReady; + } + + for (var level in items) { + // gap merging below assumes intervals are sorted - do that first + //items[level].sort(function(a,b) { return a.start - b.start; }); + + // We will use binary search to limit the following section + var startIndex = binarySearch(items, level, startTime, false); + var endIndex = binarySearch(items, level, endTime, true); + for (var i = startIndex; i <= endIndex; ++i) { + var d = items[level][i]; + var start = d.start; + var end = d.end; + // fix the level here + if (state.ready_selected == false && d.level_ready_set != undefined + && d.level_ready_set == true) + { + // switch levels + var level_tmp = d.level; + d.level = d.level_ready; + d.level_ready = level_tmp; + d.level_ready_set = false; + } + // is this block too narrow? + if ((end - start) < min_feature_time) { + // see how many more after this are also too narrow and too close to us + var count = 1; + // don't do this if we're the subject of the current search and don't merge with + // something that is + if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) == null) { + while (((i + count) < items[level].length) && + ((items[level][i + count].start - end) < min_gap_time) && + ((items[level][i + count].end - items[level][i + count].start) < min_feature_time) && + (!state.searchEnabled || searchRegex[currentPos].exec(items[level][i + count].title) == null)) { + end = items[level][i + count].end; + count++; + } + } + // are we still too narrow? if so, bloat, but make sure we don't overlap something later + if ((end - start) < min_feature_time) { + end = start + min_feature_time; + if (((i + count) < items[level].length) && (items[level][i + count].start < end)) + end = items[level][i + count].start; + } + if (count > 1) { + state.dataToDraw.push({ + id: d.id, + prof_uid: d.prof_uid, + proc: timelineElement, + level: d.level, + ready: d.ready, + start: d.start, + end: Math.round(end), + color: "#808080", + title: count + " merged tasks", + in: [], + out: [], + children: [], + parents: [] + }); + i += (count - 1); + } else { + var elem = { + id: d.id, + prof_uid: d.prof_uid, + proc: timelineElement, + level: d.level, + ready: d.ready, + start: d.start, + end: d.end, + color: d.color, + initiation: d.initiation, + title: d.title + " (expanded for visibility)", + in: d.in, + out: d.out, + children: d.children, + parents: d.parents + } + state.dataToDraw.push(elem); + if (isMemory) { + state.memoryTexts.push(elem); + } + } + } else { + var elem = { + id: d.id, + prof_uid: d.prof_uid, + proc: timelineElement, + level: d.level, + ready: d.ready, + start: d.start, + end: d.end, + opacity: d.opacity, + color: d.color, + initiation: d.initiation, + title: d.title, + in: d.in, + out: d.out, + children: d.children, + parents: d.parents + } + state.dataToDraw.push(elem); + if (isMemory) { + state.memoryTexts.push(elem); + } + } + } + } + } + } +} diff --git a/examples/testbench/good_band/legion_prof_ops.tsv b/examples/testbench/good_band/legion_prof_ops.tsv new file mode 100644 index 000000000..399ea7717 --- /dev/null +++ b/examples/testbench/good_band/legion_prof_ops.tsv @@ -0,0 +1,90 @@ +op_id desc proc level +1 legion_python_main <1> Python Processor 0x1d00000000000004 2 +42 legate::numpy::FillTask [CPU] <42> CPU Processor 0x1d00000000000002 2 +47 legate::numpy::BinaryOpTask [CPU] <47> CPU Processor 0x1d00000000000002 2 +58 legate::numpy::BinaryOpTask [CPU] <58> CPU Processor 0x1d00000000000002 2 +71 legate::numpy::BinaryOpTask [CPU] <71> CPU Processor 0x1d00000000000002 2 +77 legate::numpy::BinaryOpTask [CPU] <77> CPU Processor 0x1d00000000000002 2 +3 Tunable Operation <3> +4 Tunable Operation <4> +5 Tunable Operation <5> +6 Pending Partition Operation <6> +8 Refinement Operation <8> +7 legate::numpy::FillTask <7> +0 Operation <0> +9 legate::numpy::FillTask <9> +12 legate::numpy::FillTask <12> +11 legate::numpy::FillTask <11> +14 Refinement Operation <14> +13 legate::numpy::FillTask [CPU] <13> CPU Processor 0x1d00000000000002 2 +86 Fence Operation <86> +89 Deletion Operation <89> +88 Deletion Operation <88> +87 Deletion Operation <87> +15 legate::numpy::FillTask [CPU] <15> CPU Processor 0x1d00000000000003 2 +48 legate::numpy::BinaryOpTask [CPU] <48> CPU Processor 0x1d00000000000003 2 +79 Mapping Operation <79> +23 legate::numpy::FillTask [CPU] <23> CPU Processor 0x1d00000000000002 2 +24 legate::numpy::FillTask [CPU] <24> CPU Processor 0x1d00000000000003 2 +38 legate::numpy::FillTask [CPU] <38> CPU Processor 0x1d00000000000003 2 +10 legate::numpy::FillTask <10> +21 legate::numpy::FillTask <21> +22 legate::numpy::FillTask <22> +30 legate::numpy::FillTask <30> +31 legate::numpy::FillTask <31> +34 legate::numpy::FillTask <34> +36 legate::numpy::FillTask [CPU] <36> CPU Processor 0x1d00000000000002 2 +39 Refinement Operation <39> +16 legate::numpy::FillTask <16> +26 legate::numpy::FillTask <26> +20 legate::numpy::FillTask <20> +53 legate::numpy::BinaryOpTask [CPU] <53> CPU Processor 0x1d00000000000003 2 +27 legate::numpy::FillTask <27> +40 legate::numpy::FillTask <40> +41 legate::numpy::FillTask <41> +43 legate::numpy::FillTask [CPU] <43> CPU Processor 0x1d00000000000003 2 +19 Refinement Operation <19> +28 legate::numpy::FillTask <28> +32 Refinement Operation <32> +33 legate::numpy::FillTask [CPU] <33> CPU Processor 0x1d00000000000002 2 +35 legate::numpy::FillTask [CPU] <35> CPU Processor 0x1d00000000000003 2 +44 legate::numpy::BinaryOpTask <44> +45 legate::numpy::BinaryOpTask <45> +46 legate::numpy::BinaryOpTask <46> +25 legate::numpy::FillTask <25> +17 legate::numpy::FillTask <17> +29 legate::numpy::BinaryOpTask <29> +18 legate::numpy::FillTask <18> +37 legate::numpy::BinaryOpTask <37> +54 legate::numpy::BinaryOpTask <54> +59 legate::numpy::BinaryOpTask <59> +62 legate::numpy::BinaryOpTask <62> +68 legate::numpy::BinaryOpTask <68> +73 legate::numpy::BinaryOpTask <73> +60 legate::numpy::BinaryOpTask [CPU] <60> CPU Processor 0x1d00000000000003 2 +66 legate::numpy::BinaryOpTask [CPU] <66> CPU Processor 0x1d00000000000003 2 +72 legate::numpy::BinaryOpTask [CPU] <72> CPU Processor 0x1d00000000000003 2 +78 legate::numpy::BinaryOpTask [CPU] <78> CPU Processor 0x1d00000000000003 2 +52 legate::numpy::BinaryOpTask [CPU] <52> CPU Processor 0x1d00000000000002 2 +49 legate::numpy::BinaryOpTask <49> +50 legate::numpy::BinaryOpTask <50> +51 legate::numpy::BinaryOpTask <51> +61 legate::numpy::BinaryOpTask <61> +63 legate::numpy::BinaryOpTask <63> +64 legate::numpy::BinaryOpTask <64> +65 legate::numpy::BinaryOpTask [CPU] <65> CPU Processor 0x1d00000000000002 2 +67 legate::numpy::BinaryOpTask <67> +80 Merge Close Operation <80> +81 legate::numpy::BinaryOpTask <81> +82 legate::numpy::BinaryOpTask <82> +83 legate::numpy::BinaryOpTask <83> +55 legate::numpy::BinaryOpTask <55> +57 legate::numpy::BinaryOpTask <57> +69 legate::numpy::BinaryOpTask <69> +70 legate::numpy::BinaryOpTask <70> +84 legate::numpy::BinaryOpTask [CPU] <84> CPU Processor 0x1d00000000000002 2 +85 legate::numpy::BinaryOpTask [CPU] <85> CPU Processor 0x1d00000000000003 2 +56 legate::numpy::BinaryOpTask <56> +74 legate::numpy::BinaryOpTask <74> +75 legate::numpy::BinaryOpTask <75> +76 legate::numpy::BinaryOpTask <76> diff --git a/examples/testbench/good_band/legion_prof_processor.tsv b/examples/testbench/good_band/legion_prof_processor.tsv new file mode 100644 index 000000000..4773ccb73 --- /dev/null +++ b/examples/testbench/good_band/legion_prof_processor.tsv @@ -0,0 +1,9 @@ +full_text text tsv levels +Utility Processor 0x1d00000000000000 Utility Proc 0 tsv/Proc_0x1d00000000000000.tsv 5 +Utility Processor 0x1d00000000000001 Utility Proc 1 tsv/Proc_0x1d00000000000001.tsv 4 +CPU Processor 0x1d00000000000002 CPU Proc 2 tsv/Proc_0x1d00000000000002.tsv 1 +CPU Processor 0x1d00000000000003 CPU Proc 3 tsv/Proc_0x1d00000000000003.tsv 1 +Python Processor 0x1d00000000000004 Python Proc 4 tsv/Proc_0x1d00000000000004.tsv 1 +Dependent Partition Channel Dependent Partition Channel tsv/None.tsv 3 +System Memory 0x1e00000000000000 to System Memory 0x1e00000000000000 Channel [n0] sys to [n0] sys tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv 3 +System Memory 0x1e00000000000000 [n0] sys tsv/Mem_0x1e00000000000000.tsv 11 diff --git a/examples/testbench/good_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv b/examples/testbench/good_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv new file mode 100644 index 000000000..4203867b4 --- /dev/null +++ b/examples/testbench/good_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv @@ -0,0 +1,3 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +3 1373371.458 1387229.451 #ff6e00 1.0 size=19.073 MiB, num reqs=1$req[0]: src_inst=0x4000000000000007, dst_inst=0x400000000000000b, fields=1, type=copy, hops=1 79 647 +2 1373846.460 1387561.869 #ff6e00 1.0 size=19.073 MiB, num reqs=1$req[0]: src_inst=0x4000000000000008, dst_inst=0x400000000000000b, fields=1, type=copy, hops=1 79 648 diff --git a/examples/testbench/good_band/tsv/0 (CPU)_util.tsv b/examples/testbench/good_band/tsv/0 (CPU)_util.tsv new file mode 100644 index 000000000..4fe28da97 --- /dev/null +++ b/examples/testbench/good_band/tsv/0 (CPU)_util.tsv @@ -0,0 +1,208 @@ +time count +0.000 0.00 +1164390.880 0.50 +1164404.064 0.00 +1164431.041 0.50 +1164436.216 0.00 +1164746.447 0.50 +1164753.372 0.00 +1164794.721 0.50 +1164801.321 0.00 +1207340.857 0.50 +1207348.217 0.00 +1207357.779 0.50 +1207362.525 0.00 +1257468.208 0.50 +1257475.225 0.00 +1257512.563 0.50 +1257518.405 0.00 +1257612.061 0.50 +1257621.839 0.00 +1257633.588 0.50 +1257640.573 0.00 +1278088.519 0.50 +1278094.369 0.00 +1278227.506 0.50 +1278250.584 0.00 +1278329.460 0.50 +1278341.946 0.00 +1278465.635 0.50 +1278473.130 0.00 +1278531.783 0.50 +1278539.848 0.00 +1278559.197 0.50 +1278563.854 0.00 +1278647.025 0.50 +1278654.038 0.00 +1278661.355 0.50 +1278670.464 0.00 +1278677.818 0.50 +1278682.210 0.00 +1278732.052 0.50 +1278737.425 0.00 +1278822.472 0.50 +1278827.664 0.00 +1278836.004 0.50 +1278846.984 0.00 +1278863.656 0.50 +1278867.667 0.00 +1278941.853 0.50 +1278947.582 0.00 +1279087.247 0.50 +1279093.462 0.00 +1279119.581 0.50 +1279132.688 0.00 +1279195.488 0.50 +1279381.573 1.00 +1279387.931 0.50 +1279397.429 1.00 +1279409.712 0.50 +1279450.771 1.00 +1279457.216 0.50 +1279491.926 1.00 +1279502.598 0.50 +1279554.996 1.00 +1279565.486 0.50 +1279612.008 1.00 +1279618.651 0.50 +1279629.022 1.00 +1279637.142 0.50 +1279646.909 1.00 +1290530.227 0.50 +1290575.311 1.00 +1290673.584 0.50 +1290724.634 1.00 +1301160.372 0.50 +1301205.707 1.00 +1301522.032 0.50 +1301559.534 1.00 +1312999.079 0.50 +1313041.542 1.00 +1313329.507 0.50 +1313364.414 1.00 +1316508.577 0.50 +1316545.328 1.00 +1316831.920 0.50 +1316862.415 1.00 +1319918.397 0.50 +1319957.314 1.00 +1319964.781 0.50 +1320009.542 1.00 +1320182.092 0.50 +1320208.211 1.00 +1333283.719 0.50 +1333326.173 1.00 +1333334.715 0.50 +1333381.736 1.00 +1333389.695 0.50 +1333450.382 1.00 +1346503.982 0.50 +1346589.948 1.00 +1347048.850 0.50 +1347087.138 1.00 +1347098.437 0.50 +1347145.449 1.00 +1353143.177 0.50 +1353185.134 1.00 +1353193.257 0.50 +1353240.213 1.00 +1353587.731 0.50 +1353620.664 1.00 +1353625.527 0.50 +1353676.454 1.00 +1358415.641 0.50 +1358516.042 1.00 +1358922.645 0.50 +1358955.630 1.00 +1358961.897 0.50 +1359020.346 1.00 +1363745.920 0.50 +1363795.948 1.00 +1363805.182 0.50 +1363869.877 1.00 +1364298.334 0.50 +1364340.083 1.00 +1364346.914 0.50 +1364383.652 1.00 +1368701.245 0.50 +1368739.249 1.00 +1368746.421 0.50 +1368793.530 1.00 +1369149.144 0.50 +1369188.043 1.00 +1369203.231 0.50 +1369248.466 1.00 +1373328.678 0.50 +1373764.764 0.00 +1805328.138 0.50 +1805337.533 0.00 +1805375.803 0.50 +1805382.225 0.00 +1843775.371 0.50 +1843805.275 0.00 +1843817.171 0.50 +1843824.922 0.00 +1843844.761 0.50 +1843861.109 0.00 +1843886.263 0.50 +1843893.154 0.00 +1843937.108 0.50 +1843943.529 0.00 +1843951.637 0.50 +1843966.439 0.00 +1844034.676 0.50 +1844041.454 0.00 +1844091.466 0.50 +1844097.428 0.00 +1844123.736 0.50 +1844129.659 0.00 +1844167.643 0.50 +1844182.143 0.00 +1844214.123 0.50 +1844221.266 0.00 +1844257.222 0.50 +1844263.836 0.00 +1844301.260 0.50 +1844305.938 0.00 +1844676.874 0.50 +1844697.739 0.00 +1844723.767 0.50 +1844730.441 0.00 +1844738.308 0.50 +1844743.158 0.00 +1844770.899 0.50 +1844776.660 0.00 +1844809.980 0.50 +1844816.809 0.00 +1844857.582 0.50 +1844865.890 0.00 +1844874.628 0.50 +1844891.521 0.00 +1844898.768 0.50 +1844902.397 0.00 +1844935.962 0.50 +1844943.256 0.00 +1844963.598 0.50 +1844966.386 1.00 +1844971.617 0.50 +1844973.976 0.00 +1845015.224 0.50 +1845023.543 0.00 +1845051.132 0.50 +1845067.224 0.00 +1845079.615 0.50 +1845085.862 0.00 +1845092.849 0.50 +1845096.644 0.00 +1845103.389 0.50 +1845108.412 0.00 +1845129.295 0.50 +1845132.386 1.00 +1845137.136 0.50 +1845139.801 0.00 +1845147.332 0.50 +1845163.365 0.00 +1845168.715 0.50 +1845171.090 1.00 +1845175.087 0.50 +1845177.515 0.00 diff --git a/examples/testbench/good_band/tsv/0 (Channel)_util.tsv b/examples/testbench/good_band/tsv/0 (Channel)_util.tsv new file mode 100644 index 000000000..e13bb0242 --- /dev/null +++ b/examples/testbench/good_band/tsv/0 (Channel)_util.tsv @@ -0,0 +1,4 @@ +time count +0.000 0.00 +1373371.458 1.00 +1387561.869 0.00 diff --git a/examples/testbench/good_band/tsv/0 (Python)_util.tsv b/examples/testbench/good_band/tsv/0 (Python)_util.tsv new file mode 100644 index 000000000..9d87a3d5a --- /dev/null +++ b/examples/testbench/good_band/tsv/0 (Python)_util.tsv @@ -0,0 +1,16 @@ +time count +0.000 0.00 +494356.555 1.00 +1164322.429 0.00 +1164554.852 1.00 +1164686.388 0.00 +1164823.261 1.00 +1207258.637 0.00 +1207422.856 1.00 +1305677.005 0.00 +1307537.619 1.00 +1307553.652 0.00 +1387655.987 1.00 +1805303.104 0.00 +1805398.321 1.00 +1843718.831 0.00 diff --git a/examples/testbench/good_band/tsv/0 (System Memory)_util.tsv b/examples/testbench/good_band/tsv/0 (System Memory)_util.tsv new file mode 100644 index 000000000..c46245cd8 --- /dev/null +++ b/examples/testbench/good_band/tsv/0 (System Memory)_util.tsv @@ -0,0 +1,24 @@ +time count +0.000 0.00 +1278823.735 0.00 +1279061.877 0.01 +1280061.606 0.01 +1280246.078 0.02 +1281367.754 0.02 +1281572.958 0.03 +1282612.241 0.03 +1282784.125 0.04 +1283563.847 0.04 +1283746.860 0.05 +1307133.149 0.06 +1844151.087 0.05 +1844240.657 0.05 +1844651.511 0.04 +1844726.221 0.03 +1844793.065 0.03 +1844857.709 0.02 +1844919.518 0.02 +1844985.437 0.01 +1845081.180 0.01 +1845119.817 0.00 +1845134.718 0.00 diff --git a/examples/testbench/good_band/tsv/0 (Utility)_util.tsv b/examples/testbench/good_band/tsv/0 (Utility)_util.tsv new file mode 100644 index 000000000..e697ba587 --- /dev/null +++ b/examples/testbench/good_band/tsv/0 (Utility)_util.tsv @@ -0,0 +1,992 @@ +time count +0.000 0.00 +493837.510 0.50 +493896.375 0.00 +493931.102 0.50 +493931.677 1.00 +493944.124 0.50 +494029.929 0.00 +494058.742 0.50 +494058.910 1.00 +494064.325 0.50 +494101.567 0.00 +494125.428 0.50 +494130.615 1.00 +494135.463 0.50 +494193.707 0.00 +494208.875 0.50 +494210.784 1.00 +494214.839 0.50 +494348.350 0.00 +494368.000 0.50 +494371.632 0.00 +1164265.110 0.50 +1164304.048 0.00 +1164313.229 0.50 +1164405.071 1.00 +1164407.217 0.50 +1164511.519 0.00 +1164541.448 0.50 +1164549.085 0.00 +1164682.320 0.50 +1164714.593 0.00 +1164725.526 0.50 +1164772.567 0.00 +1164778.390 0.50 +1164819.329 0.00 +1164842.752 0.50 +1164848.390 0.00 +1207271.028 0.50 +1207305.822 1.00 +1207307.344 0.50 +1207337.594 0.00 +1207339.179 0.50 +1207399.159 0.00 +1207424.454 0.50 +1207430.784 0.00 +1257389.335 0.50 +1257422.422 0.00 +1257444.005 0.50 +1257484.492 0.00 +1257499.072 0.50 +1257585.815 0.00 +1257595.549 0.50 +1257609.470 1.00 +1257615.167 0.50 +1257624.283 0.00 +1257640.055 0.50 +1257646.736 0.00 +1277848.542 0.50 +1278028.704 1.00 +1278028.841 0.50 +1278051.446 1.00 +1278056.549 0.50 +1278061.916 0.00 +1278063.442 0.50 +1278109.764 1.00 +1278119.561 0.50 +1278137.033 1.00 +1278141.642 0.50 +1278162.126 0.00 +1278163.934 0.50 +1278180.326 1.00 +1278186.455 0.50 +1278205.113 0.00 +1278209.774 0.50 +1278308.664 0.00 +1278323.593 0.50 +1278426.961 1.00 +1278440.201 0.50 +1278461.160 1.00 +1278505.618 0.50 +1278538.494 1.00 +1278541.424 0.50 +1278559.476 1.00 +1278619.622 0.50 +1278620.037 0.00 +1278638.486 0.50 +1278641.562 1.00 +1278664.513 0.50 +1278680.314 1.00 +1278712.234 0.50 +1278726.859 1.00 +1278745.693 0.50 +1278783.666 1.00 +1278801.586 0.50 +1278818.753 1.00 +1278849.780 0.50 +1278893.781 1.00 +1278918.912 0.50 +1278940.842 1.00 +1278989.270 0.50 +1279017.443 1.00 +1279099.959 0.50 +1279133.630 1.00 +1279160.544 0.50 +1279231.730 1.00 +1279251.865 0.50 +1279320.699 1.00 +1279351.834 0.50 +1279375.598 0.00 +1279389.655 0.50 +1279418.725 1.00 +1279426.309 0.50 +1279467.951 0.00 +1279479.418 0.50 +1279508.879 1.00 +1279536.461 0.50 +1279561.577 1.00 +1279580.044 0.50 +1279591.038 0.00 +1279611.199 0.50 +1279616.772 1.00 +1279651.982 0.50 +1279674.758 1.00 +1279698.571 0.50 +1279718.086 1.00 +1279761.109 0.50 +1279774.382 0.00 +1279777.897 0.50 +1279792.958 1.00 +1279794.261 0.50 +1279823.597 1.00 +1279866.659 0.50 +1279872.496 0.00 +1279883.399 0.50 +1279895.526 1.00 +1279907.765 0.50 +1279921.310 1.00 +1279925.030 0.50 +1279945.362 0.00 +1279947.145 0.50 +1279958.591 1.00 +1279997.784 0.50 +1280008.249 0.00 +1280011.334 0.50 +1280036.518 1.00 +1280057.763 0.50 +1280076.936 1.00 +1280123.017 0.50 +1280137.759 1.00 +1280175.444 0.50 +1280192.631 1.00 +1280237.601 0.50 +1280252.240 1.00 +1280278.040 0.50 +1280290.082 1.00 +1280302.458 0.50 +1280314.319 1.00 +1280319.182 0.50 +1280324.665 1.00 +1280328.013 0.50 +1280332.985 1.00 +1280336.186 0.50 +1280340.596 1.00 +1280345.027 0.50 +1280349.935 1.00 +1280354.507 0.50 +1280360.608 1.00 +1280368.275 0.50 +1280379.031 0.00 +1280397.006 0.50 +1280404.093 0.00 +1280408.793 0.50 +1280412.723 0.00 +1280415.218 0.50 +1280418.215 1.00 +1280422.494 0.50 +1280427.978 1.00 +1280432.194 0.50 +1280436.774 1.00 +1280440.821 0.50 +1280446.196 1.00 +1280450.961 0.50 +1280456.534 1.00 +1280480.415 0.50 +1280500.201 0.00 +1280517.657 0.50 +1280519.467 1.00 +1280590.069 0.50 +1280618.696 1.00 +1280620.373 0.50 +1280640.616 1.00 +1280675.589 0.50 +1280695.112 1.00 +1280704.966 0.50 +1280724.974 1.00 +1280731.408 0.50 +1280750.931 1.00 +1280799.920 0.50 +1280819.690 1.00 +1280845.001 0.50 +1280864.265 1.00 +1280903.705 0.50 +1280923.262 1.00 +1280948.444 0.50 +1280949.533 0.00 +1280969.101 0.50 +1280975.106 1.00 +1281006.901 0.50 +1281020.886 0.00 +1281026.198 0.50 +1281040.746 1.00 +1281082.549 0.50 +1281102.897 1.00 +1281117.395 0.50 +1281128.249 0.00 +1281133.593 0.50 +1281156.030 0.00 +1281168.256 0.50 +1281168.977 1.00 +1281202.632 0.50 +1281216.424 1.00 +1281221.133 0.50 +1281244.468 1.00 +1281263.117 0.50 +1281278.236 1.00 +1281304.887 0.50 +1281307.180 0.00 +1281323.992 0.50 +1281331.290 1.00 +1281352.380 0.50 +1281369.623 1.00 +1281426.948 0.50 +1281441.165 1.00 +1281453.949 0.50 +1281469.680 1.00 +1281491.546 0.50 +1281511.464 1.00 +1281524.905 0.50 +1281540.900 1.00 +1281542.779 0.50 +1281578.718 1.00 +1281646.649 0.50 +1281662.778 1.00 +1281672.107 0.50 +1281687.437 0.00 +1281702.413 0.50 +1281711.894 1.00 +1281728.933 0.50 +1281747.438 1.00 +1281795.038 0.50 +1281819.066 1.00 +1281833.954 0.50 +1281854.322 1.00 +1281914.727 0.50 +1281935.560 1.00 +1281962.837 0.50 +1281968.754 0.00 +1281982.725 0.50 +1281987.215 1.00 +1281997.474 0.50 +1282022.385 1.00 +1282052.736 0.50 +1282073.815 1.00 +1282075.305 0.50 +1282094.433 1.00 +1282135.609 0.50 +1282156.222 0.00 +1282156.494 0.50 +1282176.348 1.00 +1282184.635 0.50 +1282204.439 1.00 +1282213.490 0.50 +1282231.574 0.00 +1282232.852 0.50 +1282247.509 1.00 +1282254.507 0.50 +1282263.334 1.00 +1282265.809 0.50 +1282284.700 1.00 +1282290.552 0.50 +1282298.502 1.00 +1282305.272 0.50 +1282312.818 1.00 +1282321.895 0.50 +1282329.352 1.00 +1282334.523 0.50 +1282342.111 1.00 +1282347.445 0.50 +1282350.095 0.00 +1282355.476 0.50 +1282370.051 1.00 +1282376.626 0.50 +1282383.996 1.00 +1282390.851 0.50 +1282398.511 1.00 +1282404.761 0.50 +1282412.358 1.00 +1282431.565 0.50 +1282451.010 1.00 +1282495.982 0.50 +1282517.522 1.00 +1282537.356 0.50 +1282560.296 1.00 +1282570.883 0.50 +1282589.505 1.00 +1282637.613 0.50 +1282666.567 1.00 +1282670.256 0.50 +1282676.118 1.00 +1282682.844 0.50 +1282687.683 1.00 +1282691.027 0.50 +1282695.682 1.00 +1282699.349 0.50 +1282704.941 1.00 +1282708.191 0.50 +1282712.962 1.00 +1282717.209 0.50 +1282721.947 1.00 +1282725.259 0.50 +1282729.621 1.00 +1282732.909 0.50 +1282738.061 1.00 +1282742.186 0.50 +1282747.803 1.00 +1282880.412 0.50 +1282895.492 1.00 +1282898.743 0.50 +1282903.269 1.00 +1282906.398 0.50 +1282911.963 1.00 +1282915.130 0.50 +1282919.738 1.00 +1282922.982 0.50 +1282928.128 1.00 +1282935.817 0.50 +1282942.383 1.00 +1282942.785 0.50 +1282966.964 0.00 +1282980.146 0.50 +1282986.367 1.00 +1282991.345 0.50 +1282998.561 1.00 +1283003.565 0.50 +1283010.418 1.00 +1283015.397 0.50 +1283022.770 1.00 +1283027.895 0.50 +1283034.875 1.00 +1283040.014 0.50 +1283046.978 1.00 +1283052.050 0.50 +1283059.186 1.00 +1283065.631 0.50 +1283073.383 1.00 +1283076.987 0.50 +1283098.801 1.00 +1283110.127 0.50 +1283130.304 1.00 +1283130.494 0.50 +1283150.656 1.00 +1283156.284 0.50 +1283163.621 0.00 +1283164.014 0.50 +1283182.622 1.00 +1283188.104 0.50 +1283195.694 1.00 +1283204.944 0.50 +1283211.677 1.00 +1283220.390 0.50 +1283227.561 1.00 +1283232.886 0.50 +1283239.761 1.00 +1283244.909 0.50 +1283251.950 0.00 +1283252.211 0.50 +1283272.054 1.00 +1283278.592 0.50 +1283285.846 1.00 +1283291.196 0.50 +1283298.174 1.00 +1283303.562 0.50 +1283311.221 1.00 +1283324.969 0.50 +1283344.437 1.00 +1283395.670 0.50 +1283414.744 1.00 +1283430.716 0.50 +1283450.278 1.00 +1283480.049 0.50 +1283500.017 1.00 +1283500.409 0.50 +1283519.252 1.00 +1283537.974 0.50 +1283621.832 1.00 +1283626.988 0.50 +1283634.116 1.00 +1283639.765 0.50 +1283647.210 1.00 +1283652.142 0.50 +1283658.525 1.00 +1283663.327 0.50 +1283669.788 1.00 +1283674.776 0.50 +1283681.015 1.00 +1283687.272 0.50 +1283695.521 1.00 +1283891.905 0.50 +1283930.408 1.00 +1283931.392 0.50 +1283956.807 1.00 +1283991.577 0.50 +1283996.266 0.00 +1284006.864 0.50 +1284019.731 1.00 +1284026.542 0.50 +1284031.957 0.00 +1284037.065 0.50 +1284043.643 0.00 +1284046.066 0.50 +1284050.070 0.00 +1284052.387 0.50 +1284055.707 1.00 +1284059.289 0.50 +1284060.505 0.00 +1284067.513 0.50 +1284070.087 1.00 +1284074.595 0.50 +1284076.801 0.00 +1284080.228 0.50 +1284085.420 1.00 +1284086.541 0.50 +1284091.929 0.00 +1284092.440 0.50 +1284096.296 0.00 +1284100.863 0.50 +1284101.982 1.00 +1284106.383 0.50 +1284107.585 0.00 +1284111.488 0.50 +1284115.765 0.00 +1284116.830 0.50 +1284121.233 1.00 +1284123.552 0.50 +1284125.707 0.00 +1284131.344 0.50 +1284132.489 1.00 +1284135.349 0.50 +1284139.516 0.00 +1284140.596 0.50 +1284144.671 0.00 +1284148.163 0.50 +1284149.723 1.00 +1284154.638 0.50 +1284156.310 0.00 +1284161.552 0.50 +1284163.452 1.00 +1284167.611 0.50 +1284172.102 1.00 +1284175.585 0.50 +1284177.046 0.00 +1284182.497 0.50 +1284189.542 0.00 +1290561.994 0.50 +1290575.892 1.00 +1290581.206 0.50 +1290645.947 0.00 +1290672.470 0.50 +1290682.613 0.00 +1290706.341 0.50 +1290712.299 0.00 +1290721.686 0.50 +1290776.945 1.00 +1290793.748 0.50 +1290814.031 1.00 +1290821.356 0.50 +1290821.681 0.00 +1290851.820 0.50 +1290857.268 0.00 +1301189.824 0.50 +1301196.603 0.00 +1301211.605 0.50 +1301251.876 0.00 +1301276.326 0.50 +1301282.541 0.00 +1301544.868 0.50 +1301552.926 0.00 +1301559.661 0.50 +1301606.151 1.00 +1301629.806 0.50 +1301641.799 0.00 +1301646.722 0.50 +1301651.116 0.00 +1301693.731 0.50 +1301697.364 0.00 +1303168.646 0.50 +1303281.263 1.00 +1303283.977 0.50 +1303305.777 1.00 +1303312.883 0.50 +1303320.693 0.00 +1303321.376 0.50 +1303344.045 1.00 +1303349.993 0.50 +1303396.088 0.00 +1303396.962 0.50 +1303414.273 1.00 +1303418.400 0.50 +1303482.714 0.00 +1303483.722 0.50 +1303497.656 1.00 +1303502.117 0.50 +1303545.046 1.00 +1303558.517 0.50 +1303573.877 1.00 +1303624.181 0.50 +1303642.161 0.00 +1303670.965 0.50 +1303671.094 1.00 +1303704.125 0.50 +1303718.836 0.00 +1303732.487 0.50 +1303745.784 1.00 +1303770.128 0.50 +1303786.168 1.00 +1303805.810 0.50 +1303811.406 0.00 +1303820.840 0.50 +1303844.177 0.00 +1303845.931 0.50 +1303856.281 1.00 +1303879.903 0.50 +1303908.169 0.00 +1303909.035 0.50 +1303922.034 1.00 +1303925.681 0.50 +1303931.496 1.00 +1303935.527 0.50 +1303940.923 1.00 +1303944.758 0.50 +1303950.746 1.00 +1303965.082 0.50 +1303983.695 1.00 +1303988.852 0.50 +1303996.469 1.00 +1304002.083 0.50 +1304010.979 1.00 +1304016.012 0.50 +1304034.134 1.00 +1304053.638 0.50 +1304057.203 0.00 +1304070.131 0.50 +1304076.332 1.00 +1304082.034 0.50 +1304089.969 1.00 +1304095.865 0.50 +1304099.441 0.00 +1304104.636 0.50 +1304120.480 1.00 +1304128.900 0.50 +1304137.321 1.00 +1304143.536 0.50 +1304151.481 1.00 +1304158.130 0.50 +1304166.492 1.00 +1304172.116 0.50 +1304179.541 1.00 +1304185.478 0.50 +1304194.596 1.00 +1304201.779 0.50 +1304225.353 1.00 +1304268.486 0.50 +1304287.341 1.00 +1304297.327 0.50 +1304317.260 1.00 +1304378.464 0.50 +1304388.941 0.00 +1304398.660 0.50 +1304402.496 1.00 +1304436.193 0.50 +1304450.099 1.00 +1304450.999 0.50 +1304470.099 1.00 +1304504.123 0.50 +1304516.057 1.00 +1304538.039 0.50 +1304551.018 1.00 +1304564.826 0.50 +1304575.121 0.00 +1304586.431 0.50 +1304587.656 1.00 +1304609.345 0.50 +1304619.350 0.00 +1304622.305 0.50 +1304637.141 1.00 +1304643.365 0.50 +1304651.780 1.00 +1304658.683 0.50 +1304666.550 1.00 +1304672.388 0.50 +1304680.459 1.00 +1304688.024 0.50 +1304690.689 0.00 +1304698.019 0.50 +1304706.331 1.00 +1304723.689 0.50 +1304762.829 1.00 +1304772.128 0.50 +1304783.673 0.00 +1304792.515 0.50 +1304816.987 1.00 +1304856.819 0.50 +1304888.752 0.00 +1304897.074 0.50 +1304903.629 1.00 +1304949.175 0.50 +1304964.588 1.00 +1305012.316 0.50 +1305034.947 1.00 +1305056.498 0.50 +1305071.433 0.00 +1305078.479 0.50 +1305086.886 1.00 +1305111.303 0.50 +1305123.950 1.00 +1305127.879 0.50 +1305132.242 1.00 +1305135.716 0.50 +1305140.603 1.00 +1305144.069 0.50 +1305148.825 1.00 +1305152.880 0.50 +1305158.699 1.00 +1305162.057 0.50 +1305168.106 1.00 +1305176.877 0.50 +1305192.136 0.00 +1305199.516 0.50 +1305206.007 1.00 +1305232.334 0.50 +1305234.115 0.00 +1305245.411 0.50 +1305252.611 1.00 +1305308.677 0.50 +1305319.714 0.00 +1305327.160 0.50 +1305339.765 1.00 +1305345.502 0.50 +1305353.891 1.00 +1305360.727 0.50 +1305370.367 1.00 +1305382.614 0.50 +1305404.041 1.00 +1305480.738 0.50 +1305504.378 1.00 +1305514.951 0.50 +1305536.821 1.00 +1305567.074 0.50 +1305594.413 1.00 +1305610.959 0.50 +1305631.496 1.00 +1305686.197 0.50 +1305712.259 1.00 +1305727.618 0.50 +1305742.024 1.00 +1305770.369 0.50 +1305783.995 1.00 +1305807.428 0.50 +1305813.329 0.00 +1305832.088 0.50 +1305888.240 1.00 +1305893.515 0.50 +1305920.984 1.00 +1305922.460 0.50 +1305952.530 1.00 +1305961.048 0.50 +1305972.370 1.00 +1305975.704 0.50 +1305994.539 1.00 +1306000.231 0.50 +1306007.662 1.00 +1306012.745 0.50 +1306018.660 1.00 +1306024.251 0.50 +1306031.062 1.00 +1306036.169 0.50 +1306042.053 1.00 +1306046.201 0.50 +1306051.923 1.00 +1306055.204 0.50 +1306061.397 1.00 +1306068.757 0.50 +1306077.209 1.00 +1306082.911 0.50 +1306089.960 1.00 +1306095.305 0.50 +1306102.116 1.00 +1306106.899 0.50 +1306113.792 1.00 +1306118.325 0.50 +1306125.177 1.00 +1306129.472 0.50 +1306135.484 1.00 +1306139.885 0.50 +1306146.163 1.00 +1306151.014 0.50 +1306157.922 1.00 +1306162.843 0.50 +1306169.196 1.00 +1306173.805 0.50 +1306180.863 1.00 +1306186.221 0.50 +1306192.428 1.00 +1306198.940 0.50 +1306207.747 1.00 +1306213.896 0.50 +1306224.076 1.00 +1306224.570 0.50 +1306244.535 1.00 +1306251.719 0.50 +1306258.625 1.00 +1306262.340 0.50 +1306266.639 1.00 +1306269.915 0.50 +1306274.647 1.00 +1306278.288 0.50 +1306284.148 1.00 +1306288.891 0.50 +1306295.085 1.00 +1306316.875 0.50 +1306337.294 1.00 +1306373.980 0.50 +1306390.469 1.00 +1306410.407 0.50 +1306431.241 0.00 +1306438.072 0.50 +1306444.023 1.00 +1306475.533 0.50 +1306487.743 1.00 +1306501.791 0.50 +1306520.623 1.00 +1306546.595 0.50 +1306556.205 0.00 +1306561.231 0.50 +1306570.551 1.00 +1306596.581 0.50 +1306597.755 0.00 +1306609.046 0.50 +1306616.486 1.00 +1306620.257 0.50 +1306625.100 1.00 +1306628.442 0.50 +1306633.053 1.00 +1306638.535 0.50 +1306643.545 1.00 +1306647.468 0.50 +1306651.973 1.00 +1306655.289 0.50 +1306659.951 1.00 +1306663.338 0.50 +1306667.811 1.00 +1306671.169 0.50 +1306676.051 1.00 +1306680.523 0.50 +1306685.372 1.00 +1306688.634 0.50 +1306692.987 1.00 +1306696.272 0.50 +1306701.710 1.00 +1306706.054 0.50 +1306710.872 1.00 +1306714.195 0.50 +1306719.516 1.00 +1306723.164 0.50 +1306727.419 1.00 +1306730.709 0.50 +1306739.454 1.00 +1306745.991 0.50 +1306751.542 1.00 +1306756.065 0.50 +1306756.354 0.00 +1306761.979 0.50 +1306766.736 0.00 +1306773.560 0.50 +1306776.655 1.00 +1306781.569 0.50 +1306790.612 0.00 +1306792.355 0.50 +1306802.720 1.00 +1306806.557 0.50 +1306811.402 0.00 +1306869.300 0.50 +1306875.443 0.00 +1306886.823 0.50 +1306898.727 0.00 +1306924.051 0.50 +1306929.726 0.00 +1306948.288 0.50 +1306999.684 1.00 +1307020.185 0.50 +1307038.067 0.00 +1307056.365 0.50 +1307059.257 1.00 +1307084.938 0.50 +1307095.699 1.00 +1307099.265 0.50 +1307154.918 1.00 +1307163.906 0.50 +1307269.010 1.00 +1307275.994 0.50 +1307300.490 1.00 +1307307.680 0.50 +1307478.161 0.00 +1307484.883 0.50 +1307497.332 1.00 +1307515.476 0.50 +1307531.573 1.00 +1307536.897 0.50 +1307545.301 1.00 +1307547.707 0.50 +1307551.859 0.00 +1307575.711 0.50 +1307583.147 0.00 +1313028.908 0.50 +1313043.492 0.00 +1313044.487 0.50 +1313088.907 0.00 +1313107.910 0.50 +1313112.001 0.00 +1313377.313 0.50 +1313383.481 0.00 +1313415.699 0.50 +1313465.770 0.00 +1313482.463 0.50 +1313486.229 0.00 +1316552.854 0.50 +1316569.677 0.00 +1316583.573 0.50 +1316625.438 0.00 +1316644.297 0.50 +1316648.163 0.00 +1316874.269 0.50 +1316881.752 0.00 +1316912.943 0.50 +1316958.130 0.00 +1316974.511 0.50 +1316978.142 0.00 +1319995.186 0.50 +1320025.818 0.00 +1320040.609 0.50 +1320044.432 0.00 +1320214.501 0.50 +1320214.870 1.00 +1320221.281 0.50 +1320270.219 0.00 +1320297.734 0.50 +1320303.704 0.00 +1333333.783 0.50 +1333386.811 0.00 +1333412.514 0.50 +1333412.634 1.00 +1333418.805 0.50 +1333418.933 0.00 +1333430.989 0.50 +1333469.596 0.00 +1333486.409 0.50 +1333490.897 0.00 +1346545.220 0.50 +1346551.558 1.00 +1346557.434 0.50 +1346606.273 0.00 +1346633.938 0.50 +1346640.148 0.00 +1347130.799 0.50 +1347181.604 0.00 +1347201.196 0.50 +1347205.096 0.00 +1353197.202 0.50 +1353243.345 0.00 +1353265.362 0.50 +1353269.535 0.00 +1353631.730 0.50 +1353696.535 0.00 +1353696.939 0.50 +1353712.876 1.00 +1353716.802 0.50 +1353730.416 0.00 +1353754.700 0.50 +1353758.956 0.00 +1358452.236 0.50 +1358458.994 0.00 +1358473.590 0.50 +1358523.159 0.00 +1358542.082 0.50 +1358545.952 0.00 +1358967.387 0.50 +1359027.712 0.00 +1359051.943 0.50 +1359070.658 0.00 +1363809.927 0.50 +1363860.938 0.00 +1363885.600 0.50 +1363890.292 0.00 +1364374.287 0.50 +1364433.513 0.00 +1364452.289 0.50 +1364456.250 0.00 +1368751.598 0.50 +1368796.172 0.00 +1368816.259 0.50 +1368820.470 0.00 +1369233.364 0.50 +1369285.700 0.00 +1369303.293 0.50 +1369306.996 0.00 +1373388.953 0.50 +1373389.096 1.00 +1373396.919 0.50 +1373442.745 0.00 +1373498.990 0.50 +1373505.271 0.00 +1373792.113 0.50 +1373798.465 0.00 +1373807.331 0.50 +1373852.739 0.00 +1373877.596 0.50 +1373884.279 0.00 +1373892.118 0.50 +1373914.139 0.00 +1373935.631 0.50 +1373948.425 0.00 +1387284.123 0.50 +1387301.770 0.00 +1387620.271 0.50 +1387635.470 0.00 +1804975.977 0.50 +1805012.283 0.00 +1805063.076 0.50 +1805068.493 0.00 +1805259.310 0.50 +1805292.870 0.00 +1805312.310 0.50 +1805350.358 1.00 +1805350.562 0.50 +1805386.009 0.00 +1805425.680 0.50 +1805431.066 0.00 +1843677.054 0.50 +1843737.041 1.00 +1843768.695 0.50 +1843815.161 0.00 +1843827.225 0.50 +1843860.017 1.00 +1843861.862 0.50 +1843891.732 1.00 +1843907.874 0.50 +1843922.152 0.00 +1843936.415 0.50 +1843992.420 1.00 +1844012.594 0.50 +1844033.640 1.00 +1844072.396 0.50 +1844093.056 1.00 +1844104.457 0.50 +1844126.888 1.00 +1844192.738 0.50 +1844231.819 1.00 +1844276.782 0.50 +1844639.970 1.00 +1844690.377 0.50 +1844718.199 1.00 +1844750.254 0.50 +1844782.026 1.00 +1844822.422 0.50 +1844849.633 1.00 +1844884.140 0.50 +1844910.803 1.00 +1844942.276 0.50 +1844947.737 0.00 +1844965.071 0.50 +1844970.793 1.00 +1845017.478 0.50 +1845051.566 0.00 +1845052.547 0.50 +1845069.252 1.00 +1845086.468 0.50 +1845104.383 0.00 +1845110.994 0.50 +1845126.065 1.00 +1845146.179 0.50 +1845155.068 0.00 diff --git a/examples/testbench/good_band/tsv/Mem_0x1e00000000000000.tsv b/examples/testbench/good_band/tsv/Mem_0x1e00000000000000.tsv new file mode 100644 index 000000000..1e1740690 --- /dev/null +++ b/examples/testbench/good_band/tsv/Mem_0x1e00000000000000.tsv @@ -0,0 +1,12 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +11 1278823.735 1844793.065 #00fff6 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000001 $Size: 19.073 MiB 13 68 +10 1279061.877 1845081.180 #00fff6 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000002 $Size: 19.073 MiB 15 70 +9 1280061.606 1844985.437 #00fff6 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000003 $Size: 19.073 MiB 24 79 +8 1280246.078 1844919.518 #00fff6 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000004 $Size: 19.073 MiB 23 77 +7 1281367.754 1844726.221 #00fff6 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000005 $Size: 19.073 MiB 36 191 +6 1281572.958 1845134.718 #00fff6 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000006 $Size: 19.073 MiB 38 81 +5 1282612.241 1844151.087 #ff0038 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000007 $Size: 19.073 MiB 47 71 +4 1282784.125 1844240.657 #ff0038 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000008 $Size: 19.073 MiB 48 73 +3 1283563.847 1844857.709 #ff0038 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048581]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000009 $Size: 19.073 MiB 52 291 +2 1283746.860 1845119.817 #ff0038 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048581]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000a $Size: 19.073 MiB 53 148 +1 1307133.149 1844651.511 #ff6e00 1.0 Region: ispace:1[0:4999999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000b $Size: 38.147 MiB 79 75 diff --git a/examples/testbench/good_band/tsv/None.tsv b/examples/testbench/good_band/tsv/None.tsv new file mode 100644 index 000000000..cc466a54c --- /dev/null +++ b/examples/testbench/good_band/tsv/None.tsv @@ -0,0 +1,5 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +3 1306638.074 1306645.058 #ffa700 1.0 Intersection Reduction 80 506 +3 1306677.611 1306682.376 #ffa700 1.0 Intersection Reduction 80 649 +3 1306758.499 1306839.247 #ffa700 1.0 Union Reduction 80 650 +3 1307245.719 1307250.230 #ff6e00 1.0 Difference 79 696 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000000.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000000.tsv new file mode 100644 index 000000000..568ef7a40 --- /dev/null +++ b/examples/testbench/good_band/tsv/Proc_0x1d00000000000000.tsv @@ -0,0 +1,304 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +5 5 493801.174 493837.510 493896.375 #f100ff 1.0 Deferred Enqueue Task 1 [[0, 4, 12]] 149 +5 5 493931.677 493931.677 493944.124 #ffc0cb 1.0 ProfTask <1> 167 +5 5 494015.963 494058.742 494101.567 #3dff00 1.0 Task Physical Dependence Analysis 1 [[0, 4, 12]] 150 +5 5 494130.615 494130.615 494135.463 #ffc0cb 1.0 ProfTask <1> 168 +5 5 494172.288 494208.875 494348.350 #3dff00 1.0 Task Physical Dependence Analysis 1 [[0, 4, 12]] 194 +5 5 1164217.469 1164265.110 1164304.048 #00ff12 1.0 Logical Dependence Analysis 3 14 +5 5 1164388.574 1164405.071 1164511.519 #007bff 1.0 Operation Physical Dependence Analysis 3 195 +5 5 1164663.131 1164682.320 1164714.593 #00ff12 1.0 Logical Dependence Analysis 4 17 +5 5 1164756.861 1164778.390 1164819.329 #007bff 1.0 Operation Physical Dependence Analysis 4 196 +5 5 1207223.090 1207271.028 1207307.344 #00ff12 1.0 Logical Dependence Analysis 5 20 +5 5 1207325.288 1207339.179 1207399.159 #007bff 1.0 Operation Physical Dependence Analysis 5 197 +5 5 1257350.514 1257389.335 1257422.422 #00ff12 1.0 Logical Dependence Analysis 6 23 +5 5 1257467.484 1257499.072 1257585.815 #007bff 1.0 Operation Physical Dependence Analysis 6 25 +5 4 1257570.248 1257609.470 1257624.283 #ff00c5 1.0 Tighten Index Space 6 151 +5 5 1257640.055 1257640.055 1257646.736 #ffc0cb 1.0 ProfTask <6> 169 +5 5 1277801.597 1277848.542 1278028.841 #00ff12 1.0 Logical Dependence Analysis 7 152 +5 4 1278051.446 1278051.446 1278056.549 #ffc0cb 1.0 ProfTask <7> 170 +5 5 1278050.047 1278063.442 1278119.561 #007bff 1.0 Operation Physical Dependence Analysis 8 153 +5 5 1278137.033 1278137.033 1278141.642 #ffc0cb 1.0 ProfTask <8> 171 +5 4 1278141.192 1278163.934 1278205.113 #007bff 1.0 Operation Physical Dependence Analysis 7 30 +5 5 1278287.286 1278323.593 1278440.201 #3dff00 1.0 Task Physical Dependence Analysis 9 34 +5 4 1278415.518 1278461.160 1278541.424 #ff7a00 1.0 Scheduler 0 36 +5 4 1278546.753 1278559.476 1278619.622 #00ff12 1.0 Logical Dependence Analysis 12 38 +5 3 1278596.469 1278638.486 1278664.513 #333399 1.0 Deferred Ready Trigger 14 275 +5 5 1278523.822 1278680.314 1278712.234 #3dff00 1.0 Task Physical Dependence Analysis 11 40 +5 3 1278726.859 1278726.859 1278745.693 #cd00ff 1.0 Defer Task Perform Mapping 15 [[0, 3, 567]] 282 +5 3 1278745.693 1278745.693 1279400.852 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 15 282 +5 3 1279400.852 1279400.852 1279508.879 #cd00ff 0.45 Defer Task Perform Mapping (ready) 15 282 +5 3 1279508.879 1279508.879 1279580.044 #cd00ff 1.0 Defer Task Perform Mapping 15 282 +4 4 1278654.209 1278783.666 1278801.586 #007bff 1.0 Operation Physical Dependence Analysis 14 42 +4 5 1278792.897 1278818.753 1278849.780 #333399 1.0 Deferred Ready Trigger 12 43 +4 4 1278839.559 1278893.781 1278918.912 #007bff 1.0 Operation Physical Dependence Analysis 12 44 +4 5 1278940.842 1278940.842 1278989.270 #ff7a00 1.0 Scheduler 0 279 +4 5 1278989.270 1278989.270 1279378.141 #ff7a00 0.15 Scheduler (waiting) 0 279 +4 5 1279378.141 1279378.141 1279418.725 #ff7a00 0.45 Scheduler (ready) 0 279 +4 5 1279418.725 1279418.725 1279467.951 #ff7a00 1.0 Scheduler 0 279 +3 4 1279017.443 1279017.443 1279092.823 #00b1ff 1.0 Mapper Continuation 15 [[0, 3, 567]] 277 +3 4 1279092.823 1279092.823 1279124.275 #00b1ff 0.15 Mapper Continuation (waiting) 15 277 +3 4 1279124.275 1279124.275 1279256.387 #00b1ff 0.45 Mapper Continuation (ready) 15 277 +3 4 1279256.387 1279256.387 1279375.598 #00b1ff 1.0 Mapper Continuation 15 277 +2 2 1279021.995 1279021.995 1279292.319 #ff3200 1.0 Mapper Call map_task for 15 15 [[0, 3, 567]] 406 +1 1 1279090.815 1279127.934 1279198.924 #ff0098 1.0 Defer Task Launch 13 [[0, 2, 566]] 409 +5 4 1279454.633 1279616.772 1279698.571 #3dff00 1.0 Task Physical Dependence Analysis 16 200 +5 3 1279718.086 1279718.086 1279761.109 #ff7a00 1.0 Scheduler 0 205 +5 3 1279761.109 1279761.109 1279808.204 #ff7a00 0.15 Scheduler (waiting) 0 205 +5 3 1279808.204 1279808.204 1279823.597 #ff7a00 0.45 Scheduler (ready) 0 205 +5 3 1279823.597 1279823.597 1279872.496 #ff7a00 1.0 Scheduler 0 205 +4 4 1279755.896 1279777.897 1279794.261 #00b1ff 1.0 Mapper Continuation 0 202 +5 5 1279581.924 1279895.526 1279925.030 #007bff 1.0 Operation Physical Dependence Analysis 19 207 +5 2 1279765.397 1279947.145 1280008.249 #3dff00 1.0 Task Physical Dependence Analysis 21 210 +5 5 1280036.518 1280036.518 1280057.763 #cd00ff 1.0 Defer Task Perform Mapping 23 [[0, 2, 568]] 324 +5 5 1280057.763 1280057.763 1280397.540 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 23 324 +5 5 1280397.540 1280397.540 1280519.467 #cd00ff 0.45 Defer Task Perform Mapping (ready) 23 324 +5 5 1280519.467 1280519.467 1280590.069 #cd00ff 1.0 Defer Task Perform Mapping 23 324 +4 4 1279899.473 1280076.936 1280123.017 #007bff 1.0 Operation Physical Dependence Analysis 18 211 +4 3 1280137.759 1280137.759 1280175.444 #ff7a00 1.0 Scheduler 0 322 +4 3 1280175.444 1280175.444 1280388.340 #ff7a00 0.15 Scheduler (waiting) 0 322 +4 3 1280388.340 1280388.340 1280415.218 #ff7a00 0.45 Scheduler (ready) 0 322 +4 3 1280415.218 1280415.218 1280480.415 #ff7a00 1.0 Scheduler 0 322 +3 4 1280192.631 1280192.631 1280273.101 #00b1ff 1.0 Mapper Continuation 23 [[0, 2, 568]] 321 +3 4 1280273.101 1280273.101 1280295.077 #00b1ff 0.15 Mapper Continuation (waiting) 23 321 +3 4 1280295.077 1280295.077 1280320.312 #00b1ff 0.45 Mapper Continuation (ready) 23 321 +3 4 1280320.312 1280320.312 1280368.275 #00b1ff 1.0 Mapper Continuation 23 321 +2 2 1280198.716 1280198.716 1280346.233 #ff3200 1.0 Mapper Call map_task for 23 23 [[0, 2, 568]] 407 +5 4 1280489.436 1280618.696 1280704.966 #ff7a00 1.0 Scheduler 0 327 +5 3 1280589.954 1280724.974 1280799.920 #3dff00 1.0 Task Physical Dependence Analysis 26 329 +5 4 1280766.907 1280819.690 1280903.705 #ff7a00 1.0 Scheduler 0 331 +5 3 1280815.462 1280923.262 1280949.533 #333399 1.0 Deferred Ready Trigger 32 447 +5 5 1280664.164 1280975.106 1281006.901 #007bff 1.0 Operation Physical Dependence Analysis 20 154 +5 3 1281026.198 1281026.198 1281082.549 #ff7a00 1.0 Scheduler 0 336 +5 3 1281082.549 1281082.549 1281148.698 #ff7a00 0.15 Scheduler (waiting) 0 336 +5 3 1281148.698 1281148.698 1281168.977 #ff7a00 0.45 Scheduler (ready) 0 336 +5 3 1281168.977 1281168.977 1281221.133 #ff7a00 1.0 Scheduler 0 336 +4 5 1281075.860 1281102.897 1281128.249 #00b1ff 1.0 Mapper Continuation 0 333 +5 2 1280891.200 1281244.468 1281304.887 #3dff00 1.0 Task Physical Dependence Analysis 30 339 +5 5 1281331.290 1281331.290 1281352.380 #00ff12 1.0 Logical Dependence Analysis 37 343 +5 5 1281352.380 1281352.380 1281562.024 #00ff12 0.15 Logical Dependence Analysis (waiting) 37 343 +5 5 1281562.024 1281562.024 1281578.718 #00ff12 0.45 Logical Dependence Analysis (ready) 37 343 +5 5 1281578.718 1281578.718 1281646.649 #00ff12 1.0 Logical Dependence Analysis 37 343 +4 4 1280936.111 1281369.623 1281426.948 #3dff00 1.0 Task Physical Dependence Analysis 31 340 +4 3 1281441.165 1281441.165 1281453.949 #cd00ff 1.0 Defer Task Perform Mapping 38 [[0, 3, 624]] 411 +4 3 1281453.949 1281453.949 1281693.157 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 38 411 +4 3 1281693.157 1281693.157 1281711.894 #cd00ff 0.45 Defer Task Perform Mapping (ready) 38 411 +4 3 1281711.894 1281711.894 1281795.038 #cd00ff 1.0 Defer Task Perform Mapping 38 411 +3 1 1280938.299 1281469.680 1281491.546 #007bff 1.0 Operation Physical Dependence Analysis 32 341 +3 4 1281477.968 1281511.464 1281542.779 #00b1ff 1.0 Mapper Continuation 37 410 +5 2 1281516.045 1281662.778 1281687.437 #ff0098 1.0 Defer Task Launch 36 [[0, 2, 623]] 345 +5 4 1281801.212 1281819.066 1281914.727 #ff7a00 1.0 Scheduler 0 413 +5 5 1281774.812 1281935.560 1281968.754 #ff0098 1.0 Defer Task Launch 38 [[0, 3, 624]] 157 +5 3 1281901.157 1281987.215 1282052.736 #3dff00 1.0 Task Physical Dependence Analysis 40 160 +5 5 1282030.295 1282073.815 1282135.609 #cd00ff 1.0 Defer Task Perform Mapping 42 [[0, 2, 3]] 163 +5 4 1282124.752 1282156.494 1282184.635 #ff0098 1.0 Defer Task Launch 42 [[0, 2, 3]] 216 +5 5 1282145.674 1282204.439 1282231.574 #ff0098 1.0 Defer Task Launch 43 [[0, 3, 626]] 218 +5 5 1282247.509 1282247.509 1282254.507 #ffc0cb 1.0 ProfTask <24> 361 +5 4 1282253.820 1282263.334 1282350.095 #ff7a00 1.0 Scheduler 0 220 +5 5 1282370.051 1282370.051 1282376.626 #ffc0cb 1.0 ProfTask <0> 362 +5 5 1282383.996 1282383.996 1282390.851 #ffc0cb 1.0 ProfTask <23> 363 +5 4 1282398.511 1282398.511 1282404.761 #ffc0cb 1.0 ProfTask <0> 364 +5 5 1282397.684 1282412.358 1282495.982 #ff7a00 1.0 Scheduler 0 222 +5 4 1282483.446 1282517.522 1282570.883 #3dff00 1.0 Task Physical Dependence Analysis 45 414 +5 5 1282524.958 1282589.505 1282637.613 #3dff00 1.0 Task Physical Dependence Analysis 46 347 +5 5 1282666.567 1282666.567 1282670.256 #ffc0cb 1.0 ProfTask <25> 365 +5 5 1282676.118 1282676.118 1282682.844 #ffc0cb 1.0 ProfTask <23> 366 +5 5 1282687.683 1282687.683 1282691.027 #ffc0cb 1.0 ProfTask <0> 367 +5 5 1282695.682 1282695.682 1282699.349 #ffc0cb 1.0 ProfTask <20> 368 +5 5 1282704.941 1282704.941 1282708.191 #ffc0cb 1.0 ProfTask <0> 369 +5 5 1282712.962 1282712.962 1282717.209 #ffc0cb 1.0 ProfTask <23> 370 +5 5 1282721.947 1282721.947 1282725.259 #ffc0cb 1.0 ProfTask <26> 371 +5 5 1282729.621 1282729.621 1282732.909 #ffc0cb 1.0 ProfTask <29> 372 +5 5 1282738.061 1282738.061 1282742.186 #ffc0cb 1.0 ProfTask <0> 373 +5 4 1282747.803 1282747.803 1282829.910 #00b1ff 1.0 Mapper Continuation 48 [[0, 3, 627]] 348 +5 4 1282829.910 1282829.910 1282854.537 #00b1ff 0.15 Mapper Continuation (waiting) 48 348 +5 4 1282854.537 1282854.537 1282869.073 #00b1ff 0.45 Mapper Continuation (ready) 48 348 +5 4 1282869.073 1282869.073 1282880.412 #00b1ff 1.0 Mapper Continuation 48 348 +4 5 1282752.164 1282752.164 1282873.147 #ff3200 1.0 Mapper Call map_task for 48 48 [[0, 3, 627]] 360 +3 3 1282844.366 1282844.366 1282849.739 #ffc0cb 1.0 ProfTask <20> 172 +3 3 1282856.291 1282856.291 1282859.931 #ffc0cb 1.0 ProfTask <27> 173 +5 5 1282895.492 1282895.492 1282898.743 #ffc0cb 1.0 ProfTask <33> 374 +5 5 1282903.269 1282903.269 1282906.398 #ffc0cb 1.0 ProfTask <0> 375 +5 5 1282911.963 1282911.963 1282915.130 #ffc0cb 1.0 ProfTask <33> 376 +5 5 1282919.738 1282919.738 1282922.982 #ffc0cb 1.0 ProfTask <28> 377 +5 5 1282928.128 1282928.128 1282935.817 #ffc0cb 1.0 ProfTask <0> 378 +5 4 1282928.718 1282942.383 1282966.964 #ff0098 1.0 Defer Task Launch 47 [[0, 2, 5]] 415 +5 5 1282986.367 1282986.367 1282991.345 #ffc0cb 1.0 ProfTask <35> 379 +5 5 1282998.561 1282998.561 1283003.565 #ffc0cb 1.0 ProfTask <35> 380 +5 5 1283010.418 1283010.418 1283015.397 #ffc0cb 1.0 ProfTask <30> 381 +5 5 1283022.770 1283022.770 1283027.895 #ffc0cb 1.0 ProfTask <36> 382 +5 5 1283034.875 1283034.875 1283040.014 #ffc0cb 1.0 ProfTask <31> 383 +5 5 1283046.978 1283046.978 1283052.050 #ffc0cb 1.0 ProfTask <32> 384 +5 4 1283059.186 1283059.186 1283065.631 #ffc0cb 1.0 ProfTask <36> 385 +5 5 1283057.281 1283073.383 1283110.127 #333399 1.0 Deferred Ready Trigger 37 416 +5 4 1283098.619 1283130.304 1283163.621 #007bff 1.0 Operation Physical Dependence Analysis 37 417 +5 5 1283182.622 1283182.622 1283188.104 #ffc0cb 1.0 ProfTask <38> 386 +5 5 1283195.694 1283195.694 1283204.944 #ffc0cb 1.0 ProfTask <37> 387 +5 5 1283211.677 1283211.677 1283220.390 #ffc0cb 1.0 ProfTask <38> 388 +5 5 1283227.561 1283227.561 1283232.886 #ffc0cb 1.0 ProfTask <36> 389 +5 4 1283239.761 1283239.761 1283244.909 #ffc0cb 1.0 ProfTask <39> 390 +5 5 1283238.880 1283252.211 1283324.969 #3dff00 1.0 Task Physical Dependence Analysis 49 353 +5 4 1283309.549 1283344.437 1283430.716 #ff7a00 1.0 Scheduler 0 354 +5 5 1283418.585 1283450.278 1283500.409 #3dff00 1.0 Task Physical Dependence Analysis 51 355 +5 4 1283519.252 1283519.252 1283537.974 #cd00ff 1.0 Defer Task Perform Mapping 53 [[0, 3, 265]] 357 +5 4 1283537.974 1283537.974 1283903.575 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 53 357 +5 4 1283903.575 1283903.575 1283930.408 #cd00ff 0.45 Defer Task Perform Mapping (ready) 53 357 +5 4 1283930.408 1283930.408 1283991.577 #cd00ff 1.0 Defer Task Perform Mapping 53 357 +4 5 1283621.832 1283621.832 1283626.988 #ffc0cb 1.0 ProfTask <38> 174 +4 5 1283634.116 1283634.116 1283639.765 #ffc0cb 1.0 ProfTask <39> 175 +4 5 1283647.210 1283647.210 1283652.142 #ffc0cb 1.0 ProfTask <40> 176 +4 5 1283658.525 1283658.525 1283663.327 #ffc0cb 1.0 ProfTask <41> 177 +4 5 1283669.788 1283669.788 1283674.776 #ffc0cb 1.0 ProfTask <42> 178 +4 5 1283681.015 1283681.015 1283687.272 #ffc0cb 1.0 ProfTask <43> 179 +4 3 1283695.521 1283695.521 1283809.423 #00b1ff 1.0 Mapper Continuation 53 [[0, 3, 265]] 356 +4 3 1283809.423 1283809.423 1283835.904 #00b1ff 0.15 Mapper Continuation (waiting) 53 356 +4 3 1283835.904 1283835.904 1283879.069 #00b1ff 0.45 Mapper Continuation (ready) 53 356 +4 3 1283879.069 1283879.069 1283891.905 #00b1ff 1.0 Mapper Continuation 53 356 +3 5 1283702.060 1283702.060 1283883.843 #ff3200 1.0 Mapper Call map_task for 53 53 [[0, 3, 265]] 166 +2 2 1283839.563 1283839.563 1283846.958 #ffc0cb 1.0 ProfTask <0> 408 +5 5 1283982.687 1284006.864 1284031.957 #ff0098 1.0 Defer Task Launch 53 [[0, 3, 265]] 359 +5 5 1284046.066 1284046.066 1284050.070 #ffc0cb 1.0 ProfTask <46> 391 +5 5 1284055.707 1284055.707 1284060.505 #ffc0cb 1.0 ProfTask <48> 392 +5 5 1284067.513 1284067.513 1284074.595 #ffc0cb 1.0 ProfTask <47> 393 +5 5 1284080.228 1284080.228 1284086.541 #ffc0cb 1.0 ProfTask <48> 394 +5 5 1284092.440 1284092.440 1284096.296 #ffc0cb 1.0 ProfTask <48> 395 +5 5 1284101.982 1284101.982 1284106.383 #ffc0cb 1.0 ProfTask <0> 396 +5 5 1284111.488 1284111.488 1284115.765 #ffc0cb 1.0 ProfTask <49> 397 +5 5 1284121.233 1284121.233 1284125.707 #ffc0cb 1.0 ProfTask <0> 398 +5 5 1284131.344 1284131.344 1284135.349 #ffc0cb 1.0 ProfTask <51> 399 +5 5 1284140.596 1284140.596 1284144.671 #ffc0cb 1.0 ProfTask <52> 400 +5 5 1284149.723 1284149.723 1284156.310 #ffc0cb 1.0 ProfTask <53> 401 +5 5 1284161.552 1284161.552 1284167.611 #ffc0cb 1.0 ProfTask <53> 402 +5 5 1284172.102 1284172.102 1284177.046 #ffc0cb 1.0 ProfTask <52> 403 +5 5 1284182.497 1284182.497 1284189.542 #ffc0cb 1.0 ProfTask <53> 404 +5 5 1290561.994 1290561.994 1290581.206 #ffc0cb 1.0 ProfTask <13> 595 +5 5 1290672.470 1290672.470 1290682.613 #ffc0cb 1.0 ProfTask <13> 596 +5 5 1290706.341 1290706.341 1290712.299 #ffc0cb 1.0 ProfTask <15> 597 +5 4 1290710.670 1290721.686 1290793.748 #006600 1.0 Post-Task Execution 15 [[0, 3, 567]] 571 +5 5 1290814.031 1290814.031 1290821.681 #ffc0cb 1.0 ProfTask <15> 598 +5 5 1290851.820 1290851.820 1290857.268 #ffc0cb 1.0 ProfTask <7> 599 +5 5 1301189.824 1301189.824 1301196.603 #ffc0cb 1.0 ProfTask <23> 600 +5 5 1301544.868 1301544.868 1301552.926 #ffc0cb 1.0 ProfTask <24> 601 +5 5 1301590.084 1301606.151 1301641.799 #009900 1.0 Deferred Commit 12 450 +5 5 1303148.986 1303168.646 1303283.977 #00ff12 1.0 Logical Dependence Analysis 54 573 +5 5 1303305.777 1303305.777 1303312.883 #ffc0cb 1.0 ProfTask <54> 602 +5 4 1303306.411 1303321.376 1303396.088 #007bff 1.0 Operation Physical Dependence Analysis 54 574 +5 5 1303414.273 1303414.273 1303418.400 #ffc0cb 1.0 ProfTask <54> 603 +5 5 1303469.495 1303483.722 1303558.517 #3dff00 1.0 Task Physical Dependence Analysis 55 454 +5 4 1303573.877 1303573.877 1303624.181 #ff7a00 1.0 Scheduler 0 457 +5 4 1303624.181 1303624.181 1303725.332 #ff7a00 0.15 Scheduler (waiting) 0 457 +5 4 1303725.332 1303725.332 1303745.784 #ff7a00 0.45 Scheduler (ready) 0 457 +5 4 1303745.784 1303745.784 1303770.128 #ff7a00 1.0 Scheduler 0 457 +5 4 1303770.128 1303770.128 1303829.434 #ff7a00 0.15 Scheduler (waiting) 0 457 +5 4 1303829.434 1303829.434 1303845.931 #ff7a00 0.45 Scheduler (ready) 0 457 +5 4 1303845.931 1303845.931 1303879.903 #ff7a00 1.0 Scheduler 0 457 +4 5 1303618.687 1303670.965 1303704.125 #00b1ff 1.0 Mapper Continuation 0 456 +4 5 1303762.868 1303786.168 1303811.406 #00b1ff 1.0 Mapper Continuation 0 577 +5 5 1303866.667 1303909.035 1303965.082 #3dff00 1.0 Task Physical Dependence Analysis 57 460 +5 5 1303983.695 1303983.695 1303988.852 #ffc0cb 1.0 ProfTask <56> 604 +5 5 1303996.469 1303996.469 1304002.083 #ffc0cb 1.0 ProfTask <58> 605 +5 4 1304001.260 1304010.979 1304053.638 #333399 1.0 Deferred Ready Trigger 59 579 +5 5 1304076.332 1304076.332 1304082.034 #ffc0cb 1.0 ProfTask <0> 606 +5 4 1304089.969 1304089.969 1304095.865 #ffc0cb 1.0 ProfTask <58> 607 +5 5 1304085.798 1304104.636 1304201.779 #ff7a00 1.0 Scheduler 0 581 +5 4 1304200.689 1304225.353 1304297.327 #00ff12 1.0 Logical Dependence Analysis 62 583 +5 5 1304252.409 1304317.260 1304388.941 #ff7a00 1.0 Scheduler 0 585 +5 4 1304379.607 1304402.496 1304450.999 #3dff00 1.0 Task Physical Dependence Analysis 64 587 +5 5 1304428.149 1304470.099 1304564.826 #cd00ff 1.0 Defer Task Perform Mapping 66 [[0, 3, 269]] 588 +5 4 1304553.849 1304586.431 1304619.350 #ff0098 1.0 Defer Task Launch 66 [[0, 3, 269]] 467 +5 5 1304637.141 1304637.141 1304643.365 #ffc0cb 1.0 ProfTask <59> 608 +5 5 1304651.780 1304651.780 1304658.683 #ffc0cb 1.0 ProfTask <59> 609 +5 5 1304666.550 1304666.550 1304672.388 #ffc0cb 1.0 ProfTask <0> 610 +5 4 1304680.459 1304680.459 1304688.024 #ffc0cb 1.0 ProfTask <61> 611 +5 5 1304679.583 1304698.019 1304772.128 #3dff00 1.0 Task Physical Dependence Analysis 67 469 +5 4 1304740.079 1304792.515 1304888.752 #ff7a00 1.0 Scheduler 0 472 +5 5 1304879.093 1304903.629 1304949.175 #3dff00 1.0 Task Physical Dependence Analysis 69 474 +5 4 1304928.889 1304964.588 1305056.498 #cd00ff 1.0 Defer Task Perform Mapping 71 [[0, 2, 9]] 476 +5 5 1305043.193 1305078.479 1305111.303 #ff0098 1.0 Defer Task Launch 71 [[0, 2, 9]] 479 +5 5 1305123.950 1305123.950 1305127.879 #ffc0cb 1.0 ProfTask <62> 612 +5 5 1305132.242 1305132.242 1305135.716 #ffc0cb 1.0 ProfTask <0> 613 +5 5 1305140.603 1305140.603 1305144.069 #ffc0cb 1.0 ProfTask <0> 614 +5 5 1305148.825 1305148.825 1305152.880 #ffc0cb 1.0 ProfTask <63> 615 +5 4 1305158.699 1305158.699 1305162.057 #ffc0cb 1.0 ProfTask <64> 616 +5 5 1305156.383 1305168.106 1305192.136 #333399 1.0 Deferred Ready Trigger 68 481 +5 4 1305184.035 1305206.007 1305232.334 #007bff 1.0 Operation Physical Dependence Analysis 68 482 +5 5 1305222.067 1305245.411 1305308.677 #ff7a00 1.0 Scheduler 0 484 +5 4 1305299.926 1305327.160 1305382.614 #3dff00 1.0 Task Physical Dependence Analysis 74 589 +5 5 1305369.809 1305404.041 1305514.951 #ff7a00 1.0 Scheduler 0 591 +5 4 1305500.072 1305536.821 1305610.959 #3dff00 1.0 Task Physical Dependence Analysis 76 593 +5 5 1305574.749 1305631.496 1305727.618 #cd00ff 1.0 Defer Task Perform Mapping 78 [[0, 3, 273]] 487 +5 4 1305674.252 1305742.024 1305770.369 #ff0098 1.0 Defer Task Launch 77 [[0, 2, 11]] 488 +5 2 1305711.951 1305783.995 1305813.329 #333399 1.0 Deferred Ready Trigger 73 490 +5 3 1305590.048 1305888.240 1305922.460 #2500ff 1.0 Prepipeline Stage 79 492 +5 5 1305952.530 1305952.530 1305961.048 #ffc0cb 1.0 ProfTask <66> 617 +5 4 1305960.182 1305972.370 1306224.570 #ff7a00 1.0 Scheduler 0 494 +5 5 1306244.535 1306244.535 1306251.719 #ffc0cb 1.0 ProfTask <74> 618 +5 5 1306258.625 1306258.625 1306262.340 #ffc0cb 1.0 ProfTask <0> 619 +5 5 1306266.639 1306266.639 1306269.915 #ffc0cb 1.0 ProfTask <0> 620 +5 5 1306274.647 1306274.647 1306278.288 #ffc0cb 1.0 ProfTask <75> 621 +5 5 1306284.148 1306284.148 1306288.891 #ffc0cb 1.0 ProfTask <76> 622 +5 4 1306287.059 1306295.085 1306373.980 #ff7a00 1.0 Scheduler 0 496 +5 5 1306361.416 1306390.469 1306431.241 #3dff00 1.0 Task Physical Dependence Analysis 82 498 +5 4 1306399.822 1306444.023 1306475.533 #3dff00 1.0 Task Physical Dependence Analysis 83 499 +5 5 1306461.902 1306487.743 1306556.205 #cd00ff 1.0 Defer Task Perform Mapping 85 [[0, 3, 630]] 504 +5 4 1306548.549 1306570.551 1306596.581 #ff0098 1.0 Defer Task Launch 85 [[0, 3, 630]] 631 +5 5 1306609.046 1306609.046 1306756.065 #007bff 1.0 Operation Physical Dependence Analysis 80 681 +5 5 1306756.065 1306756.065 1306919.478 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 80 681 +5 5 1306919.478 1306919.478 1306948.288 #007bff 0.45 Operation Physical Dependence Analysis (ready) 80 681 +5 5 1306948.288 1306948.288 1307020.185 #007bff 1.0 Operation Physical Dependence Analysis 80 681 +4 4 1306776.655 1306776.655 1306790.612 #ffc0cb 1.0 ProfTask <85> 651 +4 4 1306802.720 1306802.720 1306811.402 #ffc0cb 1.0 ProfTask <80> 652 +4 4 1306869.300 1306869.300 1306875.443 #ffc0cb 1.0 ProfTask <80> 653 +4 4 1306924.051 1306924.051 1306929.726 #ffc0cb 1.0 ProfTask <80> 654 +5 5 1307056.365 1307056.365 1307307.680 #007bff 1.0 Operation Physical Dependence Analysis 79 685 +5 5 1307307.680 1307307.680 1307458.321 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 79 685 +5 5 1307458.321 1307458.321 1307484.883 #007bff 0.45 Operation Physical Dependence Analysis (ready) 79 685 +5 5 1307484.883 1307484.883 1307547.707 #007bff 1.0 Operation Physical Dependence Analysis 79 685 +4 4 1307070.233 1307070.233 1307183.723 #ff5f00 1.0 Mapper Call map_inline for 79 79 594 +5 5 1313028.908 1313028.908 1313043.492 #ffc0cb 1.0 ProfTask <36> 655 +5 5 1313377.313 1313377.313 1313383.481 #ffc0cb 1.0 ProfTask <38> 656 +5 5 1313400.373 1313415.699 1313465.770 #006600 1.0 Post-Task Execution 38 [[0, 3, 624]] 633 +5 5 1313482.463 1313482.463 1313486.229 #ffc0cb 1.0 ProfTask <38> 657 +5 5 1316874.269 1316874.269 1316881.752 #ffc0cb 1.0 ProfTask <35> 658 +5 5 1316889.537 1316912.943 1316958.130 #006600 1.0 Post-Task Execution 35 [[0, 3, 625]] 634 +5 5 1316974.511 1316974.511 1316978.142 #ffc0cb 1.0 ProfTask <35> 659 +5 5 1319981.003 1319995.186 1320025.818 #006600 1.0 Post-Task Execution 42 [[0, 2, 3]] 635 +5 5 1320040.609 1320040.609 1320044.432 #ffc0cb 1.0 ProfTask <42> 660 +5 5 1320214.870 1320214.870 1320221.281 #ffc0cb 1.0 ProfTask <43> 661 +5 5 1333311.079 1333333.783 1333386.811 #006600 1.0 Post-Task Execution 47 [[0, 2, 5]] 689 +5 4 1333412.514 1333412.514 1333418.805 #ffc0cb 1.0 ProfTask <48> 662 +5 5 1333407.103 1333430.989 1333469.596 #006600 1.0 Post-Task Execution 48 [[0, 3, 627]] 636 +5 5 1333486.409 1333486.409 1333490.897 #ffc0cb 1.0 ProfTask <48> 663 +5 5 1346545.220 1346545.220 1346557.434 #ffc0cb 1.0 ProfTask <52> 664 +5 5 1346633.938 1346633.938 1346640.148 #ffc0cb 1.0 ProfTask <52> 665 +5 5 1347111.988 1347130.799 1347181.604 #006600 1.0 Post-Task Execution 53 [[0, 3, 265]] 638 +5 5 1347201.196 1347201.196 1347205.096 #ffc0cb 1.0 ProfTask <53> 666 +5 5 1353173.197 1353197.202 1353243.345 #006600 1.0 Post-Task Execution 58 [[0, 2, 7]] 639 +5 5 1353265.362 1353265.362 1353269.535 #ffc0cb 1.0 ProfTask <58> 667 +5 5 1353611.015 1353631.730 1353696.535 #006600 1.0 Post-Task Execution 60 [[0, 3, 267]] 640 +5 5 1353712.876 1353712.876 1353716.802 #ffc0cb 1.0 ProfTask <60> 668 +5 5 1358452.236 1358452.236 1358458.994 #ffc0cb 1.0 ProfTask <65> 669 +5 5 1358946.400 1358967.387 1359027.712 #006600 1.0 Post-Task Execution 66 [[0, 3, 269]] 692 +5 5 1363780.521 1363809.927 1363860.938 #006600 1.0 Post-Task Execution 71 [[0, 2, 9]] 641 +5 5 1363885.600 1363885.600 1363890.292 #ffc0cb 1.0 ProfTask <71> 670 +5 5 1364357.583 1364374.287 1364433.513 #006600 1.0 Post-Task Execution 72 [[0, 3, 271]] 642 +5 5 1364452.289 1364452.289 1364456.250 #ffc0cb 1.0 ProfTask <72> 671 +5 5 1368727.688 1368751.598 1368796.172 #006600 1.0 Post-Task Execution 77 [[0, 2, 11]] 643 +5 5 1368816.259 1368816.259 1368820.470 #ffc0cb 1.0 ProfTask <77> 672 +5 5 1369208.235 1369233.364 1369285.700 #006600 1.0 Post-Task Execution 78 [[0, 3, 273]] 644 +5 5 1369303.293 1369303.293 1369306.996 #ffc0cb 1.0 ProfTask <78> 673 +5 5 1373352.694 1373388.953 1373442.745 #006600 1.0 Post-Task Execution 84 [[0, 2, 680]] 645 +5 5 1373498.990 1373498.990 1373505.271 #ffc0cb 1.0 ProfTask <84> 674 +5 5 1373792.113 1373792.113 1373798.465 #ffc0cb 1.0 ProfTask <85> 675 +5 5 1373877.596 1373877.596 1373884.279 #ffc0cb 1.0 ProfTask <85> 676 +5 4 1373882.218 1373892.118 1373914.139 #009900 1.0 Deferred Commit 73 693 +5 5 1387284.123 1387284.123 1387301.770 #ffc0cb 1.0 ProfTask <79> 677 +5 5 1387620.271 1387620.271 1387635.470 #ffc0cb 1.0 ProfTask <79> 678 +5 5 1804925.007 1804975.977 1805012.283 #009900 1.0 Deferred Commit 79 694 +5 5 1805222.737 1805259.310 1805292.870 #00ff12 1.0 Logical Dependence Analysis 86 48 +5 5 1805332.667 1805350.358 1805386.009 #007bff 1.0 Operation Physical Dependence Analysis 86 695 +5 5 1843649.095 1843677.054 1843815.161 #00ff12 1.0 Logical Dependence Analysis 89 52 +5 4 1843756.306 1843860.017 1843907.874 #007bff 1.0 Operation Physical Dependence Analysis 89 54 +5 5 1843910.102 1843936.415 1844942.276 #007bff 1.0 Operation Physical Dependence Analysis 87 64 +5 2 1844929.285 1844965.071 1845051.566 #990000 1.0 Deferred Execute 88 287 +5 4 1844821.434 1845069.252 1845104.383 #009900 1.0 Garbage Collection 87 66 +5 3 1844852.242 1845126.065 1845155.068 #009900 1.0 Garbage Collection 87 67 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000001.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000001.tsv new file mode 100644 index 000000000..6b5ce879a --- /dev/null +++ b/examples/testbench/good_band/tsv/Proc_0x1d00000000000001.tsv @@ -0,0 +1,287 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +4 5 493886.718 493931.102 494029.929 #ff7a00 1.0 Scheduler 0 192 +4 5 494058.910 494058.910 494064.325 #ffc0cb 1.0 ProfTask <0> 228 +4 5 494080.457 494125.428 494193.707 #ff7a00 1.0 Scheduler 0 193 +4 5 494210.784 494210.784 494214.839 #ffc0cb 1.0 ProfTask <0> 229 +4 5 494368.000 494368.000 494371.632 #ffc0cb 1.0 ProfTask <1> 230 +4 5 1164287.507 1164313.229 1164407.217 #333399 1.0 Deferred Ready Trigger 3 15 +4 5 1164541.448 1164541.448 1164549.085 #ffc0cb 1.0 ProfTask <3> 231 +4 5 1164701.605 1164725.526 1164772.567 #333399 1.0 Deferred Ready Trigger 4 18 +4 5 1164842.752 1164842.752 1164848.390 #ffc0cb 1.0 ProfTask <4> 232 +4 5 1207290.361 1207305.822 1207337.594 #333399 1.0 Deferred Ready Trigger 5 21 +4 5 1207424.454 1207424.454 1207430.784 #ffc0cb 1.0 ProfTask <5> 233 +4 5 1257408.526 1257444.005 1257484.492 #333399 1.0 Deferred Ready Trigger 6 24 +4 5 1257563.718 1257595.549 1257615.167 #ff00c5 1.0 Tighten Index Space 6 26 +4 5 1277991.028 1278028.704 1278061.916 #333399 1.0 Deferred Ready Trigger 8 28 +4 5 1278097.793 1278109.764 1278162.126 #333399 1.0 Deferred Ready Trigger 7 198 +4 5 1278180.326 1278180.326 1278186.455 #ffc0cb 1.0 ProfTask <7> 234 +4 5 1278195.856 1278209.774 1278308.664 #ff7a00 1.0 Scheduler 0 32 +4 5 1278390.540 1278426.961 1278505.618 #ff7a00 1.0 Scheduler 0 35 +4 4 1278494.858 1278538.494 1278620.037 #3dff00 1.0 Task Physical Dependence Analysis 10 274 +4 5 1278641.562 1278641.562 1278855.517 #cd00ff 1.0 Defer Task Perform Mapping 13 [[0, 2, 566]] 46 +4 5 1278855.517 1278855.517 1278868.886 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 13 46 +4 5 1278868.886 1278868.886 1278899.184 #cd00ff 0.45 Defer Task Perform Mapping (ready) 13 46 +4 5 1278899.184 1278899.184 1279099.959 #cd00ff 1.0 Defer Task Perform Mapping 13 46 +3 4 1278659.569 1278659.569 1278953.292 #ff3200 1.0 Mapper Call map_task for 13 13 [[0, 2, 566]] 223 +4 3 1279133.630 1279133.630 1279160.544 #00ff12 1.0 Logical Dependence Analysis 17 280 +4 3 1279160.544 1279160.544 1279450.908 #00ff12 0.15 Logical Dependence Analysis (waiting) 17 280 +4 3 1279450.908 1279450.908 1279479.418 #00ff12 0.45 Logical Dependence Analysis (ready) 17 280 +4 3 1279479.418 1279479.418 1279536.461 #00ff12 1.0 Logical Dependence Analysis 17 280 +3 5 1279231.730 1279231.730 1279251.865 #ffc0cb 1.0 ProfTask <13> 422 +3 5 1279300.720 1279320.699 1279351.834 #00b1ff 1.0 Mapper Continuation 0 276 +3 4 1279342.106 1279389.655 1279426.309 #00b1ff 1.0 Mapper Continuation 17 278 +4 5 1279519.469 1279561.577 1279591.038 #333399 1.0 Deferred Ready Trigger 19 281 +4 3 1279568.066 1279611.199 1279651.982 #ff0098 1.0 Defer Task Launch 15 [[0, 3, 567]] 199 +4 5 1279666.777 1279674.758 1279774.382 #ff7a00 1.0 Scheduler 0 201 +4 4 1279554.634 1279792.958 1279866.659 #00ff12 1.0 Logical Dependence Analysis 18 204 +4 5 1279833.746 1279883.399 1279907.765 #333399 1.0 Deferred Ready Trigger 18 206 +4 5 1279909.666 1279921.310 1279945.362 #333399 1.0 Deferred Ready Trigger 17 208 +4 3 1279857.000 1279958.591 1279997.784 #3dff00 1.0 Task Physical Dependence Analysis 22 209 +4 5 1280011.334 1280011.334 1280086.285 #cd00ff 1.0 Defer Task Perform Mapping 24 [[0, 3, 569]] 212 +4 5 1280086.285 1280086.285 1280105.447 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 24 212 +4 5 1280105.447 1280105.447 1280128.872 #cd00ff 0.45 Defer Task Perform Mapping (ready) 24 212 +4 5 1280128.872 1280128.872 1280237.601 #cd00ff 1.0 Defer Task Perform Mapping 24 212 +3 3 1280018.950 1280018.950 1280162.081 #ff3200 1.0 Mapper Call map_task for 24 24 [[0, 3, 569]] 224 +4 3 1280230.049 1280252.240 1280278.040 #ff0098 1.0 Defer Task Launch 24 [[0, 3, 569]] 213 +4 4 1279937.260 1280290.082 1280302.458 #007bff 1.0 Operation Physical Dependence Analysis 17 214 +4 5 1280314.319 1280314.319 1280319.182 #ffc0cb 1.0 ProfTask <15> 235 +4 5 1280324.665 1280324.665 1280328.013 #ffc0cb 1.0 ProfTask <16> 236 +4 5 1280332.985 1280332.985 1280336.186 #ffc0cb 1.0 ProfTask <0> 237 +4 5 1280340.596 1280340.596 1280345.027 #ffc0cb 1.0 ProfTask <0> 238 +4 5 1280349.935 1280349.935 1280354.507 #ffc0cb 1.0 ProfTask <18> 239 +4 4 1280354.292 1280360.608 1280379.031 #00b1ff 1.0 Mapper Continuation 0 320 +4 5 1280397.006 1280397.006 1280404.093 #ffc0cb 1.0 ProfTask <0> 240 +4 5 1280408.793 1280408.793 1280412.723 #ffc0cb 1.0 ProfTask <18> 241 +4 5 1280418.215 1280418.215 1280422.494 #ffc0cb 1.0 ProfTask <19> 242 +4 5 1280427.978 1280427.978 1280432.194 #ffc0cb 1.0 ProfTask <17> 243 +4 5 1280436.774 1280436.774 1280440.821 #ffc0cb 1.0 ProfTask <22> 244 +4 5 1280446.196 1280446.196 1280450.961 #ffc0cb 1.0 ProfTask <21> 245 +4 4 1280450.394 1280456.534 1280500.201 #3dff00 1.0 Task Physical Dependence Analysis 25 323 +4 5 1280469.627 1280517.657 1280620.373 #ff7a00 1.0 Scheduler 0 325 +4 4 1280569.671 1280640.616 1280675.589 #333399 1.0 Deferred Ready Trigger 20 326 +4 3 1280578.972 1280695.112 1280731.408 #ff0098 1.0 Defer Task Launch 23 [[0, 2, 568]] 328 +4 2 1280605.210 1280750.931 1280845.001 #00ff12 1.0 Logical Dependence Analysis 29 330 +4 4 1280785.560 1280864.265 1280948.444 #ff7a00 1.0 Scheduler 0 446 +4 1 1280606.881 1280969.101 1281020.886 #3dff00 1.0 Task Physical Dependence Analysis 27 156 +4 4 1280999.402 1281040.746 1281117.395 #cd00ff 1.0 Defer Task Perform Mapping 33 [[0, 2, 679]] 332 +4 3 1281107.769 1281133.593 1281156.030 #ff0098 1.0 Defer Task Launch 33 [[0, 2, 679]] 334 +4 5 1280692.339 1281168.256 1281202.632 #3dff00 1.0 Task Physical Dependence Analysis 28 335 +4 4 1281185.590 1281216.424 1281263.117 #cd00ff 1.0 Defer Task Perform Mapping 35 [[0, 3, 625]] 337 +4 3 1281256.063 1281278.236 1281307.180 #ff0098 1.0 Defer Task Launch 35 [[0, 3, 625]] 338 +4 4 1281323.992 1281323.992 1281389.743 #cd00ff 1.0 Defer Task Perform Mapping 36 [[0, 2, 623]] 342 +4 4 1281389.743 1281389.743 1281408.233 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 36 342 +4 4 1281408.233 1281408.233 1281431.771 #cd00ff 0.45 Defer Task Perform Mapping (ready) 36 342 +4 4 1281431.771 1281431.771 1281524.905 #cd00ff 1.0 Defer Task Perform Mapping 36 342 +3 3 1281330.745 1281330.745 1281473.517 #ff3200 1.0 Mapper Call map_task for 36 36 [[0, 2, 623]] 225 +4 4 1281540.900 1281540.900 1281592.395 #00b1ff 1.0 Mapper Continuation 38 [[0, 3, 624]] 344 +4 4 1281592.395 1281592.395 1281613.947 #00b1ff 0.15 Mapper Continuation (waiting) 38 344 +4 4 1281613.947 1281613.947 1281635.375 #00b1ff 0.45 Mapper Continuation (ready) 38 344 +4 4 1281635.375 1281635.375 1281672.107 #00b1ff 1.0 Mapper Continuation 38 344 +3 3 1281545.926 1281545.926 1281660.734 #ff3200 1.0 Mapper Call map_task for 38 38 [[0, 3, 624]] 226 +4 2 1281620.289 1281702.413 1281728.933 #333399 1.0 Deferred Ready Trigger 39 346 +4 5 1281206.486 1281747.438 1281833.954 #3dff00 1.0 Task Physical Dependence Analysis 34 412 +4 3 1281816.726 1281854.322 1281962.837 #ff7a00 1.0 Scheduler 0 215 +4 4 1281718.810 1281982.725 1281997.474 #007bff 1.0 Operation Physical Dependence Analysis 39 158 +4 5 1281937.145 1282022.385 1282075.305 #3dff00 1.0 Task Physical Dependence Analysis 41 162 +4 4 1282053.287 1282094.433 1282156.222 #cd00ff 1.0 Defer Task Perform Mapping 43 [[0, 3, 626]] 165 +4 5 1282137.435 1282176.348 1282213.490 #333399 1.0 Deferred Ready Trigger 29 217 +4 4 1282201.355 1282232.852 1282265.809 #007bff 1.0 Operation Physical Dependence Analysis 29 219 +4 5 1282284.700 1282284.700 1282290.552 #ffc0cb 1.0 ProfTask <18> 246 +4 5 1282298.502 1282298.502 1282305.272 #ffc0cb 1.0 ProfTask <24> 247 +4 5 1282312.818 1282312.818 1282321.895 #ffc0cb 1.0 ProfTask <23> 248 +4 5 1282329.352 1282329.352 1282334.523 #ffc0cb 1.0 ProfTask <24> 249 +4 4 1282342.111 1282342.111 1282347.445 #ffc0cb 1.0 ProfTask <17> 250 +4 5 1282337.210 1282355.476 1282431.565 #3dff00 1.0 Task Physical Dependence Analysis 44 221 +4 4 1282416.515 1282451.010 1282537.356 #ff7a00 1.0 Scheduler 0 405 +4 5 1282560.296 1282560.296 1282643.907 #cd00ff 1.0 Defer Task Perform Mapping 47 [[0, 2, 5]] 349 +4 5 1282643.907 1282643.907 1282659.879 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 47 349 +4 5 1282659.879 1282659.879 1282716.702 #cd00ff 0.45 Defer Task Perform Mapping (ready) 47 349 +4 5 1282716.702 1282716.702 1282746.859 #cd00ff 1.0 Defer Task Perform Mapping 47 349 +4 5 1282746.859 1282746.859 1282821.799 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 47 349 +4 5 1282821.799 1282821.799 1282841.705 #cd00ff 0.45 Defer Task Perform Mapping (ready) 47 349 +4 5 1282841.705 1282841.705 1282942.785 #cd00ff 1.0 Defer Task Perform Mapping 47 349 +3 4 1282569.138 1282569.138 1282847.965 #ff3200 1.0 Mapper Call map_task for 47 47 [[0, 2, 5]] 227 +2 3 1282663.993 1282663.993 1282701.439 #cd00ff 1.0 Defer Task Perform Mapping 48 [[0, 3, 627]] 350 +2 3 1282701.439 1282701.439 1282890.865 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 48 350 +2 3 1282890.865 1282890.865 1282980.146 #cd00ff 0.45 Defer Task Perform Mapping (ready) 48 350 +2 3 1282980.146 1282980.146 1283076.987 #cd00ff 1.0 Defer Task Perform Mapping 48 350 +1 2 1282805.518 1282805.518 1282813.694 #ffc0cb 1.0 ProfTask <0> 507 +1 2 1282822.188 1282822.188 1282826.005 #ffc0cb 1.0 ProfTask <32> 508 +4 5 1283066.079 1283098.801 1283130.494 #ff0098 1.0 Defer Task Launch 48 [[0, 3, 627]] 351 +4 5 1283150.656 1283150.656 1283156.284 #ffc0cb 1.0 ProfTask <37> 423 +4 4 1283151.820 1283164.014 1283251.950 #ff7a00 1.0 Scheduler 0 352 +4 5 1283272.054 1283272.054 1283278.592 #ffc0cb 1.0 ProfTask <38> 424 +4 5 1283285.846 1283285.846 1283291.196 #ffc0cb 1.0 ProfTask <34> 425 +4 4 1283298.174 1283298.174 1283303.562 #ffc0cb 1.0 ProfTask <0> 426 +4 5 1283293.821 1283311.221 1283395.670 #ff7a00 1.0 Scheduler 0 418 +4 4 1283383.048 1283414.744 1283480.049 #3dff00 1.0 Task Physical Dependence Analysis 50 419 +4 5 1283500.017 1283500.017 1283591.367 #cd00ff 1.0 Defer Task Perform Mapping 52 [[0, 2, 628]] 420 +4 5 1283591.367 1283591.367 1283611.308 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 52 420 +4 5 1283611.308 1283611.308 1283641.409 #cd00ff 0.45 Defer Task Perform Mapping (ready) 52 420 +4 5 1283641.409 1283641.409 1283697.539 #cd00ff 1.0 Defer Task Perform Mapping 52 420 +4 5 1283697.539 1283697.539 1283797.270 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 52 420 +4 5 1283797.270 1283797.270 1283820.015 #cd00ff 0.45 Defer Task Perform Mapping (ready) 52 420 +4 5 1283820.015 1283820.015 1283931.392 #cd00ff 1.0 Defer Task Perform Mapping 52 420 +3 4 1283509.012 1283509.012 1283827.962 #ff3200 1.0 Mapper Call map_task for 52 52 [[0, 2, 628]] 421 +2 3 1283610.289 1283610.289 1283616.905 #ffc0cb 1.0 ProfTask <0> 251 +2 3 1283719.137 1283719.137 1283724.225 #ffc0cb 1.0 ProfTask <42> 252 +2 3 1283731.492 1283731.492 1283736.181 #ffc0cb 1.0 ProfTask <29> 253 +2 3 1283742.804 1283742.804 1283748.666 #ffc0cb 1.0 ProfTask <43> 254 +2 3 1283755.389 1283755.389 1283761.016 #ffc0cb 1.0 ProfTask <29> 255 +2 3 1283770.827 1283770.827 1283775.640 #ffc0cb 1.0 ProfTask <0> 256 +2 3 1283781.939 1283781.939 1283786.622 #ffc0cb 1.0 ProfTask <44> 257 +2 3 1283793.118 1283793.118 1283799.645 #ffc0cb 1.0 ProfTask <0> 258 +4 4 1283918.483 1283956.807 1283996.266 #ff0098 1.0 Defer Task Launch 52 [[0, 2, 628]] 358 +4 5 1284019.731 1284019.731 1284026.542 #ffc0cb 1.0 ProfTask <45> 427 +4 5 1284037.065 1284037.065 1284043.643 #ffc0cb 1.0 ProfTask <47> 428 +4 5 1284052.387 1284052.387 1284059.289 #ffc0cb 1.0 ProfTask <48> 429 +4 5 1284070.087 1284070.087 1284076.801 #ffc0cb 1.0 ProfTask <47> 430 +4 5 1284085.420 1284085.420 1284091.929 #ffc0cb 1.0 ProfTask <37> 431 +4 5 1284100.863 1284100.863 1284107.585 #ffc0cb 1.0 ProfTask <37> 432 +4 5 1284116.830 1284116.830 1284123.552 #ffc0cb 1.0 ProfTask <0> 433 +4 5 1284132.489 1284132.489 1284139.516 #ffc0cb 1.0 ProfTask <50> 434 +4 5 1284148.163 1284148.163 1284154.638 #ffc0cb 1.0 ProfTask <53> 435 +4 5 1284163.452 1284163.452 1284175.585 #ffc0cb 1.0 ProfTask <52> 436 +4 5 1290560.504 1290575.892 1290645.947 #006600 1.0 Post-Task Execution 13 [[0, 2, 566]] 570 +4 5 1290758.990 1290776.945 1290821.356 #009900 1.0 Deferred Commit 7 572 +4 5 1301188.653 1301211.605 1301251.876 #006600 1.0 Post-Task Execution 23 [[0, 2, 568]] 448 +4 5 1301276.326 1301276.326 1301282.541 #ffc0cb 1.0 ProfTask <23> 509 +4 5 1301545.784 1301559.661 1301629.806 #006600 1.0 Post-Task Execution 24 [[0, 3, 569]] 449 +4 5 1301646.722 1301646.722 1301651.116 #ffc0cb 1.0 ProfTask <24> 510 +4 5 1301693.731 1301693.731 1301697.364 #ffc0cb 1.0 ProfTask <12> 511 +4 5 1303264.188 1303281.263 1303320.693 #333399 1.0 Deferred Ready Trigger 54 451 +4 5 1303344.045 1303344.045 1303349.993 #ffc0cb 1.0 ProfTask <54> 512 +4 5 1303381.432 1303396.962 1303482.714 #ff7a00 1.0 Scheduler 0 452 +4 5 1303497.656 1303497.656 1303502.117 #ffc0cb 1.0 ProfTask <0> 513 +4 5 1303531.059 1303545.046 1303642.161 #ff7a00 1.0 Scheduler 0 455 +4 4 1303629.723 1303671.094 1303718.836 #3dff00 1.0 Task Physical Dependence Analysis 56 575 +4 5 1303700.660 1303732.487 1303805.810 #cd00ff 1.0 Defer Task Perform Mapping 58 [[0, 2, 7]] 576 +4 4 1303796.494 1303820.840 1303844.177 #ff0098 1.0 Defer Task Launch 58 [[0, 2, 7]] 578 +4 3 1303712.940 1303856.281 1303908.169 #00ff12 1.0 Logical Dependence Analysis 59 458 +4 5 1303922.034 1303922.034 1303925.681 #ffc0cb 1.0 ProfTask <55> 514 +4 5 1303931.496 1303931.496 1303935.527 #ffc0cb 1.0 ProfTask <0> 515 +4 4 1303940.923 1303940.923 1303944.758 #ffc0cb 1.0 ProfTask <0> 516 +4 5 1303940.359 1303950.746 1304016.012 #cd00ff 1.0 Defer Task Perform Mapping 60 [[0, 3, 267]] 461 +4 4 1304007.690 1304034.134 1304057.203 #ff0098 1.0 Defer Task Launch 60 [[0, 3, 267]] 462 +4 5 1304040.859 1304070.131 1304099.441 #007bff 1.0 Operation Physical Dependence Analysis 59 580 +4 5 1304120.480 1304120.480 1304128.900 #ffc0cb 1.0 ProfTask <0> 517 +4 5 1304137.321 1304137.321 1304143.536 #ffc0cb 1.0 ProfTask <59> 518 +4 5 1304151.481 1304151.481 1304158.130 #ffc0cb 1.0 ProfTask <57> 519 +4 5 1304166.492 1304166.492 1304172.116 #ffc0cb 1.0 ProfTask <60> 520 +4 5 1304179.541 1304179.541 1304185.478 #ffc0cb 1.0 ProfTask <60> 521 +4 5 1304186.066 1304194.596 1304268.486 #3dff00 1.0 Task Physical Dependence Analysis 61 582 +4 4 1304237.028 1304287.341 1304378.464 #ff7a00 1.0 Scheduler 0 584 +4 5 1304364.597 1304398.660 1304436.193 #3dff00 1.0 Task Physical Dependence Analysis 63 586 +4 4 1304419.994 1304450.099 1304504.123 #cd00ff 1.0 Defer Task Perform Mapping 65 [[0, 2, 629]] 463 +4 5 1304497.044 1304516.057 1304538.039 #ff0098 1.0 Defer Task Launch 65 [[0, 2, 629]] 464 +4 5 1304544.115 1304551.018 1304575.121 #333399 1.0 Deferred Ready Trigger 62 465 +4 4 1304566.458 1304587.656 1304609.345 #007bff 1.0 Operation Physical Dependence Analysis 62 466 +4 5 1304600.491 1304622.305 1304690.689 #ff7a00 1.0 Scheduler 0 468 +4 5 1304706.331 1304706.331 1304723.689 #00ff12 1.0 Logical Dependence Analysis 68 471 +4 5 1304723.689 1304723.689 1304798.895 #00ff12 0.15 Logical Dependence Analysis (waiting) 68 471 +4 5 1304798.895 1304798.895 1304816.987 #00ff12 0.45 Logical Dependence Analysis (ready) 68 471 +4 5 1304816.987 1304816.987 1304856.819 #00ff12 1.0 Logical Dependence Analysis 68 471 +3 4 1304719.513 1304762.829 1304783.673 #00b1ff 1.0 Mapper Continuation 68 470 +4 3 1304755.187 1304897.074 1305012.316 #ff7a00 1.0 Scheduler 0 475 +4 5 1305000.679 1305034.947 1305071.433 #3dff00 1.0 Task Physical Dependence Analysis 70 478 +4 4 1305056.724 1305086.886 1305176.877 #cd00ff 1.0 Defer Task Perform Mapping 72 [[0, 3, 271]] 480 +4 5 1305165.964 1305199.516 1305234.115 #ff0098 1.0 Defer Task Launch 72 [[0, 3, 271]] 483 +4 4 1305207.658 1305252.611 1305319.714 #00ff12 1.0 Logical Dependence Analysis 73 485 +4 5 1305339.765 1305339.765 1305345.502 #ffc0cb 1.0 ProfTask <65> 522 +4 5 1305353.891 1305353.891 1305360.727 #ffc0cb 1.0 ProfTask <65> 523 +4 4 1305357.954 1305370.367 1305480.738 #ff7a00 1.0 Scheduler 0 590 +4 5 1305465.200 1305504.378 1305567.074 #3dff00 1.0 Task Physical Dependence Analysis 75 592 +4 4 1305543.778 1305594.413 1305686.197 #cd00ff 1.0 Defer Task Perform Mapping 77 [[0, 2, 11]] 486 +4 5 1305605.824 1305712.259 1305807.428 #00ff12 1.0 Logical Dependence Analysis 79 489 +4 4 1305720.839 1305832.088 1305893.515 #ff0098 1.0 Defer Task Launch 78 [[0, 3, 273]] 491 +4 3 1305802.946 1305920.984 1305975.704 #007bff 1.0 Operation Physical Dependence Analysis 73 493 +4 5 1305994.539 1305994.539 1306000.231 #ffc0cb 1.0 ProfTask <62> 524 +4 5 1306007.662 1306007.662 1306012.745 #ffc0cb 1.0 ProfTask <62> 525 +4 5 1306018.660 1306018.660 1306024.251 #ffc0cb 1.0 ProfTask <66> 526 +4 5 1306031.062 1306031.062 1306036.169 #ffc0cb 1.0 ProfTask <0> 527 +4 5 1306042.053 1306042.053 1306046.201 #ffc0cb 1.0 ProfTask <67> 528 +4 5 1306051.923 1306051.923 1306055.204 #ffc0cb 1.0 ProfTask <68> 529 +4 5 1306061.397 1306061.397 1306068.757 #ffc0cb 1.0 ProfTask <68> 530 +4 5 1306077.209 1306077.209 1306082.911 #ffc0cb 1.0 ProfTask <0> 531 +4 5 1306089.960 1306089.960 1306095.305 #ffc0cb 1.0 ProfTask <69> 532 +4 5 1306102.116 1306102.116 1306106.899 #ffc0cb 1.0 ProfTask <0> 533 +4 5 1306113.792 1306113.792 1306118.325 #ffc0cb 1.0 ProfTask <71> 534 +4 5 1306125.177 1306125.177 1306129.472 #ffc0cb 1.0 ProfTask <70> 535 +4 5 1306135.484 1306135.484 1306139.885 #ffc0cb 1.0 ProfTask <71> 536 +4 5 1306146.163 1306146.163 1306151.014 #ffc0cb 1.0 ProfTask <72> 537 +4 5 1306157.922 1306157.922 1306162.843 #ffc0cb 1.0 ProfTask <68> 538 +4 5 1306169.196 1306169.196 1306173.805 #ffc0cb 1.0 ProfTask <68> 539 +4 5 1306180.863 1306180.863 1306186.221 #ffc0cb 1.0 ProfTask <72> 540 +4 5 1306192.428 1306192.428 1306198.940 #ffc0cb 1.0 ProfTask <0> 541 +4 5 1306207.747 1306207.747 1306213.896 #ffc0cb 1.0 ProfTask <73> 542 +4 4 1306209.300 1306224.076 1306316.875 #3dff00 1.0 Task Physical Dependence Analysis 81 495 +4 5 1306301.406 1306337.294 1306410.407 #ff7a00 1.0 Scheduler 0 497 +4 4 1306409.916 1306438.072 1306501.791 #cd00ff 1.0 Defer Task Perform Mapping 84 [[0, 2, 680]] 501 +4 5 1306493.051 1306520.623 1306546.595 #ff0098 1.0 Defer Task Launch 84 [[0, 2, 680]] 502 +4 4 1306541.621 1306561.231 1306597.755 #333399 1.0 Deferred Ready Trigger 80 505 +4 5 1306616.486 1306616.486 1306620.257 #ffc0cb 1.0 ProfTask <77> 543 +4 5 1306625.100 1306625.100 1306628.442 #ffc0cb 1.0 ProfTask <78> 544 +4 5 1306633.053 1306633.053 1306638.535 #ffc0cb 1.0 ProfTask <77> 545 +4 5 1306643.545 1306643.545 1306647.468 #ffc0cb 1.0 ProfTask <79> 546 +4 5 1306651.973 1306651.973 1306655.289 #ffc0cb 1.0 ProfTask <73> 547 +4 5 1306659.951 1306659.951 1306663.338 #ffc0cb 1.0 ProfTask <78> 548 +4 5 1306667.811 1306667.811 1306671.169 #ffc0cb 1.0 ProfTask <79> 549 +4 5 1306676.051 1306676.051 1306680.523 #ffc0cb 1.0 ProfTask <73> 550 +4 5 1306685.372 1306685.372 1306688.634 #ffc0cb 1.0 ProfTask <0> 551 +4 5 1306692.987 1306692.987 1306696.272 #ffc0cb 1.0 ProfTask <81> 552 +4 5 1306701.710 1306701.710 1306706.054 #ffc0cb 1.0 ProfTask <0> 553 +4 5 1306710.872 1306710.872 1306714.195 #ffc0cb 1.0 ProfTask <0> 554 +4 5 1306719.516 1306719.516 1306723.164 #ffc0cb 1.0 ProfTask <82> 555 +4 5 1306727.419 1306727.419 1306730.709 #ffc0cb 1.0 ProfTask <83> 556 +4 5 1306739.454 1306739.454 1306745.991 #ffc0cb 1.0 ProfTask <84> 557 +4 5 1306751.542 1306751.542 1306756.354 #ffc0cb 1.0 ProfTask <84> 558 +4 5 1306761.979 1306761.979 1306766.736 #ffc0cb 1.0 ProfTask <85> 559 +4 5 1306773.560 1306773.560 1306781.569 #ffc0cb 1.0 ProfTask <80> 560 +4 5 1306792.355 1306792.355 1306806.557 #ffc0cb 1.0 ProfTask <80> 561 +4 5 1306869.972 1306886.823 1306898.727 #ff00c5 1.0 Tighten Index Space 80 632 +4 5 1306982.462 1306999.684 1307038.067 #333399 1.0 Deferred Ready Trigger 79 682 +4 5 1307059.257 1307059.257 1307084.938 #ffc0cb 1.0 ProfTask <80> 697 +4 5 1307095.699 1307095.699 1307099.265 #ffc0cb 1.0 ProfTask <79> 698 +4 5 1307154.918 1307154.918 1307163.906 #ffc0cb 1.0 ProfTask <79> 699 +4 5 1307269.010 1307269.010 1307275.994 #ffc0cb 1.0 ProfTask <79> 700 +4 5 1307284.634 1307300.490 1307478.161 #1f00ff 1.0 Copy Fill Aggregation 79 683 +4 4 1307468.389 1307497.332 1307515.476 #00ff0f 1.0 Copy Fill Deletion 79 684 +4 5 1307531.573 1307531.573 1307536.897 #ffc0cb 1.0 ProfTask <79> 701 +4 5 1307545.301 1307545.301 1307551.859 #ffc0cb 1.0 ProfTask <79> 702 +4 5 1307575.711 1307575.711 1307583.147 #ffc0cb 1.0 ProfTask <79> 703 +4 5 1313026.911 1313044.487 1313088.907 #006600 1.0 Post-Task Execution 36 [[0, 2, 623]] 686 +4 5 1313107.910 1313107.910 1313112.001 #ffc0cb 1.0 ProfTask <36> 704 +4 5 1316552.854 1316552.854 1316569.677 #ffc0cb 1.0 ProfTask <33> 705 +4 5 1316573.910 1316583.573 1316625.438 #006600 1.0 Post-Task Execution 33 [[0, 2, 679]] 687 +4 5 1316644.297 1316644.297 1316648.163 #ffc0cb 1.0 ProfTask <33> 706 +4 5 1320198.948 1320214.501 1320270.219 #006600 1.0 Post-Task Execution 43 [[0, 3, 626]] 688 +4 5 1320297.734 1320297.734 1320303.704 #ffc0cb 1.0 ProfTask <43> 707 +4 5 1333412.634 1333412.634 1333418.933 #ffc0cb 1.0 ProfTask <47> 708 +4 5 1346531.958 1346551.558 1346606.273 #006600 1.0 Post-Task Execution 52 [[0, 2, 628]] 637 +4 5 1353664.429 1353696.939 1353730.416 #009900 1.0 Deferred Commit 54 690 +4 5 1353754.700 1353754.700 1353758.956 #ffc0cb 1.0 ProfTask <54> 709 +4 5 1358449.612 1358473.590 1358523.159 #006600 1.0 Post-Task Execution 65 [[0, 2, 629]] 691 +4 5 1358542.082 1358542.082 1358545.952 #ffc0cb 1.0 ProfTask <65> 710 +4 5 1359051.943 1359051.943 1359070.658 #ffc0cb 1.0 ProfTask <66> 711 +4 5 1373389.096 1373389.096 1373396.919 #ffc0cb 1.0 ProfTask <84> 712 +4 5 1373789.041 1373807.331 1373852.739 #006600 1.0 Post-Task Execution 85 [[0, 3, 630]] 646 +4 5 1373935.631 1373935.631 1373948.425 #ffc0cb 1.0 ProfTask <73> 713 +4 5 1805063.076 1805063.076 1805068.493 #ffc0cb 1.0 ProfTask <79> 714 +4 5 1805280.159 1805312.310 1805350.562 #333399 1.0 Deferred Ready Trigger 86 49 +4 5 1805425.680 1805425.680 1805431.066 #ffc0cb 1.0 ProfTask <86> 715 +4 5 1843719.392 1843737.041 1843768.695 #333399 1.0 Deferred Ready Trigger 89 51 +4 5 1843810.280 1843827.225 1843861.862 #006600 1.0 Post-Task Execution 1 [[0, 4, 12]] 53 +4 5 1843867.763 1843891.732 1843922.152 #333399 1.0 Deferred Ready Trigger 87 283 +4 5 1843972.301 1843992.420 1844012.594 #333399 1.0 Deferred Ready Trigger 88 56 +4 4 1844004.598 1844033.640 1844072.396 #007bff 1.0 Operation Physical Dependence Analysis 88 57 +4 3 1844042.014 1844093.056 1844104.457 #f7ff00 1.0 Trigger Complete 1 [[0, 4, 12]] 58 +4 5 1844020.689 1844126.888 1844192.738 #009900 1.0 Garbage Collection 87 60 +4 2 1844044.059 1844231.819 1844276.782 #009900 1.0 Garbage Collection 87 61 +4 5 1844608.555 1844639.970 1844690.377 #009900 1.0 Garbage Collection 87 284 +4 4 1844673.494 1844718.199 1844750.254 #009900 1.0 Garbage Collection 87 62 +4 3 1844689.761 1844782.026 1844822.422 #009900 1.0 Garbage Collection 87 63 +4 5 1844704.569 1844849.633 1844884.140 #009900 1.0 Garbage Collection 87 285 +4 2 1844722.002 1844910.803 1844947.737 #009900 1.0 Garbage Collection 87 286 +4 4 1844804.386 1844970.793 1845017.478 #009900 1.0 Garbage Collection 87 65 +4 5 1845022.789 1845052.547 1845086.468 #ff8c00 1.0 Top Finish 0 288 +4 3 1844835.242 1845110.994 1845146.179 #009900 1.0 Garbage Collection 87 289 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000002.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000002.tsv new file mode 100644 index 000000000..0b0a39c8e --- /dev/null +++ b/examples/testbench/good_band/tsv/Proc_0x1d00000000000002.tsv @@ -0,0 +1,67 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +1 3 1164390.880 1164390.880 1164404.064 #ffc0cb 1.0 ProfTask <3> 82 +1 3 1164431.041 1164431.041 1164436.216 #ffc0cb 1.0 ProfTask <3> 83 +1 3 1164746.447 1164746.447 1164753.372 #ffc0cb 1.0 ProfTask <4> 84 +1 3 1164794.721 1164794.721 1164801.321 #ffc0cb 1.0 ProfTask <4> 85 +1 3 1207340.857 1207340.857 1207348.217 #ffc0cb 1.0 ProfTask <5> 86 +1 3 1207357.779 1207357.779 1207362.525 #ffc0cb 1.0 ProfTask <5> 87 +1 3 1257468.208 1257468.208 1257475.225 #ffc0cb 1.0 ProfTask <6> 88 +1 3 1257512.563 1257512.563 1257518.405 #ffc0cb 1.0 ProfTask <6> 89 +1 3 1257612.061 1257612.061 1257621.839 #ffc0cb 1.0 ProfTask <6> 90 +1 3 1257633.588 1257633.588 1257640.573 #ffc0cb 1.0 ProfTask <6> 91 +1 3 1278088.519 1278088.519 1278094.369 #ffc0cb 1.0 ProfTask <8> 92 +1 3 1278227.506 1278227.506 1278250.584 #ffc0cb 1.0 ProfTask <7> 93 +1 3 1278329.460 1278329.460 1278341.946 #ffc0cb 1.0 ProfTask <0> 94 +1 3 1278465.635 1278465.635 1278473.130 #ffc0cb 1.0 ProfTask <9> 95 +1 3 1278531.783 1278531.783 1278539.848 #ffc0cb 1.0 ProfTask <0> 96 +1 3 1278559.197 1278559.197 1278563.854 #ffc0cb 1.0 ProfTask <0> 97 +1 3 1278647.025 1278647.025 1278654.038 #ffc0cb 1.0 ProfTask <12> 98 +1 3 1278732.052 1278732.052 1278737.425 #ffc0cb 1.0 ProfTask <11> 99 +1 3 1278822.472 1278822.472 1278827.664 #ffc0cb 1.0 ProfTask <14> 100 +1 3 1278836.004 1278836.004 1278846.984 #ffc0cb 1.0 ProfTask <13> 101 +1 3 1278863.656 1278863.656 1278867.667 #ffc0cb 1.0 ProfTask <12> 102 +1 3 1278941.853 1278941.853 1278947.582 #ffc0cb 1.0 ProfTask <12> 103 +1 3 1279087.247 1279087.247 1279093.462 #ffc0cb 1.0 ProfTask <15> 104 +1 3 1279119.581 1279119.581 1279132.688 #ffc0cb 1.0 ProfTask <13> 105 +1 3 1279182.513 1279195.488 1290530.227 #00fff6 1.0 legate::numpy::FillTask [CPU] <13> [[0, 1, 570], [0, 3, 624]] [[0, 0, 409], [0, 1, 223], [0, 1, 46]] [[0, 4, 12]] 566 +1 2 1280719.209 1290575.311 1301160.372 #00fff6 1.0 legate::numpy::FillTask [CPU] <23> [[0, 1, 448], [0, 3, 626]] [[0, 1, 328], [0, 0, 321], [0, 0, 407], [0, 0, 324]] [[0, 4, 12]] 568 +1 1 1281679.018 1301205.707 1312999.079 #00fff6 1.0 legate::numpy::FillTask [CPU] <36> [[0, 1, 686]] [[0, 2, 628], [0, 1, 342], [0, 1, 225], [0, 3, 265], [0, 0, 345]] [[0, 4, 12]] 623 +1 3 1290605.372 1313041.542 1316508.577 #00fff6 1.0 legate::numpy::FillTask [CPU] <33> [[0, 1, 687]] [[0, 1, 334], [0, 1, 332]] [[0, 4, 12]] 679 +1 2 1301228.669 1316545.328 1319918.397 #00fff6 1.0 legate::numpy::FillTask [CPU] <42> [[0, 0, 635]] [[0, 0, 163], [0, 0, 216]] [[0, 4, 12]] 3 +1 3 1319957.314 1319957.314 1319964.781 #ffc0cb 1.0 ProfTask <42> 106 +1 3 1319992.164 1320009.542 1333283.719 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <47> [[0, 2, 628], [0, 0, 689]] [[0, 1, 227], [0, 0, 415], [0, 1, 349]] [[0, 4, 12]] 5 +1 3 1333326.173 1333326.173 1333334.715 #ffc0cb 1.0 ProfTask <47> 107 +1 3 1333355.300 1333381.736 1346503.982 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <52> [[0, 2, 7], [0, 2, 623], [0, 1, 637]] [[0, 1, 420], [0, 1, 421], [0, 1, 358], [0, 2, 5]] [[0, 4, 12]] 628 +1 3 1346566.949 1346589.948 1353143.177 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <58> [[0, 3, 269], [0, 0, 639]] [[0, 1, 576], [0, 1, 578], [0, 2, 628]] [[0, 4, 12]] 7 +1 3 1353185.134 1353185.134 1353193.257 #ffc0cb 1.0 ProfTask <58> 108 +1 3 1353219.426 1353240.213 1358415.641 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <65> [[0, 1, 691], [0, 2, 9], [0, 3, 267]] [[0, 1, 463], [0, 1, 464], [0, 3, 265]] [[0, 4, 12]] 629 +1 3 1358489.897 1358516.042 1363745.920 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <71> [[0, 0, 641], [0, 2, 11]] [[0, 0, 479], [0, 2, 629], [0, 0, 476]] [[0, 4, 12]] 9 +1 3 1363795.948 1363795.948 1363805.182 #ffc0cb 1.0 ProfTask <71> 109 +1 3 1363840.145 1363869.877 1368701.245 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <77> [[0, 3, 630], [0, 0, 643]] [[0, 0, 488], [0, 2, 9], [0, 1, 486]] [[0, 4, 12]] 11 +1 3 1368739.249 1368739.249 1368746.421 #ffc0cb 1.0 ProfTask <77> 110 +1 3 1368771.516 1368793.530 1373328.678 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <84> [[0, 0, 645]] [[0, 1, 502], [0, 1, 501], [0, 3, 273]] [[0, 4, 12]] 680 +1 3 1805328.138 1805328.138 1805337.533 #ffc0cb 1.0 ProfTask <86> 111 +1 3 1805375.803 1805375.803 1805382.225 #ffc0cb 1.0 ProfTask <86> 112 +1 3 1843775.371 1843775.371 1843805.275 #ffc0cb 1.0 ProfTask <1> 113 +1 3 1843817.171 1843817.171 1843824.922 #ffc0cb 1.0 ProfTask <89> 114 +1 3 1843844.761 1843844.761 1843861.109 #ffc0cb 1.0 ProfTask <89> 115 +1 3 1843886.263 1843886.263 1843893.154 #ffc0cb 1.0 ProfTask <1> 116 +1 3 1843937.108 1843937.108 1843943.529 #ffc0cb 1.0 ProfTask <89> 117 +1 3 1844034.676 1844034.676 1844041.454 #ffc0cb 1.0 ProfTask <88> 118 +1 3 1844091.466 1844091.466 1844097.428 #ffc0cb 1.0 ProfTask <88> 119 +1 3 1844123.736 1844123.736 1844129.659 #ffc0cb 1.0 ProfTask <1> 120 +1 3 1844167.643 1844167.643 1844182.143 #ffc0cb 1.0 ProfTask <47> 121 +1 3 1844214.123 1844214.123 1844221.266 #ffc0cb 1.0 ProfTask <87> 122 +1 3 1844257.222 1844257.222 1844263.836 #ffc0cb 1.0 ProfTask <48> 123 +1 3 1844301.260 1844301.260 1844305.938 #ffc0cb 1.0 ProfTask <87> 124 +1 3 1844676.874 1844676.874 1844697.739 #ffc0cb 1.0 ProfTask <79> 125 +1 3 1844770.899 1844770.899 1844776.660 #ffc0cb 1.0 ProfTask <87> 126 +1 3 1844809.980 1844809.980 1844816.809 #ffc0cb 1.0 ProfTask <13> 127 +1 3 1844857.582 1844857.582 1844865.890 #ffc0cb 1.0 ProfTask <87> 128 +1 3 1844935.962 1844935.962 1844943.256 #ffc0cb 1.0 ProfTask <23> 129 +1 3 1844963.598 1844963.598 1844971.617 #ffc0cb 1.0 ProfTask <87> 130 +1 3 1845015.224 1845015.224 1845023.543 #ffc0cb 1.0 ProfTask <24> 131 +1 3 1845051.132 1845051.132 1845067.224 #ffc0cb 1.0 ProfTask <87> 132 +1 3 1845129.295 1845129.295 1845137.136 #ffc0cb 1.0 ProfTask <87> 133 +1 3 1845147.332 1845147.332 1845163.365 #ffc0cb 1.0 ProfTask <38> 134 +1 3 1845171.090 1845171.090 1845177.515 #ffc0cb 1.0 ProfTask <87> 135 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000003.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000003.tsv new file mode 100644 index 000000000..251bedb73 --- /dev/null +++ b/examples/testbench/good_band/tsv/Proc_0x1d00000000000003.tsv @@ -0,0 +1,38 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +1 3 1278661.355 1278661.355 1278670.464 #ffc0cb 1.0 ProfTask <10> 292 +1 3 1278677.818 1278677.818 1278682.210 #ffc0cb 1.0 ProfTask <14> 293 +1 3 1279381.573 1279381.573 1279387.931 #ffc0cb 1.0 ProfTask <0> 294 +1 3 1279397.429 1279397.429 1279409.712 #ffc0cb 1.0 ProfTask <15> 295 +1 3 1279450.771 1279450.771 1279457.216 #ffc0cb 1.0 ProfTask <17> 296 +1 3 1279491.926 1279491.926 1279502.598 #ffc0cb 1.0 ProfTask <0> 297 +1 3 1279554.996 1279554.996 1279565.486 #ffc0cb 1.0 ProfTask <17> 298 +1 3 1279612.008 1279612.008 1279618.651 #ffc0cb 1.0 ProfTask <19> 299 +1 3 1279629.022 1279629.022 1279637.142 #ffc0cb 1.0 ProfTask <15> 300 +1 3 1279637.815 1279646.909 1290673.584 #00fff6 1.0 legate::numpy::FillTask [CPU] <15> [[0, 0, 571]] [[0, 0, 406], [0, 0, 277], [0, 0, 282], [0, 1, 199], [0, 3, 569]] [[0, 4, 12]] 567 +1 2 1280268.662 1290724.634 1301522.032 #00fff6 1.0 legate::numpy::FillTask [CPU] <24> [[0, 3, 567], [0, 1, 449]] [[0, 1, 212], [0, 1, 224], [0, 1, 213]] 569 +1 1 1281955.581 1301559.534 1313329.507 #00fff6 1.0 legate::numpy::FillTask [CPU] <38> [[0, 3, 627], [0, 0, 633]] [[0, 2, 566], [0, 1, 344], [0, 0, 157], [0, 0, 411], [0, 1, 226]] [[0, 4, 12]] 624 +1 3 1290746.977 1313364.414 1316831.920 #00fff6 1.0 legate::numpy::FillTask [CPU] <35> [[0, 0, 634]] [[0, 1, 337], [0, 3, 626], [0, 1, 338]] 625 +1 2 1301577.337 1316862.415 1320182.092 #00fff6 1.0 legate::numpy::FillTask [CPU] <43> [[0, 1, 688], [0, 3, 625], [0, 3, 627]] [[0, 1, 165], [0, 0, 218], [0, 2, 568]] [[0, 4, 12]] 626 +1 3 1320203.531 1320208.211 1333389.695 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <48> [[0, 0, 636], [0, 3, 265]] [[0, 0, 348], [0, 1, 351], [0, 3, 626], [0, 3, 624], [0, 0, 360], [0, 1, 350]] [[0, 4, 12]] 627 +1 3 1333436.151 1333450.382 1347048.850 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <53> [[0, 2, 623], [0, 0, 638], [0, 2, 629]] [[0, 0, 359], [0, 0, 357], [0, 0, 356], [0, 3, 627], [0, 0, 166]] [[0, 4, 12]] 265 +1 3 1347087.138 1347087.138 1347098.437 #ffc0cb 1.0 ProfTask <53> 301 +1 3 1347122.092 1347145.449 1353587.731 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <60> [[0, 0, 640]] [[0, 3, 269], [0, 1, 461], [0, 2, 629], [0, 1, 462]] [[0, 4, 12]] 267 +1 3 1353620.664 1353620.664 1353625.527 #ffc0cb 1.0 ProfTask <60> 302 +1 3 1353653.992 1353676.454 1358922.645 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <66> [[0, 0, 692], [0, 3, 271], [0, 3, 267]] [[0, 2, 7], [0, 0, 467], [0, 0, 588]] [[0, 4, 12]] 269 +1 3 1358955.630 1358955.630 1358961.897 #ffc0cb 1.0 ProfTask <66> 303 +1 3 1358980.811 1359020.346 1364298.334 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <72> [[0, 0, 642], [0, 3, 273]] [[0, 1, 480], [0, 3, 269], [0, 1, 483]] [[0, 4, 12]] 271 +1 3 1364340.083 1364340.083 1364346.914 #ffc0cb 1.0 ProfTask <72> 304 +1 3 1364370.248 1364383.652 1369149.144 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <78> [[0, 0, 644], [0, 2, 680]] [[0, 1, 491], [0, 3, 271], [0, 0, 487]] [[0, 4, 12]] 273 +1 3 1369188.043 1369188.043 1369203.231 #ffc0cb 1.0 ProfTask <78> 305 +1 3 1369224.914 1369248.466 1373764.764 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <85> [[0, 1, 646]] [[0, 0, 631], [0, 0, 504], [0, 2, 11]] [[0, 4, 12]] 630 +1 3 1843951.637 1843951.637 1843966.439 #ffc0cb 1.0 ProfTask <87> 306 +1 3 1844723.767 1844723.767 1844730.441 #ffc0cb 1.0 ProfTask <87> 307 +1 3 1844738.308 1844738.308 1844743.158 #ffc0cb 1.0 ProfTask <36> 308 +1 3 1844874.628 1844874.628 1844891.521 #ffc0cb 1.0 ProfTask <52> 309 +1 3 1844898.768 1844898.768 1844902.397 #ffc0cb 1.0 ProfTask <87> 310 +1 3 1844966.386 1844966.386 1844973.976 #ffc0cb 1.0 ProfTask <87> 311 +1 3 1845079.615 1845079.615 1845085.862 #ffc0cb 1.0 ProfTask <88> 312 +1 3 1845092.849 1845092.849 1845096.644 #ffc0cb 1.0 ProfTask <15> 313 +1 3 1845103.389 1845103.389 1845108.412 #ffc0cb 1.0 ProfTask <0> 314 +1 3 1845132.386 1845132.386 1845139.801 #ffc0cb 1.0 ProfTask <53> 315 +1 3 1845168.715 1845168.715 1845175.087 #ffc0cb 1.0 ProfTask <87> 316 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000004.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000004.tsv new file mode 100644 index 000000000..3b3340a0f --- /dev/null +++ b/examples/testbench/good_band/tsv/Proc_0x1d00000000000004.tsv @@ -0,0 +1,20 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +1 1 494356.555 494356.555 1164322.429 #eb00ff 1.0 legion_python_main <1> [[0, 1, 58], [0, 1, 53]] [[0, 0, 150], [0, 0, 149], [0, 0, 194]] [[0, 2, 566], [0, 2, 679], [0, 3, 624], [0, 3, 630], [0, 2, 3], [0, 3, 627], [0, 3, 267], [0, 3, 273], [0, 2, 9], [0, 2, 680], [0, 2, 5], [0, 3, 265], [0, 2, 628], [0, 3, 567], [0, 2, 7], [0, 3, 271], [0, 2, 623], [0, 3, 626], [0, 2, 629], [0, 2, 568], [0, 3, 269], [0, 2, 11]] 12 +1 1 1164322.429 1164322.429 1164469.122 #eb00ff 0.15 legion_python_main <1> (waiting) 12 +1 1 1164469.122 1164469.122 1164554.852 #eb00ff 0.45 legion_python_main <1> (ready) 12 +1 1 1164554.852 1164554.852 1164686.388 #eb00ff 1.0 legion_python_main <1> 12 +1 1 1164686.388 1164686.388 1164801.809 #eb00ff 0.15 legion_python_main <1> (waiting) 12 +1 1 1164801.809 1164801.809 1164823.261 #eb00ff 0.45 legion_python_main <1> (ready) 12 +1 1 1164823.261 1164823.261 1207258.637 #eb00ff 1.0 legion_python_main <1> 12 +1 1 1207258.637 1207258.637 1207381.756 #eb00ff 0.15 legion_python_main <1> (waiting) 12 +1 1 1207381.756 1207381.756 1207422.856 #eb00ff 0.45 legion_python_main <1> (ready) 12 +1 1 1207422.856 1207422.856 1305677.005 #eb00ff 1.0 legion_python_main <1> 12 +1 1 1305677.005 1305677.005 1307506.675 #eb00ff 0.15 legion_python_main <1> (waiting) 12 +1 1 1307506.675 1307506.675 1307537.619 #eb00ff 0.45 legion_python_main <1> (ready) 12 +1 1 1307537.619 1307537.619 1307553.652 #eb00ff 1.0 legion_python_main <1> 12 +1 1 1307553.652 1307553.652 1387621.722 #eb00ff 0.15 legion_python_main <1> (waiting) 12 +1 1 1387621.722 1387621.722 1387655.987 #eb00ff 0.45 legion_python_main <1> (ready) 12 +1 1 1387655.987 1387655.987 1805303.104 #eb00ff 1.0 legion_python_main <1> 12 +1 1 1805303.104 1805303.104 1805357.525 #eb00ff 0.15 legion_python_main <1> (waiting) 12 +1 1 1805357.525 1805357.525 1805398.321 #eb00ff 0.45 legion_python_main <1> (ready) 12 +1 1 1805398.321 1805398.321 1843718.831 #eb00ff 1.0 legion_python_main <1> 12 diff --git a/examples/testbench/good_band/tsv/all (CPU)_util.tsv b/examples/testbench/good_band/tsv/all (CPU)_util.tsv new file mode 100644 index 000000000..4fe28da97 --- /dev/null +++ b/examples/testbench/good_band/tsv/all (CPU)_util.tsv @@ -0,0 +1,208 @@ +time count +0.000 0.00 +1164390.880 0.50 +1164404.064 0.00 +1164431.041 0.50 +1164436.216 0.00 +1164746.447 0.50 +1164753.372 0.00 +1164794.721 0.50 +1164801.321 0.00 +1207340.857 0.50 +1207348.217 0.00 +1207357.779 0.50 +1207362.525 0.00 +1257468.208 0.50 +1257475.225 0.00 +1257512.563 0.50 +1257518.405 0.00 +1257612.061 0.50 +1257621.839 0.00 +1257633.588 0.50 +1257640.573 0.00 +1278088.519 0.50 +1278094.369 0.00 +1278227.506 0.50 +1278250.584 0.00 +1278329.460 0.50 +1278341.946 0.00 +1278465.635 0.50 +1278473.130 0.00 +1278531.783 0.50 +1278539.848 0.00 +1278559.197 0.50 +1278563.854 0.00 +1278647.025 0.50 +1278654.038 0.00 +1278661.355 0.50 +1278670.464 0.00 +1278677.818 0.50 +1278682.210 0.00 +1278732.052 0.50 +1278737.425 0.00 +1278822.472 0.50 +1278827.664 0.00 +1278836.004 0.50 +1278846.984 0.00 +1278863.656 0.50 +1278867.667 0.00 +1278941.853 0.50 +1278947.582 0.00 +1279087.247 0.50 +1279093.462 0.00 +1279119.581 0.50 +1279132.688 0.00 +1279195.488 0.50 +1279381.573 1.00 +1279387.931 0.50 +1279397.429 1.00 +1279409.712 0.50 +1279450.771 1.00 +1279457.216 0.50 +1279491.926 1.00 +1279502.598 0.50 +1279554.996 1.00 +1279565.486 0.50 +1279612.008 1.00 +1279618.651 0.50 +1279629.022 1.00 +1279637.142 0.50 +1279646.909 1.00 +1290530.227 0.50 +1290575.311 1.00 +1290673.584 0.50 +1290724.634 1.00 +1301160.372 0.50 +1301205.707 1.00 +1301522.032 0.50 +1301559.534 1.00 +1312999.079 0.50 +1313041.542 1.00 +1313329.507 0.50 +1313364.414 1.00 +1316508.577 0.50 +1316545.328 1.00 +1316831.920 0.50 +1316862.415 1.00 +1319918.397 0.50 +1319957.314 1.00 +1319964.781 0.50 +1320009.542 1.00 +1320182.092 0.50 +1320208.211 1.00 +1333283.719 0.50 +1333326.173 1.00 +1333334.715 0.50 +1333381.736 1.00 +1333389.695 0.50 +1333450.382 1.00 +1346503.982 0.50 +1346589.948 1.00 +1347048.850 0.50 +1347087.138 1.00 +1347098.437 0.50 +1347145.449 1.00 +1353143.177 0.50 +1353185.134 1.00 +1353193.257 0.50 +1353240.213 1.00 +1353587.731 0.50 +1353620.664 1.00 +1353625.527 0.50 +1353676.454 1.00 +1358415.641 0.50 +1358516.042 1.00 +1358922.645 0.50 +1358955.630 1.00 +1358961.897 0.50 +1359020.346 1.00 +1363745.920 0.50 +1363795.948 1.00 +1363805.182 0.50 +1363869.877 1.00 +1364298.334 0.50 +1364340.083 1.00 +1364346.914 0.50 +1364383.652 1.00 +1368701.245 0.50 +1368739.249 1.00 +1368746.421 0.50 +1368793.530 1.00 +1369149.144 0.50 +1369188.043 1.00 +1369203.231 0.50 +1369248.466 1.00 +1373328.678 0.50 +1373764.764 0.00 +1805328.138 0.50 +1805337.533 0.00 +1805375.803 0.50 +1805382.225 0.00 +1843775.371 0.50 +1843805.275 0.00 +1843817.171 0.50 +1843824.922 0.00 +1843844.761 0.50 +1843861.109 0.00 +1843886.263 0.50 +1843893.154 0.00 +1843937.108 0.50 +1843943.529 0.00 +1843951.637 0.50 +1843966.439 0.00 +1844034.676 0.50 +1844041.454 0.00 +1844091.466 0.50 +1844097.428 0.00 +1844123.736 0.50 +1844129.659 0.00 +1844167.643 0.50 +1844182.143 0.00 +1844214.123 0.50 +1844221.266 0.00 +1844257.222 0.50 +1844263.836 0.00 +1844301.260 0.50 +1844305.938 0.00 +1844676.874 0.50 +1844697.739 0.00 +1844723.767 0.50 +1844730.441 0.00 +1844738.308 0.50 +1844743.158 0.00 +1844770.899 0.50 +1844776.660 0.00 +1844809.980 0.50 +1844816.809 0.00 +1844857.582 0.50 +1844865.890 0.00 +1844874.628 0.50 +1844891.521 0.00 +1844898.768 0.50 +1844902.397 0.00 +1844935.962 0.50 +1844943.256 0.00 +1844963.598 0.50 +1844966.386 1.00 +1844971.617 0.50 +1844973.976 0.00 +1845015.224 0.50 +1845023.543 0.00 +1845051.132 0.50 +1845067.224 0.00 +1845079.615 0.50 +1845085.862 0.00 +1845092.849 0.50 +1845096.644 0.00 +1845103.389 0.50 +1845108.412 0.00 +1845129.295 0.50 +1845132.386 1.00 +1845137.136 0.50 +1845139.801 0.00 +1845147.332 0.50 +1845163.365 0.00 +1845168.715 0.50 +1845171.090 1.00 +1845175.087 0.50 +1845177.515 0.00 diff --git a/examples/testbench/good_band/tsv/all (Channel)_util.tsv b/examples/testbench/good_band/tsv/all (Channel)_util.tsv new file mode 100644 index 000000000..e13bb0242 --- /dev/null +++ b/examples/testbench/good_band/tsv/all (Channel)_util.tsv @@ -0,0 +1,4 @@ +time count +0.000 0.00 +1373371.458 1.00 +1387561.869 0.00 diff --git a/examples/testbench/good_band/tsv/all (Python)_util.tsv b/examples/testbench/good_band/tsv/all (Python)_util.tsv new file mode 100644 index 000000000..9d87a3d5a --- /dev/null +++ b/examples/testbench/good_band/tsv/all (Python)_util.tsv @@ -0,0 +1,16 @@ +time count +0.000 0.00 +494356.555 1.00 +1164322.429 0.00 +1164554.852 1.00 +1164686.388 0.00 +1164823.261 1.00 +1207258.637 0.00 +1207422.856 1.00 +1305677.005 0.00 +1307537.619 1.00 +1307553.652 0.00 +1387655.987 1.00 +1805303.104 0.00 +1805398.321 1.00 +1843718.831 0.00 diff --git a/examples/testbench/good_band/tsv/all (System Memory)_util.tsv b/examples/testbench/good_band/tsv/all (System Memory)_util.tsv new file mode 100644 index 000000000..c46245cd8 --- /dev/null +++ b/examples/testbench/good_band/tsv/all (System Memory)_util.tsv @@ -0,0 +1,24 @@ +time count +0.000 0.00 +1278823.735 0.00 +1279061.877 0.01 +1280061.606 0.01 +1280246.078 0.02 +1281367.754 0.02 +1281572.958 0.03 +1282612.241 0.03 +1282784.125 0.04 +1283563.847 0.04 +1283746.860 0.05 +1307133.149 0.06 +1844151.087 0.05 +1844240.657 0.05 +1844651.511 0.04 +1844726.221 0.03 +1844793.065 0.03 +1844857.709 0.02 +1844919.518 0.02 +1844985.437 0.01 +1845081.180 0.01 +1845119.817 0.00 +1845134.718 0.00 diff --git a/examples/testbench/good_band/tsv/all (Utility)_util.tsv b/examples/testbench/good_band/tsv/all (Utility)_util.tsv new file mode 100644 index 000000000..e697ba587 --- /dev/null +++ b/examples/testbench/good_band/tsv/all (Utility)_util.tsv @@ -0,0 +1,992 @@ +time count +0.000 0.00 +493837.510 0.50 +493896.375 0.00 +493931.102 0.50 +493931.677 1.00 +493944.124 0.50 +494029.929 0.00 +494058.742 0.50 +494058.910 1.00 +494064.325 0.50 +494101.567 0.00 +494125.428 0.50 +494130.615 1.00 +494135.463 0.50 +494193.707 0.00 +494208.875 0.50 +494210.784 1.00 +494214.839 0.50 +494348.350 0.00 +494368.000 0.50 +494371.632 0.00 +1164265.110 0.50 +1164304.048 0.00 +1164313.229 0.50 +1164405.071 1.00 +1164407.217 0.50 +1164511.519 0.00 +1164541.448 0.50 +1164549.085 0.00 +1164682.320 0.50 +1164714.593 0.00 +1164725.526 0.50 +1164772.567 0.00 +1164778.390 0.50 +1164819.329 0.00 +1164842.752 0.50 +1164848.390 0.00 +1207271.028 0.50 +1207305.822 1.00 +1207307.344 0.50 +1207337.594 0.00 +1207339.179 0.50 +1207399.159 0.00 +1207424.454 0.50 +1207430.784 0.00 +1257389.335 0.50 +1257422.422 0.00 +1257444.005 0.50 +1257484.492 0.00 +1257499.072 0.50 +1257585.815 0.00 +1257595.549 0.50 +1257609.470 1.00 +1257615.167 0.50 +1257624.283 0.00 +1257640.055 0.50 +1257646.736 0.00 +1277848.542 0.50 +1278028.704 1.00 +1278028.841 0.50 +1278051.446 1.00 +1278056.549 0.50 +1278061.916 0.00 +1278063.442 0.50 +1278109.764 1.00 +1278119.561 0.50 +1278137.033 1.00 +1278141.642 0.50 +1278162.126 0.00 +1278163.934 0.50 +1278180.326 1.00 +1278186.455 0.50 +1278205.113 0.00 +1278209.774 0.50 +1278308.664 0.00 +1278323.593 0.50 +1278426.961 1.00 +1278440.201 0.50 +1278461.160 1.00 +1278505.618 0.50 +1278538.494 1.00 +1278541.424 0.50 +1278559.476 1.00 +1278619.622 0.50 +1278620.037 0.00 +1278638.486 0.50 +1278641.562 1.00 +1278664.513 0.50 +1278680.314 1.00 +1278712.234 0.50 +1278726.859 1.00 +1278745.693 0.50 +1278783.666 1.00 +1278801.586 0.50 +1278818.753 1.00 +1278849.780 0.50 +1278893.781 1.00 +1278918.912 0.50 +1278940.842 1.00 +1278989.270 0.50 +1279017.443 1.00 +1279099.959 0.50 +1279133.630 1.00 +1279160.544 0.50 +1279231.730 1.00 +1279251.865 0.50 +1279320.699 1.00 +1279351.834 0.50 +1279375.598 0.00 +1279389.655 0.50 +1279418.725 1.00 +1279426.309 0.50 +1279467.951 0.00 +1279479.418 0.50 +1279508.879 1.00 +1279536.461 0.50 +1279561.577 1.00 +1279580.044 0.50 +1279591.038 0.00 +1279611.199 0.50 +1279616.772 1.00 +1279651.982 0.50 +1279674.758 1.00 +1279698.571 0.50 +1279718.086 1.00 +1279761.109 0.50 +1279774.382 0.00 +1279777.897 0.50 +1279792.958 1.00 +1279794.261 0.50 +1279823.597 1.00 +1279866.659 0.50 +1279872.496 0.00 +1279883.399 0.50 +1279895.526 1.00 +1279907.765 0.50 +1279921.310 1.00 +1279925.030 0.50 +1279945.362 0.00 +1279947.145 0.50 +1279958.591 1.00 +1279997.784 0.50 +1280008.249 0.00 +1280011.334 0.50 +1280036.518 1.00 +1280057.763 0.50 +1280076.936 1.00 +1280123.017 0.50 +1280137.759 1.00 +1280175.444 0.50 +1280192.631 1.00 +1280237.601 0.50 +1280252.240 1.00 +1280278.040 0.50 +1280290.082 1.00 +1280302.458 0.50 +1280314.319 1.00 +1280319.182 0.50 +1280324.665 1.00 +1280328.013 0.50 +1280332.985 1.00 +1280336.186 0.50 +1280340.596 1.00 +1280345.027 0.50 +1280349.935 1.00 +1280354.507 0.50 +1280360.608 1.00 +1280368.275 0.50 +1280379.031 0.00 +1280397.006 0.50 +1280404.093 0.00 +1280408.793 0.50 +1280412.723 0.00 +1280415.218 0.50 +1280418.215 1.00 +1280422.494 0.50 +1280427.978 1.00 +1280432.194 0.50 +1280436.774 1.00 +1280440.821 0.50 +1280446.196 1.00 +1280450.961 0.50 +1280456.534 1.00 +1280480.415 0.50 +1280500.201 0.00 +1280517.657 0.50 +1280519.467 1.00 +1280590.069 0.50 +1280618.696 1.00 +1280620.373 0.50 +1280640.616 1.00 +1280675.589 0.50 +1280695.112 1.00 +1280704.966 0.50 +1280724.974 1.00 +1280731.408 0.50 +1280750.931 1.00 +1280799.920 0.50 +1280819.690 1.00 +1280845.001 0.50 +1280864.265 1.00 +1280903.705 0.50 +1280923.262 1.00 +1280948.444 0.50 +1280949.533 0.00 +1280969.101 0.50 +1280975.106 1.00 +1281006.901 0.50 +1281020.886 0.00 +1281026.198 0.50 +1281040.746 1.00 +1281082.549 0.50 +1281102.897 1.00 +1281117.395 0.50 +1281128.249 0.00 +1281133.593 0.50 +1281156.030 0.00 +1281168.256 0.50 +1281168.977 1.00 +1281202.632 0.50 +1281216.424 1.00 +1281221.133 0.50 +1281244.468 1.00 +1281263.117 0.50 +1281278.236 1.00 +1281304.887 0.50 +1281307.180 0.00 +1281323.992 0.50 +1281331.290 1.00 +1281352.380 0.50 +1281369.623 1.00 +1281426.948 0.50 +1281441.165 1.00 +1281453.949 0.50 +1281469.680 1.00 +1281491.546 0.50 +1281511.464 1.00 +1281524.905 0.50 +1281540.900 1.00 +1281542.779 0.50 +1281578.718 1.00 +1281646.649 0.50 +1281662.778 1.00 +1281672.107 0.50 +1281687.437 0.00 +1281702.413 0.50 +1281711.894 1.00 +1281728.933 0.50 +1281747.438 1.00 +1281795.038 0.50 +1281819.066 1.00 +1281833.954 0.50 +1281854.322 1.00 +1281914.727 0.50 +1281935.560 1.00 +1281962.837 0.50 +1281968.754 0.00 +1281982.725 0.50 +1281987.215 1.00 +1281997.474 0.50 +1282022.385 1.00 +1282052.736 0.50 +1282073.815 1.00 +1282075.305 0.50 +1282094.433 1.00 +1282135.609 0.50 +1282156.222 0.00 +1282156.494 0.50 +1282176.348 1.00 +1282184.635 0.50 +1282204.439 1.00 +1282213.490 0.50 +1282231.574 0.00 +1282232.852 0.50 +1282247.509 1.00 +1282254.507 0.50 +1282263.334 1.00 +1282265.809 0.50 +1282284.700 1.00 +1282290.552 0.50 +1282298.502 1.00 +1282305.272 0.50 +1282312.818 1.00 +1282321.895 0.50 +1282329.352 1.00 +1282334.523 0.50 +1282342.111 1.00 +1282347.445 0.50 +1282350.095 0.00 +1282355.476 0.50 +1282370.051 1.00 +1282376.626 0.50 +1282383.996 1.00 +1282390.851 0.50 +1282398.511 1.00 +1282404.761 0.50 +1282412.358 1.00 +1282431.565 0.50 +1282451.010 1.00 +1282495.982 0.50 +1282517.522 1.00 +1282537.356 0.50 +1282560.296 1.00 +1282570.883 0.50 +1282589.505 1.00 +1282637.613 0.50 +1282666.567 1.00 +1282670.256 0.50 +1282676.118 1.00 +1282682.844 0.50 +1282687.683 1.00 +1282691.027 0.50 +1282695.682 1.00 +1282699.349 0.50 +1282704.941 1.00 +1282708.191 0.50 +1282712.962 1.00 +1282717.209 0.50 +1282721.947 1.00 +1282725.259 0.50 +1282729.621 1.00 +1282732.909 0.50 +1282738.061 1.00 +1282742.186 0.50 +1282747.803 1.00 +1282880.412 0.50 +1282895.492 1.00 +1282898.743 0.50 +1282903.269 1.00 +1282906.398 0.50 +1282911.963 1.00 +1282915.130 0.50 +1282919.738 1.00 +1282922.982 0.50 +1282928.128 1.00 +1282935.817 0.50 +1282942.383 1.00 +1282942.785 0.50 +1282966.964 0.00 +1282980.146 0.50 +1282986.367 1.00 +1282991.345 0.50 +1282998.561 1.00 +1283003.565 0.50 +1283010.418 1.00 +1283015.397 0.50 +1283022.770 1.00 +1283027.895 0.50 +1283034.875 1.00 +1283040.014 0.50 +1283046.978 1.00 +1283052.050 0.50 +1283059.186 1.00 +1283065.631 0.50 +1283073.383 1.00 +1283076.987 0.50 +1283098.801 1.00 +1283110.127 0.50 +1283130.304 1.00 +1283130.494 0.50 +1283150.656 1.00 +1283156.284 0.50 +1283163.621 0.00 +1283164.014 0.50 +1283182.622 1.00 +1283188.104 0.50 +1283195.694 1.00 +1283204.944 0.50 +1283211.677 1.00 +1283220.390 0.50 +1283227.561 1.00 +1283232.886 0.50 +1283239.761 1.00 +1283244.909 0.50 +1283251.950 0.00 +1283252.211 0.50 +1283272.054 1.00 +1283278.592 0.50 +1283285.846 1.00 +1283291.196 0.50 +1283298.174 1.00 +1283303.562 0.50 +1283311.221 1.00 +1283324.969 0.50 +1283344.437 1.00 +1283395.670 0.50 +1283414.744 1.00 +1283430.716 0.50 +1283450.278 1.00 +1283480.049 0.50 +1283500.017 1.00 +1283500.409 0.50 +1283519.252 1.00 +1283537.974 0.50 +1283621.832 1.00 +1283626.988 0.50 +1283634.116 1.00 +1283639.765 0.50 +1283647.210 1.00 +1283652.142 0.50 +1283658.525 1.00 +1283663.327 0.50 +1283669.788 1.00 +1283674.776 0.50 +1283681.015 1.00 +1283687.272 0.50 +1283695.521 1.00 +1283891.905 0.50 +1283930.408 1.00 +1283931.392 0.50 +1283956.807 1.00 +1283991.577 0.50 +1283996.266 0.00 +1284006.864 0.50 +1284019.731 1.00 +1284026.542 0.50 +1284031.957 0.00 +1284037.065 0.50 +1284043.643 0.00 +1284046.066 0.50 +1284050.070 0.00 +1284052.387 0.50 +1284055.707 1.00 +1284059.289 0.50 +1284060.505 0.00 +1284067.513 0.50 +1284070.087 1.00 +1284074.595 0.50 +1284076.801 0.00 +1284080.228 0.50 +1284085.420 1.00 +1284086.541 0.50 +1284091.929 0.00 +1284092.440 0.50 +1284096.296 0.00 +1284100.863 0.50 +1284101.982 1.00 +1284106.383 0.50 +1284107.585 0.00 +1284111.488 0.50 +1284115.765 0.00 +1284116.830 0.50 +1284121.233 1.00 +1284123.552 0.50 +1284125.707 0.00 +1284131.344 0.50 +1284132.489 1.00 +1284135.349 0.50 +1284139.516 0.00 +1284140.596 0.50 +1284144.671 0.00 +1284148.163 0.50 +1284149.723 1.00 +1284154.638 0.50 +1284156.310 0.00 +1284161.552 0.50 +1284163.452 1.00 +1284167.611 0.50 +1284172.102 1.00 +1284175.585 0.50 +1284177.046 0.00 +1284182.497 0.50 +1284189.542 0.00 +1290561.994 0.50 +1290575.892 1.00 +1290581.206 0.50 +1290645.947 0.00 +1290672.470 0.50 +1290682.613 0.00 +1290706.341 0.50 +1290712.299 0.00 +1290721.686 0.50 +1290776.945 1.00 +1290793.748 0.50 +1290814.031 1.00 +1290821.356 0.50 +1290821.681 0.00 +1290851.820 0.50 +1290857.268 0.00 +1301189.824 0.50 +1301196.603 0.00 +1301211.605 0.50 +1301251.876 0.00 +1301276.326 0.50 +1301282.541 0.00 +1301544.868 0.50 +1301552.926 0.00 +1301559.661 0.50 +1301606.151 1.00 +1301629.806 0.50 +1301641.799 0.00 +1301646.722 0.50 +1301651.116 0.00 +1301693.731 0.50 +1301697.364 0.00 +1303168.646 0.50 +1303281.263 1.00 +1303283.977 0.50 +1303305.777 1.00 +1303312.883 0.50 +1303320.693 0.00 +1303321.376 0.50 +1303344.045 1.00 +1303349.993 0.50 +1303396.088 0.00 +1303396.962 0.50 +1303414.273 1.00 +1303418.400 0.50 +1303482.714 0.00 +1303483.722 0.50 +1303497.656 1.00 +1303502.117 0.50 +1303545.046 1.00 +1303558.517 0.50 +1303573.877 1.00 +1303624.181 0.50 +1303642.161 0.00 +1303670.965 0.50 +1303671.094 1.00 +1303704.125 0.50 +1303718.836 0.00 +1303732.487 0.50 +1303745.784 1.00 +1303770.128 0.50 +1303786.168 1.00 +1303805.810 0.50 +1303811.406 0.00 +1303820.840 0.50 +1303844.177 0.00 +1303845.931 0.50 +1303856.281 1.00 +1303879.903 0.50 +1303908.169 0.00 +1303909.035 0.50 +1303922.034 1.00 +1303925.681 0.50 +1303931.496 1.00 +1303935.527 0.50 +1303940.923 1.00 +1303944.758 0.50 +1303950.746 1.00 +1303965.082 0.50 +1303983.695 1.00 +1303988.852 0.50 +1303996.469 1.00 +1304002.083 0.50 +1304010.979 1.00 +1304016.012 0.50 +1304034.134 1.00 +1304053.638 0.50 +1304057.203 0.00 +1304070.131 0.50 +1304076.332 1.00 +1304082.034 0.50 +1304089.969 1.00 +1304095.865 0.50 +1304099.441 0.00 +1304104.636 0.50 +1304120.480 1.00 +1304128.900 0.50 +1304137.321 1.00 +1304143.536 0.50 +1304151.481 1.00 +1304158.130 0.50 +1304166.492 1.00 +1304172.116 0.50 +1304179.541 1.00 +1304185.478 0.50 +1304194.596 1.00 +1304201.779 0.50 +1304225.353 1.00 +1304268.486 0.50 +1304287.341 1.00 +1304297.327 0.50 +1304317.260 1.00 +1304378.464 0.50 +1304388.941 0.00 +1304398.660 0.50 +1304402.496 1.00 +1304436.193 0.50 +1304450.099 1.00 +1304450.999 0.50 +1304470.099 1.00 +1304504.123 0.50 +1304516.057 1.00 +1304538.039 0.50 +1304551.018 1.00 +1304564.826 0.50 +1304575.121 0.00 +1304586.431 0.50 +1304587.656 1.00 +1304609.345 0.50 +1304619.350 0.00 +1304622.305 0.50 +1304637.141 1.00 +1304643.365 0.50 +1304651.780 1.00 +1304658.683 0.50 +1304666.550 1.00 +1304672.388 0.50 +1304680.459 1.00 +1304688.024 0.50 +1304690.689 0.00 +1304698.019 0.50 +1304706.331 1.00 +1304723.689 0.50 +1304762.829 1.00 +1304772.128 0.50 +1304783.673 0.00 +1304792.515 0.50 +1304816.987 1.00 +1304856.819 0.50 +1304888.752 0.00 +1304897.074 0.50 +1304903.629 1.00 +1304949.175 0.50 +1304964.588 1.00 +1305012.316 0.50 +1305034.947 1.00 +1305056.498 0.50 +1305071.433 0.00 +1305078.479 0.50 +1305086.886 1.00 +1305111.303 0.50 +1305123.950 1.00 +1305127.879 0.50 +1305132.242 1.00 +1305135.716 0.50 +1305140.603 1.00 +1305144.069 0.50 +1305148.825 1.00 +1305152.880 0.50 +1305158.699 1.00 +1305162.057 0.50 +1305168.106 1.00 +1305176.877 0.50 +1305192.136 0.00 +1305199.516 0.50 +1305206.007 1.00 +1305232.334 0.50 +1305234.115 0.00 +1305245.411 0.50 +1305252.611 1.00 +1305308.677 0.50 +1305319.714 0.00 +1305327.160 0.50 +1305339.765 1.00 +1305345.502 0.50 +1305353.891 1.00 +1305360.727 0.50 +1305370.367 1.00 +1305382.614 0.50 +1305404.041 1.00 +1305480.738 0.50 +1305504.378 1.00 +1305514.951 0.50 +1305536.821 1.00 +1305567.074 0.50 +1305594.413 1.00 +1305610.959 0.50 +1305631.496 1.00 +1305686.197 0.50 +1305712.259 1.00 +1305727.618 0.50 +1305742.024 1.00 +1305770.369 0.50 +1305783.995 1.00 +1305807.428 0.50 +1305813.329 0.00 +1305832.088 0.50 +1305888.240 1.00 +1305893.515 0.50 +1305920.984 1.00 +1305922.460 0.50 +1305952.530 1.00 +1305961.048 0.50 +1305972.370 1.00 +1305975.704 0.50 +1305994.539 1.00 +1306000.231 0.50 +1306007.662 1.00 +1306012.745 0.50 +1306018.660 1.00 +1306024.251 0.50 +1306031.062 1.00 +1306036.169 0.50 +1306042.053 1.00 +1306046.201 0.50 +1306051.923 1.00 +1306055.204 0.50 +1306061.397 1.00 +1306068.757 0.50 +1306077.209 1.00 +1306082.911 0.50 +1306089.960 1.00 +1306095.305 0.50 +1306102.116 1.00 +1306106.899 0.50 +1306113.792 1.00 +1306118.325 0.50 +1306125.177 1.00 +1306129.472 0.50 +1306135.484 1.00 +1306139.885 0.50 +1306146.163 1.00 +1306151.014 0.50 +1306157.922 1.00 +1306162.843 0.50 +1306169.196 1.00 +1306173.805 0.50 +1306180.863 1.00 +1306186.221 0.50 +1306192.428 1.00 +1306198.940 0.50 +1306207.747 1.00 +1306213.896 0.50 +1306224.076 1.00 +1306224.570 0.50 +1306244.535 1.00 +1306251.719 0.50 +1306258.625 1.00 +1306262.340 0.50 +1306266.639 1.00 +1306269.915 0.50 +1306274.647 1.00 +1306278.288 0.50 +1306284.148 1.00 +1306288.891 0.50 +1306295.085 1.00 +1306316.875 0.50 +1306337.294 1.00 +1306373.980 0.50 +1306390.469 1.00 +1306410.407 0.50 +1306431.241 0.00 +1306438.072 0.50 +1306444.023 1.00 +1306475.533 0.50 +1306487.743 1.00 +1306501.791 0.50 +1306520.623 1.00 +1306546.595 0.50 +1306556.205 0.00 +1306561.231 0.50 +1306570.551 1.00 +1306596.581 0.50 +1306597.755 0.00 +1306609.046 0.50 +1306616.486 1.00 +1306620.257 0.50 +1306625.100 1.00 +1306628.442 0.50 +1306633.053 1.00 +1306638.535 0.50 +1306643.545 1.00 +1306647.468 0.50 +1306651.973 1.00 +1306655.289 0.50 +1306659.951 1.00 +1306663.338 0.50 +1306667.811 1.00 +1306671.169 0.50 +1306676.051 1.00 +1306680.523 0.50 +1306685.372 1.00 +1306688.634 0.50 +1306692.987 1.00 +1306696.272 0.50 +1306701.710 1.00 +1306706.054 0.50 +1306710.872 1.00 +1306714.195 0.50 +1306719.516 1.00 +1306723.164 0.50 +1306727.419 1.00 +1306730.709 0.50 +1306739.454 1.00 +1306745.991 0.50 +1306751.542 1.00 +1306756.065 0.50 +1306756.354 0.00 +1306761.979 0.50 +1306766.736 0.00 +1306773.560 0.50 +1306776.655 1.00 +1306781.569 0.50 +1306790.612 0.00 +1306792.355 0.50 +1306802.720 1.00 +1306806.557 0.50 +1306811.402 0.00 +1306869.300 0.50 +1306875.443 0.00 +1306886.823 0.50 +1306898.727 0.00 +1306924.051 0.50 +1306929.726 0.00 +1306948.288 0.50 +1306999.684 1.00 +1307020.185 0.50 +1307038.067 0.00 +1307056.365 0.50 +1307059.257 1.00 +1307084.938 0.50 +1307095.699 1.00 +1307099.265 0.50 +1307154.918 1.00 +1307163.906 0.50 +1307269.010 1.00 +1307275.994 0.50 +1307300.490 1.00 +1307307.680 0.50 +1307478.161 0.00 +1307484.883 0.50 +1307497.332 1.00 +1307515.476 0.50 +1307531.573 1.00 +1307536.897 0.50 +1307545.301 1.00 +1307547.707 0.50 +1307551.859 0.00 +1307575.711 0.50 +1307583.147 0.00 +1313028.908 0.50 +1313043.492 0.00 +1313044.487 0.50 +1313088.907 0.00 +1313107.910 0.50 +1313112.001 0.00 +1313377.313 0.50 +1313383.481 0.00 +1313415.699 0.50 +1313465.770 0.00 +1313482.463 0.50 +1313486.229 0.00 +1316552.854 0.50 +1316569.677 0.00 +1316583.573 0.50 +1316625.438 0.00 +1316644.297 0.50 +1316648.163 0.00 +1316874.269 0.50 +1316881.752 0.00 +1316912.943 0.50 +1316958.130 0.00 +1316974.511 0.50 +1316978.142 0.00 +1319995.186 0.50 +1320025.818 0.00 +1320040.609 0.50 +1320044.432 0.00 +1320214.501 0.50 +1320214.870 1.00 +1320221.281 0.50 +1320270.219 0.00 +1320297.734 0.50 +1320303.704 0.00 +1333333.783 0.50 +1333386.811 0.00 +1333412.514 0.50 +1333412.634 1.00 +1333418.805 0.50 +1333418.933 0.00 +1333430.989 0.50 +1333469.596 0.00 +1333486.409 0.50 +1333490.897 0.00 +1346545.220 0.50 +1346551.558 1.00 +1346557.434 0.50 +1346606.273 0.00 +1346633.938 0.50 +1346640.148 0.00 +1347130.799 0.50 +1347181.604 0.00 +1347201.196 0.50 +1347205.096 0.00 +1353197.202 0.50 +1353243.345 0.00 +1353265.362 0.50 +1353269.535 0.00 +1353631.730 0.50 +1353696.535 0.00 +1353696.939 0.50 +1353712.876 1.00 +1353716.802 0.50 +1353730.416 0.00 +1353754.700 0.50 +1353758.956 0.00 +1358452.236 0.50 +1358458.994 0.00 +1358473.590 0.50 +1358523.159 0.00 +1358542.082 0.50 +1358545.952 0.00 +1358967.387 0.50 +1359027.712 0.00 +1359051.943 0.50 +1359070.658 0.00 +1363809.927 0.50 +1363860.938 0.00 +1363885.600 0.50 +1363890.292 0.00 +1364374.287 0.50 +1364433.513 0.00 +1364452.289 0.50 +1364456.250 0.00 +1368751.598 0.50 +1368796.172 0.00 +1368816.259 0.50 +1368820.470 0.00 +1369233.364 0.50 +1369285.700 0.00 +1369303.293 0.50 +1369306.996 0.00 +1373388.953 0.50 +1373389.096 1.00 +1373396.919 0.50 +1373442.745 0.00 +1373498.990 0.50 +1373505.271 0.00 +1373792.113 0.50 +1373798.465 0.00 +1373807.331 0.50 +1373852.739 0.00 +1373877.596 0.50 +1373884.279 0.00 +1373892.118 0.50 +1373914.139 0.00 +1373935.631 0.50 +1373948.425 0.00 +1387284.123 0.50 +1387301.770 0.00 +1387620.271 0.50 +1387635.470 0.00 +1804975.977 0.50 +1805012.283 0.00 +1805063.076 0.50 +1805068.493 0.00 +1805259.310 0.50 +1805292.870 0.00 +1805312.310 0.50 +1805350.358 1.00 +1805350.562 0.50 +1805386.009 0.00 +1805425.680 0.50 +1805431.066 0.00 +1843677.054 0.50 +1843737.041 1.00 +1843768.695 0.50 +1843815.161 0.00 +1843827.225 0.50 +1843860.017 1.00 +1843861.862 0.50 +1843891.732 1.00 +1843907.874 0.50 +1843922.152 0.00 +1843936.415 0.50 +1843992.420 1.00 +1844012.594 0.50 +1844033.640 1.00 +1844072.396 0.50 +1844093.056 1.00 +1844104.457 0.50 +1844126.888 1.00 +1844192.738 0.50 +1844231.819 1.00 +1844276.782 0.50 +1844639.970 1.00 +1844690.377 0.50 +1844718.199 1.00 +1844750.254 0.50 +1844782.026 1.00 +1844822.422 0.50 +1844849.633 1.00 +1844884.140 0.50 +1844910.803 1.00 +1844942.276 0.50 +1844947.737 0.00 +1844965.071 0.50 +1844970.793 1.00 +1845017.478 0.50 +1845051.566 0.00 +1845052.547 0.50 +1845069.252 1.00 +1845086.468 0.50 +1845104.383 0.00 +1845110.994 0.50 +1845126.065 1.00 +1845146.179 0.50 +1845155.068 0.00 diff --git a/examples/testbench/legion_prof/dataflow_legion_python_main_1.pdf b/examples/testbench/legion_prof/dataflow_legion_python_main_1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..49ba1be92373ebda1448adea7f5931c32ec07b29 GIT binary patch literal 33085 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 WjUAoOEdm1N<>w=0Vv<&oA^bnr2%($+ literal 0 HcmV?d00001 diff --git a/examples/testbench/legion_prof/index.html b/examples/testbench/legion_prof/index.html new file mode 100644 index 000000000..2f9a68d06 --- /dev/null +++ b/examples/testbench/legion_prof/index.html @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + +
+
Node Range: :
+
+ + +
+
+
+
+
+
+ + diff --git a/examples/testbench/legion_prof/js/timeline.js b/examples/testbench/legion_prof/js/timeline.js new file mode 100644 index 000000000..ba3db5e30 --- /dev/null +++ b/examples/testbench/legion_prof/js/timeline.js @@ -0,0 +1,2734 @@ +// Some of the constants are read in from load_scale_json +var constants = { + margin_left: 350, + margin_right: 75, + margin_bottom: 50, + margin_top: 50, + min_feature_width: 3, + min_gap_width: 1, + util_height: 100, + util_levels: 4, + elem_separation: 2, +} + +var op_dependencies = {}; +var base_map = {}; +var prof_uid_map = {}; + +// Contains the children for each util file +var util_files = {}; + +var state = {}; +var mouseX = 0; +var utilline = d3.svg.line() + .interpolate("step-after") + .x(function(d) { return state.x(+d.time); }) + .y(function(d) { return state.y(+d.count); }); +var timeBisector = d3.bisector(function(d) { return d.time; }).left; +// const num_colors = 20; +// var color = d3.scale.linear() +// .domain([0, num_colors]) +// .range(["green", "blue", "red", "yellow"]); + +String.prototype.hashCode = function() { + var hash = 0; + if (this.length == 0) return hash; + for (i = 0; i < this.length; i++) { + var c = this.charCodeAt(i); + var b = this.charCodeAt(c % this.length); + hash = ((hash<<5)-hash)^c^b; + hash = hash & hash; + } + return Math.abs(hash); +} + +function parseURLParameters() { + var match, + pl = /\+/g, // Regex for replacing addition symbol with a space + search = /([^&=]+)=?([^&]*)/g, + decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, + query = window.location.search.substring(1); + + var urlParams = {}; + while (match = search.exec(query)) + urlParams[decode(match[1])] = decode(match[2]); + + if ("collapseAll" in urlParams) + state.collapseAll = (urlParams["collapseAll"].toLowerCase() === "true"); + + if ("resolution" in urlParams) + state.resolution = Math.max(1, parseFloat(urlParams["resolution"])); + // adjust zoom + var zstart = constants.start; + if ("start" in urlParams) + zstart = Math.max(constants.start, parseFloat(urlParams["start"])); + + var zend = constants.end; + if ("end" in urlParams) + zend = Math.min(constants.end, parseFloat(urlParams["end"])); + + if(zstart < zend) { + // set zoom to get: (zend - start) * zoom * scale = $("#timeline").width() + var newZoom = $("#timeline").width() / state.scale / (zend - zstart); + adjustZoom(newZoom, false); + + // set scrollLeft to get: zstart * zoom * state.scale = scrollLeft() + $("#timeline").scrollLeft(convertToPos(state, zstart)); + } + + if ("search" in urlParams) { + state.searchEnabled = true; + searchRegex = new Array(sizeHistory); + currentPos = 0; + nextPos = 1; + searchRegex[currentPos] = new RegExp(urlParams["search"]); + } +} + +function makeTimelineTransparent() { + state.timelineSvg.select("g#timeline").style("opacity", "0.1"); + $("#timeline").css("overflow-x", "hidden"); + state.timelineSvg.select("g#lines").style("opacity", "0.1"); + state.timelineSvg.select("g.locator").style("opacity", "0.1"); + state.timelineSvg.selectAll("path.util").style("opacity", "0.1"); +} + +function makeTimelineOpaque() { + state.timelineSvg.select("g#timeline").style("opacity", "1.0"); + $("#timeline").css("overflow-x", "scroll"); + state.timelineSvg.select("g#lines").style("opacity", "1.0"); + state.timelineSvg.select("g.locator").style("opacity", "1.0"); + state.timelineSvg.selectAll("path.util").style("opacity", "1.0"); +} + +function mouseMoveHandlerWhenDown() { + var p = d3.mouse(this); + var select_block = state.timelineSvg.select("rect.select-block"); + var select_text = state.timelineSvg.select("text.select-block"); + var newWidth = Math.abs(p[0] - mouseX); + select_block.attr("width", newWidth); + if (p[0] >= mouseX) { + select_block.attr("x", mouseX); + select_text.attr("x", mouseX + (p[0] - mouseX) / 2); + } else { + select_block.attr("x", p[0]); + select_text.attr("x", p[0] + (mouseX - p[0]) / 2); + } + var time = convertToTime(state, newWidth); + select_text.text(getTimeString(time, time)); +} + +function mouseMoveHandlerWhenUp() { + var p = d3.mouse(this); + var x = parseFloat(p[0]); + var scrollLeft = $("#timeline").scrollLeft(); + var paneWidth = $("#timeline").width(); + var currentTime = convertToTime(state, x); + + state.timelineSvg.select("g.locator").remove(); + var locator = state.timelineSvg.append("g").attr("class", "locator"); + locator.insert("line") + .attr({ + x1: p[0], + y1: 0, + x2: p[0], + y2: p[1] - state.thickness / 2, + class: "locator", + }); + locator.append("line") + .attr({ + x1: p[0], + y1: p[1] + state.thickness / 2, + x2: p[0], + y2: state.height, + class: "locator", + }); + var locatorText = locator.append("text"); + var text = getTimeString(currentTime, convertToTime(state, paneWidth)); + locatorText.attr("class", "locator").text(text) + if ((x - scrollLeft) < paneWidth - 100) { + locatorText.attr({x: x + 2, y: $(window).scrollTop() + 10}); + locatorText.attr("anchor", "start"); + } + else { + locatorText.attr({x: x - 2 - text.length * 7, y: $(window).scrollTop() + 10}); + locatorText.attr("anchor", "end"); + } +} + +function mouseDownHandler() { + state.timelineSvg.select("g.locator").remove(); + var p = d3.mouse(this); + state.timelineSvg.append("rect") + .attr({ + x : p[0], + y : 0, + class : "select-block", + width : 0, + height : state.height + }); + state.timelineSvg.append("text") + .attr({ + x : p[0], + y : p[1], + class : "select-block", + anchor : "middle", + "text-anchor" : "middle", + }).text("0 us"); + mouseX = p[0]; + state.timelineSvg.on("mousemove", null); + state.timelineSvg.on("mousemove", mouseMoveHandlerWhenDown); + $(document).off("keydown"); +} + +function get_kind(name) { + var util_regex = /\((.*?)\)/; + var kind_match = util_regex.exec(name); + if (kind_match) { + return kind_match[1]; + } +} + +function getLineColor(elem) { + var kind = get_kind(elem.text); + const colorMap = { + "CPU": "steelblue", + "GPU": "olivedrab", + "Utility": "crimson", + "IO": "orangered", + "Proc Group": "orangered", + "Proc Set": "orangered", + "OpenMP": "orangered", + "Python": "olivedrab", + "System Memory": "olivedrab", + "GASNet Global Memory": "crimson", + "Registered Memory": "darkmagenta", + "Socket Memory": "orangered", + "Zero-Copy Memory": "crimson", + "Framebuffer Memory": "blue", + "Disk Memory": "darkgoldenrod", + "HDF5 Memory": "olivedrab", + "File Memory": "orangered", + "L3 Cache Memory": "crimson", + "L2 Cache Memory": "darkmagenta", + "L1 Cache Memory": "olivedrab", + "Channel": "orangered" + }; + return colorMap[kind]; +} + +function drawUtil() { + // TODO: Add to state + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + var start_time = convertToTime(state, windowStart); + var end_time = convertToTime(state, windowEnd); + var filteredUtilData = []; + for (var i = 0; i < state.flattenedLayoutData.length; i++) { + var elem = state.flattenedLayoutData[i]; + if (elem.type == "util" && elem.enabled && elem.loaded && elem.visible) { + filteredUtilData.push(filterUtilData(elem)); + } + } + + state.x = d3.scale.linear().range([0, convertToPos(state, end_time)]); + state.x.domain([0, end_time]); + state.timelineSvg.selectAll("rect.util").remove(); + state.timelineSvg.selectAll("path.util").remove(); + var paths = state.timelineSvg.selectAll("path") + .data(filteredUtilData); + var totalWidth = windowStart + $("#timeline").width(); + paths.enter().append("rect") + .attr("class", "util") + .attr("base_y", lineLevelCalculator) + .attr("y", lineLevelCalculator) + .attr("x", 0) + .attr("fill", "transparent") + .attr("width", totalWidth) + .attr("height", constants.util_levels * state.thickness) + .on("mouseover", mouseover) + .on("mousemove", mousemove) + .on("mouseout", function() { + state.timelineSvg.select("g.focus").remove(); + state.timelineSvg.select("g.utilDesc").remove(); + }); + paths.enter().append("path") + .attr("base_y", lineLevelCalculator) + .attr("class", "util") + .attr("id", function(d, i) { return "util" + i}) + .attr("d", function (d) { return utilline(d.data); }) + .attr("stroke", getLineColor) + .on("mouseover", mouseover) + .on("mousemove", mousemove) + .on("mouseout", function() { + state.timelineSvg.select("g.focus").remove(); + state.timelineSvg.select("g.utilDesc").remove(); + }) + .attr("transform", + function(d) { + var y = lineLevelCalculator(d); + return "translate(0," + y + ")" + }); +} + + +function mouseUpHandler() { + var p = d3.mouse(this); + var select_block = state.timelineSvg.select("rect.select-block"); + var prevZoom = state.zoom; + var selectWidth = parseInt(select_block.attr("width")); + var svgWidth = state.timelineSvg.attr("width"); + if (state.rangeZoom && selectWidth > 10) { + var x = select_block.attr("x"); + state.zoomHistory.push({zoom: prevZoom, start: $("#timeline").scrollLeft()}); + adjustZoom(svgWidth / selectWidth, false); + $("#timeline").scrollLeft(x / prevZoom * state.zoom); + } + + state.timelineSvg.selectAll("rect.select-block").remove(); + state.timelineSvg.selectAll("text.select-block").remove(); + mouseX = 0; + state.timelineSvg.on("mousemove", null); + state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); + $(document).on("keydown", defaultKeydown); +} + +function turnOffMouseHandlers() { + state.timelineSvg.on("mousedown", null); + state.timelineSvg.on("mouseup", null); + state.timelineSvg.on("mousemove", null); + state.timelineSvg.on("mousemove", null); + // prevent right-click menu + state.timelineSvg.on("contextmenu", function () { + d3.event.preventDefault(); + }); +} + +function turnOnMouseHandlers() { + state.timelineSvg.on("mousedown", mouseDownHandler); + state.timelineSvg.on("mouseup", mouseUpHandler); + state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); + // prevent right-click menu + state.timelineSvg.on("contextmenu", function () { + d3.event.preventDefault(); + }); +} + +function drawLoaderIcon() { + var loaderGroup = state.loaderSvg.append("g") + .attr({ + id: "loader-icon", + }); + loaderGroup.append("path") + .attr({ + opacity: 0.2, + stroke: "steelblue", + fill: "#000", + d: "M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z" + }); + var path = loaderGroup.append("path") + .attr({ + stroke: "steelblue", + fill: "#000", + d: "M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0C22.32,8.481,24.301,9.057,26.013,10.047z" + }); + path.append("animateTransform") + .attr({ + attributeType: "xml", + attributeName: "transform", + type: "rotate", + from: "0 20 20", + to: "360 20 20", + dur: "0.5s", + repeatCount: "indefinite" + }); + state.loaderSvg.select("g").attr("visibility", "hidden"); + state.loaderSvg.attr("width", "0px") + .attr("height", "0px"); +} + +function showLoaderIcon() { + state.numLoading++; + state.loaderSvg.select("g").attr("visibility", "visible"); + state.loaderSvg.attr("width", "40px") + .attr("height", "40px"); +} + +function hideLoaderIcon() { + state.numLoading--; + if (state.numLoading == 0) { + state.loaderSvg.select("g").attr("visibility", "hidden"); + state.loaderSvg.attr("width", "0px") + .attr("height", "0px"); +; + } +} + +function get_time_str(time_val, convert) +{ + if (convert) { + if (time_val >= 1000000) { + var val = time_val/1000000; + val = parseFloat(val.toFixed(3)) + return val.toString() + " sec"; + } + if (time_val >= 1000) { + var val = time_val/1000; + val = parseFloat(val.toFixed(3)) + return val.toString() + " ms"; + } + } + return time_val.toString() + " us"; +} + +function getMouseOver() { + var paneWidth = $("#timeline").width(); + var left = paneWidth / 3; + var right = paneWidth * 2 / 3; + return function(d, i) { + var p = d3.mouse(this); + var x = parseFloat(p[0]); + var y = timelineLevelCalculator(d) - 5; + var descView = state.timelineSvg.append("g") + .attr("id", "desc"); + var text = descView.append("text") + .attr("x", x) + .attr("y", y) + .attr("class", "desc"); + var depElem = prof_uid_map[d.prof_uid][0]; + if ((depElem.in.length != 0) || (depElem.out.length != 0) || + (depElem.children.length !== 0) || (depElem.parents.length !==0 )) { + d3.select(this).style("cursor", "pointer"); + } + // descTexts is an array of Texts we will store in the desc view + var descTexts = []; + var total = d.end - d.start; + var delay = d.start - d.ready; + total = parseFloat(total.toFixed(3)) + delay = parseFloat(delay.toFixed(3)) + var initiation = ""; + // Insert texts in reverse order + if ((d.ready != undefined) && (d.ready != "") && (delay != 0)) { + descTexts.push("Ready State: " + get_time_str(delay,false)); + } + descTexts.push("End: " + get_time_str(d.end, false)); + descTexts.push("Start: " + get_time_str(d.start, false)); + descTexts.push("Total: " + get_time_str(total, true)); + if ((d.initiation != undefined) && d.initiation != "") { + descTexts.push("Initiator: " + state.operations[d.initiation].desc); + } + + // split d.title + var titles = d.title.split("$"); + if (titles.length > 0) { + for (var i = titles.length-1; i >= 0; --i) { + descTexts.push(titles[i]); + } + } + var title = text.append("tspan") + .attr("x", x) + .attr("dy", -12) + .attr("class", "desc") + .text(descTexts[0].replace(/ /g, "\u00A0")); // preserve spacing + + for (var i = 1; i < descTexts.length; ++i) { + var elem = text.append("tspan") + .attr("x", x) + .attr("dy", -12) + .attr("class", "desc") + .text(descTexts[i].replace(/ /g, "\u00A0")); // preserve spacing + } + + var bbox = descView.node().getBBox(); + var padding = 2; + var rect = descView.insert("rect", "text") + .attr("x", bbox.x - 2*padding) + .attr("y", bbox.y - padding) + .attr("width", bbox.width + (padding*4)) + .attr("height", bbox.height + (padding*2)) + .style("fill", "#222") + .style("opacity", "0.7"); + + var bboxRight = bbox.x + bbox.width; + var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); + + // If the box moves off the screen, nudge it back + if (bboxRight > timelineRight) { + var translation = -(bboxRight - timelineRight + 20); + descView.attr("transform", "translate(" + translation + ",0)"); + } + }; +} + +var sizeHistory = 10; +var currentPos; +var nextPos; +var searchRegex = null; + +function showSlider() { + $('#lowerLimit').text($('#node_slider').slider("values", 0)); + $('#upperLimit').text($('#node_slider').slider("values", 1)); +} + +function createMenuList1() { + var memory_kinds = []; + var num_nodes = state.num_nodes; + var num_mems = 0; + var dropdown_options = [ + { value: "ready", + id: "ready_all", + text: "View", + count: 1, + low_range: 0, + high_range: 1 + }, + { value: "memories", + id: "memories_all", + text: "Memories", + count: num_mems, + low_range: 0, + high_range: num_mems -1 + } + ]; + + // memories list + dropdown_options_memories = []; + + // misc items list + var pkind = { + id: "rr", + value: "rdy", + count: 1, + low_range: 0, + high_range: 1, + text: "Ready State" + }; + + dropdown_options_misc = []; + dropdown_options_misc.push(pkind); + + // create the remaining entries + function appendKind(elem) { + var value = state.processor_kinds[elem]; + if (elem.includes("Memory") && (value.count >= 0)) + { + num_mems = num_mems+1; + dropdown_options_memories.push(value); + } + if ((value.count >= 0) && (value.low_range != -1)) { + dropdown_options.push(value); + } + } + Object.keys(state.processor_kinds).forEach(appendKind); + + // main menu + d3.select("#dropdown").selectAll("optgroup") + .data(dropdown_options) + .enter() + .append("optgroup") + .attr('label', function(d) { return d.text;}) + .attr("id", function(d) { return d.id;}) + .attr("value", function(d) { return d.value;}); + + for (var j=0; j val)) + kind_proc.low_range = val; + if (kind_proc.high_range < val) + kind_proc.high_range = val; + } + } + } + + // Util graphs will have processors as their children as well. + if (type == "util") { + // get the children for the util view + var proc_children = getProcessors(text); + var count = 1; + var node_id = get_node_id(text); + var kind = get_kind(text); + // add to processor kinds: union of all processor kinds + if (!(kind in state.processor_kinds)) { + var pkind = { + id: kind, + value: kind, + count: proc_children.length, + low_range: -1, + high_range: -1, + text: kind + }; + state.processor_kinds[kind] = pkind; + } + if (state.processor_kinds[kind].count < proc_children.length) + state.processor_kinds[kind].count = proc_children.length; + + proc_children.forEach(function(proc_child) { + var child_element = getElement(depth + 1, proc_child.text, + proc_child.full_text, "proc", + proc_child.height, load_proc_timeline, + proc_child.tsv, element, undefined, + true, false); + element.children.push(child_element); + }); + } + + return element; +} + + +function calculateLayout() { + + // First element in the layout will be the all_util. All first-level + // elements will start off not enabled, and will be uncollapsed later + // programmatically + var num_nodes = Object.keys(util_files).length; + if (num_nodes > 1) { + var proc_kinds = util_files["all"]; + proc_kinds.forEach(function(name) { + var kind = "(" + get_kind(name) + ")"; + var util_name = "all nodes " + kind; + var kind_element = getElement(0, util_name, undefined, "util", + constants.util_levels, load_util, + "tsv/" + name + "_util.tsv", + undefined, util_files[kind], false, true); + state.layoutData.push(kind_element); + }); + } + + var seen_nodes = []; + state.processors.forEach(function(proc) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + var proc_regex = /(Processor|Memory) 0x1(e|d)([a-fA-f0-9]{4})[a-fA-f0-9]{10}$/; + // Memory Channel + var proc_channel_regex = /(Memory) 0x1(e)([a-fA-f0-9]{4})[a-fA-f0-9]{10}.*Channel/; + var proc_channel_match = proc_channel_regex.exec(proc.full_text); + var proc_match = proc_regex.exec(proc.full_text); + proc_match = proc_match || proc_channel_match; + if (proc_match) { + var node_id = parseInt(proc_match[3], 16); + if (!(node_id in seen_nodes)) { + seen_nodes[node_id] = 1; + if (node_id in util_files) { + var proc_kinds = util_files[node_id]; + proc_kinds.forEach(function(kind) { + var util_name = "node " + kind; + var kind_element = getElement(0, util_name, undefined, "util", + constants.util_levels, load_util, + "tsv/" + kind + "_util.tsv", + undefined, util_files[kind], + false, true); + state.layoutData.push(kind_element); + }); + } + } + } + else { + state.layoutData.push(getElement(0, proc.text, proc.full_text, "proc", + proc.height, load_proc_timeline, + proc.tsv, undefined, undefined, + false, true)); + } + }); + state.num_nodes = seen_nodes.length; +} + +function getElemCoords(elems) { + var proc = elems[0].proc; + var level = elems[0].level; + var startX = convertToPos(state, elems[0].start); + var endX = convertToPos(state, elems[elems.length-1].end); + var endBase = +proc.base; + var endLevel = endBase + level; + var y = dependencyLineLevelCalculator(endLevel); + return {startX: startX, endX: endX, y: y}; +} + + +function addLine(group, x1, x2, y1, y2, color, dashed) { + var line; + if (dashed) { + line = group.append("line") + .attr("x1", x1) + .attr("y1", y1) + .attr("x2", x2) + .attr("y2", y2) + .style("stroke", color) + .style("stroke-dasharray", "3,3") + .style("stroke-width", "1px"); + } else { + line = group.append("line") + .attr("x1", x1) + .attr("y1", y1) + .attr("x2", x2) + .attr("y2", y2) + .style("stroke", color) + .style("stroke-width", "1px"); + } + + var slope = (y2 - y1) / (x2 - x1); + var intercept = y1 - (slope * x1); + var triangleRotation = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI - 90; + + group.append("line") + .attr("x1", x1) + .attr("y1", y1) + .attr("x2", x2) + .attr("y2", y2) + .style("stroke", "transparent") + .style("stroke-width", "20px") + .on("mouseover", function() { + group.append("g") + .attr("class", "marker") + .append("path") + .attr("d", d3.svg.symbol().type("triangle-down").size(20)) + .style("stroke", color) + .style("fill", color); + }) + .on("mousemove", function() { + var marker = group.select("g.marker"); + var px = d3.mouse(this)[0] - 10; + var py = d3.mouse(this)[1] - ((slope > 0 ? 1 : -1) * 20); + if (px < Math.min(x1, x2)) { + px += 20; + } + if (py < Math.min(y1, y2)) { + py += 40; + } + + // some linear algebra here + var cx = (slope * py + px - slope * intercept) / (slope * slope + 1); + var cy = (slope * slope * py + slope * px + intercept) / (slope * slope + 1); + + marker.attr("transform", "translate(" + cx + "," + cy + ") rotate(" + triangleRotation + ")"); + }) + .on("mouseout", function() { + group.select("g.marker").remove(); + }); + + group.append("circle") + .attr("cx", x1) + .attr("cy", y1) + .attr("fill", "white") + .attr("stroke", "black") + .attr("r", 2.5) + .style("stroke-width", "1px"); + + group.append("circle") + .attr("cx", x2) + .attr("cy", y2) + .attr("fill", "white") + .attr("stroke", "black") + .attr("r", 2.5) + .style("stroke-width", "1px"); +} + + +function drawCriticalPath() { + state.timelineSvg.selectAll("g.critical_path_lines").remove(); + if (state.critical_path == undefined || !state.display_critical_path) { + return; + } + var depGroup = state.timelineSvg.append("g") + .attr("class", "critical_path_lines"); + state.critical_path.forEach(function(op) { + var proc = base_map[op[0] + "," + op[1]]; // set in calculateBases + if (proc != undefined && proc.visible && proc.enabled && proc.loaded && proc.selected) { + var elems = prof_uid_map[op[2]]; + if (elems != undefined) { + var coords = getElemCoords(elems) + var startX = coords.startX; + var endX = coords.endX; + var y = coords.y; + elems[0].out.forEach(function(dep) { + if (dep[2] in state.critical_path_prof_uids) { + var depElems = prof_uid_map[dep[2]]; + if (depElems != undefined) { + var depProc = depElems[0].proc; + // is the proc visible? + if (depProc.visible && depProc.enabled && depProc.loaded) { + var depCoords = getElemCoords(depElems); + var depX = depCoords.endX; + var depY = depCoords.y; + addLine(depGroup, depX, startX, depY, y, "grey", false); + } + } + } + }); + // Draw parent-child lines + var lastChildCoords = undefined; + var firstChildCoords = undefined; + elems[0].children.forEach(function(child) { + if (child[2] in state.critical_path_prof_uids) { + var childElems = prof_uid_map[child[2]]; + var childCoords = getElemCoords(childElems); + if (childElems !== undefined) { + if (lastChildCoords === undefined || + childCoords.startX > lastChildCoords.startX) { + lastChildCoords = childCoords; + } + if (firstChildCoords === undefined || + childCoords.endX < firstChildCoords.endX) { + firstChildCoords = childCoords; + } + } + } + }); + if (firstChildCoords !== undefined) { + addLine(depGroup, startX, firstChildCoords.startX, + y, firstChildCoords.y, "grey", true); + } + if (lastChildCoords !== undefined) { + addLine(depGroup, lastChildCoords.endX, endX, + lastChildCoords.y, y, "grey", true); + } + } + } + }); +} + +function drawDependencies() { + state.timelineSvg.select("g.dependencies").remove(); + var timelineEvent = state.dependencyEvent; + if (timelineEvent == undefined || + !timelineEvent.proc.visible || !timelineEvent.proc.enabled) { + return; // don't draw in this case, the src isn't present + } + var srcElems = prof_uid_map[timelineEvent.prof_uid]; + timelineEvent = srcElems[0]; // only the first elem will have deps and children + var srcCoords = getElemCoords(srcElems); + var srcStartX = srcCoords.startX; + var srcEndX = srcCoords.endX; + var srcY = srcCoords.y; + var depGroup = state.timelineSvg.append("g") + .attr("class", "dependencies"); + + var addDependency = function(dep, dir, dashed) { + var depProc = base_map[dep[0] + "," + dep[1]]; // set in calculateBases + if (depProc.visible && depProc.enabled && depProc.selected) { + var depElems = prof_uid_map[dep[2]]; + if (depElems != undefined) { + console.log(dir); + var depCoords = getElemCoords(depElems); + var dstY = depCoords.y; + if (dir === "in") { + addLine(depGroup, srcEndX, depCoords.startX, srcY, dstY, "black", dashed); + } else if (dir === "out") { + addLine(depGroup, depCoords.endX, srcStartX, dstY, srcY, "black", dashed); + } else if (dir === "parent") { + addLine(depGroup, depCoords.startX, srcStartX, dstY, srcY, "black", dashed); + addLine(depGroup, srcEndX, depCoords.endX, srcY, dstY, "black", dashed); + } else if (dir === "child") { + addLine(depGroup, srcStartX, depCoords.startX, srcY, dstY, "black", dashed); + addLine(depGroup, depCoords.endX, srcEndX, dstY, srcY, "black", dashed); + } + + } + } + } + + if (state.drawDeps) { + timelineEvent.in.forEach(function(dep) {addDependency(dep, "in", false)}); + timelineEvent.out.forEach(function(dep) {addDependency(dep, "out", false)}); + } + if (state.drawChildren) { + timelineEvent.parents.forEach(function(dep) {addDependency(dep, "parent", true)}); + timelineEvent.children.forEach(function(dep) {addDependency(dep, "child", true)}); + } +} + +function timelineEventsExistAndEqual(a, b) { + if (a == undefined || b == undefined) { + return false; + } + return (a.proc.base == b.proc.base) && (a.prof_uid == b.prof_uid); +} + +function timelineElementStrokeCalculator(elem) { + if (timelineEventsExistAndEqual(elem, state.dependencyEvent)) { + return true; + } else if (state.display_critical_path && + elem.prof_uid in state.critical_path_prof_uids) { + return true; + } + return false; +} + +function timelineEventMouseDown(_timelineEvent) { + // only the first event of this uid will have information + var timelineEvent = prof_uid_map[_timelineEvent.prof_uid][0]; + var hasDependencies = ((timelineEvent.in.length != 0) || + (timelineEvent.out.length != 0)); + + if (hasDependencies) { + if (timelineEventsExistAndEqual(timelineEvent, state.dependencyEvent)) { + if (d3.event.button === 0) { + state.drawDeps = !state.drawDeps; + } else if (d3.event.button === 2) { + state.drawChildren = !state.drawChildren; + } + if (state.drawDeps === false && state.drawChildren === false) { + state.dependencyEvent = undefined; + } + } else { + timelineEvent.in.concat(timelineEvent.out).forEach(function(dep) { + expandByNodeProc(dep[0], dep[1]) + }); + state.dependencyEvent = timelineEvent; + if (d3.event.button === 0) { + state.drawDeps = true; + } else if (d3.event.button === 2) { + state.drawChildren = true; + } + } + redraw(); + } +} + +function drawTimeline() { + showLoaderIcon() + + updateURL(state.zoom, state.scale); + var timelineGroup = state.timelineSvg.select("g#timeline"); + timelineGroup.selectAll("rect").remove(); + timelineGroup.selectAll("text").remove(); + var timeline = timelineGroup.selectAll("rect") + .data(state.dataToDraw, function(d) { return d.proc.base + "-" + d.id; }); + var timelineText = timelineGroup.selectAll("text") + .data(state.memoryTexts); + var mouseOver = getMouseOver(); + + timeline.enter().append("rect"); + + timeline + .attr("id", function(d) { return "block-" + d.proc.base + "-" + d.id; }) + .attr("x", function(d) { return convertToPos(state, d.start); }) + .attr("y", timelineLevelCalculator) + .style("fill", function(d) { + if (!state.searchEnabled || + searchRegex[currentPos].exec(d.title) == null) + return d.color; + else return "#ff0000"; + }) + .attr("width", function(d) { + return Math.max(constants.min_feature_width, convertToPos(state, d.end - d.start)); + }) + .attr("stroke", function(d) { + if (timelineElementStrokeCalculator(d)) { + return "red"; + } else { + return "black"; + } + }) + .attr("stroke-width", function(d) { + if (timelineElementStrokeCalculator(d)) { + return "1.5"; + } else { + return "0.5"; + } + }) + .attr("height", state.thickness) + .style("opacity", function(d) { + if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) != null || searchRegex[currentPos].exec(d.initiation) != null) { + return d.opacity; + } + else return 0.05; + }) + .on("mouseout", function(d, i) { + if ((d.in.length != 0) || (d.out.length != 0)) { + d3.select(this).style("cursor", "default"); + } + state.timelineSvg.selectAll("#desc").remove(); + }) + .on("mousedown", timelineEventMouseDown) + + + timelineText.enter().append("text"); + + timelineText + .attr("class", "timeline") + .attr("y", timelineTextLevelCalculator) + .attr("text-anchor", "start") + .text(function(d) { + var sizeRegex = /Size=(.*)/; + var match = sizeRegex.exec(d.title); + return match[1]; + }) + .attr("visibility", function(d) { + var textWidth = this.getComputedTextLength(); + var startX = convertToPos(state, d.start); + var endX = convertToPos(state, d.end); + var boxWidth = endX - startX; + return boxWidth > textWidth ? "visible" : "hidden"; + }) + .attr("x", function(d) { + var textWidth = this.getComputedTextLength(); + var midPoint = convertToPos(state, d.start + (d.end - d.start) / 2); + midPoint -= textWidth / 2; + return midPoint + }); + + drawUtil(); + timeline.on("mouseover", mouseOver); + timeline.exit().remove(); + hideLoaderIcon(); +} + +function redraw() { + if (state.numLoading == 0) { + calculateBases(); + filterAndMergeBlocks(state); + constants.max_level = calculateVisibileLevels(); + recalculateHeight(); + drawTimeline(); + drawDependencies(); + drawCriticalPath(); + drawLayout(); + } +} + +function calculateVisibileLevels() { + var levels = 0; + state.flattenedLayoutData.forEach(function(elem) { + if (elem.visible) { + if (elem.enabled) { + if (state.ready_selected && elem.num_levels_ready != undefined) + levels += elem.num_levels_ready; + else + levels += elem.num_levels; + } + levels += constants.elem_separation; + } + }); + return levels; +} + +function is_proc(proc) { + // the full text of this proc should start with 0x1d to be a processor + return /0x1d/.exec(proc.full_text) !== undefined; +} + +function is_proc_string(text) +{ + return /0x1d/.exec(text) != undefined; +} + +function is_mem_string(text) { + return /0x1e/.exec(text) != undefined; +} + +function get_node_val(text) { + var match = /\d+/.exec(text); + if (match) { + var val = parseInt(text.match(/\d+/)); + return val; + } + return match; +} + +function get_node_id(text) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + var proc_regex = /(Memory|Processor) 0x1(e|d)([a-fA-f0-9]{4})/; + var proc_match = proc_regex.exec(text); + // if there's only one node, then per-node graphs are redundant + if (proc_match) { + var node_id = parseInt(proc_match[3], 16); + return node_id + } +} + +function get_proc_in_node(text) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + var proc_regex = /Processor 0x1d[a-fA-f0-9]{11}([a-fA-f0-9]{3})/; + var proc_match = proc_regex.exec(text); + // if there's only one node, then per-node graphs are redundant + if (proc_match) { + var proc_in_node = parseInt(proc_match[1], 16); + return proc_in_node; + } +} + +function calculateBases() { + var base = 0; + state.flattenedLayoutData.forEach(function(elem) { + elem.base = base; + var node_id = get_node_id(elem.full_text); + var proc_in_node = get_proc_in_node(elem.full_text); + if (node_id != undefined && proc_in_node != undefined) { + base_map[(+node_id) + "," + (+proc_in_node)] = elem; + } + if (elem.visible) { + if (elem.enabled) { + if (state.ready_selected && elem.num_levels_ready != undefined) + base += elem.num_levels_ready; + else + base += elem.num_levels; + } + base += constants.elem_separation; + } + }); +} + +function expandHandler(elem, index) { + elem.expanded = !elem.expanded; + + if (elem.expanded) { + function expandChild(child) { + child.visible = true; + //child.enabled = true; + if(!child.loaded) { + showLoaderIcon(); + child.loader(child); // will redraw the timeline once loaded + } else if (child.expanded) { + child.children.forEach(expandChild); + } + } + elem.children.forEach(expandChild); + } else { + function collapseChildren(child) { + child.visible = false; + child.children.forEach(collapseChildren); + } + elem.children.forEach(collapseChildren); + } + redraw(); +} + +// This handler is called when you collapse/uncollapse a row in the +// timeline +function collapseHandler(d, index) { + d.enabled = !d.enabled; + + if (!d.loaded) { + // should always be expanding here + showLoaderIcon(); + //var elem = state.flattenedLayoutData[index]; + d.loader(d); // will redraw the timeline once loaded + } else { + redraw(); + } +} + +// This expands a particular element and its parents if necessary +function expandElementAndParents(elem) { + if (elem !== undefined) { + var elemPath = []; // path up to parent + var curElem = elem; + while (curElem != undefined) { + elemPath.push(curElem); + curElem = curElem.parent; + } + + for (var i = elemPath.length - 1; i >= 0; --i) { + var elem = elemPath[i]; + if (!elem.expanded) { + expandHandler(elem); + } + // uncollapse if necessary + if ((i == 0) && !elem.enabled) { + collapseHandler(elem); + } + } + } +} + + +function expandByNodeProc(node, proc) { + // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 + // ugh why isn't there string formatting + var nodeHex = ("0000" + node.toString(16)).slice(-4); + var procHex = ("000" + proc.toString(16)).slice(-3); + var expectedTitle = "0x1d" + nodeHex + "0000000" + procHex; + var matchedElement = undefined; + for (var i = 0; i < state.flattenedLayoutData.length; i++) { + var timelineElement = state.flattenedLayoutData[i]; + if ((timelineElement.full_text != undefined) && + (timelineElement.full_text.indexOf(expectedTitle) !=-1)) { + matchedElement = timelineElement; + break; + } + } + expandElementAndParents(matchedElement) +} + + +function lineLevelCalculator(timelineElement) { + var level = timelineElement.base + 1; + if (timelineElement.enabled) { + if (state.ready_selected && timelineElement.num_levels_ready != undefined) + level += timelineElement.num_levels_ready; + else + level += timelineElement.num_levels; + } + return constants.margin_top + level * state.thickness; +}; + +function utilLevelCalculator(timelineElement) { + var level = timelineElement.base; + if (timelineElement.enabled) { + if (state.ready_selected && timelineElement.num_levels_ready != undefined) + level += timeLineElement.num_levels_ready; + else + level += timeLineElement.num_levels; + } + return constants.margin_top + level * state.thickness; +}; + + +function timelineLevelCalculator(timelineEvent) { + return constants.margin_top + + (timelineEvent.proc.base + timelineEvent.level) * state.thickness; +}; + +function timelineTextLevelCalculator(timelineEvent) { + return constants.margin_top + + (timelineEvent.proc.base + timelineEvent.level + 0.75) * state.thickness; +}; + +function dependencyLineLevelCalculator(level) { + return constants.margin_top + ((level+0.5) * state.thickness); +} + +function drawLayout() { + d3.select("#processors").select("svg").remove(); + state.timelineSvg.select("g#lines").remove(); + + var data = state.flattenedLayoutData; + var svg = d3.select("#processors").append("svg") + .attr("width", constants.margin_left) + .attr("height", state.height); + + var namesGroup = svg.selectAll(".processors") + .data(data) + .enter().append("g"); + + var names = namesGroup.append("text"); + + var thickness = state.thickness; + var xCalculator = function(d) { return (d.depth + 1) * 15; }; + names.attr("text-anchor", "start") + .attr("class", "processor") + .text(function(d) { return d.text; }) + .attr("x", xCalculator) + .attr("y", lineLevelCalculator) + .attr("visibility", function(elem) { + return (elem.visible) ? "visible" : "hidden" + }) + .style("fill", "#000000") + .style("opacity", function(proc) { + return (proc.enabled) ? 1 : 0.5; + }); + + + // names.each(function(d) { + // var elem = d3.select(this); + // var text = d.text; + // var tokens = d.text.split(" to "); + // if (tokens.length == 1) + // elem.append("tspan").text(d.text); + // else { + // var source = tokens[0]; + // var target = tokens[1].replace(" Channel", ""); + // elem.append("tspan").text(source) + // .attr("x", xCalculator) + // .attr("dy", -10); + // elem.append("tspan").text("==> " + target) + // .attr("x", xCalculator) + // .attr("dy", 10); + // } + // }); + names.on({ + "mouseover": function(d) { + d3.select(this).style("cursor", "pointer") + if (d.full_text != undefined) { + var x = xCalculator(d); + var y = lineLevelCalculator(d) - state.thickness; + + var overlaySvg = d3.select("#overlay").append("svg"); + var descView = overlaySvg.append("g").attr("id", "desc"); + + var text = descView.append("text") + .attr("x", x) + .attr("y", y) + .attr("text-anchor", "start") + .attr("class", "desc") + .text(unescape(escape(d.full_text))); + + var bbox = text.node().getBBox(); + var padding = 2; + var rect = descView.insert("rect", "text") + .attr("x", bbox.x - padding) + .attr("y", bbox.y - padding) + .attr("width", bbox.width + (padding*2)) + .attr("height", bbox.height + (padding*2)) + .style("fill", "#222") + .style("opacity", "0.7"); + + overlaySvg.attr("width", bbox.x + bbox.width + (padding*2)) + .attr("height", bbox.y + bbox.height + (padding*2)); + } + }, + "mouseout": function(d) { + d3.select(this).style("cursor", "default") + if (d.full_text != undefined) { + d3.select("#overlay").selectAll("svg").remove(); + } + }, + "click": collapseHandler + }); + + var expandableNodes = namesGroup.filter(function(elem) { + return elem.children.length > 0; + }); + + var expand_group = expandableNodes.append("g"); + + var expand_clickable = expand_group.append("circle") + .attr("fill", "transparent") + .attr("stroke", "transparent") + .attr("r", 8); + var expand_icons = expand_group.append("path"); + var arc = d3.svg.symbol().type('triangle-down') + .size(12); + + + //.attr("transform", function(elem) { + // var x = constants.margin_left - 10; + // var y = lineLevelCalculator(elem); + // return "translate(" + x + "," + y + ")"; + //}) + expand_icons.attr("class", "processor") + .attr("d", arc) + .attr("visibility", function(elem) { + return (elem.visible) ? "visible" : "hidden" + }) + .style("fill", "#000000") + .style("stroke", "#000000") + .style("opacity", function(proc) { + return (proc.enabled) ? 1 : 0.5; + }); + + expand_group.each(function(elem) { + var path = d3.select(this); + var x = elem.depth * 15 + 5; + var y = lineLevelCalculator(elem) - 3; + + if (elem.expanded) { + path.attr("transform", "translate(" + x + ", " + y + ") rotate(0)"); + } else { + path.attr("transform", "translate(" + x + ", " + y + ") rotate(30)"); + } + + }); + + + expand_group.on({ + "mouseover": function(d) { + d3.select(this).style("cursor", "pointer") + }, + "mouseout": function(d) { + d3.select(this).style("cursor", "default") + }, + "click": expandHandler + }); + + + var lines = state.timelineSvg + .append("g") + .attr("id", "lines"); + + var thickness = state.thickness; + lines.selectAll(".lines") + .data(data) + .enter().append("line") + .attr("x1", 0) + .attr("y1", lineLevelCalculator) + .attr("x2", state.zoom * state.width) + .attr("y2", lineLevelCalculator) + .attr("visibility", function(elem) { + return (elem.visible) ? "visible" : "hidden" + }) + .style("stroke", "#000000") + .style("stroke-width", "2px") + .style("opacity", function(proc) { + return (proc.enabled) ? 1 : 0.5; + }); +} + +function drawHelpBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + + var helpBoxGroup = popUpSvg.append("g"); + var helpBoxWidth = Math.min(450, width - 100); + var helpTextOffset = 20; + var helpBoxHeight = Math.min(helpMessage.length * helpTextOffset + 100, + height - 100); + + var boxStartX = (width - helpBoxWidth) / 2; + var boxStartY = (height - helpBoxHeight) / 2; + + helpBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: helpBoxWidth, + height: helpBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var helpText = helpBoxGroup.append("text") + .attr("class", "help-box") + .style("width", helpBoxWidth); + var helpTitle = "Keyboard Shortcuts"; + helpText.append("tspan") + .attr({ x: boxStartX + helpBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text(helpTitle); + var off = 15; + for (var i = 0; i < helpMessage.length; ++i) { + helpText.append("tspan") + .style("font-size", "12pt") + .attr("text-anchor", "start") + .attr({ x: boxStartX + 30, dy: off + helpTextOffset}) + .text(helpMessage[i]); + off = 0; + } +} + +function evalExpandRequest(re) { + var re = new RegExp(re); + state.flattenedLayoutData.forEach(function(elem) { + if (re.exec(elem.text)) { + expandElementAndParents(elem); + } + }); + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); +} + +function drawExpandBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + var expandBoxGroup = popUpSvg.append("g"); + var expandBoxWidth = Math.min(450, width - 100); + var expandBoxHeight = Math.min(220, height - 100); + + var thicknessRatio = state.thickness / state.baseThickness; + var boxStartX = (width - expandBoxWidth) / 2; + var boxStartY = (height - expandBoxHeight) / 2; + + expandBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: expandBoxWidth, + height: expandBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var expandText = expandBoxGroup.append("text") + .attr("class", "expand-box") + .style("width", expandBoxWidth); + expandText.append("tspan") + .attr({ x: boxStartX + expandBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text("expand"); + var expandInputWidth = expandBoxWidth - 40; + var expandInputHeight = 50; + var expandInputStartY = 65; + + + expandBoxGroup.append("foreignObject") + .attr({ x: boxStartX + 20, y: boxStartY + expandInputStartY, + width: expandInputWidth, height: expandBoxHeight - expandInputStartY}) + .attr("text-anchor", "middle") + .html( + "" + + "
" + + "" + + "Presets" + + "" + + "
" + + "
" + + "" + + "" + + "" + + "" + + "" + + "" + + "
" + ); + $("input.expand-box").focus(); +} + +function drawSearchBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + var searchBoxGroup = popUpSvg.append("g"); + var searchBoxWidth = Math.min(450, width - 100); + var searchBoxHeight = Math.min(250, height - 100); + + var thicknessRatio = state.thickness / state.baseThickness; + var boxStartX = (width - searchBoxWidth) / 2; + var boxStartY = (height - searchBoxHeight) / 2; + + searchBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: searchBoxWidth, + height: searchBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var searchText = searchBoxGroup.append("text") + .attr("class", "search-box") + .style("width", searchBoxWidth); + searchText.append("tspan") + .attr({ x: boxStartX + searchBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text("Search"); + var searchInputWidth = searchBoxWidth - 40; + var searchInputHeight = 50; + searchBoxGroup.append("foreignObject") + .attr({ x: boxStartX + 20, y: boxStartY + 150, + width: searchInputWidth, height: searchInputHeight}) + .attr("text-anchor", "middle") + .html(""); + $("input.search-box").focus(); +} + +function drawSearchHistoryBox() { + var width = $(window).width(); + var height = $(window).height(); + var popUpSvg = d3.select("#pop-up").select("svg"); + + var historyBoxGroup = popUpSvg.append("g"); + var historyBoxWidth = Math.min(450, width - 100); + var historyBoxHeight = Math.min(350, height - 100); + + var boxStartX = (width - historyBoxWidth) / 2; + var boxStartY = (height - historyBoxHeight) / 2; + + historyBoxGroup.append("rect") + .attr({ + rx: 30, + ry: 30, + x: boxStartX, + y: boxStartY, + width: historyBoxWidth, + height: historyBoxHeight, + style: "fill: #222; opacity: 0.8;" + }); + var historyText = historyBoxGroup.append("text") + .attr("class", "history-box") + .style("width", historyBoxWidth); + var historyTitle = "Search History"; + historyText.append("tspan") + .attr({ x: boxStartX + historyBoxWidth / 2, y: boxStartY + 50}) + .attr("text-anchor", "middle") + .style("font-size", "20pt") + .text(historyTitle); + if (searchRegex != null) { + var off = 15; + var id = 1; + for (var i = 0; i < sizeHistory; ++i) { + var pos = (nextPos + i) % sizeHistory; + var regex = searchRegex[pos]; + if (regex != null) { + if (pos == currentPos) prefix = ">>> "; + else prefix = id + " : "; + historyText.append("tspan") + .attr("text-anchor", "start") + .attr({ x: boxStartX + 30, dy: off + 25}) + .text(prefix + regex.source); + off = 0; + id++; + } + } + } +} + +function updateURL() { + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + var start_time = convertToTime(state, windowStart); + var end_time = convertToTime(state, windowEnd); + var url = window.location.href.split('?')[0]; + url += "?start=" + start_time; + url += "&end=" + end_time; + url += "&collapseAll=" + state.collapseAll; + url += "&resolution=" + state.resolution; + if (state.searchEnabled) + url += "&search=" + searchRegex[currentPos].source; + window.history.replaceState("", "", url); +} + +function adjustZoom(newZoom, scroll) { + var prevZoom = state.zoom; + state.zoom = Math.round(newZoom * 10) / 10; + + var svg = d3.select("#timeline").select("svg"); + + svg.attr("width", state.zoom * state.width) + .attr("height", state.height); + + var timelineGroup = svg.select("g#timeline"); + //timelineGroup.selectAll("rect").remove(); + + svg.select("g#lines").selectAll("line") + .attr("x2", state.zoom * state.width); + svg.selectAll("#desc").remove(); + svg.selectAll("g.locator").remove(); + d3.select("#overlay").selectAll("svg").remove(); + + if (scroll) { + var paneWidth = $("#timeline").width(); + var pos = ($("#timeline").scrollLeft() + paneWidth / 2) / prevZoom; + // this will trigger a scroll event which in turn redraws the timeline + $("#timeline").scrollLeft(pos * state.zoom - state.width / 2); + } else { + filterAndMergeBlocks(state); + drawTimeline(); + } + drawDependencies(); + drawCriticalPath(); +} + +function recalculateHeight() { + // adjust the height based on the new thickness and max level + state.height = constants.margin_top + constants.margin_bottom + + (state.thickness * constants.max_level); + var util_height = constants.util_levels * state.thickness; + state.y = d3.scale.linear().range([util_height, 0]); + state.y.domain([0, 1]); + + d3.select("#processors").select("svg").remove(); + var svg = d3.select("#timeline").select("svg"); + svg.attr("width", state.zoom * state.width) + .attr("height", state.height); + var lines = state.timelineSvg.select("g#lines"); + lines.remove(); + + svg.selectAll("#desc").remove(); + svg.selectAll("g.locator").remove(); + d3.select("#overlay").selectAll("svg").remove(); + +} + +function adjustThickness(newThickness) { + state.thickness = newThickness; + recalculateHeight(); + drawTimeline(); + drawLayout(); +} + +function suppressdefault(e) { + if (e.preventDefault) e.preventDefault(); + if (e.stopPropagation) e.stopPropagation(); +} + +function setKeyHandler(handler) { + $(document).off("keydown"); + $(document).on("keydown", handler); +} + +function makeModalKeyHandler(validKeys, callback) { + return function(e) { + if (!e) e = event; + var code = e.keyCode || e.charCode; + if (!(e.ctrlKey || e.metaKey || e.altKey)) { + for (var i = 0; i < validKeys.length; ++i) { + if (keys[code] == validKeys[i]) { + callback(keys[code]); + return false; + } + } + } + return true; + } +} + +function displayPopUp() { + d3.select("#pop-up").append("svg") + .attr("width", $(window).width()) + .attr("height", $(window).height()); +} + +function removePopUp() { + var popUpSvg = d3.select("#pop-up").selectAll("svg").remove(); +} + + +function defaultKeydown(e) { + if (!e) e = event; + + var code = e.keyCode || e.charCode; + var commandType = Command.none; + var modifier = e.ctrlKey || e.metaKey || e.altKey; + var multiFnKeys = e.metaKey && e.ctrlKey || e.altKey && e.ctrlKey; + + var translatedCode = keys[code]; + + if (!modifier) { + commandType = noModifierCommands[translatedCode]; + } else if (!multiFnKeys) { + commandType = modifierCommands[translatedCode]; + } else { + commandType = multipleModifierCommands[translatedCode]; + } + + if (commandType == undefined) { + if (e.metaKey || e.altKey) + state.rangeZoom = false; + return true; + } + + suppressdefault(e); + if (commandType == Command.help) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + // make help box visible + displayPopUp(); + drawHelpBox(); + setKeyHandler(makeModalKeyHandler(['/', 'esc'], function(key) { + // make help box invisible + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + else if (commandType == Command.search) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + displayPopUp(); + drawSearchBox(); + setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { + if (key == 'enter') { + var re = $("input.search-box").val(); + if (re.trim() != "") { + if (searchRegex == null) { + searchRegex = new Array(sizeHistory); + currentPos = -1; + nextPos = 0; + } + currentPos = nextPos; + nextPos = (nextPos + 1) % sizeHistory; + searchRegex[currentPos] = new RegExp(re); + state.searchEnabled = true; + } + } + removePopUp(); + if (state.searchEnabled) { + filterAndMergeBlocks(state); + drawTimeline(); + } + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + else if (commandType == Command.expand) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + displayPopUp(); + drawExpandBox(); + setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { + if (key == 'enter') { + var re = $("input.expand-box").val(); + if (re.trim() != "") { + re = new RegExp(re); + state.flattenedLayoutData.forEach(function(elem) { + if (re.exec(elem.text)) { + expandElementAndParents(elem); + } + }); + } + } + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + else if (commandType == Command.search_history) { + turnOffMouseHandlers(); + makeTimelineTransparent(); + displayPopUp(); + drawSearchHistoryBox(); + setKeyHandler(makeModalKeyHandler(['h', 'esc'], function(key) { + removePopUp(); + makeTimelineOpaque(); + setKeyHandler(defaultKeydown); + turnOnMouseHandlers(); + })); + return false; + } + + if (commandType == Command.zix) { + var inc = 4.0; + adjustZoom(state.zoom + inc, true); + } else if (commandType == Command.zox) { + var dec = 4.0; + if (state.zoom - dec > 0) + adjustZoom(state.zoom - dec, true); + } else if (commandType == Command.zrx) { + state.zoomHistory = Array(); + adjustZoom(1.0, false); + $("#timeline").scrollLeft(0); + } else if (commandType == Command.zux) { + if (state.zoomHistory.length > 0) { + var previousZoomHistory = state.zoomHistory.pop(); + adjustZoom(previousZoomHistory.zoom, false); + $("#timeline").scrollLeft(previousZoomHistory.start); + } + } else if (commandType == Command.ziy) + adjustThickness(state.thickness * 2); + else if (commandType == Command.zoy) + adjustThickness(state.thickness / 2); + else if (commandType == Command.zry) { + state.height = $(window).height() - constants.margin_bottom - constants.margin_top; + state.thickness = state.height / constants.max_level; + adjustThickness(state.thickness); + } + else if (commandType == Command.clear_search) { + state.searchEnabled = false; + searchRegex = null; + filterAndMergeBlocks(state); + drawTimeline(); + } + else if (commandType == Command.toggle_search) { + if (searchRegex != null) { + state.searchEnabled = !state.searchEnabled; + filterAndMergeBlocks(state); + drawTimeline(); + } + } + else if (commandType == Command.previous_search || + commandType == Command.next_search) { + if (state.searchEnabled) { + var pos = commandType == Command.previous_search ? + (currentPos - 1 + sizeHistory) % sizeHistory : + (currentPos + 1) % sizeHistory; + var sentinel = commandType == Command.previous_search ? + (nextPos - 1 + sizeHistory) % sizeHistory : nextPos; + if (pos != sentinel && searchRegex[pos] != null) { + currentPos = pos; + filterAndMergeBlocks(state); + drawTimeline(); + } + } + } + else if (commandType == Command.toggle_critical_path) { + state.display_critical_path = !state.display_critical_path; + if (state.display_critical_path) { + state.critical_path.forEach(function(op) { + expandByNodeProc(op[0], op[1]); + }); + } + redraw(); + } + return false; +} + +function defaultKeyUp(e) { + if (!e) e = event; + if (!(e.metaKey || e.altKey)) { + state.rangeZoom = true; + } + return true; +} + +function load_proc_timeline(proc) { + var proc_name = proc.full_text; + state.processorData[proc_name] = {}; + var num_levels_ready = proc.num_levels; + if (state.ready_selected) { + proc.num_levels_ready = proc.num_levels; + } + d3.tsv(proc.tsv, + function(d, i) { + var level = +d.level; + var ready = +d.ready; + var start = +d.start; + var end = +d.end; + var level_ready = +d.level_ready; + var total = end - start; + var _in = d.in === "" ? [] : JSON.parse(d.in) + var out = d.out === "" ? [] : JSON.parse(d.out) + var children = d.children === "" ? [] : JSON.parse(d.children) + var parents = d.parents === "" ? [] : JSON.parse(d.parents) + if (total > state.resolution) { + return { + id: i, + level: level, + level_ready: level_ready, + ready: ready, + start: start, + end: end, + color: d.color, + opacity: d.opacity, + initiation: d.initiation, + title: d.title, + in: _in, + out: out, + children: children, + parents: parents, + prof_uid: d.prof_uid, + proc: proc + }; + } + }, + function(data) { + var num_levels_ready=0 + // split profiling items by which level they're on + for(var i = 0; i < data.length; i++) { + var d = data[i]; + var level_sel=d.level; + if (level_sel in state.processorData[proc_name]) { + state.processorData[proc_name][level_sel].push(d); + } else { + state.processorData[proc_name][level_sel] = [d]; + } + if ((d.level_ready != undefined) && (d.level_ready != 0) && + num_levels_ready < d.level_ready) + num_levels_ready = d.level_ready; + + if (d.prof_uid != undefined && d.prof_uid !== "") { + if (d.prof_uid in prof_uid_map) { + prof_uid_map[d.prof_uid].push(d); + } else { + prof_uid_map[d.prof_uid] = [d]; + } + } + } + if (num_levels_ready > proc.num_levels) + proc.num_levels_ready = num_levels_ready; + else + proc.num_levels_ready = proc.num_levels; + proc.loaded = true; + hideLoaderIcon(); + redraw(); + } + ); +} + +function initTimelineElements() { + var timelineGroup = state.timelineSvg.append("g") + .attr("id", "timeline"); + + $("#timeline").scrollLeft(0); + parseURLParameters(); + + var windowCenterY = $(window).height() / 2; + $(window).scroll(function() { + $("#loader-icon").css("top", $(window).scrollTop() + windowCenterY); + $("#pop-up").css("top", $(window).scrollTop()); + }); + + // set scroll callback + var timer = null; + $("#timeline").scroll(function() { + if (timer !== null) { + clearTimeout(timer); + } + timer = setTimeout(function() { + filterAndMergeBlocks(state); + drawTimeline(); + }, 100); + }); + if (!state.collapseAll) { + // initially load in all the cpu processors and the "all util" + var util_regex = /node/; + for (var i = 0; i < state.flattenedLayoutData.length; i++) { + var timelineElement = state.flattenedLayoutData[i]; + if (timelineElement.type == "util" && + util_regex.exec(timelineElement.text) && + timelineElement.depth == 0) { + collapseHandler(timelineElement, i); + } + } + } + turnOnMouseHandlers(); +} + + +function load_ops_and_timeline() { + d3.tsv("legion_prof_ops.tsv", // TODO: move to tsv folder + function(d) { + return d; + }, + function(data) { + data.forEach(function(d) { + state.operations[parseInt(d.op_id)] = d; + }); + // initTimelineElements depends on the ops to be loaded + initTimelineElements(); + } + ); +} + +function load_procs(callback) { + d3.tsv('legion_prof_processor.tsv', + function(d) { + return { + full_text: d.full_text, + text: d.text, + height: +d.levels, + tsv: d.tsv + }; + }, + function(data) { + var prevEnd = 0; + var base = 0; + data.forEach(function(proc) { + proc.enabled = false; + proc.loaded = false; + proc.base = base; + + base += 2; + }); + state.processors = data; + calculateLayout(); + + // flatten the layout and get the new calculated max num levels + flattenLayout(); + calculateBases(); + drawLayout(); + createMenuList1(); + callback(); + + // TODO: fix + load_critical_path(); + } + ); +} + +function getMinElement(arr, mapF) { + if (arr.length === undefined || arr.length == 0) { + throw "invalid array: " + arr; + } + var minElement = arr[0]; + if (mapF === undefined) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] < minElement) { + minElement = arr[i]; + } + } + } else { + minValue = mapF(minElement); + for (var i = 1; i < arr.length; i++) { + var elem = arr[i]; + var value = mapF(elem); + if (value < minValue) { + minElement = elem; + minValue = value; + } + } + } + return minElement; +} + +function filterUtilData(timelineElem) { + var data = state.utilData[timelineElem.tsv]; // TODO: attach to object + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + var start_time = convertToTime(state, windowStart - 100); + var end_time = convertToTime(state, windowEnd + 100); + + var startIndex = timeBisector(data, start_time); + var endIndex = timeBisector(data, end_time); + + startIndex = Math.max(0, startIndex - 1); + endIndex = Math.min(data.length, endIndex + 2); + var length = endIndex - startIndex; + var newData = Array(); + // we will average points together if they are too close together + var resolution = 1; // 3 pixel resolution + var elem = {time: 0, count: 0}; + var startTime = data[startIndex].time; + var startX = convertToPos(state, startTime); + var endTime = 0; + + for (var i = startIndex; i < endIndex - 1; i++) { + endTime = data[i+1].time; + elem.count += data[i].count * (endTime - data[i].time); + //elem.time += data[i].time; + var endX = convertToPos(state, endTime); + if ((endX - startX) >= resolution || i == (endIndex - 2)) { + var totalTime = endTime - startTime; + elem.count /= totalTime; + //avgElem.time /= windowSize; + elem.time = startTime; + newData.push(elem); + elem = {time: 0, count: 0}; + startX = endX; + startTime = endTime; + } + } + + newData.push({time: endTime, count:0}); + + return { + text: timelineElem.text, + base: timelineElem.base, + num_levels: timelineElem.num_levels, + num_levels_ready: timelineElem.num_levels_ready, + data: newData + }; +} + +function mouseover() { + var focus = state.timelineSvg.append("g") + .attr("class", "focus"); + + focus.append("circle") + .attr("fill", "none") + .attr("stroke", "black") + .attr("r", 4.5); + + var utilDescView = state.timelineSvg.append("g") + .attr("class", "utilDesc"); + utilDescView.append("text") + .attr("x", 7) + .attr("y", -4.5) + .attr("class", "desc") + .attr("dy", ".35em"); + utilDescView.insert("rect", "text") + .style("fill", "#222") + .style("opacity", "0.7"); +} + +function mousemove(d, i) { + var line = document.getElementById("util" + i); + + // offset for this particular line grapgh + var base_y = +line.getAttribute("base_y"); + var px = d3.mouse(line)[0]; + var py = d3.mouse(line)[1] + base_y; + + var start = 0; + var end = line.getTotalLength(); + var target = undefined; + var pos = undefined; + + // https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91 + while (true){ + target = Math.floor((start + end) / 2); + pos = line.getPointAtLength(target); + if ((target === end || target === start) && pos.x !== px) { + break; + } + if (pos.x > px) end = target; + else if (pos.x < px) start = target; + else break; //position found + } + + + var cx = pos.x; + var cy = pos.y + base_y; + + var focus = state.timelineSvg.select("g.focus"); + focus.attr("transform", "translate(" + cx + "," + cy + ")"); + + var utilDescView = state.timelineSvg.select("g.utilDesc"); + utilDescView.attr("transform", "translate(" + (px + 10) + "," + (py - 10) + ")"); + var text = utilDescView.select("text") + + text.text(Math.round(state.y.invert(pos.y) * 100) + "% utilization"); + + var bbox = text.node().getBBox(); + var padding = 2; + var rect = utilDescView.select("rect", "text"); + rect.attr("x", bbox.x - padding) + .attr("y", bbox.y - padding) + .attr("width", bbox.width + (padding*2)) + .attr("height", bbox.height + (padding*2)); + + var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); + var bboxRight = px + bbox.x + bbox.width; + // If the box moves off the screen, nudge it back + if (bboxRight > timelineRight) { + var translation = -(bboxRight - timelineRight + 20); + text.attr("transform", "translate(" + translation + ",0)"); + rect.attr("transform", "translate(" + translation + ",0)"); + } +} + +// Get the data +function load_util(elem) { + var util_file = elem.tsv; + + // exit early if we already loaded it + if(state.utilData[util_file]) { + elem.loaded = true; + hideLoaderIcon(); + redraw(); + return; + } + + d3.tsv(util_file, + function(d) { + return { + time: +d.time, + count: +d.count + }; + }, + function(error, data) { + state.utilData[util_file] = data; + elem.loaded = true; + hideLoaderIcon(); + redraw(); + } + ); +} + +function load_critical_path() { + $.getJSON("json/critical_path.json", function(json) { + state.critical_path = json.map(function(p) {return p.tuple}); + state.critical_path_prof_uids = {}; + state.critical_path.forEach(function(p) { + state.critical_path_prof_uids[p[2]] = 1; + }); + }); +} + +function load_data() { + load_procs(load_ops_and_timeline); +} + +function initializeState() { + var margin = constants.margin_left + constants.margin_right; + state.width = $(window).width() - margin; + state.height = $(window).height() - constants.margin_bottom; + state.scale = state.width / (constants.end - constants.start); + state.zoom = 1.0; + state.zoomHistory = Array(); + state.numLoading = 0; + state.dependencyEvent = undefined; + state.drawDeps = false; + state.drawChildren = false; + + state.layoutData = []; + state.flattenedLayoutData = []; + + state.profilingData = {}; + state.processorData = {}; + state.utilData = []; + + state.operations = {}; + state.thickness = 20; //Math.max(state.height / constants.max_level, 20); + state.baseThickness = state.height / constants.max_level; + state.height = constants.max_level * state.thickness; + state.resolution = 10; // time (in us) of the smallest feature we want to load + state.searchEnabled = false; + state.rangeZoom = true; + state.collapseAll = false; + state.display_critical_path = false; + state.processor_kinds = {}; + + // display task ready state? + state.ready_selected = false; + // TODO: change this + state.x = d3.scale.linear().range([0, state.width]); + state.y = d3.scale.linear().range([constants.util_levels * state.thickness, 0]); + state.y.domain([0, 1]); + + setKeyHandler(defaultKeydown); + $(document).on("keyup", defaultKeyUp); + state.timelineSvg = d3.select("#timeline").select("svg").remove(); + state.timelineSvg = d3.select("#timeline").append("svg") + .attr("width", state.zoom * state.width) + .attr("height", state.height); + + state.loaderSvg = d3.select("#loader-icon").select("svg").remove(); + state.loaderSvg = d3.select("#loader-icon").append("svg") + .attr("width", "40px") + .attr("height", "40px"); + + d3.select("#processors").select("svg").remove(); + + drawLoaderIcon(); + drawHelpBox(); + load_data(); +} + +function load_util_json(callback) { + $.getJSON("json/utils.json", function(json) { + util_files = json; + callback(); + }); +} + +// Loads constants such as max_level, start/end time, and number of levels +// of a util view +function load_scale_json(callback) { + $.getJSON("json/scale.json", function(json) { + // add the read-in constants + $.each(json, function(key, val) { + constants[key] = val; + }); + load_util_json(callback); + }); +} + +function load_op_deps_json(callback) { + $.getJSON("json/op_dependencies.json", function(json) { + op_dependencies = json; + load_scale_json(callback); + }); +} + +function load_jsons(callback) { + load_scale_json(callback); +} + +function main() { + load_jsons(initializeState); +} + +main(); diff --git a/examples/testbench/legion_prof/js/util.js b/examples/testbench/legion_prof/js/util.js new file mode 100644 index 000000000..16ea770f2 --- /dev/null +++ b/examples/testbench/legion_prof/js/util.js @@ -0,0 +1,378 @@ +//----------------------------------------------------------------------------- +// UTILS +//----------------------------------------------------------------------------- + +var helpMessage = [ + "Zoom-in (x-axis) : Ctrl + / 4", + "Zoom-out (x-axis) : Ctrl - / 3", + "Reset zoom (x-axis): Ctrl 0 / 0", + "Undo zoom (x-axis) : u / U", + "Zoom-in (y-axis) : Ctrl-Alt + / 2", + "Zoom-out (y-axis) : Ctrl-Alt - / 1", + "Reset zoom (y-axis): Ctrl-Alt 0 / `", + "Range Zoom-in : drag-select", + "Measure duration : Alt + drag-select", + "Expand : e / E", + "Draw Critical Path : a / A", + "Search : s / S", + "Search History : h / H", + "Previous Search : p / P", + "Next Search : n / N", + "Clear Search : c / C", + "Toggle Search : t / T", +]; + +var Command = { + none : 0, + help : 1, + zox : 2, + zix : 3, + zrx : 4, + zux : 5, + zoy : 6, + ziy : 7, + zry : 8, + search : 9, + clear_search : 10, + toggle_search : 11, + expand: 12, + toggle_critical_path: 13, + search_history : 14, + previous_search : 15, + next_search : 16 +}; + +// commands without a modifier key pressed +var noModifierCommands = { + '0': Command.zrx, + '1': Command.zoy, + '2': Command.ziy, + '3': Command.zox, + '4': Command.zix, + 'c': Command.clear_search, + 'e': Command.expand, + 'h': Command.search_history, + 'n': Command.next_search, + 'p': Command.previous_search, + 's': Command.search, + 'a': Command.toggle_critical_path, + 't': Command.toggle_search, + 'u': Command.zux, + '/': Command.help +}; + +var modifierCommands = { + '+': Command.zix, + '-': Command.zox, + '0': Command.zrx +} + +var multipleModifierCommands = { + '+': Command.ziy, + '-': Command.zoy, + '0': Command.zry +} + +var keys = { + 13 : 'enter', + 27 : 'esc', + 48 : '0', + 49 : '1', + 50 : '2', + 51 : '3', + 52 : '4', + 61 : '+', // Firefox + 65 : 'a', + 67 : 'c', + 69 : 'e', + 72 : 'h', + 78 : 'n', + 80 : 'p', + 83 : 's', + 84 : 't', + 85 : 'u', + 173 : '-', // Firefox + 187 : '+', + 189 : '-', + 191 : '/', + 192 : '`' +}; + +/** + * Function: convertToTime + * + * Description: + * Takes a value and converts it to time. The input 'x' can either be + * a single position on the timeline, or it can be a width. + */ +function convertToTime(state, x) { + return x / state.zoom / state.scale; +} + +/** + * Function: convertToPos + * + * Description: + * Takes a time and converts it to a position in the window. + * The 'time' parameter MUST BE IN us + */ +function convertToPos(state, time) { + return time * state.zoom * state.scale; +} + +/** + * Function: getTimeString + * + * Description: + * This function takes a time (in us) as well as a 'width' + * field. The 'width' field determines over what interval + * the time is being considered. + * + * If the width is too large, the time will be converted + * to either ms or sec. + * + * The function will return a string representation of the + * (possibly) scaled time at the end of the method + */ +function getTimeString(time, timeWidth) { + var unit = "us"; + var scaledTime = Math.floor(time); + if (timeWidth >= 100000) { + var scaledTime = Math.floor(time / 1000); + unit = "ms"; + } else if (timeWidth >= 100000000) { + var scaledTime = Math.floor(time / 1000000); + unit = "s"; + } + return scaledTime + " " + unit; +} + +// timeField should be 'end' for the left hand side and +// 'start' for the right hand side +function binarySearch(data, level, time, useStart) { + var low = 0; + var high = data[level].length; + while (true) { + // ugh is there a way to do integer division in javascrtipt? + var mid = Math.floor((high - low) / 2) + low; + + // In this case, we haven't found it. This is as close + // as we were able to get. + if (low == high || low == mid) { + return low; + } else if (high == mid) { + return high; + } + var midTime; + if (useStart) { + midTime = data[level][mid].start; + } else { + midTime = data[level][mid].end; + } + + if (midTime > time) { + // need to look below + high = mid; + } else if (midTime < time) { + // need to look above + low = mid; + } else { + // Exact Match + return mid; + } + } +} + +dataReady = {}; +function redoData(proc) { + dataReady = {}; + var items = state.processorData[proc.full_text]; + for (var level in items) { + for (var j = 0; j< items[level].length; j++) { + d = items[level][j]; + // ready state items + if (d.level_ready != undefined && d.level_ready != "" && + d.ready != undefined && d.ready != "") { + // if the level has already been switched, then don't do anything + var level_to_set = d.level_ready; + if (d.level_ready_set != undefined && d.level_ready_set == true) + level_to_set = d.level; + var d_ready = { + id: d.id+items[level].length+1, // unique id + level: level_to_set, + level_ready: d.level, + ready: d.ready, + start: d.ready, + end: d.start, + color: d.color, + opacity: "0.45", + initiation: d.initiation, + title: d.title + " (ready)", + in: d.in, + out: d.out, + children: d.children, + parents: d.parents, + prof_uid: d.prof_uid, + proc: d.proc + }; + // switch levels if we need to + if (d.level_ready_set == undefined || d.level_ready_set == false) + { + var level_tmp = d.level; + d.level = d.level_ready; + d.level_ready = level_tmp; + d.level_ready_set = true; + } + if (d.level_ready in dataReady){ + dataReady[d.level_ready].push(d_ready); + dataReady[d.level_ready].push(d); + } + else { + dataReady[d.level_ready] = [d_ready]; + dataReady[d.level_ready].push(d); + } + } + // add items to the level + else { + if (d.level in dataReady) + dataReady[d.level].push(d); + else + dataReady[d.level] = [d]; + } + } + } +} + +function readyData(proc) { + redoData(proc); +} + +function filterAndMergeBlocks(state) { + var windowStart = $("#timeline").scrollLeft(); + var windowEnd = windowStart + $("#timeline").width(); + state.dataToDraw = Array(); + state.memoryTexts = Array(); + var startTime = convertToTime(state, windowStart); + var endTime = convertToTime(state, windowEnd); + var min_feature_time = convertToTime(state, constants.min_feature_width); + var min_gap_time = convertToTime(state, constants.min_gap_width); + for (var index in state.flattenedLayoutData) { + var timelineElement = state.flattenedLayoutData[index]; + if (timelineElement.type == "proc" && timelineElement.enabled && timelineElement.visible) { + var items = state.processorData[timelineElement.full_text]; + var memoryRegex = /Memory/; + var isMemory = memoryRegex.exec(timelineElement.text); + if (state.ready_selected) { + readyData(timelineElement); + items = dataReady; + } + + for (var level in items) { + // gap merging below assumes intervals are sorted - do that first + //items[level].sort(function(a,b) { return a.start - b.start; }); + + // We will use binary search to limit the following section + var startIndex = binarySearch(items, level, startTime, false); + var endIndex = binarySearch(items, level, endTime, true); + for (var i = startIndex; i <= endIndex; ++i) { + var d = items[level][i]; + var start = d.start; + var end = d.end; + // fix the level here + if (state.ready_selected == false && d.level_ready_set != undefined + && d.level_ready_set == true) + { + // switch levels + var level_tmp = d.level; + d.level = d.level_ready; + d.level_ready = level_tmp; + d.level_ready_set = false; + } + // is this block too narrow? + if ((end - start) < min_feature_time) { + // see how many more after this are also too narrow and too close to us + var count = 1; + // don't do this if we're the subject of the current search and don't merge with + // something that is + if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) == null) { + while (((i + count) < items[level].length) && + ((items[level][i + count].start - end) < min_gap_time) && + ((items[level][i + count].end - items[level][i + count].start) < min_feature_time) && + (!state.searchEnabled || searchRegex[currentPos].exec(items[level][i + count].title) == null)) { + end = items[level][i + count].end; + count++; + } + } + // are we still too narrow? if so, bloat, but make sure we don't overlap something later + if ((end - start) < min_feature_time) { + end = start + min_feature_time; + if (((i + count) < items[level].length) && (items[level][i + count].start < end)) + end = items[level][i + count].start; + } + if (count > 1) { + state.dataToDraw.push({ + id: d.id, + prof_uid: d.prof_uid, + proc: timelineElement, + level: d.level, + ready: d.ready, + start: d.start, + end: Math.round(end), + color: "#808080", + title: count + " merged tasks", + in: [], + out: [], + children: [], + parents: [] + }); + i += (count - 1); + } else { + var elem = { + id: d.id, + prof_uid: d.prof_uid, + proc: timelineElement, + level: d.level, + ready: d.ready, + start: d.start, + end: d.end, + color: d.color, + initiation: d.initiation, + title: d.title + " (expanded for visibility)", + in: d.in, + out: d.out, + children: d.children, + parents: d.parents + } + state.dataToDraw.push(elem); + if (isMemory) { + state.memoryTexts.push(elem); + } + } + } else { + var elem = { + id: d.id, + prof_uid: d.prof_uid, + proc: timelineElement, + level: d.level, + ready: d.ready, + start: d.start, + end: d.end, + opacity: d.opacity, + color: d.color, + initiation: d.initiation, + title: d.title, + in: d.in, + out: d.out, + children: d.children, + parents: d.parents + } + state.dataToDraw.push(elem); + if (isMemory) { + state.memoryTexts.push(elem); + } + } + } + } + } + } +} diff --git a/examples/testbench/legion_prof/legion_prof_ops.tsv b/examples/testbench/legion_prof/legion_prof_ops.tsv new file mode 100644 index 000000000..fc406664e --- /dev/null +++ b/examples/testbench/legion_prof/legion_prof_ops.tsv @@ -0,0 +1,59 @@ +op_id desc proc level +1 legion_python_main <1> Python Processor 0x1d00000000000003 2 +28 Task Operation <28> +34 Task Operation <34> +39 Task Operation <39> +40 Task Operation <40> +8 legate::numpy::FillTask [CPU] <8> CPU Processor 0x1d00000000000002 2 +12 legate::numpy::FillTask [CPU] <12> CPU Processor 0x1d00000000000002 2 +13 legate::numpy::FillTask [CPU] <13> CPU Processor 0x1d00000000000002 2 +23 legate::numpy::FusedOpTask [CPU] <23> CPU Processor 0x1d00000000000002 2 +35 legate::numpy::FusedOpTask [CPU] <35> CPU Processor 0x1d00000000000002 2 +0 Operation <0> +3 Tunable Operation <3> +5 Tunable Operation <5> +6 legate::numpy::FillTask [CPU] <6> CPU Processor 0x1d00000000000002 2 +7 Merge Close Operation <7> +11 Merge Close Operation <11> +10 legate::numpy::FillTask [CPU] <10> CPU Processor 0x1d00000000000002 2 +14 legate::numpy::FillTask [CPU] <14> CPU Processor 0x1d00000000000002 2 +15 Attach Operation <15> +16 Merge Close Operation <16> +17 Attach Operation <17> +18 Merge Close Operation <18> +19 Attach Operation <19> +20 Merge Close Operation <20> +21 Attach Operation <21> +22 Merge Close Operation <22> +24 Merge Close Operation <24> +36 Merge Close Operation <36> +37 Merge Close Operation <37> +38 Mapping Operation <38> +50 Deletion Operation <50> +51 Deletion Operation <51> +52 Deletion Operation <52> +53 Deletion Operation <53> +54 Deletion Operation <54> +55 Deletion Operation <55> +56 Deletion Operation <56> +57 Deletion Operation <57> +58 Deletion Operation <58> +9 Merge Close Operation <9> +4 Tunable Operation <4> +25 Attach Operation <25> +27 Attach Operation <27> +30 Attach Operation <30> +32 Attach Operation <32> +41 Fence Operation <41> +42 Detach Operation <42> +43 Detach Operation <43> +44 Detach Operation <44> +45 Detach Operation <45> +46 Detach Operation <46> +47 Detach Operation <47> +48 Detach Operation <48> +49 Detach Operation <49> +29 Merge Close Operation <29> +33 Merge Close Operation <33> +26 Merge Close Operation <26> +31 Merge Close Operation <31> diff --git a/examples/testbench/legion_prof/legion_prof_processor.tsv b/examples/testbench/legion_prof/legion_prof_processor.tsv new file mode 100644 index 000000000..80cc631bf --- /dev/null +++ b/examples/testbench/legion_prof/legion_prof_processor.tsv @@ -0,0 +1,6 @@ +full_text text tsv levels +Utility Processor 0x1d00000000000000 Utility Proc 0 tsv/Proc_0x1d00000000000000.tsv 3 +Utility Processor 0x1d00000000000001 Utility Proc 1 tsv/Proc_0x1d00000000000001.tsv 2 +CPU Processor 0x1d00000000000002 CPU Proc 2 tsv/Proc_0x1d00000000000002.tsv 1 +Python Processor 0x1d00000000000003 Python Proc 3 tsv/Proc_0x1d00000000000003.tsv 1 +System Memory 0x1e00000000000000 [n0] sys tsv/Mem_0x1e00000000000000.tsv 7 diff --git a/examples/testbench/legion_prof/tsv/0 (CPU)_util.tsv b/examples/testbench/legion_prof/tsv/0 (CPU)_util.tsv new file mode 100644 index 000000000..b5a809961 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/0 (CPU)_util.tsv @@ -0,0 +1,206 @@ +time count +0.000 0.00 +1131871.414 1.00 +1131877.823 0.00 +1131902.582 1.00 +1131907.442 0.00 +1131967.180 1.00 +1131973.556 0.00 +1887540.878 1.00 +1887549.090 0.00 +2004081.928 1.00 +2004089.422 0.00 +2064305.095 1.00 +2064310.462 0.00 +2064366.713 1.00 +2064373.269 0.00 +2064467.966 1.00 +2064474.773 0.00 +2064854.771 1.00 +2064860.185 0.00 +2064917.697 1.00 +2065292.716 0.00 +2065321.206 1.00 +2065629.402 0.00 +2065651.028 1.00 +2065655.364 0.00 +2065660.845 1.00 +2065664.930 0.00 +2065670.191 1.00 +2065674.528 0.00 +2065678.796 1.00 +2065682.654 0.00 +2065686.872 1.00 +2065690.098 0.00 +2065694.309 1.00 +2065697.477 0.00 +2065703.630 1.00 +2065708.390 0.00 +2065714.725 1.00 +2065719.262 0.00 +2065723.840 1.00 +2065727.832 0.00 +2065780.941 1.00 +2066111.116 0.00 +2066144.783 1.00 +2066215.987 0.00 +2066245.594 1.00 +2066251.163 0.00 +2066259.095 1.00 +2066264.225 0.00 +2066301.621 1.00 +2066377.311 0.00 +2066405.630 1.00 +2066412.893 0.00 +2066421.100 1.00 +2066427.548 0.00 +2066471.431 1.00 +2066479.071 0.00 +2066535.583 1.00 +2066593.473 0.00 +2067346.675 1.00 +2067354.303 0.00 +2067387.727 1.00 +2067394.617 0.00 +2067442.872 1.00 +2067451.090 0.00 +2067474.731 1.00 +2067480.297 0.00 +2067488.729 1.00 +2067495.305 0.00 +2067532.311 1.00 +2067539.293 0.00 +2067571.934 1.00 +2067579.663 0.00 +2067606.592 1.00 +2067612.221 0.00 +2067621.464 1.00 +2067627.153 0.00 +2067662.795 1.00 +2067670.163 0.00 +2067679.315 1.00 +2067686.512 0.00 +2067705.097 1.00 +2067711.610 0.00 +2067719.563 1.00 +2067726.024 0.00 +2067760.488 1.00 +2067767.837 0.00 +2067834.393 1.00 +2067841.326 0.00 +2067867.718 1.00 +2067875.021 0.00 +2067900.658 1.00 +2067906.286 0.00 +2067951.131 1.00 +2067956.251 0.00 +2067963.814 1.00 +2067967.314 0.00 +2068872.288 1.00 +2068882.867 0.00 +2069260.928 1.00 +2070348.048 0.00 +2070377.866 1.00 +2070383.587 0.00 +2070819.172 1.00 +2070828.288 0.00 +2070840.483 1.00 +2070848.019 0.00 +2070858.887 1.00 +2070866.815 0.00 +2071135.872 1.00 +2071143.400 0.00 +2071175.560 1.00 +2071188.129 0.00 +2071441.366 1.00 +2072373.142 0.00 +2072407.594 1.00 +2072415.756 0.00 +2223654.660 1.00 +2223670.393 0.00 +2223681.067 1.00 +2223688.333 0.00 +2223729.950 1.00 +2223735.924 0.00 +2223828.994 1.00 +2223833.763 0.00 +2223878.262 1.00 +2223882.918 0.00 +2223928.589 1.00 +2223933.189 0.00 +2223979.621 1.00 +2223984.034 0.00 +2224047.331 1.00 +2224051.623 0.00 +2224101.138 1.00 +2224106.757 0.00 +2224148.335 1.00 +2224161.362 0.00 +2224186.534 1.00 +2224191.200 0.00 +2224220.301 1.00 +2224223.906 0.00 +2224253.499 1.00 +2224257.289 0.00 +2224316.993 1.00 +2224321.896 0.00 +2224371.021 1.00 +2224376.481 0.00 +2224382.616 1.00 +2224387.519 0.00 +2224404.275 1.00 +2224409.090 0.00 +2224422.632 1.00 +2224427.511 0.00 +2224432.534 1.00 +2224435.672 0.00 +2224462.197 1.00 +2224466.176 0.00 +2224561.477 1.00 +2224567.447 0.00 +2224577.316 1.00 +2224583.749 0.00 +2224592.176 1.00 +2224597.422 0.00 +2224605.256 1.00 +2224611.578 0.00 +2224625.618 1.00 +2224631.298 0.00 +2224640.500 1.00 +2224647.306 0.00 +2224655.645 1.00 +2224662.140 0.00 +2224723.627 1.00 +2224727.850 0.00 +2224771.060 1.00 +2224775.847 0.00 +2224811.759 1.00 +2224816.039 0.00 +2224822.127 1.00 +2224825.941 0.00 +2224867.885 1.00 +2224872.650 0.00 +2224902.872 1.00 +2224908.376 0.00 +2224914.147 1.00 +2224917.592 0.00 +2224963.214 1.00 +2224967.510 0.00 +2225013.096 1.00 +2225017.772 0.00 +2225061.833 1.00 +2225067.872 0.00 +2225110.405 1.00 +2225115.363 0.00 +2225145.405 1.00 +2225149.977 0.00 +2225157.536 1.00 +2225162.322 0.00 +2225219.074 1.00 +2225225.623 0.00 +2225247.956 1.00 +2225252.965 0.00 +2225278.124 1.00 +2225284.676 0.00 +2225330.082 1.00 +2225334.333 0.00 diff --git a/examples/testbench/legion_prof/tsv/0 (Python)_util.tsv b/examples/testbench/legion_prof/tsv/0 (Python)_util.tsv new file mode 100644 index 000000000..2aea9b2e8 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/0 (Python)_util.tsv @@ -0,0 +1,16 @@ +time count +0.000 0.00 +1134192.460 1.00 +1887460.195 0.00 +1887666.489 1.00 +1887795.983 0.00 +1888027.844 1.00 +2004013.143 0.00 +2004155.450 1.00 +2071175.689 0.00 +2071636.356 1.00 +2071651.215 0.00 +2072465.988 1.00 +2125746.910 0.00 +2125906.215 1.00 +2223592.200 0.00 diff --git a/examples/testbench/legion_prof/tsv/0 (System Memory)_util.tsv b/examples/testbench/legion_prof/tsv/0 (System Memory)_util.tsv new file mode 100644 index 000000000..f6914d7c8 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/0 (System Memory)_util.tsv @@ -0,0 +1,16 @@ +time count +0.000 0.00 +2064650.117 0.00 +2065147.467 0.00 +2065598.615 0.00 +2069053.346 0.00 +2069121.527 0.00 +2071048.359 0.00 +2071113.099 0.00 +2224133.183 0.00 +2224204.270 0.00 +2224388.739 0.00 +2224448.793 0.00 +2224510.529 0.00 +2224556.754 0.00 +2224609.631 0.00 diff --git a/examples/testbench/legion_prof/tsv/0 (Utility)_util.tsv b/examples/testbench/legion_prof/tsv/0 (Utility)_util.tsv new file mode 100644 index 000000000..67767ff36 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/0 (Utility)_util.tsv @@ -0,0 +1,648 @@ +time count +0.000 0.00 +1131662.511 0.50 +1131743.730 0.00 +1131750.448 0.50 +1131777.645 1.00 +1131796.014 0.50 +1131842.077 1.00 +1131847.857 0.50 +1131875.771 1.00 +1131881.475 0.50 +1131943.421 1.00 +1131945.331 0.50 +1132089.267 0.00 +1132112.899 0.50 +1132119.532 0.00 +1887393.247 0.50 +1887455.149 0.00 +1887469.337 0.50 +1887480.054 1.00 +1887485.915 0.50 +1887516.954 0.00 +1887535.605 0.50 +1887638.705 0.00 +1887666.368 0.50 +1887676.134 0.00 +1887805.820 0.50 +1887841.593 0.00 +1887867.399 0.50 +1887872.806 0.00 +1887873.868 0.50 +1887911.228 0.00 +1887939.316 0.50 +1887942.877 1.00 +1887943.976 0.50 +1887986.727 0.00 +1888015.869 0.50 +1888019.680 0.00 +2004015.227 0.50 +2004050.023 1.00 +2004051.755 0.50 +2004073.805 0.00 +2004078.517 0.50 +2004100.736 1.00 +2004106.103 0.50 +2004121.149 0.00 +2004142.069 0.50 +2004145.762 0.00 +2064129.215 0.50 +2064271.214 1.00 +2064275.023 0.50 +2064295.923 1.00 +2064297.548 0.50 +2064314.243 1.00 +2064318.757 0.50 +2064336.527 1.00 +2064342.601 0.50 +2064358.130 0.00 +2064363.504 0.50 +2064372.340 1.00 +2064378.142 0.50 +2064439.767 1.00 +2064440.663 0.50 +2064491.009 1.00 +2064519.103 0.50 +2064684.275 1.00 +2064696.490 0.50 +2064796.569 1.00 +2064815.504 0.50 +2064851.735 1.00 +2064912.591 0.50 +2064920.144 0.00 +2064938.430 0.50 +2064939.541 1.00 +2064943.295 0.50 +2064949.158 1.00 +2064959.621 0.50 +2064960.112 0.00 +2064966.408 0.50 +2064974.539 1.00 +2064979.176 0.50 +2064985.140 1.00 +2064987.569 0.50 +2065001.319 1.00 +2065005.803 0.50 +2065008.315 0.00 +2065011.887 0.50 +2065021.505 1.00 +2065026.318 0.50 +2065074.606 0.00 +2065080.934 0.50 +2065087.801 1.00 +2065093.099 0.50 +2065175.981 1.00 +2065183.321 0.50 +2065193.676 1.00 +2065222.977 0.50 +2065259.007 0.00 +2065260.230 0.50 +2065279.744 0.00 +2065285.153 0.50 +2065290.919 0.00 +2065298.864 0.50 +2065304.046 0.00 +2065311.838 0.50 +2065314.647 1.00 +2065323.070 0.50 +2065330.219 1.00 +2065357.418 0.50 +2065374.476 0.00 +2065376.792 0.50 +2065395.290 1.00 +2065404.409 0.50 +2065406.576 0.00 +2065413.072 0.50 +2065431.175 1.00 +2065437.527 0.50 +2065462.884 1.00 +2065463.379 0.50 +2065478.480 1.00 +2065518.172 0.50 +2065531.848 1.00 +2065541.822 0.50 +2065555.739 1.00 +2065572.335 0.50 +2065594.419 1.00 +2065660.636 0.50 +2065705.960 1.00 +2065742.165 0.50 +2065761.473 1.00 +2065773.170 0.50 +2065786.367 0.00 +2065798.928 0.50 +2065820.023 1.00 +2065822.530 0.50 +2065831.153 1.00 +2065836.685 0.50 +2065841.234 1.00 +2065844.525 0.50 +2065873.896 1.00 +2065876.598 0.50 +2065899.023 1.00 +2065909.599 0.50 +2065965.066 0.00 +2065981.765 0.50 +2065991.392 1.00 +2066001.818 0.50 +2066047.656 1.00 +2066048.507 0.50 +2066070.084 1.00 +2066079.325 0.50 +2066081.533 0.00 +2066094.843 0.50 +2066102.388 1.00 +2066108.878 0.50 +2066135.812 1.00 +2066147.756 0.50 +2066156.610 1.00 +2066197.991 0.50 +2066210.980 0.00 +2066220.415 0.50 +2066235.493 1.00 +2066242.836 0.50 +2066253.371 1.00 +2066284.954 0.50 +2066303.311 0.00 +2066319.571 0.50 +2066330.336 1.00 +2066339.047 0.50 +2066349.384 1.00 +2066355.745 0.50 +2066365.568 1.00 +2066367.395 0.50 +2066384.163 1.00 +2066388.487 0.50 +2066394.872 1.00 +2066398.119 0.50 +2066420.978 1.00 +2066445.626 0.50 +2066461.318 1.00 +2066463.174 0.50 +2066479.174 1.00 +2066483.256 0.50 +2066515.270 0.00 +2066529.232 0.50 +2066533.681 0.00 +2066627.150 0.50 +2066634.424 0.00 +2066642.926 0.50 +2066670.867 0.00 +2066698.558 0.50 +2066703.281 0.00 +2067301.801 0.50 +2067308.792 1.00 +2067319.124 0.50 +2067341.192 1.00 +2067367.273 0.50 +2067368.328 0.00 +2067388.990 0.50 +2067395.492 1.00 +2067401.134 0.50 +2067420.603 0.00 +2067421.580 0.50 +2067439.875 1.00 +2067454.232 0.50 +2067455.291 0.00 +2067472.127 0.50 +2067474.609 1.00 +2067512.496 0.50 +2067527.751 1.00 +2067549.614 0.50 +2067566.785 1.00 +2067579.536 0.50 +2067590.043 0.00 +2067602.973 0.50 +2067607.985 1.00 +2067641.326 0.50 +2067641.791 0.00 +2067656.500 0.50 +2067663.628 1.00 +2067679.151 0.50 +2067681.707 0.00 +2067705.309 0.50 +2067706.016 1.00 +2067735.601 0.50 +2067752.698 0.00 +2067762.961 0.50 +2067774.098 1.00 +2067780.707 0.50 +2067810.448 0.00 +2067816.908 0.50 +2067830.114 1.00 +2067845.249 0.50 +2067868.331 1.00 +2067873.646 0.50 +2067911.279 1.00 +2067928.423 0.50 +2067944.485 0.00 +2067945.510 0.50 +2067997.003 0.00 +2068005.933 0.50 +2068011.781 1.00 +2068016.154 0.50 +2068034.238 0.00 +2068034.716 0.50 +2068050.192 1.00 +2068053.972 0.50 +2068081.412 0.00 +2068099.841 0.50 +2068103.496 0.00 +2068718.776 0.50 +2068819.324 0.00 +2068819.800 0.50 +2068838.765 1.00 +2068843.921 0.50 +2068845.196 0.00 +2068851.002 0.50 +2068869.449 1.00 +2068873.194 0.50 +2068888.720 1.00 +2068893.183 0.50 +2068895.729 0.00 +2068899.579 0.50 +2068920.805 1.00 +2068925.382 0.50 +2068967.735 0.00 +2068981.108 0.50 +2068987.640 1.00 +2068992.969 0.50 +2069083.012 1.00 +2069106.618 0.50 +2069147.523 1.00 +2069165.785 0.50 +2069234.110 1.00 +2069255.619 0.50 +2069272.218 1.00 +2069279.820 0.50 +2069292.337 0.00 +2069296.143 0.50 +2069304.388 0.00 +2069306.933 0.50 +2069322.918 1.00 +2069326.187 0.50 +2069340.380 1.00 +2069345.572 0.50 +2069352.748 1.00 +2069356.475 0.50 +2069374.511 1.00 +2069390.333 0.50 +2069390.747 0.00 +2069407.691 0.50 +2069418.366 1.00 +2069425.098 0.50 +2069432.480 1.00 +2069437.167 0.50 +2069444.029 1.00 +2069449.166 0.50 +2069456.488 1.00 +2069488.484 0.50 +2069500.754 0.00 +2069509.402 0.50 +2069521.646 1.00 +2069528.013 0.50 +2069535.567 0.00 +2069535.964 0.50 +2069555.271 1.00 +2069565.176 0.50 +2069568.751 0.00 +2069581.553 0.50 +2069631.187 1.00 +2069638.355 0.50 +2069659.704 1.00 +2069663.194 0.50 +2069689.634 1.00 +2069729.027 0.50 +2069736.823 0.00 +2069756.624 0.50 +2069762.525 1.00 +2069769.736 0.50 +2069778.737 1.00 +2069783.086 0.50 +2069790.728 1.00 +2069792.334 0.50 +2069810.149 1.00 +2069831.359 0.50 +2069849.405 1.00 +2069870.888 0.50 +2069877.565 0.00 +2069886.021 0.50 +2069894.631 0.00 +2069907.512 0.50 +2069911.435 1.00 +2069922.920 0.50 +2069941.733 0.00 +2069947.237 0.50 +2069960.854 1.00 +2069966.367 0.50 +2069974.700 0.00 +2069978.389 0.50 +2069998.435 1.00 +2070005.542 0.50 +2070010.923 0.00 +2070014.959 0.50 +2070032.572 1.00 +2070036.122 0.50 +2070040.870 1.00 +2070044.094 0.50 +2070048.472 1.00 +2070051.774 0.50 +2070056.245 1.00 +2070060.009 0.50 +2070067.424 1.00 +2070073.169 0.50 +2070075.913 0.00 +2070081.771 0.50 +2070087.538 0.00 +2070094.373 0.50 +2070099.524 0.00 +2070101.685 0.50 +2070107.471 1.00 +2070108.096 0.50 +2070113.258 0.00 +2070116.927 0.50 +2070120.860 1.00 +2070123.965 0.50 +2070125.106 0.00 +2070131.877 0.50 +2070133.033 1.00 +2070136.189 0.50 +2070139.695 0.00 +2070141.398 0.50 +2070145.072 0.00 +2070148.618 0.50 +2070150.171 1.00 +2070154.829 0.50 +2070155.876 0.00 +2070159.785 0.50 +2070164.050 0.00 +2070164.942 0.50 +2070170.490 0.00 +2070311.079 0.50 +2070326.801 0.00 +2070329.126 0.50 +2070369.981 0.00 +2070370.602 0.50 +2070377.373 0.00 +2070385.334 0.50 +2070388.785 1.00 +2070392.574 0.50 +2070426.871 0.00 +2070469.051 0.50 +2070475.390 0.00 +2070698.337 0.50 +2070781.152 1.00 +2070791.932 0.50 +2070806.013 0.00 +2070812.162 0.50 +2070823.632 1.00 +2070835.663 0.50 +2070843.027 0.00 +2070851.863 0.50 +2070860.505 1.00 +2070865.751 0.50 +2070872.848 1.00 +2070873.378 0.50 +2070889.815 1.00 +2070895.005 0.50 +2070895.393 0.00 +2070901.054 0.50 +2070912.589 1.00 +2070917.128 0.50 +2070962.074 0.00 +2070975.805 0.50 +2070982.478 1.00 +2070987.821 0.50 +2071077.383 1.00 +2071100.087 0.50 +2071113.591 1.00 +2071152.023 0.50 +2071213.450 1.00 +2071219.974 0.50 +2071426.355 1.00 +2071432.285 0.50 +2071450.221 1.00 +2071458.232 0.50 +2071475.719 0.00 +2071485.324 0.50 +2071501.085 1.00 +2071507.744 0.50 +2071649.220 0.00 +2071675.248 0.50 +2071681.510 0.00 +2071933.817 0.50 +2071943.818 1.00 +2071946.793 0.50 +2071971.528 1.00 +2071975.936 0.50 +2072004.306 0.00 +2072030.588 0.50 +2072036.622 0.00 +2072345.424 0.50 +2072358.717 0.00 +2072364.643 0.50 +2072392.367 0.00 +2072393.575 0.50 +2072400.046 0.00 +2072409.183 0.50 +2072416.299 1.00 +2072424.207 0.50 +2072446.614 0.00 +2072472.619 0.50 +2072478.026 0.00 +2125594.978 0.50 +2125632.752 0.00 +2125703.515 0.50 +2125736.612 0.00 +2125756.869 0.50 +2125782.049 0.00 +2125799.828 0.50 +2125832.850 0.00 +2125852.771 0.50 +2125854.803 1.00 +2125859.590 0.50 +2125862.182 0.00 +2125867.246 0.50 +2125872.861 1.00 +2125873.486 0.50 +2125881.155 0.00 +2142117.664 0.50 +2142134.517 1.00 +2142169.070 0.50 +2142358.907 0.00 +2142379.766 0.50 +2142408.752 0.00 +2142421.085 0.50 +2142427.615 1.00 +2142458.056 0.50 +2142459.315 0.00 +2142479.998 0.50 +2142484.084 1.00 +2142508.841 0.50 +2142515.953 0.00 +2142532.780 0.50 +2142536.863 1.00 +2142562.055 0.50 +2142567.397 0.00 +2142583.695 0.50 +2142588.483 1.00 +2142608.823 0.50 +2142626.280 1.00 +2142703.362 0.50 +2142703.838 0.00 +2142733.551 0.50 +2142734.195 1.00 +2142782.824 0.50 +2142785.276 0.00 +2142814.771 0.50 +2142815.494 1.00 +2142861.600 0.50 +2142864.105 0.00 +2142883.833 0.50 +2142886.938 1.00 +2142927.830 0.50 +2142935.202 0.00 +2142956.698 0.50 +2142960.779 1.00 +2142996.567 0.50 +2143001.829 0.00 +2143017.553 0.50 +2143022.880 1.00 +2143036.927 0.50 +2143044.755 0.00 +2143061.789 0.50 +2143069.506 1.00 +2143079.681 0.50 +2143090.109 0.00 +2143099.040 0.50 +2143115.876 1.00 +2143122.640 0.50 +2143135.627 0.00 +2143142.620 0.50 +2143148.702 0.00 +2143155.140 0.50 +2143156.407 1.00 +2143161.598 0.50 +2143162.254 0.00 +2143171.528 0.50 +2143172.191 1.00 +2143177.719 0.50 +2143178.522 0.00 +2143185.422 0.50 +2143187.525 1.00 +2143191.048 0.50 +2143193.553 0.00 +2143198.224 0.50 +2143201.377 1.00 +2143203.776 0.50 +2143207.104 0.00 +2143211.338 0.50 +2143214.741 1.00 +2143217.153 0.50 +2143220.451 0.00 +2143224.599 0.50 +2143228.060 1.00 +2143230.439 0.50 +2143233.807 0.00 +2143237.897 0.50 +2143242.015 1.00 +2143243.990 0.50 +2143248.158 0.00 +2143251.772 0.50 +2143255.895 1.00 +2143257.547 0.50 +2143261.633 0.00 +2143265.286 0.50 +2143269.666 1.00 +2143270.949 0.50 +2143275.896 0.00 +2143278.912 0.50 +2143284.717 1.00 +2143285.057 0.50 +2143290.933 0.00 +2143293.352 0.50 +2143298.720 0.00 +2143299.577 0.50 +2143305.733 0.00 +2143306.574 0.50 +2143312.669 0.00 +2143314.699 0.50 +2143320.490 1.00 +2143321.041 0.50 +2143326.021 0.00 +2223542.740 0.50 +2223616.705 1.00 +2223642.437 0.50 +2223677.391 1.00 +2223704.338 0.50 +2223734.963 1.00 +2223802.748 0.50 +2223832.624 1.00 +2223858.909 0.50 +2223882.005 1.00 +2223910.536 0.50 +2223931.926 1.00 +2223959.271 0.50 +2223980.553 1.00 +2224025.655 0.50 +2224049.819 1.00 +2224080.825 0.50 +2224105.842 1.00 +2224166.333 0.50 +2224191.035 1.00 +2224232.413 0.50 +2224263.865 1.00 +2224296.398 0.50 +2224318.069 1.00 +2224347.889 0.50 +2224355.751 0.00 +2224375.532 0.50 +2224376.294 1.00 +2224402.223 0.50 +2224417.523 0.00 +2224426.629 0.50 +2224439.970 1.00 +2224479.424 0.50 +2224502.241 1.00 +2224530.123 0.50 +2224548.176 1.00 +2224579.936 0.50 +2224600.946 1.00 +2224638.734 0.50 +2224661.822 1.00 +2224698.721 0.50 +2224723.490 1.00 +2224750.426 0.50 +2224773.650 1.00 +2224786.089 0.50 +2224803.090 0.00 +2224815.571 0.50 +2224820.990 1.00 +2224845.602 0.50 +2224869.634 1.00 +2224881.576 0.50 +2224899.178 0.00 +2224907.668 0.50 +2224920.916 1.00 +2224944.521 0.50 +2224966.963 1.00 +2224994.594 0.50 +2225014.514 1.00 +2225039.487 0.50 +2225062.158 1.00 +2225090.887 0.50 +2225112.927 1.00 +2225125.099 0.50 +2225132.778 0.00 +2225153.557 0.50 +2225195.458 1.00 +2225195.976 0.50 +2225219.705 1.00 +2225224.165 0.50 +2225253.992 1.00 +2225258.537 0.50 +2225281.446 1.00 +2225309.583 0.50 +2225312.131 0.00 +2225335.279 0.50 +2225341.226 0.00 diff --git a/examples/testbench/legion_prof/tsv/Mem_0x1e00000000000000.tsv b/examples/testbench/legion_prof/tsv/Mem_0x1e00000000000000.tsv new file mode 100644 index 000000000..75255cee7 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/Mem_0x1e00000000000000.tsv @@ -0,0 +1,8 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +7 2064650.117 2224204.270 #00fff6 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000001 $Size: 468.750 KiB 6 128 +6 2065147.467 2224388.739 #00fff6 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000002 $Size: 468.750 KiB 8 129 +5 2065598.615 2224609.631 #00fff6 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000003 $Size: 468.750 KiB 10 125 +4 2069053.346 2224448.793 #ff7a00 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048584]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000008 $Size: 468.750 KiB 23 130 +3 2069121.527 2224510.529 #ff7a00 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048585]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000009 $Size: 468.750 KiB 23 131 +2 2071048.359 2224133.183 #ff7a00 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048590]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000e $Size: 468.750 KiB 35 127 +1 2071113.099 2224556.754 #ff7a00 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048591]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000f $Size: 468.750 KiB 35 126 diff --git a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000000.tsv b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000000.tsv new file mode 100644 index 000000000..78775a78e --- /dev/null +++ b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000000.tsv @@ -0,0 +1,174 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +3 6 1131636.472 1131662.511 1131743.730 #c4ff00 1.0 Deferred Enqueue Task 1 [[0, 3, 16]] 227 +3 6 1131777.645 1131777.645 1131796.014 #ffc0cb 1.0 ProfTask <1> 236 +3 6 1131825.852 1131842.077 1131881.475 #ee00ff 1.0 Task Physical Dependence Analysis 1 [[0, 3, 16]] 19 +3 6 1131929.728 1131943.421 1132089.267 #ee00ff 1.0 Task Physical Dependence Analysis 1 [[0, 3, 16]] 245 +3 6 1887337.668 1887393.247 1887455.149 #007bff 1.0 Logical Dependence Analysis 3 228 +3 6 1887480.054 1887480.054 1887485.915 #ffc0cb 1.0 ProfTask <3> 237 +3 6 1887504.651 1887535.605 1887638.705 #001eff 1.0 Operation Physical Dependence Analysis 3 246 +3 6 1887763.546 1887805.820 1887841.593 #007bff 1.0 Logical Dependence Analysis 4 230 +3 6 1887867.399 1887867.399 1887872.806 #ffc0cb 1.0 ProfTask <4> 238 +3 6 1887890.796 1887942.877 1887986.727 #001eff 1.0 Operation Physical Dependence Analysis 4 231 +3 6 1888015.869 1888015.869 1888019.680 #ffc0cb 1.0 ProfTask <4> 239 +3 6 2003971.035 2004015.227 2004051.755 #007bff 1.0 Logical Dependence Analysis 5 24 +3 6 2004063.491 2004078.517 2004121.149 #001eff 1.0 Operation Physical Dependence Analysis 5 249 +3 6 2064084.727 2064129.215 2064275.023 #007bff 1.0 Logical Dependence Analysis 6 [[0, 2, 244]] 26 +3 6 2064287.989 2064295.923 2064342.601 #001eff 1.0 Operation Physical Dependence Analysis 7 28 +3 6 2064350.761 2064363.504 2064440.663 #9d00ff 1.0 Scheduler 0 29 +3 6 2064491.009 2064491.009 2064519.103 #007bff 1.0 Logical Dependence Analysis 8 [[0, 2, 7]] 233 +3 6 2064519.103 2064519.103 2064832.086 #007bff 0.15 Logical Dependence Analysis (waiting) 8 233 +3 6 2064832.086 2064832.086 2064851.735 #007bff 0.45 Logical Dependence Analysis (ready) 8 233 +3 6 2064851.735 2064851.735 2064920.144 #007bff 1.0 Logical Dependence Analysis 8 233 +2 5 2064684.275 2064684.275 2064696.490 #ffc0cb 1.0 ProfTask <6> 291 +2 5 2064765.377 2064796.569 2064815.504 #ff00ad 1.0 Mapper Continuation 8 [[0, 2, 7]] 30 +3 6 2064939.541 2064939.541 2064943.295 #ffc0cb 1.0 ProfTask <6> 240 +3 6 2064949.158 2064949.158 2064960.112 #ffc0cb 1.0 ProfTask <8> 241 +3 5 2064951.272 2064966.408 2064987.569 #001eff 1.0 Operation Physical Dependence Analysis 9 234 +3 5 2065001.319 2065001.319 2065005.803 #ffc0cb 1.0 ProfTask <9> 242 +3 6 2064998.019 2065011.887 2065074.606 #9d00ff 1.0 Scheduler 0 235 +3 6 2065087.801 2065087.801 2065093.099 #ffc0cb 1.0 ProfTask <0> 243 +3 5 2065175.981 2065175.981 2065183.321 #ffc0cb 1.0 ProfTask <8> 292 +3 6 2065193.676 2065193.676 2065222.977 #007bff 1.0 Logical Dependence Analysis 10 [[0, 2, 298]] 256 +3 6 2065222.977 2065222.977 2065295.140 #007bff 0.15 Logical Dependence Analysis (waiting) 10 256 +3 6 2065295.140 2065295.140 2065314.647 #007bff 0.45 Logical Dependence Analysis (ready) 10 256 +3 6 2065314.647 2065314.647 2065357.418 #007bff 1.0 Logical Dependence Analysis 10 256 +2 5 2065218.157 2065260.230 2065279.744 #ff00ad 1.0 Mapper Continuation 10 [[0, 2, 298]] 255 +3 5 2065338.495 2065376.792 2065406.576 #333399 1.0 Deferred Ready Trigger 11 33 +3 6 2065422.853 2065431.175 2065463.379 #333399 1.0 Deferred Ready Trigger 10 [[0, 2, 298]] 36 +3 5 2065439.589 2065478.480 2065518.172 #007bff 1.0 Logical Dependence Analysis 12 [[0, 2, 9]] 37 +3 6 2065507.551 2065531.848 2065541.822 #333399 1.0 Deferred Ready Trigger 12 [[0, 2, 9]] 38 +3 6 2065555.739 2065555.739 2065620.847 #ee00ff 1.0 Task Physical Dependence Analysis 10 [[0, 2, 298]] 288 +3 6 2065620.847 2065620.847 2065644.003 #ee00ff 0.15 Task Physical Dependence Analysis (waiting) 10 288 +3 6 2065644.003 2065644.003 2065671.369 #ee00ff 0.45 Task Physical Dependence Analysis (ready) 10 288 +3 6 2065671.369 2065671.369 2065773.170 #ee00ff 1.0 Task Physical Dependence Analysis 10 288 +2 5 2065562.363 2065562.363 2065707.741 #ff0b00 1.0 Mapper Call map_task for 10 10 [[0, 2, 298]] 290 +3 6 2065798.928 2065798.928 2065822.530 #ffc0cb 1.0 ProfTask <8> 293 +3 6 2065831.153 2065831.153 2065836.685 #ffc0cb 1.0 ProfTask <10> 294 +3 6 2065841.234 2065841.234 2065844.525 #ffc0cb 1.0 ProfTask <0> 295 +3 6 2065854.207 2065873.896 2065965.066 #ee00ff 1.0 Task Physical Dependence Analysis 12 [[0, 2, 9]] 300 +3 6 2065991.392 2065991.392 2066001.818 #ffc0cb 1.0 ProfTask <12> 323 +3 6 2066028.814 2066047.656 2066079.325 #333399 1.0 Deferred Ready Trigger 13 [[0, 2, 11]] 301 +3 6 2066102.388 2066102.388 2066108.878 #ffc0cb 1.0 ProfTask <13> 324 +3 6 2066135.812 2066135.812 2066147.756 #ffc0cb 1.0 ProfTask <10> 325 +3 5 2066135.907 2066156.610 2066197.991 #006600 1.0 Post-Task Execution 10 [[0, 2, 298]] 349 +3 6 2066194.275 2066220.415 2066303.311 #ee00ff 1.0 Task Physical Dependence Analysis 13 [[0, 2, 11]] 303 +3 6 2066330.336 2066330.336 2066339.047 #ffc0cb 1.0 ProfTask <12> 326 +3 6 2066349.384 2066349.384 2066355.745 #ffc0cb 1.0 ProfTask <13> 327 +3 6 2066356.299 2066365.568 2066398.119 #333399 1.0 Deferred Ready Trigger 14 [[0, 2, 299]] 42 +3 6 2066398.294 2066420.978 2066445.626 #006600 1.0 Post-Task Execution 13 [[0, 2, 11]] 43 +3 6 2066454.530 2066461.318 2066515.270 #ee00ff 1.0 Task Physical Dependence Analysis 14 [[0, 2, 299]] 304 +3 6 2066529.232 2066529.232 2066533.681 #ffc0cb 1.0 ProfTask <14> 328 +3 6 2066627.150 2066627.150 2066634.424 #ffc0cb 1.0 ProfTask <14> 329 +3 6 2066698.558 2066698.558 2066703.281 #ffc0cb 1.0 ProfTask <14> 330 +3 6 2067285.724 2067301.801 2067368.328 #007bff 1.0 Logical Dependence Analysis 15 306 +3 6 2067395.492 2067395.492 2067401.134 #ffc0cb 1.0 ProfTask <15> 331 +3 6 2067406.666 2067421.580 2067455.291 #333399 1.0 Deferred Ready Trigger 15 51 +3 5 2067438.999 2067474.609 2067579.536 #001eff 1.0 Operation Physical Dependence Analysis 15 55 +3 4 2067578.560 2067607.985 2067641.326 #333399 1.0 Deferred Ready Trigger 17 57 +3 6 2067552.580 2067663.628 2067679.151 #f7ff00 1.0 Prepipeline Stage 19 60 +3 5 2067626.890 2067705.309 2067752.698 #001eff 1.0 Operation Physical Dependence Analysis 17 307 +3 6 2067774.098 2067774.098 2067780.707 #ffc0cb 1.0 ProfTask <17> 332 +3 6 2067784.883 2067816.908 2067873.646 #001eff 1.0 Operation Physical Dependence Analysis 19 67 +3 6 2067893.332 2067911.279 2067944.485 #333399 1.0 Deferred Ready Trigger 22 70 +3 6 2067977.348 2068005.933 2068034.238 #333399 1.0 Deferred Ready Trigger 21 308 +3 6 2068050.192 2068050.192 2068053.972 #ffc0cb 1.0 ProfTask <21> 333 +3 6 2068701.125 2068718.776 2068819.324 #007bff 1.0 Logical Dependence Analysis 23 [[0, 2, 13]] 309 +3 5 2068838.765 2068838.765 2068843.921 #ffc0cb 1.0 ProfTask <23> 334 +3 6 2068834.478 2068851.002 2068873.194 #001eff 1.0 Operation Physical Dependence Analysis 24 310 +3 5 2068888.720 2068888.720 2068893.183 #ffc0cb 1.0 ProfTask <24> 335 +3 6 2068884.784 2068899.579 2068967.735 #9d00ff 1.0 Scheduler 0 355 +3 5 2068958.116 2068981.108 2069255.619 #ee00ff 1.0 Task Physical Dependence Analysis 23 [[0, 2, 13]] 311 +2 6 2068988.209 2068988.209 2069159.228 #ff0b00 1.0 Mapper Call map_task for 23 23 [[0, 2, 13]] 321 +3 6 2069257.831 2069272.218 2069292.337 #333399 1.0 Deferred Ready Trigger 26 357 +3 5 2069284.832 2069306.933 2069326.187 #001eff 1.0 Operation Physical Dependence Analysis 26 359 +3 6 2069340.380 2069340.380 2069345.572 #ffc0cb 1.0 ProfTask <23> 336 +3 5 2069340.950 2069352.748 2069390.333 #001eff 1.0 Operation Physical Dependence Analysis 25 361 +3 6 2069375.203 2069407.691 2069488.484 #007bff 1.0 Logical Dependence Analysis 27 312 +3 6 2069488.981 2069509.402 2069535.567 #001eff 1.0 Operation Physical Dependence Analysis 29 364 +3 5 2069531.900 2069555.271 2069568.751 #f7ff00 1.0 Prepipeline Stage 30 366 +3 6 2069608.648 2069631.187 2069663.194 #333399 1.0 Deferred Ready Trigger 31 368 +3 5 2069650.683 2069689.634 2069729.027 #001eff 1.0 Operation Physical Dependence Analysis 31 369 +3 6 2069703.806 2069756.624 2069792.334 #333399 1.0 Deferred Ready Trigger 30 370 +3 6 2069797.392 2069810.149 2069877.565 #007bff 1.0 Logical Dependence Analysis 32 315 +3 6 2069881.531 2069907.512 2069922.920 #006600 1.0 Post-Task Execution 28 373 +3 5 2069861.000 2069947.237 2069974.700 #001eff 1.0 Operation Physical Dependence Analysis 33 374 +3 5 2069998.435 2069998.435 2070005.542 #ffc0cb 1.0 ProfTask <27> 337 +3 6 2069996.220 2070014.959 2070075.913 #001eff 1.0 Operation Physical Dependence Analysis 32 317 +3 6 2070101.685 2070101.685 2070108.096 #ffc0cb 1.0 ProfTask <27> 338 +3 6 2070116.927 2070116.927 2070123.965 #ffc0cb 1.0 ProfTask <30> 339 +3 6 2070133.033 2070133.033 2070139.695 #ffc0cb 1.0 ProfTask <32> 340 +3 6 2070148.618 2070148.618 2070155.876 #ffc0cb 1.0 ProfTask <28> 341 +3 6 2070164.942 2070164.942 2070170.490 #ffc0cb 1.0 ProfTask <32> 342 +3 6 2070293.609 2070311.079 2070326.801 #006600 1.0 Post-Task Execution 34 318 +3 5 2070370.602 2070370.602 2070377.373 #ffc0cb 1.0 ProfTask <34> 343 +3 6 2070369.776 2070385.334 2070426.871 #006600 1.0 Post-Task Execution 23 [[0, 2, 13]] 377 +3 6 2070667.976 2070698.337 2070791.932 #007bff 1.0 Logical Dependence Analysis 35 [[0, 2, 15]] 73 +3 5 2070768.213 2070812.162 2070835.663 #333399 1.0 Deferred Ready Trigger 37 77 +3 6 2070826.521 2070851.863 2070873.378 #001eff 1.0 Operation Physical Dependence Analysis 37 319 +3 5 2070889.815 2070889.815 2070895.005 #ffc0cb 1.0 ProfTask <37> 344 +3 6 2070884.998 2070901.054 2070962.074 #9d00ff 1.0 Scheduler 0 380 +3 5 2070975.805 2070975.805 2071133.560 #ee00ff 1.0 Task Physical Dependence Analysis 35 [[0, 2, 15]] 320 +3 5 2071133.560 2071133.560 2071172.787 #ee00ff 0.15 Task Physical Dependence Analysis (waiting) 35 320 +3 5 2071172.787 2071172.787 2071230.794 #ee00ff 0.45 Task Physical Dependence Analysis (ready) 35 320 +3 5 2071230.794 2071230.794 2071432.285 #ee00ff 1.0 Task Physical Dependence Analysis 35 320 +2 6 2070983.664 2070983.664 2071255.461 #ff0b00 1.0 Mapper Call map_task for 35 35 [[0, 2, 15]] 322 +1 4 2071094.504 2071179.516 2071190.430 #f7ff00 1.0 Prepipeline Stage 38 381 +3 6 2071450.221 2071450.221 2071458.232 #ffc0cb 1.0 ProfTask <35> 345 +3 6 2071462.205 2071485.324 2071649.220 #001eff 1.0 Operation Physical Dependence Analysis 38 383 +3 6 2071898.389 2071933.817 2071946.793 #006600 1.0 Post-Task Execution 39 455 +3 6 2071971.528 2071971.528 2071975.936 #ffc0cb 1.0 ProfTask <39> 475 +3 6 2072030.588 2072030.588 2072036.622 #ffc0cb 1.0 ProfTask <39> 476 +3 6 2072328.841 2072345.424 2072358.717 #006600 1.0 Post-Task Execution 40 457 +3 6 2072393.575 2072393.575 2072400.046 #ffc0cb 1.0 ProfTask <40> 477 +3 5 2072394.979 2072409.183 2072446.614 #006600 1.0 Post-Task Execution 35 [[0, 2, 15]] 458 +3 6 2072472.619 2072472.619 2072478.026 #ffc0cb 1.0 ProfTask <35> 478 +3 6 2125438.432 2125594.978 2125632.752 #009900 1.0 Deferred Commit 38 385 +3 6 2125645.320 2125703.515 2125736.612 #007bff 1.0 Logical Dependence Analysis 41 459 +3 5 2125724.982 2125756.869 2125782.049 #333399 1.0 Deferred Ready Trigger 41 460 +3 6 2125771.586 2125799.828 2125832.850 #001eff 1.0 Operation Physical Dependence Analysis 41 386 +3 6 2125852.771 2125852.771 2125859.590 #ffc0cb 1.0 ProfTask <41> 479 +3 6 2125867.246 2125867.246 2125873.486 #ffc0cb 1.0 ProfTask <41> 480 +3 6 2140637.501 2142117.664 2142358.907 #007bff 1.0 Logical Dependence Analysis 42 387 +3 5 2142231.268 2142379.766 2142408.752 #333399 1.0 Deferred Ready Trigger 42 462 +3 4 2142266.330 2142427.615 2142458.056 #333399 1.0 Deferred Ready Trigger 44 463 +3 3 2142283.931 2142479.998 2142508.841 #333399 1.0 Deferred Ready Trigger 45 464 +3 2 2142315.059 2142532.780 2142562.055 #333399 1.0 Deferred Ready Trigger 47 465 +3 1 2142347.612 2142583.695 2142608.823 #333399 1.0 Deferred Ready Trigger 49 466 +3 6 2142444.331 2142626.280 2142703.362 #001eff 1.0 Operation Physical Dependence Analysis 44 391 +3 5 2142444.978 2142733.551 2142785.276 #001eff 1.0 Operation Physical Dependence Analysis 43 468 +3 4 2142549.062 2142815.494 2142864.105 #001eff 1.0 Operation Physical Dependence Analysis 47 393 +3 3 2142553.937 2142883.833 2142927.830 #001eff 1.0 Operation Physical Dependence Analysis 48 394 +3 2 2142674.619 2142956.698 2142996.567 #009900 1.0 Garbage Collection 44 395 +3 6 2142766.968 2143017.553 2143036.927 #009900 1.0 Garbage Collection 45 396 +3 5 2142845.594 2143061.789 2143079.681 #009900 1.0 Garbage Collection 46 397 +3 4 2142913.343 2143099.040 2143122.640 #009900 1.0 Garbage Collection 48 398 +3 6 2143142.620 2143142.620 2143148.702 #ffc0cb 1.0 ProfTask <42> 481 +3 6 2143156.407 2143156.407 2143162.254 #ffc0cb 1.0 ProfTask <42> 482 +3 6 2143171.528 2143171.528 2143177.719 #ffc0cb 1.0 ProfTask <44> 483 +3 6 2143185.422 2143185.422 2143191.048 #ffc0cb 1.0 ProfTask <45> 484 +3 6 2143198.224 2143198.224 2143203.776 #ffc0cb 1.0 ProfTask <47> 485 +3 6 2143211.338 2143211.338 2143217.153 #ffc0cb 1.0 ProfTask <49> 486 +3 6 2143224.599 2143224.599 2143230.439 #ffc0cb 1.0 ProfTask <42> 487 +3 6 2143237.897 2143237.897 2143243.990 #ffc0cb 1.0 ProfTask <43> 488 +3 6 2143251.772 2143251.772 2143257.547 #ffc0cb 1.0 ProfTask <46> 489 +3 6 2143265.286 2143265.286 2143270.949 #ffc0cb 1.0 ProfTask <49> 490 +3 6 2143278.912 2143278.912 2143285.057 #ffc0cb 1.0 ProfTask <42> 491 +3 6 2143293.352 2143293.352 2143298.720 #ffc0cb 1.0 ProfTask <43> 492 +3 6 2143306.574 2143306.574 2143312.669 #ffc0cb 1.0 ProfTask <47> 493 +3 6 2143320.490 2143320.490 2143326.021 #ffc0cb 1.0 ProfTask <49> 494 +3 6 2223513.340 2223542.740 2223802.748 #007bff 1.0 Logical Dependence Analysis 50 83 +3 5 2223773.308 2223832.624 2223858.909 #333399 1.0 Deferred Ready Trigger 51 85 +3 6 2223848.090 2223882.005 2223910.536 #001eff 1.0 Operation Physical Dependence Analysis 51 86 +3 5 2223889.580 2223931.926 2223959.271 #333399 1.0 Deferred Ready Trigger 52 88 +3 6 2223948.000 2223980.553 2224025.655 #001eff 1.0 Operation Physical Dependence Analysis 52 89 +3 5 2224003.975 2224049.819 2224080.825 #333399 1.0 Deferred Ready Trigger 53 91 +3 6 2224030.127 2224105.842 2224166.333 #009900 1.0 Garbage Collection 50 92 +3 4 2224062.367 2224191.035 2224232.413 #009900 1.0 Garbage Collection 50 93 +3 3 2224068.115 2224263.865 2224296.398 #001eff 1.0 Operation Physical Dependence Analysis 53 94 +3 6 2224274.059 2224318.069 2224355.751 #333399 1.0 Deferred Ready Trigger 54 97 +3 5 2224317.587 2224375.532 2224402.223 #990000 1.0 Deferred Execute 51 98 +3 6 2224388.205 2224426.629 2224786.089 #990000 1.0 Deferred Execute 52 107 +3 5 2224767.393 2224815.571 2224881.576 #990000 1.0 Deferred Execute 53 111 +3 6 2224865.471 2224907.668 2225132.778 #990000 1.0 Deferred Execute 54 120 +3 6 2225177.967 2225195.458 2225224.165 #990000 1.0 Deferred Execute 56 122 +3 6 2225241.887 2225253.992 2225312.131 #990000 1.0 Deferred Execute 58 399 diff --git a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000001.tsv b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000001.tsv new file mode 100644 index 000000000..c974b81fa --- /dev/null +++ b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000001.tsv @@ -0,0 +1,169 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +2 7 1131726.584 1131750.448 1131847.857 #9d00ff 1.0 Scheduler 0 18 +2 7 1131865.246 1131875.771 1131945.331 #9d00ff 1.0 Scheduler 0 20 +2 7 1132112.899 1132112.899 1132119.532 #ffc0cb 1.0 ProfTask <1> 260 +2 7 1887430.900 1887469.337 1887516.954 #333399 1.0 Deferred Ready Trigger 3 22 +2 7 1887666.368 1887666.368 1887676.134 #ffc0cb 1.0 ProfTask <3> 261 +2 7 1887820.758 1887873.868 1887911.228 #333399 1.0 Deferred Ready Trigger 4 247 +2 7 1887939.316 1887939.316 1887943.976 #ffc0cb 1.0 ProfTask <4> 262 +2 7 2004033.501 2004050.023 2004073.805 #333399 1.0 Deferred Ready Trigger 5 248 +2 7 2004100.736 2004100.736 2004106.103 #ffc0cb 1.0 ProfTask <5> 263 +2 7 2004142.069 2004142.069 2004145.762 #ffc0cb 1.0 ProfTask <5> 264 +2 7 2064237.437 2064271.214 2064297.548 #333399 1.0 Deferred Ready Trigger 7 250 +2 7 2064314.243 2064314.243 2064318.757 #ffc0cb 1.0 ProfTask <7> 265 +2 7 2064325.150 2064336.527 2064358.130 #333399 1.0 Deferred Ready Trigger 6 [[0, 2, 244]] 251 +2 7 2064372.340 2064372.340 2064378.142 #ffc0cb 1.0 ProfTask <6> 266 +2 7 2064425.658 2064439.767 2064912.591 #ee00ff 1.0 Task Physical Dependence Analysis 6 [[0, 2, 244]] 232 +1 6 2064460.470 2064460.470 2064757.963 #ff0b00 1.0 Mapper Call map_task for 6 6 [[0, 2, 244]] 258 +2 6 2064895.840 2064938.430 2064959.621 #333399 1.0 Deferred Ready Trigger 9 252 +2 7 2064974.539 2064974.539 2064979.176 #ffc0cb 1.0 ProfTask <9> 267 +2 6 2064977.098 2064985.140 2065008.315 #333399 1.0 Deferred Ready Trigger 8 [[0, 2, 7]] 253 +2 7 2065021.505 2065021.505 2065026.318 #ffc0cb 1.0 ProfTask <8> 268 +2 7 2065063.470 2065080.934 2065259.007 #ee00ff 1.0 Task Physical Dependence Analysis 8 [[0, 2, 7]] 254 +1 6 2065092.988 2065092.988 2065205.897 #ff0b00 1.0 Mapper Call map_task for 8 8 [[0, 2, 7]] 259 +2 7 2065285.153 2065285.153 2065290.919 #ffc0cb 1.0 ProfTask <8> 269 +2 7 2065298.864 2065298.864 2065304.046 #ffc0cb 1.0 ProfTask <10> 270 +2 7 2065311.838 2065311.838 2065323.070 #ffc0cb 1.0 ProfTask <6> 271 +2 6 2065314.045 2065330.219 2065374.476 #006600 1.0 Post-Task Execution 6 [[0, 2, 244]] 31 +2 6 2065395.290 2065395.290 2065404.409 #ffc0cb 1.0 ProfTask <10> 272 +2 7 2065392.769 2065413.072 2065437.527 #001eff 1.0 Operation Physical Dependence Analysis 11 34 +2 7 2065449.415 2065462.884 2065572.335 #9d00ff 1.0 Scheduler 0 39 +2 6 2065594.419 2065594.419 2065660.636 #9d00ff 1.0 Scheduler 0 257 +2 6 2065660.636 2065660.636 2065797.939 #9d00ff 0.15 Scheduler (waiting) 0 257 +2 6 2065797.939 2065797.939 2065820.023 #9d00ff 0.45 Scheduler (ready) 0 257 +2 6 2065820.023 2065820.023 2065876.598 #9d00ff 1.0 Scheduler 0 257 +1 7 2065645.624 2065705.960 2065742.165 #006600 1.0 Post-Task Execution 8 [[0, 2, 7]] 287 +1 5 2065714.422 2065761.473 2065786.367 #ff00ad 1.0 Mapper Continuation 0 289 +2 7 2065899.023 2065899.023 2065909.599 #ffc0cb 1.0 ProfTask <0> 273 +2 7 2065942.215 2065981.765 2066048.507 #007bff 1.0 Logical Dependence Analysis 13 [[0, 2, 11]] 348 +2 6 2066070.084 2066070.084 2066081.533 #ffc0cb 1.0 ProfTask <13> 400 +2 7 2066066.582 2066094.843 2066210.980 #9d00ff 1.0 Scheduler 0 40 +2 7 2066235.493 2066235.493 2066242.836 #ffc0cb 1.0 ProfTask <10> 401 +2 6 2066236.561 2066253.371 2066284.954 #006600 1.0 Post-Task Execution 12 [[0, 2, 9]] 302 +2 5 2066240.578 2066319.571 2066367.395 #007bff 1.0 Logical Dependence Analysis 14 [[0, 2, 299]] 350 +2 6 2066384.163 2066384.163 2066388.487 #ffc0cb 1.0 ProfTask <14> 402 +2 7 2066383.816 2066394.872 2066463.174 #9d00ff 1.0 Scheduler 0 351 +2 7 2066479.174 2066479.174 2066483.256 #ffc0cb 1.0 ProfTask <0> 403 +2 7 2066612.567 2066642.926 2066670.867 #006600 1.0 Post-Task Execution 14 [[0, 2, 299]] 305 +2 7 2067269.088 2067308.792 2067319.124 #f7ff00 1.0 Prepipeline Stage 15 45 +2 7 2067333.123 2067341.192 2067367.273 #333399 1.0 Deferred Ready Trigger 16 47 +2 6 2067355.636 2067388.990 2067420.603 #001eff 1.0 Operation Physical Dependence Analysis 16 48 +2 7 2067426.791 2067439.875 2067454.232 #f7ff00 1.0 Prepipeline Stage 17 50 +2 6 2067441.364 2067472.127 2067512.496 #007bff 1.0 Logical Dependence Analysis 17 52 +2 7 2067491.307 2067527.751 2067549.614 #333399 1.0 Deferred Ready Trigger 18 54 +2 6 2067539.805 2067566.785 2067590.043 #001eff 1.0 Operation Physical Dependence Analysis 18 56 +2 7 2067572.388 2067602.973 2067641.791 #007bff 1.0 Logical Dependence Analysis 19 59 +2 6 2067619.191 2067656.500 2067681.707 #333399 1.0 Deferred Ready Trigger 20 62 +2 7 2067670.435 2067706.016 2067735.601 #001eff 1.0 Operation Physical Dependence Analysis 20 63 +2 6 2067721.619 2067762.961 2067810.448 #333399 1.0 Deferred Ready Trigger 19 64 +2 7 2067816.229 2067830.114 2067845.249 #f7ff00 1.0 Prepipeline Stage 21 66 +2 6 2067836.417 2067868.331 2067928.423 #007bff 1.0 Logical Dependence Analysis 21 68 +2 7 2067930.983 2067945.510 2067997.003 #001eff 1.0 Operation Physical Dependence Analysis 22 352 +2 7 2068011.781 2068011.781 2068016.154 #ffc0cb 1.0 ProfTask <22> 404 +2 7 2068021.691 2068034.716 2068081.412 #001eff 1.0 Operation Physical Dependence Analysis 21 353 +2 7 2068099.841 2068099.841 2068103.496 #ffc0cb 1.0 ProfTask <21> 405 +2 7 2068787.182 2068819.800 2068845.196 #333399 1.0 Deferred Ready Trigger 24 72 +2 7 2068859.786 2068869.449 2068895.729 #333399 1.0 Deferred Ready Trigger 23 [[0, 2, 13]] 354 +2 7 2068920.805 2068920.805 2068925.382 #ffc0cb 1.0 ProfTask <23> 406 +2 7 2068987.640 2068987.640 2068992.969 #ffc0cb 1.0 ProfTask <0> 407 +2 7 2069083.012 2069083.012 2069106.618 #ffc0cb 1.0 ProfTask <23> 408 +2 7 2069147.523 2069147.523 2069165.785 #ffc0cb 1.0 ProfTask <23> 409 +2 7 2069217.627 2069234.110 2069279.820 #007bff 1.0 Logical Dependence Analysis 25 356 +2 7 2069203.330 2069296.143 2069304.388 #f7ff00 1.0 Prepipeline Stage 25 358 +2 7 2069316.441 2069322.918 2069356.475 #333399 1.0 Deferred Ready Trigger 25 360 +2 7 2069358.027 2069374.511 2069390.747 #f7ff00 1.0 Prepipeline Stage 27 362 +2 7 2069418.366 2069418.366 2069425.098 #ffc0cb 1.0 ProfTask <25> 410 +2 7 2069432.480 2069432.480 2069437.167 #ffc0cb 1.0 ProfTask <26> 411 +2 7 2069444.029 2069444.029 2069449.166 #ffc0cb 1.0 ProfTask <25> 412 +2 6 2069444.938 2069456.488 2069500.754 #333399 1.0 Deferred Ready Trigger 29 363 +2 6 2069521.646 2069521.646 2069528.013 #ffc0cb 1.0 ProfTask <26> 413 +2 7 2069521.212 2069535.964 2069565.176 #333399 1.0 Deferred Ready Trigger 27 365 +2 7 2069567.777 2069581.553 2069638.355 #007bff 1.0 Logical Dependence Analysis 30 367 +2 6 2069553.670 2069659.704 2069736.823 #001eff 1.0 Operation Physical Dependence Analysis 27 313 +2 7 2069762.525 2069762.525 2069769.736 #ffc0cb 1.0 ProfTask <25> 414 +2 6 2069778.737 2069778.737 2069783.086 #ffc0cb 1.0 ProfTask <25> 415 +2 7 2069777.307 2069790.728 2069831.359 #001eff 1.0 Operation Physical Dependence Analysis 30 314 +2 7 2069837.412 2069849.405 2069870.888 #333399 1.0 Deferred Ready Trigger 33 371 +2 7 2069778.190 2069886.021 2069894.631 #f7ff00 1.0 Prepipeline Stage 32 372 +2 6 2069889.106 2069911.435 2069941.733 #3dff00 1.0 Trigger Complete 28 316 +2 6 2069960.854 2069960.854 2069966.367 #ffc0cb 1.0 ProfTask <27> 416 +2 7 2069960.237 2069978.389 2070010.923 #333399 1.0 Deferred Ready Trigger 32 375 +2 7 2070032.572 2070032.572 2070036.122 #ffc0cb 1.0 ProfTask <29> 417 +2 7 2070040.870 2070040.870 2070044.094 #ffc0cb 1.0 ProfTask <29> 418 +2 7 2070048.472 2070048.472 2070051.774 #ffc0cb 1.0 ProfTask <27> 419 +2 7 2070056.245 2070056.245 2070060.009 #ffc0cb 1.0 ProfTask <30> 420 +2 7 2070067.424 2070067.424 2070073.169 #ffc0cb 1.0 ProfTask <30> 421 +2 7 2070081.771 2070081.771 2070087.538 #ffc0cb 1.0 ProfTask <31> 422 +2 7 2070094.373 2070094.373 2070099.524 #ffc0cb 1.0 ProfTask <31> 423 +2 7 2070107.471 2070107.471 2070113.258 #ffc0cb 1.0 ProfTask <30> 424 +2 7 2070120.860 2070120.860 2070125.106 #ffc0cb 1.0 ProfTask <33> 425 +2 7 2070131.877 2070131.877 2070136.189 #ffc0cb 1.0 ProfTask <32> 426 +2 7 2070141.398 2070141.398 2070145.072 #ffc0cb 1.0 ProfTask <28> 427 +2 7 2070150.171 2070150.171 2070154.829 #ffc0cb 1.0 ProfTask <33> 428 +2 7 2070159.785 2070159.785 2070164.050 #ffc0cb 1.0 ProfTask <32> 429 +2 7 2070310.674 2070329.126 2070369.981 #3dff00 1.0 Trigger Complete 34 376 +2 7 2070388.785 2070388.785 2070392.574 #ffc0cb 1.0 ProfTask <34> 430 +2 7 2070469.051 2070469.051 2070475.390 #ffc0cb 1.0 ProfTask <23> 431 +2 7 2070749.142 2070781.152 2070806.013 #333399 1.0 Deferred Ready Trigger 36 75 +2 6 2070797.695 2070823.632 2070843.027 #001eff 1.0 Operation Physical Dependence Analysis 36 378 +2 7 2070860.505 2070860.505 2070865.751 #ffc0cb 1.0 ProfTask <36> 432 +2 6 2070861.048 2070872.848 2070895.393 #333399 1.0 Deferred Ready Trigger 35 [[0, 2, 15]] 379 +2 7 2070912.589 2070912.589 2070917.128 #ffc0cb 1.0 ProfTask <35> 433 +2 7 2070982.478 2070982.478 2070987.821 #ffc0cb 1.0 ProfTask <0> 434 +2 7 2071077.383 2071077.383 2071100.087 #ffc0cb 1.0 ProfTask <35> 435 +2 7 2071106.819 2071113.591 2071152.023 #007bff 1.0 Logical Dependence Analysis 38 79 +2 7 2071213.450 2071213.450 2071219.974 #ffc0cb 1.0 ProfTask <38> 436 +2 7 2071391.508 2071426.355 2071475.719 #333399 1.0 Deferred Ready Trigger 38 382 +2 7 2071501.085 2071501.085 2071507.744 #ffc0cb 1.0 ProfTask <38> 437 +2 7 2071675.248 2071675.248 2071681.510 #ffc0cb 1.0 ProfTask <38> 438 +2 7 2071919.090 2071943.818 2072004.306 #3dff00 1.0 Trigger Complete 39 456 +2 7 2072340.685 2072364.643 2072392.367 #3dff00 1.0 Trigger Complete 40 384 +2 7 2072416.299 2072416.299 2072424.207 #ffc0cb 1.0 ProfTask <40> 439 +2 7 2125854.803 2125854.803 2125862.182 #ffc0cb 1.0 ProfTask <38> 440 +2 7 2125872.861 2125872.861 2125881.155 #ffc0cb 1.0 ProfTask <41> 441 +2 7 2140598.711 2142134.517 2142169.070 #f7ff00 1.0 Prepipeline Stage 42 461 +2 7 2142250.991 2142421.085 2142459.315 #333399 1.0 Deferred Ready Trigger 43 388 +2 6 2142299.250 2142484.084 2142515.953 #333399 1.0 Deferred Ready Trigger 46 389 +2 5 2142332.758 2142536.863 2142567.397 #333399 1.0 Deferred Ready Trigger 48 390 +2 4 2142398.468 2142588.483 2142703.838 #001eff 1.0 Operation Physical Dependence Analysis 42 467 +2 7 2142496.269 2142734.195 2142782.824 #001eff 1.0 Operation Physical Dependence Analysis 45 392 +2 3 2142502.585 2142814.771 2142861.600 #001eff 1.0 Operation Physical Dependence Analysis 46 469 +2 6 2142598.817 2142886.938 2142935.202 #001eff 1.0 Operation Physical Dependence Analysis 49 470 +2 5 2142677.812 2142960.779 2143001.829 #009900 1.0 Garbage Collection 42 471 +2 4 2142769.448 2143022.880 2143044.755 #009900 1.0 Garbage Collection 43 472 +2 7 2142848.058 2143069.506 2143090.109 #009900 1.0 Garbage Collection 47 473 +2 3 2142918.009 2143115.876 2143135.627 #009900 1.0 Garbage Collection 49 474 +2 7 2143155.140 2143155.140 2143161.598 #ffc0cb 1.0 ProfTask <42> 442 +2 7 2143172.191 2143172.191 2143178.522 #ffc0cb 1.0 ProfTask <43> 443 +2 7 2143187.525 2143187.525 2143193.553 #ffc0cb 1.0 ProfTask <46> 444 +2 7 2143201.377 2143201.377 2143207.104 #ffc0cb 1.0 ProfTask <48> 445 +2 7 2143214.741 2143214.741 2143220.451 #ffc0cb 1.0 ProfTask <44> 446 +2 7 2143228.060 2143228.060 2143233.807 #ffc0cb 1.0 ProfTask <45> 447 +2 7 2143242.015 2143242.015 2143248.158 #ffc0cb 1.0 ProfTask <47> 448 +2 7 2143255.895 2143255.895 2143261.633 #ffc0cb 1.0 ProfTask <48> 449 +2 7 2143269.666 2143269.666 2143275.896 #ffc0cb 1.0 ProfTask <44> 450 +2 7 2143284.717 2143284.717 2143290.933 #ffc0cb 1.0 ProfTask <45> 451 +2 7 2143299.577 2143299.577 2143305.733 #ffc0cb 1.0 ProfTask <46> 452 +2 7 2143314.699 2143314.699 2143321.041 #ffc0cb 1.0 ProfTask <48> 453 +2 7 2223597.529 2223616.705 2223642.437 #333399 1.0 Deferred Ready Trigger 50 81 +2 7 2223649.894 2223677.391 2223704.338 #006600 1.0 Post-Task Execution 1 [[0, 3, 16]] 82 +2 6 2223632.052 2223734.963 2224347.889 #001eff 1.0 Operation Physical Dependence Analysis 50 95 +2 7 2224083.656 2224376.294 2224417.523 #009900 1.0 Garbage Collection 50 99 +2 5 2224105.062 2224439.970 2224479.424 #009900 1.0 Garbage Collection 50 100 +2 4 2224122.255 2224502.241 2224530.123 #009900 1.0 Garbage Collection 50 101 +2 3 2224174.081 2224548.176 2224579.936 #009900 1.0 Garbage Collection 50 102 +2 2 2224202.446 2224600.946 2224638.734 #009900 1.0 Garbage Collection 50 103 +2 1 2224342.247 2224661.822 2224698.721 #001eff 1.0 Operation Physical Dependence Analysis 54 104 +2 7 2224676.790 2224723.490 2224750.426 #333399 1.0 Deferred Ready Trigger 55 106 +2 6 2224739.059 2224773.650 2224803.090 #001eff 1.0 Operation Physical Dependence Analysis 55 108 +2 7 2224780.989 2224820.990 2224845.602 #333399 1.0 Deferred Ready Trigger 56 110 +2 6 2224835.122 2224869.634 2224899.178 #001eff 1.0 Operation Physical Dependence Analysis 56 112 +2 7 2224877.537 2224920.916 2224944.521 #333399 1.0 Deferred Ready Trigger 57 114 +2 6 2224934.343 2224966.963 2224994.594 #001eff 1.0 Operation Physical Dependence Analysis 57 115 +2 7 2224974.658 2225014.514 2225039.487 #333399 1.0 Deferred Ready Trigger 58 117 +2 6 2225028.841 2225062.158 2225090.887 #001eff 1.0 Operation Physical Dependence Analysis 58 118 +2 7 2225070.170 2225112.927 2225125.099 #3dff00 1.0 Trigger Complete 1 [[0, 3, 16]] 119 +2 6 2225114.068 2225153.557 2225195.976 #990000 1.0 Deferred Execute 55 121 +2 7 2225208.142 2225219.705 2225258.537 #990000 1.0 Deferred Execute 57 123 +2 7 2225273.472 2225281.446 2225309.583 #5eff00 1.0 Top Finish 0 124 +2 7 2225335.279 2225335.279 2225341.226 #ffc0cb 1.0 ProfTask <58> 454 diff --git a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000002.tsv b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000002.tsv new file mode 100644 index 000000000..6b101db3e --- /dev/null +++ b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000002.tsv @@ -0,0 +1,103 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +1 2 1131871.414 1131871.414 1131877.823 #ffc0cb 1.0 ProfTask <0> 132 +1 2 1131902.582 1131902.582 1131907.442 #ffc0cb 1.0 ProfTask <1> 133 +1 2 1131967.180 1131967.180 1131973.556 #ffc0cb 1.0 ProfTask <0> 134 +1 2 1887540.878 1887540.878 1887549.090 #ffc0cb 1.0 ProfTask <3> 135 +1 2 2004081.928 2004081.928 2004089.422 #ffc0cb 1.0 ProfTask <5> 136 +1 2 2064305.095 2064305.095 2064310.462 #ffc0cb 1.0 ProfTask <6> 137 +1 2 2064366.713 2064366.713 2064373.269 #ffc0cb 1.0 ProfTask <7> 138 +1 2 2064467.966 2064467.966 2064474.773 #ffc0cb 1.0 ProfTask <0> 139 +1 2 2064854.771 2064854.771 2064860.185 #ffc0cb 1.0 ProfTask <8> 140 +1 2 2064900.104 2064917.697 2065292.716 #00fff6 1.0 legate::numpy::FillTask [CPU] <6> [[0, 1, 31], [0, 2, 13]] [[0, 0, 26], [0, 1, 251], [0, 1, 258], [0, 1, 232]] [[0, 3, 16]] 244 +1 1 2065246.858 2065321.206 2065629.402 #00fff6 1.0 legate::numpy::FillTask [CPU] <8> [[0, 1, 287], [0, 2, 11]] [[0, 1, 253], [0, 0, 233], [0, 1, 254], [0, 1, 259], [0, 0, 30]] [[0, 3, 16]] 7 +1 2 2065651.028 2065651.028 2065655.364 #ffc0cb 1.0 ProfTask <6> 141 +1 2 2065660.845 2065660.845 2065664.930 #ffc0cb 1.0 ProfTask <11> 142 +1 2 2065670.191 2065670.191 2065674.528 #ffc0cb 1.0 ProfTask <11> 143 +1 2 2065678.796 2065678.796 2065682.654 #ffc0cb 1.0 ProfTask <10> 144 +1 2 2065686.872 2065686.872 2065690.098 #ffc0cb 1.0 ProfTask <12> 145 +1 2 2065694.309 2065694.309 2065697.477 #ffc0cb 1.0 ProfTask <12> 146 +1 2 2065703.630 2065703.630 2065708.390 #ffc0cb 1.0 ProfTask <0> 147 +1 2 2065714.725 2065714.725 2065719.262 #ffc0cb 1.0 ProfTask <10> 148 +1 2 2065723.840 2065723.840 2065727.832 #ffc0cb 1.0 ProfTask <8> 149 +1 2 2065758.538 2065780.941 2066111.116 #00fff6 1.0 legate::numpy::FillTask [CPU] <10> [[0, 2, 299], [0, 0, 349]] [[0, 0, 288], [0, 0, 290], [0, 0, 255], [0, 0, 36], [0, 0, 256]] [[0, 3, 16]] 298 +1 1 2065952.164 2066144.783 2066215.987 #00fff6 1.0 legate::numpy::FillTask [CPU] <12> [[0, 1, 302]] [[0, 0, 38], [0, 0, 300], [0, 0, 37]] [[0, 3, 16]] 9 +1 2 2066245.594 2066245.594 2066251.163 #ffc0cb 1.0 ProfTask <0> 150 +1 2 2066259.095 2066259.095 2066264.225 #ffc0cb 1.0 ProfTask <12> 151 +1 2 2066286.943 2066301.621 2066377.311 #00fff6 1.0 legate::numpy::FillTask [CPU] <13> [[0, 0, 43], [0, 2, 13]] [[0, 0, 303], [0, 2, 7], [0, 1, 348], [0, 0, 301]] [[0, 3, 16]] 11 +1 2 2066405.630 2066405.630 2066412.893 #ffc0cb 1.0 ProfTask <13> 152 +1 2 2066421.100 2066421.100 2066427.548 #ffc0cb 1.0 ProfTask <14> 153 +1 2 2066471.431 2066471.431 2066479.071 #ffc0cb 1.0 ProfTask <13> 154 +1 2 2066505.171 2066535.583 2066593.473 #00fff6 1.0 legate::numpy::FillTask [CPU] <14> [[0, 2, 13], [0, 1, 305]] [[0, 2, 298], [0, 0, 304], [0, 0, 42], [0, 1, 350]] [[0, 3, 16]] 299 +1 2 2067346.675 2067346.675 2067354.303 #ffc0cb 1.0 ProfTask <15> 155 +1 2 2067387.727 2067387.727 2067394.617 #ffc0cb 1.0 ProfTask <16> 156 +1 2 2067442.872 2067442.872 2067451.090 #ffc0cb 1.0 ProfTask <16> 157 +1 2 2067474.731 2067474.731 2067480.297 #ffc0cb 1.0 ProfTask <17> 158 +1 2 2067488.729 2067488.729 2067495.305 #ffc0cb 1.0 ProfTask <15> 159 +1 2 2067532.311 2067532.311 2067539.293 #ffc0cb 1.0 ProfTask <17> 160 +1 2 2067571.934 2067571.934 2067579.663 #ffc0cb 1.0 ProfTask <18> 161 +1 2 2067606.592 2067606.592 2067612.221 #ffc0cb 1.0 ProfTask <15> 162 +1 2 2067621.464 2067621.464 2067627.153 #ffc0cb 1.0 ProfTask <18> 163 +1 2 2067662.795 2067662.795 2067670.163 #ffc0cb 1.0 ProfTask <17> 164 +1 2 2067679.315 2067679.315 2067686.512 #ffc0cb 1.0 ProfTask <19> 165 +1 2 2067705.097 2067705.097 2067711.610 #ffc0cb 1.0 ProfTask <19> 166 +1 2 2067719.563 2067719.563 2067726.024 #ffc0cb 1.0 ProfTask <20> 167 +1 2 2067760.488 2067760.488 2067767.837 #ffc0cb 1.0 ProfTask <20> 168 +1 2 2067834.393 2067834.393 2067841.326 #ffc0cb 1.0 ProfTask <19> 169 +1 2 2067867.718 2067867.718 2067875.021 #ffc0cb 1.0 ProfTask <21> 170 +1 2 2067900.658 2067900.658 2067906.286 #ffc0cb 1.0 ProfTask <19> 171 +1 2 2067951.131 2067951.131 2067956.251 #ffc0cb 1.0 ProfTask <21> 172 +1 2 2067963.814 2067963.814 2067967.314 #ffc0cb 1.0 ProfTask <22> 173 +1 2 2068872.288 2068872.288 2068882.867 #ffc0cb 1.0 ProfTask <24> 174 +1 2 2069241.423 2069260.928 2070348.048 #ff7a00 1.0 legate::numpy::FusedOpTask [CPU] <23> [[0, 0, 377]] [[0, 0, 309], [0, 1, 354], [0, 2, 244], [0, 2, 299], [0, 0, 321], [0, 0, 311], [0, 2, 11]] [[0, 3, 16]] 13 +1 2 2070377.866 2070377.866 2070383.587 #ffc0cb 1.0 ProfTask <23> 175 +1 2 2070819.172 2070819.172 2070828.288 #ffc0cb 1.0 ProfTask <35> 176 +1 2 2070840.483 2070840.483 2070848.019 #ffc0cb 1.0 ProfTask <36> 177 +1 2 2070858.887 2070858.887 2070866.815 #ffc0cb 1.0 ProfTask <37> 178 +1 2 2071135.872 2071135.872 2071143.400 #ffc0cb 1.0 ProfTask <35> 179 +1 2 2071175.560 2071175.560 2071188.129 #ffc0cb 1.0 ProfTask <38> 180 +1 2 2071419.524 2071441.366 2072373.142 #ff7a00 1.0 legate::numpy::FusedOpTask [CPU] <35> [[0, 0, 458]] [[0, 1, 379], [0, 0, 320], [0, 0, 322], [0, 0, 73]] [[0, 3, 16]] 15 +1 2 2072407.594 2072407.594 2072415.756 #ffc0cb 1.0 ProfTask <35> 181 +1 2 2223654.660 2223654.660 2223670.393 #ffc0cb 1.0 ProfTask <1> 182 +1 2 2223681.067 2223681.067 2223688.333 #ffc0cb 1.0 ProfTask <50> 183 +1 2 2223729.950 2223729.950 2223735.924 #ffc0cb 1.0 ProfTask <1> 184 +1 2 2223828.994 2223828.994 2223833.763 #ffc0cb 1.0 ProfTask <50> 185 +1 2 2223878.262 2223878.262 2223882.918 #ffc0cb 1.0 ProfTask <51> 186 +1 2 2223928.589 2223928.589 2223933.189 #ffc0cb 1.0 ProfTask <51> 187 +1 2 2223979.621 2223979.621 2223984.034 #ffc0cb 1.0 ProfTask <52> 188 +1 2 2224047.331 2224047.331 2224051.623 #ffc0cb 1.0 ProfTask <52> 189 +1 2 2224101.138 2224101.138 2224106.757 #ffc0cb 1.0 ProfTask <53> 190 +1 2 2224148.335 2224148.335 2224161.362 #ffc0cb 1.0 ProfTask <35> 191 +1 2 2224186.534 2224186.534 2224191.200 #ffc0cb 1.0 ProfTask <50> 192 +1 2 2224220.301 2224220.301 2224223.906 #ffc0cb 1.0 ProfTask <6> 193 +1 2 2224253.499 2224253.499 2224257.289 #ffc0cb 1.0 ProfTask <50> 194 +1 2 2224316.993 2224316.993 2224321.896 #ffc0cb 1.0 ProfTask <53> 195 +1 2 2224371.021 2224371.021 2224376.481 #ffc0cb 1.0 ProfTask <50> 196 +1 2 2224382.616 2224382.616 2224387.519 #ffc0cb 1.0 ProfTask <54> 197 +1 2 2224404.275 2224404.275 2224409.090 #ffc0cb 1.0 ProfTask <8> 198 +1 2 2224422.632 2224422.632 2224427.511 #ffc0cb 1.0 ProfTask <51> 199 +1 2 2224432.534 2224432.534 2224435.672 #ffc0cb 1.0 ProfTask <50> 200 +1 2 2224462.197 2224462.197 2224466.176 #ffc0cb 1.0 ProfTask <23> 201 +1 2 2224561.477 2224561.477 2224567.447 #ffc0cb 1.0 ProfTask <50> 202 +1 2 2224577.316 2224577.316 2224583.749 #ffc0cb 1.0 ProfTask <23> 203 +1 2 2224592.176 2224592.176 2224597.422 #ffc0cb 1.0 ProfTask <50> 204 +1 2 2224605.256 2224605.256 2224611.578 #ffc0cb 1.0 ProfTask <35> 205 +1 2 2224625.618 2224625.618 2224631.298 #ffc0cb 1.0 ProfTask <50> 206 +1 2 2224640.500 2224640.500 2224647.306 #ffc0cb 1.0 ProfTask <10> 207 +1 2 2224655.645 2224655.645 2224662.140 #ffc0cb 1.0 ProfTask <50> 208 +1 2 2224723.627 2224723.627 2224727.850 #ffc0cb 1.0 ProfTask <54> 209 +1 2 2224771.060 2224771.060 2224775.847 #ffc0cb 1.0 ProfTask <55> 210 +1 2 2224811.759 2224811.759 2224816.039 #ffc0cb 1.0 ProfTask <52> 211 +1 2 2224822.127 2224822.127 2224825.941 #ffc0cb 1.0 ProfTask <55> 212 +1 2 2224867.885 2224867.885 2224872.650 #ffc0cb 1.0 ProfTask <56> 213 +1 2 2224902.872 2224902.872 2224908.376 #ffc0cb 1.0 ProfTask <53> 214 +1 2 2224914.147 2224914.147 2224917.592 #ffc0cb 1.0 ProfTask <56> 215 +1 2 2224963.214 2224963.214 2224967.510 #ffc0cb 1.0 ProfTask <57> 216 +1 2 2225013.096 2225013.096 2225017.772 #ffc0cb 1.0 ProfTask <57> 217 +1 2 2225061.833 2225061.833 2225067.872 #ffc0cb 1.0 ProfTask <58> 218 +1 2 2225110.405 2225110.405 2225115.363 #ffc0cb 1.0 ProfTask <58> 219 +1 2 2225145.405 2225145.405 2225149.977 #ffc0cb 1.0 ProfTask <1> 220 +1 2 2225157.536 2225157.536 2225162.322 #ffc0cb 1.0 ProfTask <54> 221 +1 2 2225219.074 2225219.074 2225225.623 #ffc0cb 1.0 ProfTask <55> 222 +1 2 2225247.956 2225247.956 2225252.965 #ffc0cb 1.0 ProfTask <56> 223 +1 2 2225278.124 2225278.124 2225284.676 #ffc0cb 1.0 ProfTask <57> 224 +1 2 2225330.082 2225330.082 2225334.333 #ffc0cb 1.0 ProfTask <0> 225 diff --git a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000003.tsv b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000003.tsv new file mode 100644 index 000000000..1e74f88b1 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000003.tsv @@ -0,0 +1,20 @@ +level level_ready ready start end color opacity title initiation in out children parents prof_uid +1 1 1134192.460 1134192.460 1887460.195 #eb00ff 1.0 legion_python_main <1> [[0, 1, 82], [0, 1, 119]] [[0, 0, 227], [0, 0, 19], [0, 0, 245]] [[0, 2, 7], [0, 2, 299], [0, 2, 13], [0, 2, 244], [0, 2, 9], [0, 2, 15], [0, 2, 298], [0, 2, 11]] 16 +1 1 1887460.195 1887460.195 1887589.038 #eb00ff 0.15 legion_python_main <1> (waiting) 16 +1 1 1887589.038 1887589.038 1887666.489 #eb00ff 0.45 legion_python_main <1> (ready) 16 +1 1 1887666.489 1887666.489 1887795.983 #eb00ff 1.0 legion_python_main <1> 16 +1 1 1887795.983 1887795.983 1887960.477 #eb00ff 0.15 legion_python_main <1> (waiting) 16 +1 1 1887960.477 1887960.477 1888027.844 #eb00ff 0.45 legion_python_main <1> (ready) 16 +1 1 1888027.844 1888027.844 2004013.143 #eb00ff 1.0 legion_python_main <1> 16 +1 1 2004013.143 2004013.143 2004103.065 #eb00ff 0.15 legion_python_main <1> (waiting) 16 +1 1 2004103.065 2004103.065 2004155.450 #eb00ff 0.45 legion_python_main <1> (ready) 16 +1 1 2004155.450 2004155.450 2071175.689 #eb00ff 1.0 legion_python_main <1> 16 +1 1 2071175.689 2071175.689 2071586.179 #eb00ff 0.15 legion_python_main <1> (waiting) 16 +1 1 2071586.179 2071586.179 2071636.356 #eb00ff 0.45 legion_python_main <1> (ready) 16 +1 1 2071636.356 2071636.356 2071651.215 #eb00ff 1.0 legion_python_main <1> 16 +1 1 2071651.215 2071651.215 2072431.368 #eb00ff 0.15 legion_python_main <1> (waiting) 16 +1 1 2072431.368 2072431.368 2072465.988 #eb00ff 0.45 legion_python_main <1> (ready) 16 +1 1 2072465.988 2072465.988 2125746.910 #eb00ff 1.0 legion_python_main <1> 16 +1 1 2125746.910 2125746.910 2125806.643 #eb00ff 0.15 legion_python_main <1> (waiting) 16 +1 1 2125806.643 2125806.643 2125906.215 #eb00ff 0.45 legion_python_main <1> (ready) 16 +1 1 2125906.215 2125906.215 2223592.200 #eb00ff 1.0 legion_python_main <1> 16 diff --git a/examples/testbench/legion_prof/tsv/all (CPU)_util.tsv b/examples/testbench/legion_prof/tsv/all (CPU)_util.tsv new file mode 100644 index 000000000..b5a809961 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/all (CPU)_util.tsv @@ -0,0 +1,206 @@ +time count +0.000 0.00 +1131871.414 1.00 +1131877.823 0.00 +1131902.582 1.00 +1131907.442 0.00 +1131967.180 1.00 +1131973.556 0.00 +1887540.878 1.00 +1887549.090 0.00 +2004081.928 1.00 +2004089.422 0.00 +2064305.095 1.00 +2064310.462 0.00 +2064366.713 1.00 +2064373.269 0.00 +2064467.966 1.00 +2064474.773 0.00 +2064854.771 1.00 +2064860.185 0.00 +2064917.697 1.00 +2065292.716 0.00 +2065321.206 1.00 +2065629.402 0.00 +2065651.028 1.00 +2065655.364 0.00 +2065660.845 1.00 +2065664.930 0.00 +2065670.191 1.00 +2065674.528 0.00 +2065678.796 1.00 +2065682.654 0.00 +2065686.872 1.00 +2065690.098 0.00 +2065694.309 1.00 +2065697.477 0.00 +2065703.630 1.00 +2065708.390 0.00 +2065714.725 1.00 +2065719.262 0.00 +2065723.840 1.00 +2065727.832 0.00 +2065780.941 1.00 +2066111.116 0.00 +2066144.783 1.00 +2066215.987 0.00 +2066245.594 1.00 +2066251.163 0.00 +2066259.095 1.00 +2066264.225 0.00 +2066301.621 1.00 +2066377.311 0.00 +2066405.630 1.00 +2066412.893 0.00 +2066421.100 1.00 +2066427.548 0.00 +2066471.431 1.00 +2066479.071 0.00 +2066535.583 1.00 +2066593.473 0.00 +2067346.675 1.00 +2067354.303 0.00 +2067387.727 1.00 +2067394.617 0.00 +2067442.872 1.00 +2067451.090 0.00 +2067474.731 1.00 +2067480.297 0.00 +2067488.729 1.00 +2067495.305 0.00 +2067532.311 1.00 +2067539.293 0.00 +2067571.934 1.00 +2067579.663 0.00 +2067606.592 1.00 +2067612.221 0.00 +2067621.464 1.00 +2067627.153 0.00 +2067662.795 1.00 +2067670.163 0.00 +2067679.315 1.00 +2067686.512 0.00 +2067705.097 1.00 +2067711.610 0.00 +2067719.563 1.00 +2067726.024 0.00 +2067760.488 1.00 +2067767.837 0.00 +2067834.393 1.00 +2067841.326 0.00 +2067867.718 1.00 +2067875.021 0.00 +2067900.658 1.00 +2067906.286 0.00 +2067951.131 1.00 +2067956.251 0.00 +2067963.814 1.00 +2067967.314 0.00 +2068872.288 1.00 +2068882.867 0.00 +2069260.928 1.00 +2070348.048 0.00 +2070377.866 1.00 +2070383.587 0.00 +2070819.172 1.00 +2070828.288 0.00 +2070840.483 1.00 +2070848.019 0.00 +2070858.887 1.00 +2070866.815 0.00 +2071135.872 1.00 +2071143.400 0.00 +2071175.560 1.00 +2071188.129 0.00 +2071441.366 1.00 +2072373.142 0.00 +2072407.594 1.00 +2072415.756 0.00 +2223654.660 1.00 +2223670.393 0.00 +2223681.067 1.00 +2223688.333 0.00 +2223729.950 1.00 +2223735.924 0.00 +2223828.994 1.00 +2223833.763 0.00 +2223878.262 1.00 +2223882.918 0.00 +2223928.589 1.00 +2223933.189 0.00 +2223979.621 1.00 +2223984.034 0.00 +2224047.331 1.00 +2224051.623 0.00 +2224101.138 1.00 +2224106.757 0.00 +2224148.335 1.00 +2224161.362 0.00 +2224186.534 1.00 +2224191.200 0.00 +2224220.301 1.00 +2224223.906 0.00 +2224253.499 1.00 +2224257.289 0.00 +2224316.993 1.00 +2224321.896 0.00 +2224371.021 1.00 +2224376.481 0.00 +2224382.616 1.00 +2224387.519 0.00 +2224404.275 1.00 +2224409.090 0.00 +2224422.632 1.00 +2224427.511 0.00 +2224432.534 1.00 +2224435.672 0.00 +2224462.197 1.00 +2224466.176 0.00 +2224561.477 1.00 +2224567.447 0.00 +2224577.316 1.00 +2224583.749 0.00 +2224592.176 1.00 +2224597.422 0.00 +2224605.256 1.00 +2224611.578 0.00 +2224625.618 1.00 +2224631.298 0.00 +2224640.500 1.00 +2224647.306 0.00 +2224655.645 1.00 +2224662.140 0.00 +2224723.627 1.00 +2224727.850 0.00 +2224771.060 1.00 +2224775.847 0.00 +2224811.759 1.00 +2224816.039 0.00 +2224822.127 1.00 +2224825.941 0.00 +2224867.885 1.00 +2224872.650 0.00 +2224902.872 1.00 +2224908.376 0.00 +2224914.147 1.00 +2224917.592 0.00 +2224963.214 1.00 +2224967.510 0.00 +2225013.096 1.00 +2225017.772 0.00 +2225061.833 1.00 +2225067.872 0.00 +2225110.405 1.00 +2225115.363 0.00 +2225145.405 1.00 +2225149.977 0.00 +2225157.536 1.00 +2225162.322 0.00 +2225219.074 1.00 +2225225.623 0.00 +2225247.956 1.00 +2225252.965 0.00 +2225278.124 1.00 +2225284.676 0.00 +2225330.082 1.00 +2225334.333 0.00 diff --git a/examples/testbench/legion_prof/tsv/all (Python)_util.tsv b/examples/testbench/legion_prof/tsv/all (Python)_util.tsv new file mode 100644 index 000000000..2aea9b2e8 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/all (Python)_util.tsv @@ -0,0 +1,16 @@ +time count +0.000 0.00 +1134192.460 1.00 +1887460.195 0.00 +1887666.489 1.00 +1887795.983 0.00 +1888027.844 1.00 +2004013.143 0.00 +2004155.450 1.00 +2071175.689 0.00 +2071636.356 1.00 +2071651.215 0.00 +2072465.988 1.00 +2125746.910 0.00 +2125906.215 1.00 +2223592.200 0.00 diff --git a/examples/testbench/legion_prof/tsv/all (System Memory)_util.tsv b/examples/testbench/legion_prof/tsv/all (System Memory)_util.tsv new file mode 100644 index 000000000..f6914d7c8 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/all (System Memory)_util.tsv @@ -0,0 +1,16 @@ +time count +0.000 0.00 +2064650.117 0.00 +2065147.467 0.00 +2065598.615 0.00 +2069053.346 0.00 +2069121.527 0.00 +2071048.359 0.00 +2071113.099 0.00 +2224133.183 0.00 +2224204.270 0.00 +2224388.739 0.00 +2224448.793 0.00 +2224510.529 0.00 +2224556.754 0.00 +2224609.631 0.00 diff --git a/examples/testbench/legion_prof/tsv/all (Utility)_util.tsv b/examples/testbench/legion_prof/tsv/all (Utility)_util.tsv new file mode 100644 index 000000000..67767ff36 --- /dev/null +++ b/examples/testbench/legion_prof/tsv/all (Utility)_util.tsv @@ -0,0 +1,648 @@ +time count +0.000 0.00 +1131662.511 0.50 +1131743.730 0.00 +1131750.448 0.50 +1131777.645 1.00 +1131796.014 0.50 +1131842.077 1.00 +1131847.857 0.50 +1131875.771 1.00 +1131881.475 0.50 +1131943.421 1.00 +1131945.331 0.50 +1132089.267 0.00 +1132112.899 0.50 +1132119.532 0.00 +1887393.247 0.50 +1887455.149 0.00 +1887469.337 0.50 +1887480.054 1.00 +1887485.915 0.50 +1887516.954 0.00 +1887535.605 0.50 +1887638.705 0.00 +1887666.368 0.50 +1887676.134 0.00 +1887805.820 0.50 +1887841.593 0.00 +1887867.399 0.50 +1887872.806 0.00 +1887873.868 0.50 +1887911.228 0.00 +1887939.316 0.50 +1887942.877 1.00 +1887943.976 0.50 +1887986.727 0.00 +1888015.869 0.50 +1888019.680 0.00 +2004015.227 0.50 +2004050.023 1.00 +2004051.755 0.50 +2004073.805 0.00 +2004078.517 0.50 +2004100.736 1.00 +2004106.103 0.50 +2004121.149 0.00 +2004142.069 0.50 +2004145.762 0.00 +2064129.215 0.50 +2064271.214 1.00 +2064275.023 0.50 +2064295.923 1.00 +2064297.548 0.50 +2064314.243 1.00 +2064318.757 0.50 +2064336.527 1.00 +2064342.601 0.50 +2064358.130 0.00 +2064363.504 0.50 +2064372.340 1.00 +2064378.142 0.50 +2064439.767 1.00 +2064440.663 0.50 +2064491.009 1.00 +2064519.103 0.50 +2064684.275 1.00 +2064696.490 0.50 +2064796.569 1.00 +2064815.504 0.50 +2064851.735 1.00 +2064912.591 0.50 +2064920.144 0.00 +2064938.430 0.50 +2064939.541 1.00 +2064943.295 0.50 +2064949.158 1.00 +2064959.621 0.50 +2064960.112 0.00 +2064966.408 0.50 +2064974.539 1.00 +2064979.176 0.50 +2064985.140 1.00 +2064987.569 0.50 +2065001.319 1.00 +2065005.803 0.50 +2065008.315 0.00 +2065011.887 0.50 +2065021.505 1.00 +2065026.318 0.50 +2065074.606 0.00 +2065080.934 0.50 +2065087.801 1.00 +2065093.099 0.50 +2065175.981 1.00 +2065183.321 0.50 +2065193.676 1.00 +2065222.977 0.50 +2065259.007 0.00 +2065260.230 0.50 +2065279.744 0.00 +2065285.153 0.50 +2065290.919 0.00 +2065298.864 0.50 +2065304.046 0.00 +2065311.838 0.50 +2065314.647 1.00 +2065323.070 0.50 +2065330.219 1.00 +2065357.418 0.50 +2065374.476 0.00 +2065376.792 0.50 +2065395.290 1.00 +2065404.409 0.50 +2065406.576 0.00 +2065413.072 0.50 +2065431.175 1.00 +2065437.527 0.50 +2065462.884 1.00 +2065463.379 0.50 +2065478.480 1.00 +2065518.172 0.50 +2065531.848 1.00 +2065541.822 0.50 +2065555.739 1.00 +2065572.335 0.50 +2065594.419 1.00 +2065660.636 0.50 +2065705.960 1.00 +2065742.165 0.50 +2065761.473 1.00 +2065773.170 0.50 +2065786.367 0.00 +2065798.928 0.50 +2065820.023 1.00 +2065822.530 0.50 +2065831.153 1.00 +2065836.685 0.50 +2065841.234 1.00 +2065844.525 0.50 +2065873.896 1.00 +2065876.598 0.50 +2065899.023 1.00 +2065909.599 0.50 +2065965.066 0.00 +2065981.765 0.50 +2065991.392 1.00 +2066001.818 0.50 +2066047.656 1.00 +2066048.507 0.50 +2066070.084 1.00 +2066079.325 0.50 +2066081.533 0.00 +2066094.843 0.50 +2066102.388 1.00 +2066108.878 0.50 +2066135.812 1.00 +2066147.756 0.50 +2066156.610 1.00 +2066197.991 0.50 +2066210.980 0.00 +2066220.415 0.50 +2066235.493 1.00 +2066242.836 0.50 +2066253.371 1.00 +2066284.954 0.50 +2066303.311 0.00 +2066319.571 0.50 +2066330.336 1.00 +2066339.047 0.50 +2066349.384 1.00 +2066355.745 0.50 +2066365.568 1.00 +2066367.395 0.50 +2066384.163 1.00 +2066388.487 0.50 +2066394.872 1.00 +2066398.119 0.50 +2066420.978 1.00 +2066445.626 0.50 +2066461.318 1.00 +2066463.174 0.50 +2066479.174 1.00 +2066483.256 0.50 +2066515.270 0.00 +2066529.232 0.50 +2066533.681 0.00 +2066627.150 0.50 +2066634.424 0.00 +2066642.926 0.50 +2066670.867 0.00 +2066698.558 0.50 +2066703.281 0.00 +2067301.801 0.50 +2067308.792 1.00 +2067319.124 0.50 +2067341.192 1.00 +2067367.273 0.50 +2067368.328 0.00 +2067388.990 0.50 +2067395.492 1.00 +2067401.134 0.50 +2067420.603 0.00 +2067421.580 0.50 +2067439.875 1.00 +2067454.232 0.50 +2067455.291 0.00 +2067472.127 0.50 +2067474.609 1.00 +2067512.496 0.50 +2067527.751 1.00 +2067549.614 0.50 +2067566.785 1.00 +2067579.536 0.50 +2067590.043 0.00 +2067602.973 0.50 +2067607.985 1.00 +2067641.326 0.50 +2067641.791 0.00 +2067656.500 0.50 +2067663.628 1.00 +2067679.151 0.50 +2067681.707 0.00 +2067705.309 0.50 +2067706.016 1.00 +2067735.601 0.50 +2067752.698 0.00 +2067762.961 0.50 +2067774.098 1.00 +2067780.707 0.50 +2067810.448 0.00 +2067816.908 0.50 +2067830.114 1.00 +2067845.249 0.50 +2067868.331 1.00 +2067873.646 0.50 +2067911.279 1.00 +2067928.423 0.50 +2067944.485 0.00 +2067945.510 0.50 +2067997.003 0.00 +2068005.933 0.50 +2068011.781 1.00 +2068016.154 0.50 +2068034.238 0.00 +2068034.716 0.50 +2068050.192 1.00 +2068053.972 0.50 +2068081.412 0.00 +2068099.841 0.50 +2068103.496 0.00 +2068718.776 0.50 +2068819.324 0.00 +2068819.800 0.50 +2068838.765 1.00 +2068843.921 0.50 +2068845.196 0.00 +2068851.002 0.50 +2068869.449 1.00 +2068873.194 0.50 +2068888.720 1.00 +2068893.183 0.50 +2068895.729 0.00 +2068899.579 0.50 +2068920.805 1.00 +2068925.382 0.50 +2068967.735 0.00 +2068981.108 0.50 +2068987.640 1.00 +2068992.969 0.50 +2069083.012 1.00 +2069106.618 0.50 +2069147.523 1.00 +2069165.785 0.50 +2069234.110 1.00 +2069255.619 0.50 +2069272.218 1.00 +2069279.820 0.50 +2069292.337 0.00 +2069296.143 0.50 +2069304.388 0.00 +2069306.933 0.50 +2069322.918 1.00 +2069326.187 0.50 +2069340.380 1.00 +2069345.572 0.50 +2069352.748 1.00 +2069356.475 0.50 +2069374.511 1.00 +2069390.333 0.50 +2069390.747 0.00 +2069407.691 0.50 +2069418.366 1.00 +2069425.098 0.50 +2069432.480 1.00 +2069437.167 0.50 +2069444.029 1.00 +2069449.166 0.50 +2069456.488 1.00 +2069488.484 0.50 +2069500.754 0.00 +2069509.402 0.50 +2069521.646 1.00 +2069528.013 0.50 +2069535.567 0.00 +2069535.964 0.50 +2069555.271 1.00 +2069565.176 0.50 +2069568.751 0.00 +2069581.553 0.50 +2069631.187 1.00 +2069638.355 0.50 +2069659.704 1.00 +2069663.194 0.50 +2069689.634 1.00 +2069729.027 0.50 +2069736.823 0.00 +2069756.624 0.50 +2069762.525 1.00 +2069769.736 0.50 +2069778.737 1.00 +2069783.086 0.50 +2069790.728 1.00 +2069792.334 0.50 +2069810.149 1.00 +2069831.359 0.50 +2069849.405 1.00 +2069870.888 0.50 +2069877.565 0.00 +2069886.021 0.50 +2069894.631 0.00 +2069907.512 0.50 +2069911.435 1.00 +2069922.920 0.50 +2069941.733 0.00 +2069947.237 0.50 +2069960.854 1.00 +2069966.367 0.50 +2069974.700 0.00 +2069978.389 0.50 +2069998.435 1.00 +2070005.542 0.50 +2070010.923 0.00 +2070014.959 0.50 +2070032.572 1.00 +2070036.122 0.50 +2070040.870 1.00 +2070044.094 0.50 +2070048.472 1.00 +2070051.774 0.50 +2070056.245 1.00 +2070060.009 0.50 +2070067.424 1.00 +2070073.169 0.50 +2070075.913 0.00 +2070081.771 0.50 +2070087.538 0.00 +2070094.373 0.50 +2070099.524 0.00 +2070101.685 0.50 +2070107.471 1.00 +2070108.096 0.50 +2070113.258 0.00 +2070116.927 0.50 +2070120.860 1.00 +2070123.965 0.50 +2070125.106 0.00 +2070131.877 0.50 +2070133.033 1.00 +2070136.189 0.50 +2070139.695 0.00 +2070141.398 0.50 +2070145.072 0.00 +2070148.618 0.50 +2070150.171 1.00 +2070154.829 0.50 +2070155.876 0.00 +2070159.785 0.50 +2070164.050 0.00 +2070164.942 0.50 +2070170.490 0.00 +2070311.079 0.50 +2070326.801 0.00 +2070329.126 0.50 +2070369.981 0.00 +2070370.602 0.50 +2070377.373 0.00 +2070385.334 0.50 +2070388.785 1.00 +2070392.574 0.50 +2070426.871 0.00 +2070469.051 0.50 +2070475.390 0.00 +2070698.337 0.50 +2070781.152 1.00 +2070791.932 0.50 +2070806.013 0.00 +2070812.162 0.50 +2070823.632 1.00 +2070835.663 0.50 +2070843.027 0.00 +2070851.863 0.50 +2070860.505 1.00 +2070865.751 0.50 +2070872.848 1.00 +2070873.378 0.50 +2070889.815 1.00 +2070895.005 0.50 +2070895.393 0.00 +2070901.054 0.50 +2070912.589 1.00 +2070917.128 0.50 +2070962.074 0.00 +2070975.805 0.50 +2070982.478 1.00 +2070987.821 0.50 +2071077.383 1.00 +2071100.087 0.50 +2071113.591 1.00 +2071152.023 0.50 +2071213.450 1.00 +2071219.974 0.50 +2071426.355 1.00 +2071432.285 0.50 +2071450.221 1.00 +2071458.232 0.50 +2071475.719 0.00 +2071485.324 0.50 +2071501.085 1.00 +2071507.744 0.50 +2071649.220 0.00 +2071675.248 0.50 +2071681.510 0.00 +2071933.817 0.50 +2071943.818 1.00 +2071946.793 0.50 +2071971.528 1.00 +2071975.936 0.50 +2072004.306 0.00 +2072030.588 0.50 +2072036.622 0.00 +2072345.424 0.50 +2072358.717 0.00 +2072364.643 0.50 +2072392.367 0.00 +2072393.575 0.50 +2072400.046 0.00 +2072409.183 0.50 +2072416.299 1.00 +2072424.207 0.50 +2072446.614 0.00 +2072472.619 0.50 +2072478.026 0.00 +2125594.978 0.50 +2125632.752 0.00 +2125703.515 0.50 +2125736.612 0.00 +2125756.869 0.50 +2125782.049 0.00 +2125799.828 0.50 +2125832.850 0.00 +2125852.771 0.50 +2125854.803 1.00 +2125859.590 0.50 +2125862.182 0.00 +2125867.246 0.50 +2125872.861 1.00 +2125873.486 0.50 +2125881.155 0.00 +2142117.664 0.50 +2142134.517 1.00 +2142169.070 0.50 +2142358.907 0.00 +2142379.766 0.50 +2142408.752 0.00 +2142421.085 0.50 +2142427.615 1.00 +2142458.056 0.50 +2142459.315 0.00 +2142479.998 0.50 +2142484.084 1.00 +2142508.841 0.50 +2142515.953 0.00 +2142532.780 0.50 +2142536.863 1.00 +2142562.055 0.50 +2142567.397 0.00 +2142583.695 0.50 +2142588.483 1.00 +2142608.823 0.50 +2142626.280 1.00 +2142703.362 0.50 +2142703.838 0.00 +2142733.551 0.50 +2142734.195 1.00 +2142782.824 0.50 +2142785.276 0.00 +2142814.771 0.50 +2142815.494 1.00 +2142861.600 0.50 +2142864.105 0.00 +2142883.833 0.50 +2142886.938 1.00 +2142927.830 0.50 +2142935.202 0.00 +2142956.698 0.50 +2142960.779 1.00 +2142996.567 0.50 +2143001.829 0.00 +2143017.553 0.50 +2143022.880 1.00 +2143036.927 0.50 +2143044.755 0.00 +2143061.789 0.50 +2143069.506 1.00 +2143079.681 0.50 +2143090.109 0.00 +2143099.040 0.50 +2143115.876 1.00 +2143122.640 0.50 +2143135.627 0.00 +2143142.620 0.50 +2143148.702 0.00 +2143155.140 0.50 +2143156.407 1.00 +2143161.598 0.50 +2143162.254 0.00 +2143171.528 0.50 +2143172.191 1.00 +2143177.719 0.50 +2143178.522 0.00 +2143185.422 0.50 +2143187.525 1.00 +2143191.048 0.50 +2143193.553 0.00 +2143198.224 0.50 +2143201.377 1.00 +2143203.776 0.50 +2143207.104 0.00 +2143211.338 0.50 +2143214.741 1.00 +2143217.153 0.50 +2143220.451 0.00 +2143224.599 0.50 +2143228.060 1.00 +2143230.439 0.50 +2143233.807 0.00 +2143237.897 0.50 +2143242.015 1.00 +2143243.990 0.50 +2143248.158 0.00 +2143251.772 0.50 +2143255.895 1.00 +2143257.547 0.50 +2143261.633 0.00 +2143265.286 0.50 +2143269.666 1.00 +2143270.949 0.50 +2143275.896 0.00 +2143278.912 0.50 +2143284.717 1.00 +2143285.057 0.50 +2143290.933 0.00 +2143293.352 0.50 +2143298.720 0.00 +2143299.577 0.50 +2143305.733 0.00 +2143306.574 0.50 +2143312.669 0.00 +2143314.699 0.50 +2143320.490 1.00 +2143321.041 0.50 +2143326.021 0.00 +2223542.740 0.50 +2223616.705 1.00 +2223642.437 0.50 +2223677.391 1.00 +2223704.338 0.50 +2223734.963 1.00 +2223802.748 0.50 +2223832.624 1.00 +2223858.909 0.50 +2223882.005 1.00 +2223910.536 0.50 +2223931.926 1.00 +2223959.271 0.50 +2223980.553 1.00 +2224025.655 0.50 +2224049.819 1.00 +2224080.825 0.50 +2224105.842 1.00 +2224166.333 0.50 +2224191.035 1.00 +2224232.413 0.50 +2224263.865 1.00 +2224296.398 0.50 +2224318.069 1.00 +2224347.889 0.50 +2224355.751 0.00 +2224375.532 0.50 +2224376.294 1.00 +2224402.223 0.50 +2224417.523 0.00 +2224426.629 0.50 +2224439.970 1.00 +2224479.424 0.50 +2224502.241 1.00 +2224530.123 0.50 +2224548.176 1.00 +2224579.936 0.50 +2224600.946 1.00 +2224638.734 0.50 +2224661.822 1.00 +2224698.721 0.50 +2224723.490 1.00 +2224750.426 0.50 +2224773.650 1.00 +2224786.089 0.50 +2224803.090 0.00 +2224815.571 0.50 +2224820.990 1.00 +2224845.602 0.50 +2224869.634 1.00 +2224881.576 0.50 +2224899.178 0.00 +2224907.668 0.50 +2224920.916 1.00 +2224944.521 0.50 +2224966.963 1.00 +2224994.594 0.50 +2225014.514 1.00 +2225039.487 0.50 +2225062.158 1.00 +2225090.887 0.50 +2225112.927 1.00 +2225125.099 0.50 +2225132.778 0.00 +2225153.557 0.50 +2225195.458 1.00 +2225195.976 0.50 +2225219.705 1.00 +2225224.165 0.50 +2225253.992 1.00 +2225258.537 0.50 +2225281.446 1.00 +2225309.583 0.50 +2225312.131 0.00 +2225335.279 0.50 +2225341.226 0.00 diff --git a/examples/testbench/test.py b/examples/testbench/test.py new file mode 100644 index 000000000..951d73a04 --- /dev/null +++ b/examples/testbench/test.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime + +#import pdb +#pdb.set_trace() +import legate.numpy as np + +#import numpy as np +#import numpy as np +N=500000 +M=2 +b1 = np.zeros(N) +b2 = np.zeros(N) +b3 = np.zeros(N) +b4 = np.zeros(N) +b5 = np.zeros(N) + +b1.fill(2) +b2.fill(3) +b3.fill(4) + +#dummy ops +# dumb hack so the loop starts at nOps=10 +# so the window/pipe is empty +b3.fill(4) +b3.fill(4) +#gg=b1+b2+b3 +#print(gg) +#for i in range(10000): +for i in range(1000): + b1=b1+b2+b3+b4+b5+b1+b2+b3+b4+b5+b1 + #b3+=b3 + #b3=b1+b2 + +#print(b3) +""" +def shor_form(a): + a+=a + return a +def long_form(a): + a=a+a + return a +import ast,inspect +func_src = inspect.getsource(long_form) +entry_node = ast.parse(func_src) +print(ast.dump(entry_node)) + +func_src = inspect.getsource(shor_form) +entry_node = ast.parse(func_src) +print(ast.dump(entry_node)) + + + + +#a=a+a +#a=a+a +#b=mul_add(b, b1,b2) +#print(sum(g)) + + +long_form(b,b1,b2) +#c = np.sum(a, axis=0) +c = np.dot(a,b) +#c = np.dot(a,b) +#c = np.dot(a,b) + +#sink? +print(sum(c)) + + + +n1 = 300 +n2= 20 +a = npo.zeros((n1,n2)) +b = npo.zeros((N)) +c= npo.zeros((N)) +print("s",sum(long_form(a,b,c))) +a+=a +M=800000 +d0 = np.zeros(M) +d0.fill(1) +d1 = np.zeros(M) +d2 = np.zeros(M) +print(sum(e)) +""" diff --git a/src/fused/binary_op_template.inl b/src/fused/binary_op_template.inl index d3ab7e975..10e538033 100644 --- a/src/fused/binary_op_template.inl +++ b/src/fused/binary_op_template.inl @@ -97,7 +97,7 @@ static void binary_op_template(TaskContext& context) op_dispatch(args.op_code, BinaryOpDispatch{}, args); */ //std::cout<<"fused inputs"<().hi.x; + int nOps = 10;// inputs[0].shape<1>().hi.x; //std::cout<<"nops "<()); - int inputStart=4; + int inputStart=0; int outputStart=0; for (int i=0; i +#include +#include namespace legate { namespace numpy { @@ -54,39 +56,11 @@ struct BinaryOpImplBody { } }; -void inline_leaf_task(const Task *task, - const std::vector ®ions, - Context ctx, Runtime *runtime) -{ - printf("Hello from 'inline_leaf_task' being inlined into leaf 'fused op'\n"); -} + //op id refers not to the op's type, but the index in the list of fused ops void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) { - //grab all the stores - /* - const int nMetaDataArrs=7; - Store& inputStartsStore = context.inputs()[0]; - Store& outputStartsStore = context.inputs()[1]; - Store& offsetStartsStore = context.inputs()[2]; - Store& offsetsStore = context.inputs()[3]; - Store& reductionStartsStore = context.inputs()[4]; - Store& scalarStartsStore = context.inputs()[5]; - */ - //grab pointers to all the metadata arrays - //using ARG = legate_type_of; - //auto opRect = context.inputs()[0].shape<1>(); //iterator over range(0,nOps) - //auto offsetMetaRect = context.inputs()[3].shape<1>(); //iter over range(0, nInputs+nOutputs) - - /* - auto inputStarts = inputStartsStore.read_accessor().ptr(opRect); - auto outputStarts = outputStartsStore.read_accessor().ptr(opRect); - auto offsetStarts = offsetStartsStore.read_accessor().ptr(opRect); - auto offsets = offsetsStore.read_accessor().ptr(offsetMetaRect); - auto reductionStarts = reductionStartsStore.read_accessor().ptr(opRect); - auto scalarStarts = scalarStartsStore.read_accessor().ptr(opRect); - */ auto inputStarts = context.fusionMetadata.inputStarts; auto outputStarts = context.fusionMetadata.outputStarts; auto offsetStarts = context.fusionMetadata.offsetStarts; @@ -114,6 +88,7 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) //std::cout<<"packing input "<().hi.x; - //auto offsetMetaRect = context.inputs()[3].shape<1>(); - //std::cout<; - //const Store& offsetsStore = context.inputs()[3]; - //auto offsets = offsetsStore.read_accessor().ptr(offsetMetaRect); - - //const Store& taskIDStore = context.inputs()[6]; - //auto opRect = context.inputs()[6].shape<1>(); - //auto taskIDs = offsetsStore.read_accessor().ptr(opRect); - int nOps = context.fusionMetadata.nOps; - //pack inputs + //struct timeval start, end; MakeshiftSerializer ms; + //gettimeofday(&start, NULL); + for (int i=0; iindex_point; - for (int i=0; i< context.task_->regions.size();i++) + + //add appropriate region requirements for this op + std::vector reqIds = ms.getReqIds(); + for (int32_t reqIdx : reqIds) { - auto& req = context.task_->regions[i]; + auto& req = context.task_->regions[reqIdx]; leaf_launcher.add_region_requirement(req); - } - - leaf_launcher.enable_inlining=true; + } context.runtime_->execute_task(context.context_, leaf_launcher); } + //gettimeofday(&end, NULL); + + //gettimeofday(&end, NULL); + //printf("%ld\n", ((end.tv_sec * 1000000 + end.tv_usec) +// - (start.tv_sec * 1000000 + start.tv_usec))); + } namespace // unnamed diff --git a/time.sh b/time.sh new file mode 100644 index 000000000..ba3194669 --- /dev/null +++ b/time.sh @@ -0,0 +1 @@ +time ../legate.core/install/bin/legate -m cProfile -s tottime examples/testbench/test.py --cpus 2 > temp_file && head -n 20 temp_file From 4232c3c6e5c208c2a411cc825ea71da18ae3174a Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 3 Oct 2021 20:32:24 -0700 Subject: [PATCH 08/46] remove profiling files --- examples/benchmark.py | 52 - examples/black_scholes.py | 144 - examples/cg.py | 281 -- examples/gemm.py | 128 - examples/jacobi.py | 130 - examples/kmeans.py | 246 -- examples/kmeans_slow.py | 247 -- examples/kmeans_sort.py | 248 -- examples/linreg.py | 160 - examples/logreg.py | 172 -- examples/lstm_backward.py | 134 - examples/lstm_forward.py | 124 - examples/lstm_full.py | 429 --- examples/stencil.py | 107 - examples/testbench/contrived.py | 49 - .../dataflow_legion_python_main_1.pdf | Bin 33085 -> 0 bytes .../dataflow_legion_python_main_1.pdf | Bin 31513 -> 0 bytes .../event_graph_legion_python_main_1.pdf | Bin 27557 -> 0 bytes examples/testbench/decent_band/index.html | 115 - examples/testbench/decent_band/js/timeline.js | 2734 ----------------- examples/testbench/decent_band/js/util.js | 378 --- .../testbench/decent_band/legion_prof_ops.tsv | 90 - .../decent_band/legion_prof_processor.tsv | 9 - ...000,_System_Memory_0x1e00000000000000).tsv | 3 - .../decent_band/tsv/0 (CPU)_util.tsv | 288 -- .../decent_band/tsv/0 (Channel)_util.tsv | 4 - .../decent_band/tsv/0 (Python)_util.tsv | 14 - .../tsv/0 (System Memory)_util.tsv | 24 - .../decent_band/tsv/0 (Utility)_util.tsv | 924 ------ .../tsv/Mem_0x1e00000000000000.tsv | 12 - examples/testbench/decent_band/tsv/None.tsv | 5 - .../tsv/Proc_0x1d00000000000000.tsv | 297 -- .../tsv/Proc_0x1d00000000000001.tsv | 266 -- .../tsv/Proc_0x1d00000000000002.tsv | 93 - .../tsv/Proc_0x1d00000000000003.tsv | 52 - .../tsv/Proc_0x1d00000000000004.tsv | 17 - .../decent_band/tsv/all (CPU)_util.tsv | 288 -- .../decent_band/tsv/all (Channel)_util.tsv | 4 - .../decent_band/tsv/all (Python)_util.tsv | 14 - .../tsv/all (System Memory)_util.tsv | 24 - .../decent_band/tsv/all (Utility)_util.tsv | 924 ------ .../event_graph_legion_python_main_1.pdf | Bin 25345 -> 0 bytes examples/testbench/go.sh | 15 - .../dataflow_legion_python_main_1.pdf | Bin 31522 -> 0 bytes .../event_graph_legion_python_main_1.pdf | Bin 27545 -> 0 bytes examples/testbench/good_band/index.html | 115 - examples/testbench/good_band/js/timeline.js | 2734 ----------------- examples/testbench/good_band/js/util.js | 378 --- .../testbench/good_band/legion_prof_ops.tsv | 90 - .../good_band/legion_prof_processor.tsv | 9 - ...000,_System_Memory_0x1e00000000000000).tsv | 3 - .../testbench/good_band/tsv/0 (CPU)_util.tsv | 208 -- .../good_band/tsv/0 (Channel)_util.tsv | 4 - .../good_band/tsv/0 (Python)_util.tsv | 16 - .../good_band/tsv/0 (System Memory)_util.tsv | 24 - .../good_band/tsv/0 (Utility)_util.tsv | 992 ------ .../good_band/tsv/Mem_0x1e00000000000000.tsv | 12 - examples/testbench/good_band/tsv/None.tsv | 5 - .../good_band/tsv/Proc_0x1d00000000000000.tsv | 304 -- .../good_band/tsv/Proc_0x1d00000000000001.tsv | 287 -- .../good_band/tsv/Proc_0x1d00000000000002.tsv | 67 - .../good_band/tsv/Proc_0x1d00000000000003.tsv | 38 - .../good_band/tsv/Proc_0x1d00000000000004.tsv | 20 - .../good_band/tsv/all (CPU)_util.tsv | 208 -- .../good_band/tsv/all (Channel)_util.tsv | 4 - .../good_band/tsv/all (Python)_util.tsv | 16 - .../tsv/all (System Memory)_util.tsv | 24 - .../good_band/tsv/all (Utility)_util.tsv | 992 ------ .../dataflow_legion_python_main_1.pdf | Bin 33085 -> 0 bytes .../event_graph_legion_python_main_1.pdf | Bin 25345 -> 0 bytes examples/testbench/legion_prof/index.html | 115 - examples/testbench/legion_prof/js/timeline.js | 2734 ----------------- examples/testbench/legion_prof/js/util.js | 378 --- .../testbench/legion_prof/legion_prof_ops.tsv | 59 - .../legion_prof/legion_prof_processor.tsv | 6 - .../legion_prof/tsv/0 (CPU)_util.tsv | 206 -- .../legion_prof/tsv/0 (Python)_util.tsv | 16 - .../tsv/0 (System Memory)_util.tsv | 16 - .../legion_prof/tsv/0 (Utility)_util.tsv | 648 ---- .../tsv/Mem_0x1e00000000000000.tsv | 8 - .../tsv/Proc_0x1d00000000000000.tsv | 174 -- .../tsv/Proc_0x1d00000000000001.tsv | 169 - .../tsv/Proc_0x1d00000000000002.tsv | 103 - .../tsv/Proc_0x1d00000000000003.tsv | 20 - .../legion_prof/tsv/all (CPU)_util.tsv | 206 -- .../legion_prof/tsv/all (Python)_util.tsv | 16 - .../tsv/all (System Memory)_util.tsv | 16 - .../legion_prof/tsv/all (Utility)_util.tsv | 648 ---- examples/testbench/test.py | 104 - examples/wgrad.py | 112 - 90 files changed, 21549 deletions(-) delete mode 100644 examples/benchmark.py delete mode 100644 examples/black_scholes.py delete mode 100644 examples/cg.py delete mode 100644 examples/gemm.py delete mode 100644 examples/jacobi.py delete mode 100644 examples/kmeans.py delete mode 100644 examples/kmeans_slow.py delete mode 100644 examples/kmeans_sort.py delete mode 100644 examples/linreg.py delete mode 100644 examples/logreg.py delete mode 100644 examples/lstm_backward.py delete mode 100644 examples/lstm_forward.py delete mode 100644 examples/lstm_full.py delete mode 100644 examples/stencil.py delete mode 100644 examples/testbench/contrived.py delete mode 100644 examples/testbench/dataflow_legion_python_main_1.pdf delete mode 100644 examples/testbench/decent_band/dataflow_legion_python_main_1.pdf delete mode 100644 examples/testbench/decent_band/event_graph_legion_python_main_1.pdf delete mode 100644 examples/testbench/decent_band/index.html delete mode 100644 examples/testbench/decent_band/js/timeline.js delete mode 100644 examples/testbench/decent_band/js/util.js delete mode 100644 examples/testbench/decent_band/legion_prof_ops.tsv delete mode 100644 examples/testbench/decent_band/legion_prof_processor.tsv delete mode 100644 examples/testbench/decent_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv delete mode 100644 examples/testbench/decent_band/tsv/0 (CPU)_util.tsv delete mode 100644 examples/testbench/decent_band/tsv/0 (Channel)_util.tsv delete mode 100644 examples/testbench/decent_band/tsv/0 (Python)_util.tsv delete mode 100644 examples/testbench/decent_band/tsv/0 (System Memory)_util.tsv delete mode 100644 examples/testbench/decent_band/tsv/0 (Utility)_util.tsv delete mode 100644 examples/testbench/decent_band/tsv/Mem_0x1e00000000000000.tsv delete mode 100644 examples/testbench/decent_band/tsv/None.tsv delete mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000000.tsv delete mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000001.tsv delete mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000002.tsv delete mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000003.tsv delete mode 100644 examples/testbench/decent_band/tsv/Proc_0x1d00000000000004.tsv delete mode 100644 examples/testbench/decent_band/tsv/all (CPU)_util.tsv delete mode 100644 examples/testbench/decent_band/tsv/all (Channel)_util.tsv delete mode 100644 examples/testbench/decent_band/tsv/all (Python)_util.tsv delete mode 100644 examples/testbench/decent_band/tsv/all (System Memory)_util.tsv delete mode 100644 examples/testbench/decent_band/tsv/all (Utility)_util.tsv delete mode 100644 examples/testbench/event_graph_legion_python_main_1.pdf delete mode 100644 examples/testbench/go.sh delete mode 100644 examples/testbench/good_band/dataflow_legion_python_main_1.pdf delete mode 100644 examples/testbench/good_band/event_graph_legion_python_main_1.pdf delete mode 100644 examples/testbench/good_band/index.html delete mode 100644 examples/testbench/good_band/js/timeline.js delete mode 100644 examples/testbench/good_band/js/util.js delete mode 100644 examples/testbench/good_band/legion_prof_ops.tsv delete mode 100644 examples/testbench/good_band/legion_prof_processor.tsv delete mode 100644 examples/testbench/good_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv delete mode 100644 examples/testbench/good_band/tsv/0 (CPU)_util.tsv delete mode 100644 examples/testbench/good_band/tsv/0 (Channel)_util.tsv delete mode 100644 examples/testbench/good_band/tsv/0 (Python)_util.tsv delete mode 100644 examples/testbench/good_band/tsv/0 (System Memory)_util.tsv delete mode 100644 examples/testbench/good_band/tsv/0 (Utility)_util.tsv delete mode 100644 examples/testbench/good_band/tsv/Mem_0x1e00000000000000.tsv delete mode 100644 examples/testbench/good_band/tsv/None.tsv delete mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000000.tsv delete mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000001.tsv delete mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000002.tsv delete mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000003.tsv delete mode 100644 examples/testbench/good_band/tsv/Proc_0x1d00000000000004.tsv delete mode 100644 examples/testbench/good_band/tsv/all (CPU)_util.tsv delete mode 100644 examples/testbench/good_band/tsv/all (Channel)_util.tsv delete mode 100644 examples/testbench/good_band/tsv/all (Python)_util.tsv delete mode 100644 examples/testbench/good_band/tsv/all (System Memory)_util.tsv delete mode 100644 examples/testbench/good_band/tsv/all (Utility)_util.tsv delete mode 100644 examples/testbench/legion_prof/dataflow_legion_python_main_1.pdf delete mode 100644 examples/testbench/legion_prof/event_graph_legion_python_main_1.pdf delete mode 100644 examples/testbench/legion_prof/index.html delete mode 100644 examples/testbench/legion_prof/js/timeline.js delete mode 100644 examples/testbench/legion_prof/js/util.js delete mode 100644 examples/testbench/legion_prof/legion_prof_ops.tsv delete mode 100644 examples/testbench/legion_prof/legion_prof_processor.tsv delete mode 100644 examples/testbench/legion_prof/tsv/0 (CPU)_util.tsv delete mode 100644 examples/testbench/legion_prof/tsv/0 (Python)_util.tsv delete mode 100644 examples/testbench/legion_prof/tsv/0 (System Memory)_util.tsv delete mode 100644 examples/testbench/legion_prof/tsv/0 (Utility)_util.tsv delete mode 100644 examples/testbench/legion_prof/tsv/Mem_0x1e00000000000000.tsv delete mode 100644 examples/testbench/legion_prof/tsv/Proc_0x1d00000000000000.tsv delete mode 100644 examples/testbench/legion_prof/tsv/Proc_0x1d00000000000001.tsv delete mode 100644 examples/testbench/legion_prof/tsv/Proc_0x1d00000000000002.tsv delete mode 100644 examples/testbench/legion_prof/tsv/Proc_0x1d00000000000003.tsv delete mode 100644 examples/testbench/legion_prof/tsv/all (CPU)_util.tsv delete mode 100644 examples/testbench/legion_prof/tsv/all (Python)_util.tsv delete mode 100644 examples/testbench/legion_prof/tsv/all (System Memory)_util.tsv delete mode 100644 examples/testbench/legion_prof/tsv/all (Utility)_util.tsv delete mode 100644 examples/testbench/test.py delete mode 100644 examples/wgrad.py diff --git a/examples/benchmark.py b/examples/benchmark.py deleted file mode 100644 index 429480a94..000000000 --- a/examples/benchmark.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import math -import sys - -if sys.version_info > (3, 0): - from functools import reduce - - -# A helper method for benchmarking applications -def run_benchmark(f, samples, name, args): - if samples > 1: - results = [f(*args) for s in range(samples)] - # Remove the largest and the smallest ones - if samples >= 3: - results.remove(max(results)) - if samples >= 2: - results.remove(min(results)) - mean = sum(results) / len(results) - variance = sum(map(lambda x: (x - mean) ** 2, results)) / len(results) - stddev = math.sqrt(variance) - print("-----------------------------------------------") - print("BENCHMARK RESULTS: " + name) - print("Total Samples: " + str(samples)) - print("Average Time: " + str(mean) + " ms") - print("Variance: " + str(variance) + " ms") - print("Stddev: " + str(stddev) + " ms") - print( - "All Results: " - + reduce(lambda x, y: x + y, map(lambda x: str(x) + ", ", results)) - ) - print("-----------------------------------------------") - else: - # Just run the application like normal - f(*args) diff --git a/examples/black_scholes.py b/examples/black_scholes.py deleted file mode 100644 index 7dafe85af..000000000 --- a/examples/black_scholes.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime -import math - -from benchmark import run_benchmark - -import legate.numpy as np - - -def generate_random(N, min, max, D): - diff = D(max) - D(min) - rands = np.random.random(N).astype(D) - rands = rands * diff - rands = rands + D(min) - return rands - - -def initialize(N, D): - S = generate_random(N, 5, 30, D) - X = generate_random(N, 1, 100, D) - T = generate_random(N, 0.25, 10, D) - R = 0.02 - V = 0.3 - return S, X, T, R, V - - -def cnd(d): - A1 = 0.31938153 - A2 = -0.356563782 - A3 = 1.781477937 - A4 = -1.821255978 - A5 = 1.330274429 - RSQRT2PI = 0.39894228040143267793994605993438 - - K = 1.0 / (1.0 + 0.2316419 * np.absolute(d)) - - cnd = ( - RSQRT2PI - * np.exp(-0.5 * d * d) - * (K * (A1 + K * (A2 + K * (A3 + K * (A4 + K * A5))))) - ) - - return np.where(d > 0, 1.0 - cnd, cnd) - - -def black_scholes(S, X, T, R, V): - sqrt_t = np.sqrt(T) - d1 = np.log(S / X) + (R + 0.5 * V * V) * T / (V * sqrt_t) - d2 = d1 - V * sqrt_t - cnd_d1 = cnd(d1) - cnd_d2 = cnd(d2) - exp_rt = np.exp(-R * T) - call_result = S * cnd_d1 - X * exp_rt * cnd_d2 - put_result = X * exp_rt * (1.0 - cnd_d2) - S * (1.0 - cnd_d1) - return call_result, put_result - - -def run_black_scholes(N, D): - print("Running black scholes on %dK options..." % N) - N *= 1000 - start = datetime.datetime.now() - S, X, T, R, V = initialize(N, D) - call, put = black_scholes(S, X, T, R, V) - # Check the result for NaNs to synchronize before stopping timing - call_sum = np.sum(call) - put_sum = np.sum(put) - assert not math.isnan(call_sum) and not math.isnan(put_sum) - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-n", - "--num", - type=int, - default=10, - dest="N", - help="number of options to price in thousands", - ) - parser.add_argument( - "-p", - "--precision", - type=int, - default=32, - dest="P", - help="precision of the computation in bits", - ) - parser.add_argument( - "-b", - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - args = parser.parse_args() - if args.P == 16: - run_benchmark( - run_black_scholes, - args.benchmark, - "Black Scholes", - (args.N, np.float16), - ) - elif args.P == 32: - run_benchmark( - run_black_scholes, - args.benchmark, - "Black Scholes", - (args.N, np.float32), - ) - elif args.P == 64: - run_benchmark( - run_black_scholes, - args.benchmark, - "Black Scholes", - (args.N, np.float64), - ) - else: - raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/cg.py b/examples/cg.py deleted file mode 100644 index f6f9b688c..000000000 --- a/examples/cg.py +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime - -from benchmark import run_benchmark - -import legate.numpy as np - - -# This is technically dead code right now, but we'll keep it around in -# case we want to generate a symmetrix positive definite matrix later -def generate_random(N): - print("Generating %dx%d symmetric positive definite system..." % (N, N)) - # Generate a random matrix - A = np.random.rand(N, N) - # Make sure the matrix is symmetric - A = 0.5 * (A + A.T) - # Now make sure that it is positive definite - A = A + N * np.eye(N) - b = np.random.rand(N) - return A, b - - -def generate_2D(N, corners): - if corners: - print( - "Generating %dx%d 2-D adjacency system with corners..." - % (N ** 2, N ** 2) - ) - A = np.zeros((N ** 2, N ** 2)) + 8 * np.eye(N ** 2) - else: - print( - "Generating %dx%d 2-D adjacency system without corners..." - % (N ** 2, N ** 2) - ) - A = np.zeros((N ** 2, N ** 2)) + 4 * np.eye(N ** 2) - # These are the same for both cases - off_one = np.full(N ** 2 - 1, -1, dtype=np.float64) - A += np.diag(off_one, k=1) - A += np.diag(off_one, k=-1) - off_N = np.full(N * (N - 1), -1, dtype=np.float64) - A += np.diag(off_N, k=N) - A += np.diag(off_N, k=-N) - # If we have corners then we have four more cases - if corners: - off_N_plus = np.full(N * (N - 1) - 1, -1, dtype=np.float64) - A += np.diag(off_N_plus, k=N + 1) - A += np.diag(off_N_plus, k=-(N + 1)) - off_N_minus = np.full(N * (N - 1) + 1, -1, dtype=np.float64) - A += np.diag(off_N_minus, k=N - 1) - A += np.diag(off_N_minus, k=-(N - 1)) - # Then we can generate a random b matrix - b = np.random.rand(N ** 2) - return A, b - - -def solve(A, b, conv_iters, max_iters, verbose): - print("Solving system...") - x = np.zeros(A.shape[1]) - r = b - A.dot(x) - p = r - rsold = r.dot(r) - converged = -1 - # Should always converge in fewer iterations than this - max_iters = ( - min(max_iters, b.shape[0]) if max_iters is not None else b.shape[0] - ) - for i in range(max_iters): - Ap = A.dot(p) - alpha = rsold / (p.dot(Ap)) - x = x + alpha * p - r = r - alpha * Ap - rsnew = r.dot(r) - # We only do the convergence test every conv_iters or on the last - # iteration - if (i % conv_iters == 0 or i == (max_iters - 1)) and np.sqrt( - rsnew - ) < 1e-10: - converged = i - break - if verbose: - print("Residual: " + str(rsnew)) - beta = rsnew / rsold - p = r + beta * p - rsold = rsnew - if converged < 0: - print("Convergence FAILURE!") - else: - print("Converged in %d iterations" % (converged)) - return x - - -def precondition(A, N, corners): - if corners: - d = 8 * (N ** 2) - else: - d = 4 * (N ** 2) - M = np.diag(np.full(N ** 2, 1.0 / d)) - return M - - -def preconditioned_solve(A, M, b, conv_iters, max_iters, verbose): - print("Solving system with preconditioner...") - x = np.zeros(A.shape[1]) - r = b - A.dot(x) - z = M.dot(r) - p = z - rzold = r.dot(z) - converged = -1 - # Should always converge in fewer iterations than this - max_iters = ( - min(max_iters, b.shape[0]) if max_iters is not None else b.shape[0] - ) - for i in range(max_iters): - Ap = A.dot(p) - alpha = rzold / (p.dot(Ap)) - x = x + alpha * p - r = r - alpha * Ap - rznew = r.dot(r) - # We only do the convergence test every conv_iters or on the - # last iteration - if (i % conv_iters == 0 or i == (max_iters - 1)) and np.sqrt( - rznew - ) < 1e-10: - converged = i - break - if verbose: - print("Residual: " + str(rznew)) - z = M.dot(r) - rznew = r.dot(z) - beta = rznew / rzold - p = z + beta * p - rzold = rznew - if converged < 0: - print("Convergence FAILURE!") - else: - print("Converged in %d iterations" % (converged)) - return x - - -def check(A, x, b): - print("Checking result...") - if np.allclose(A.dot(x), b): - print("PASS!") - else: - print("FAIL!") - - -def run_cg( - N, - corners, - preconditioner, - conv_iters, - max_iters, - perform_check, - timing, - verbose, -): - start = datetime.datetime.now() - # A, b = generate_random(N) - A, b = generate_2D(N, corners) - if preconditioner: - M = precondition(A, N, corners) - x = preconditioned_solve(A, M, b, conv_iters, max_iters, verbose) - else: - x = solve(A, b, conv_iters, max_iters, verbose) - if perform_check: - check(A, x, b) - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - if timing: - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-c", - "--check", - dest="check", - action="store_true", - help="check the result of the solve", - ) - parser.add_argument( - "-k", - "--corners", - dest="corners", - action="store_true", - help="include corners when generating the adjacency matrix", - ) - parser.add_argument( - "-i", - "--iters", - type=int, - default=25, - dest="conv_iters", - help="iterations between convergence tests", - ) - parser.add_argument( - "-p", - "--pre", - dest="precondition", - action="store_true", - help="use a Jacobi preconditioner", - ) - parser.add_argument( - "-m", - "--max", - type=int, - default=None, - dest="max_iters", - help="bound the maximum number of iterations", - ) - parser.add_argument( - "-n", - "--num", - type=int, - default=10, - dest="N", - help="number of elements in one dimension", - ) - parser.add_argument( - "-t", - "--time", - dest="timing", - action="store_true", - help="perform timing", - ) - parser.add_argument( - "-v", - "--verbose", - dest="verbose", - action="store_true", - help="print verbose output", - ) - parser.add_argument( - "-b", - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - - args = parser.parse_args() - run_benchmark( - run_cg, - args.benchmark, - "PreCG" if args.precondition else "CG", - ( - args.N, - args.corners, - args.precondition, - args.conv_iters, - args.max_iters, - args.check, - args.timing, - args.verbose, - ), - ) diff --git a/examples/gemm.py b/examples/gemm.py deleted file mode 100644 index b3bd0d523..000000000 --- a/examples/gemm.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime -import math - -from benchmark import run_benchmark - -import legate.numpy as np - - -def initialize(M, N, K, ft): - A = np.random.rand(N, N).astype(ft) - B = np.random.rand(N, N).astype(ft) - C = np.zeros((N, N), dtype=ft) - return A, B, C - - -def total_flops(M, N, K): - return M * N * (2 * K - 1) - - -def total_space(M, N, K, ft): - return (M * N + M * K + K * N) * np.dtype(ft).itemsize - - -def run_gemm(N, I, ft): # noqa: E741 - print("Problem Size: M=" + str(N) + " N=" + str(N) + " K=" + str(N)) - print("Total Iterations: " + str(I)) - flops = total_flops(N, N, N) - print("Total Flops: " + str(flops / 1e9) + " GFLOPS/iter") - space = total_space(N, N, N, ft) - print("Total Size: " + str(space / 1e6) + " MB") - A, B, C = initialize(N, N, N, ft) - # Compute some sums and check for NaNs to force synchronization - # before we start the timing - assert not math.isnan(np.sum(A)) - assert not math.isnan(np.sum(B)) - assert not math.isnan(np.sum(C)) - start = datetime.datetime.now() - # Run for as many iterations as was requested - for idx in range(I): - np.dot(A, B, out=C) - # We need to rotate the matrices to keep Legate honest - # about moving data so it can't just duplicate A and B - # on the first iteration and reuse them, this means - # that A, B, C all need to be square - A, B, C = B, C, A - # Do another sum to synchronize for timings, B is last output - assert not math.isnan(np.sum(B)) - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - print("Elapsed Time: " + str(total) + " ms") - average = total / I - print("Average GEMM: " + str(average) + " ms") - print("FLOPS/s: " + str(flops / (average * 1e6)) + " GFLOPS/s") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-i", - "--iter", - type=int, - default=100, - dest="I", - help="number of iterations to run", - ) - parser.add_argument( - "-n", - "--num", - type=int, - default=100, - dest="N", - help="number of elements in one dimension", - ) - parser.add_argument( - "-p", - "--precision", - type=int, - default=32, - dest="P", - help="number of bits of precision to use for the gemm computation " - "(16,32,64)", - ) - parser.add_argument( - "-b", - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - args = parser.parse_args() - if args.P == 16: - run_benchmark( - run_gemm, args.benchmark, "HGEMM", (args.N, args.I, np.float16) - ) - elif args.P == 32: - run_benchmark( - run_gemm, args.benchmark, "SGEMM", (args.N, args.I, np.float32) - ) - elif args.P == 64: - run_benchmark( - run_gemm, args.benchmark, "DGEMM", (args.N, args.I, np.float64) - ) - else: - raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/jacobi.py b/examples/jacobi.py deleted file mode 100644 index 7bc2bed5f..000000000 --- a/examples/jacobi.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime -import math - -from benchmark import run_benchmark - -import legate.numpy as np - - -def generate_random(N): - print("Generating %dx%d system..." % (N, N)) - # Generate a random matrix - A = np.random.rand(N, N) - # Make sure that it is diagonally dominate - A = A + N * np.eye(N) - # Generate a random vector - b = np.random.rand(N) - return A, b - - -def solve(A, b, iters, verbose): - print("Solving system...") - x = np.zeros(A.shape[1]) - d = np.diag(A) - R = A - np.diag(d) - for i in range(iters): - x = (b - np.dot(R, x)) / d - return x - - -def check(A, x, b): - print("Checking result...") - if np.allclose(A.dot(x), b): - print("PASS!") - else: - print("FAIL!") - - -def run_jacobi(N, iters, perform_check, timing, verbose): - start = datetime.datetime.now() - A, b = generate_random(N) - x = solve(A, b, iters, verbose) - if perform_check: - check(A, x, b) - else: - # Need a synchronization here for timing - assert not math.isnan(np.sum(x)) - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - if timing: - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-c", - "--check", - dest="check", - action="store_true", - help="check the result of the solve", - ) - parser.add_argument( - "-i", - "--iters", - type=int, - default=1000, - dest="iters", - help="number of iterations to run", - ) - parser.add_argument( - "-n", - "--num", - type=int, - default=100, - dest="N", - help="number of elements in one dimension", - ) - parser.add_argument( - "-t", - "--time", - dest="timing", - action="store_true", - help="perform timing", - ) - parser.add_argument( - "-v", - "--verbose", - dest="verbose", - action="store_true", - help="print verbose output", - ) - parser.add_argument( - "-b", - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - - args = parser.parse_args() - run_benchmark( - run_jacobi, - args.benchmark, - "Jacobi", - (args.N, args.iters, args.check, args.timing, args.verbose), - ) diff --git a/examples/kmeans.py b/examples/kmeans.py deleted file mode 100644 index c7636e51d..000000000 --- a/examples/kmeans.py +++ /dev/null @@ -1,246 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -# Derived from https://github.com/bryancatanzaro/kmeans - -from __future__ import print_function - -import argparse -import datetime - -from benchmark import run_benchmark - -import legate.numpy as np - - -def initialize(N, D, C, T): - # Uncomment this if we want execution to be deterministic with - # original numpy np.random.seed(0) - data = np.random.random((N, D)).astype(T) - # Since points are random, we'll just generate some random centers - centroids = np.random.random((C, D)).astype(T) - return data, centroids - - -def calculate_distances(data, centroids, data_dots): - centroid_dots = np.square(np.linalg.norm(centroids, ord=2, axis=1)) - pairwise_distances = ( - data_dots[:, np.newaxis] + centroid_dots[np.newaxis, :] - ) - # ||x-y||^2 = ||x||^2 + ||y||^2 - 2 x . y - # pairwise_distances has ||x||^2 + ||y||^2, so beta = 1 - # The gemm calculates x.y for all x and y, so alpha = -2.0 - pairwise_distances -= 2.0 * np.dot(data, centroids.T) - return pairwise_distances - - -def relabel(pairwise_distances): - return np.argmin(pairwise_distances, axis=1) - - -def find_centroids(centroids, data, labels, pairwise_distances, zero_point, C): - # Get the number of points associated with each centroid - counts = np.bincount(labels, minlength=C) - - # more bincounts using the positions as weights produce the unnormalized - # updated centroid locations (have to do each dimension separately since - # a weight cannot be a vector) - for idx in range(data.shape[1]): - centroids[:, idx] = np.bincount( - labels, weights=data[:, idx], minlength=C - ) - - # would have been nice if numpy offered a combined amin/argmin to avoid - # iterating over pairwise_distances twice - distance_sum = np.sum(np.amin(pairwise_distances, axis=1)) - - # To avoid introducing divide by zero errors - # If a centroid has no weight, we'll do no normalization - # This will keep its coordinates defined. - counts = np.maximum(counts, np.ones((1,), dtype=np.uint64)) - centroids /= counts[:, np.newaxis] - return distance_sum - - -def run_kmeans(C, D, T, I, N, S, benchmarking): # noqa: E741 - print("Running kmeans...") - print("Number of data points: " + str(N)) - print("Number of dimensions: " + str(D)) - print("Number of centroids: " + str(C)) - print("Max iterations: " + str(I)) - start = datetime.datetime.now() - data, centroids = initialize(N, D, C, T) - - data_dots = np.square(np.linalg.norm(data, ord=2, axis=1)) - zero_point = np.zeros((1, data.shape[1]), dtype=data.dtype) - - labels = None - iteration = 0 - prior_distance_sum = None - # We run for max iterations or until we converge - # We only test convergence every S iterations - while iteration < I: - pairwise_distances = calculate_distances(data, centroids, data_dots) - - new_labels = relabel(pairwise_distances) - - distance_sum = find_centroids( - centroids, data, new_labels, pairwise_distances, zero_point, C - ) - - if iteration > 0 and iteration % S == 0: - changes = np.not_equal(labels, new_labels) - total_changes = np.sum(changes) - delta = distance_sum / prior_distance_sum - print( - "Iteration " - + str(iteration) - + " produced " - + str(total_changes) - + " changes, and total distance is " - + str(distance_sum) - ) - # We ignore the result of the threshold test in the case - # that we are running performance benchmarks to measure - # performance for a certain number of iterations - if delta > 1 - 0.000001 and not benchmarking: - print("Threshold triggered, terminating iterations early") - break - prior_distance_sum = distance_sum - labels = new_labels - iteration += 1 - # This final distance sum also synchronizes the results - print( - "Final distance sum at iteration " - + str(iteration) - + ": " - + str(prior_distance_sum) - ) - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-c", - "--centers", - type=int, - default=10, - dest="C", - help="number of centroids", - ) - parser.add_argument( - "-d", - "--dims", - type=int, - default=2, - dest="D", - help="number of dimensions for each input data point", - ) - parser.add_argument( - "-m", - "--max-iters", - type=int, - default=1000, - dest="I", - help="maximum number of iterations to run the algorithm for", - ) - parser.add_argument( - "-n", - "--num", - type=int, - default=10, - dest="N", - help="number of elements in the data set in thousands", - ) - parser.add_argument( - "-p", - "--precision", - type=int, - default=32, - dest="P", - help="precision of the computation in bits", - ) - parser.add_argument( - "-s", - "--sample", - type=int, - default=25, - dest="S", - help="number of iterations between sampling the log likelihood", - ) - parser.add_argument( - "-b", - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application" - " (default 1 - normal execution)", - ) - args = parser.parse_args() - if args.P == 16: - run_benchmark( - run_kmeans, - args.benchmark, - "KMEANS(H)", - ( - args.C, - args.D, - np.float16, - args.I, - args.N * 1000, - args.S, - args.benchmark > 1, - ), - ) - elif args.P == 32: - run_benchmark( - run_kmeans, - args.benchmark, - "KMEANS(S)", - ( - args.C, - args.D, - np.float32, - args.I, - args.N * 1000, - args.S, - args.benchmark > 1, - ), - ) - elif args.P == 64: - run_benchmark( - run_kmeans, - args.benchmark, - "KMEANS(D)", - ( - args.C, - args.D, - np.float64, - args.I, - args.N * 1000, - args.S, - args.benchmark > 1, - ), - ) - else: - raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/kmeans_slow.py b/examples/kmeans_slow.py deleted file mode 100644 index 070122891..000000000 --- a/examples/kmeans_slow.py +++ /dev/null @@ -1,247 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -# Derived from https://github.com/bryancatanzaro/kmeans - -from __future__ import print_function - -import argparse -import datetime - -from benchmark import run_benchmark - -import legate.numpy as np - - -def initialize(N, D, C, T): - # Uncomment this if we want execution to be deterministic - # np.random.seed(0) - data = np.random.random((N, D)).astype(T) - # Since points are random, we'll just generate some random centers - centroids = np.random.random((C, D)).astype(T) - return data, centroids - - -def calculate_distances(data, centroids, data_dots): - centroid_dots = np.square(np.linalg.norm(centroids, ord=2, axis=1)) - pairwise_distances = ( - data_dots[:, np.newaxis] + centroid_dots[np.newaxis, :] - ) - # ||x-y||^2 = ||x||^2 + ||y||^2 - 2 x . y - # pairwise_distances has ||x||^2 + ||y||^2, so beta = 1 - # The gemm calculates x.y for all x and y, so alpha = -2.0 - pairwise_distances -= 2.0 * np.dot(data, centroids.T) - return pairwise_distances - - -def relabel(pairwise_distances): - return np.argmin(pairwise_distances, axis=1) - - -def find_centroids( - centroids, data, labels, pairwise_distances, zero_point, C, D -): - # Get the number of points associated with each centroid - counts = np.bincount(labels, minlength=C) - # Build label masks for each centroid and sum across all the - # points assocated with each new centroid - distance_sum = 0.0 - for idx in range(C): - # Boolean mask indicating where the points are for this center - centroid_mask = labels == idx - centroids[idx, :] = np.sum( - np.where(centroid_mask[..., np.newaxis], data, zero_point), axis=0 - ) - distance_sum += np.sum( - np.where(centroid_mask, pairwise_distances[:, idx], 0.0) - ) - # To avoid introducing divide by zero errors - # If a centroid has no weight, we'll do no normalization - # This will keep its coordinates defined. - counts = np.maximum(counts, np.ones((1,), dtype=np.uint64)) - centroids /= counts[:, np.newaxis] - return distance_sum - - -def run_kmeans(C, D, T, I, N, S, benchmarking): # noqa: E741 - print("Running kmeans...") - print("Number of data points: " + str(N)) - print("Number of dimensions: " + str(D)) - print("Number of centroids: " + str(C)) - print("Max iterations: " + str(I)) - start = datetime.datetime.now() - data, centroids = initialize(N, D, C, T) - - data_dots = np.square(np.linalg.norm(data, ord=2, axis=1)) - zero_point = np.zeros((1, data.shape[1]), dtype=data.dtype) - - labels = None - iteration = 0 - prior_distance_sum = None - # We run for max iterations or until we converge - # We only test convergence every S iterations - while iteration < I: - pairwise_distances = calculate_distances(data, centroids, data_dots) - - new_labels = relabel(pairwise_distances) - - distance_sum = find_centroids( - centroids, data, new_labels, pairwise_distances, zero_point, C, D - ) - - if iteration > 0 and iteration % S == 0: - changes = np.not_equal(labels, new_labels) - total_changes = np.sum(changes) - delta = distance_sum / prior_distance_sum - print( - "Iteration " - + str(iteration) - + " produced " - + str(total_changes) - + " changes, and total distance is " - + str(distance_sum) - ) - # We ignore the result of the threshold test in the case - # that we are running performance benchmarks to measure - # performance for a certain number of iterations - if delta > 1 - 0.000001 and not benchmarking: - print("Threshold triggered, terminating iterations early") - break - prior_distance_sum = distance_sum - labels = new_labels - iteration += 1 - # This final distance sum also synchronizes the results - print( - "Final distance sum at iteration " - + str(iteration) - + ": " - + str(prior_distance_sum) - ) - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-c", - "--centers", - type=int, - default=10, - dest="C", - help="number of centroids", - ) - parser.add_argument( - "-d", - "--dims", - type=int, - default=2, - dest="D", - help="number of dimensions for each input data point", - ) - parser.add_argument( - "-m", - "--max-iters", - type=int, - default=1000, - dest="I", - help="maximum number of iterations to run the algorithm for", - ) - parser.add_argument( - "-n", - "--num", - type=int, - default=10, - dest="N", - help="number of elements in the data set in thousands", - ) - parser.add_argument( - "-p", - "--precision", - type=int, - default=32, - dest="P", - help="precision of the computation in bits", - ) - parser.add_argument( - "-s", - "--sample", - type=int, - default=25, - dest="S", - help="number of iterations between sampling the log likelihood", - ) - parser.add_argument( - "-b", - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - args = parser.parse_args() - if args.P == 16: - run_benchmark( - run_kmeans, - args.benchmark, - "KMEANS(H)", - ( - args.C, - args.D, - np.float16, - args.I, - args.N * 1000, - args.S, - args.benchmark > 1, - ), - ) - elif args.P == 32: - run_benchmark( - run_kmeans, - args.benchmark, - "KMEANS(S)", - ( - args.C, - args.D, - np.float32, - args.I, - args.N * 1000, - args.S, - args.benchmark > 1, - ), - ) - elif args.P == 64: - run_benchmark( - run_kmeans, - args.benchmark, - "KMEANS(D)", - ( - args.C, - args.D, - np.float64, - args.I, - args.N * 1000, - args.S, - args.benchmark > 1, - ), - ) - else: - raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/kmeans_sort.py b/examples/kmeans_sort.py deleted file mode 100644 index 10cf8d355..000000000 --- a/examples/kmeans_sort.py +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -# Derived from https://github.com/bryancatanzaro/kmeans - -from __future__ import print_function - -import argparse -import datetime - -from benchmark import run_benchmark - -import legate.numpy as np - -try: - xrange -except NameError: - xrange = range - - -def initialize(N, D, C, T): - # Uncomment this if we want execution to be deterministic - # np.random.seed(0) - data = np.random.random((N, D)).astype(T) - # Since points are random, we'll just generate some random centers - centroids = np.random.random((C, D)).astype(T) - return data, centroids - - -def calculate_distances(data, centroids, data_dots): - centroid_dots = np.square(np.linalg.norm(centroids, ord=2, axis=1)) - pairwise_distances = ( - data_dots[:, np.newaxis] + centroid_dots[np.newaxis, :] - ) - # ||x-y||^2 = ||x||^2 + ||y||^2 - 2 x . y - # pairwise_distances has ||x||^2 + ||y||^2, so beta = 1 - # The gemm calculates x.y for all x and y, so alpha = -2.0 - pairwise_distances -= 2.0 * np.dot(data, centroids.T) - return pairwise_distances - - -def relabel(pairwise_distances, data_index): - new_labels = np.argmin(pairwise_distances, axis=1) - distances = pairwise_distances[data_index, new_labels] - return new_labels, distances - - -def find_centroids(data, labels, C, D): - # Sort the points by their labels - indices = np.argsort(labels) - sorted_points = data[indices] - # Compute counts and indexes for ending of sets of points for each centroid - counts = np.bincount(labels, minlength=C) - indexes = np.cumsum(counts) - # Now we can use the indexes to split the array into sub-arrays and then - # sum across them to create the centroids - centroids = np.empty((C, D), dtype=data.dtype) - ragged_arrays = np.split(sorted_points, indexes) - for idx in xrange(C): - centroids[idx, :] = np.sum(ragged_arrays[idx], axis=0) - # To avoid introducing divide by zero errors - # If a centroid has no weight, we'll do no normalization - # This will keep its coordinates defined. - counts = np.maximum(counts, 1) - return centroids / counts[:, np.newaxis] - - -def run_kmeans(C, D, T, I, N, S, benchmarking): # noqa: E741 - print("Running kmeans...") - print("Number of data points: " + str(N)) - print("Number of dimensions: " + str(D)) - print("Number of centroids: " + str(C)) - print("Max iterations: " + str(I)) - start = datetime.datetime.now() - data, centroids = initialize(N, D, C, T) - - data_dots = np.square(np.linalg.norm(data, ord=2, axis=1)) - data_index = np.linspace(0, N - 1, N, dtype=np.int) - - labels = None - iteration = 0 - prior_distance_sum = None - # We run for max iterations or until we converge - # We only test convergence every S iterations - while iteration < I: - pairwise_distances = calculate_distances(data, centroids, data_dots) - - new_labels, distances = relabel(pairwise_distances, data_index) - distance_sum = np.sum(distances) - - centroids = find_centroids(data, new_labels, C, D) - - if iteration > 0 and iteration % S == 0: - changes = np.not_equal(labels, new_labels) - total_changes = np.sum(changes) - delta = distance_sum / prior_distance_sum - print( - "Iteration " - + str(iteration) - + " produced " - + str(total_changes) - + " changes, and total distance is " - + str(distance_sum) - ) - # We ignore the result of the threshold test in the case that we - # are running performance benchmarks to measure performance for a - # certain number of iterations - if delta > 1 - 0.000001 and not benchmarking: - print("Threshold triggered, terminating iterations early") - break - prior_distance_sum = distance_sum - labels = new_labels - iteration += 1 - # This final distance sum also synchronizes the results - print( - "Final distance sum at iteration " - + str(iteration) - + ": " - + str(prior_distance_sum) - ) - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-c", - "--centers", - type=int, - default=10, - dest="C", - help="number of centroids", - ) - parser.add_argument( - "-d", - "--dims", - type=int, - default=2, - dest="D", - help="number of dimensions for each input data point", - ) - parser.add_argument( - "-m", - "--max-iters", - type=int, - default=1000, - dest="I", - help="maximum number of iterations to run the algorithm for", - ) - parser.add_argument( - "-n", - "--num", - type=int, - default=10, - dest="N", - help="number of elements in the data set in thousands", - ) - parser.add_argument( - "-p", - "--precision", - type=int, - default=32, - dest="P", - help="precision of the computation in bits", - ) - parser.add_argument( - "-s", - "--sample", - type=int, - default=25, - dest="S", - help="number of iterations between sampling the log likelihood", - ) - parser.add_argument( - "-b", - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - args = parser.parse_args() - if args.P == 16: - run_benchmark( - run_kmeans, - args.benchmark, - "KMEANS(H)", - ( - args.C, - args.D, - np.float16, - args.I, - args.N * 1000, - args.S, - args.benchmark > 1, - ), - ) - elif args.P == 32: - run_benchmark( - run_kmeans, - args.benchmark, - "KMEANS(S)", - ( - args.C, - args.D, - np.float32, - args.I, - args.N * 1000, - args.S, - args.benchmark > 1, - ), - ) - elif args.P == 64: - run_benchmark( - run_kmeans, - args.benchmark, - "KMEANS(D)", - ( - args.C, - args.D, - np.float64, - args.I, - args.N * 1000, - args.S, - args.benchmark > 1, - ), - ) - else: - raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/linreg.py b/examples/linreg.py deleted file mode 100644 index ed5f43015..000000000 --- a/examples/linreg.py +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime -import math - -from benchmark import run_benchmark - -import legate.numpy as np - - -def initialize(N, F, T): - # We'll generate some random inputs here - # since we don't need it to converge - x = np.random.randn(N, F).astype(T) - y = np.random.random(N).astype(T) - return x, y - - -def linear_regression( - T, features, target, steps, learning_rate, sample, add_intercept=False -): - if add_intercept: - intercept = np.ones((features.shape[0], 1), dtype=T) - features = np.hstack((intercept, features)) - - weights = np.zeros(features.shape[1], dtype=T) - - for step in range(steps): - scores = np.dot(features, weights) - error = scores - target - gradient = -(1.0 / len(features)) * error.dot(features) - weights += learning_rate * gradient - - if step % sample == 0: - print( - "Error of step " - + str(step) - + ": " - + str(np.sum(np.power(error, 2))) - ) - - return weights - - -def run_linear_regression(N, F, T, I, S, B): # noqa: E741 - print("Running linear regression...") - print("Number of data points: " + str(N) + "K") - print("Number of features: " + str(F)) - print("Number of iterations: " + str(I)) - start = datetime.datetime.now() - features, target = initialize(N * 1000, F, T) - weights = linear_regression(T, features, target, I, 1e-5, S, B) - # Check the weights for NaNs to synchronize before stopping timing - assert not math.isnan(np.sum(weights)) - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-b", - "--intercept", - dest="B", - action="store_true", - help="include an intercept in the calculation", - ) - parser.add_argument( - "-f", - "--features", - type=int, - default=32, - dest="F", - help="number of features for each input data point", - ) - parser.add_argument( - "-i", - "--iterations", - type=int, - default=1000, - dest="I", - help="number of iterations to run the algorithm for", - ) - parser.add_argument( - "-n", - "--num", - type=int, - default=10, - dest="N", - help="number of elements in the data set in thousands", - ) - parser.add_argument( - "-p", - "--precision", - type=int, - default=32, - dest="P", - help="precision of the computation in bits", - ) - parser.add_argument( - "-s", - "--sample", - type=int, - default=100, - dest="S", - help="number of iterations between sampling the log likelihood", - ) - parser.add_argument( - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - args = parser.parse_args() - if args.P == 16: - run_benchmark( - run_linear_regression, - args.benchmark, - "LINREG(H)", - (args.N, args.F, np.float16, args.I, args.S, args.B), - ) - elif args.P == 32: - run_benchmark( - run_linear_regression, - args.benchmark, - "LINREG(S)", - (args.N, args.F, np.float32, args.I, args.S, args.B), - ) - elif args.P == 64: - run_benchmark( - run_linear_regression, - args.benchmark, - "LINREG(D)", - (args.N, args.F, np.float64, args.I, args.S, args.B), - ) - else: - raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/logreg.py b/examples/logreg.py deleted file mode 100644 index 46a013fa3..000000000 --- a/examples/logreg.py +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime -import math - -from benchmark import run_benchmark - -import legate.numpy as np - - -def initialize(N, F, T): - # We'll generate some random inputs here - # since we don't need it to converge - x = np.random.randn(N, F).astype(T) - # Give the results either a 0 or 1 value - y = np.floor(2.0 * np.random.random(N).astype(T)) - return x, y - - -def sigmoid(x): - return 1.0 / (1.0 + np.exp(-x)) - - -def log_likelihood(features, target, weights): - scores = np.dot(features, weights) - return np.sum(target * scores - np.log(1.0 + np.exp(scores))) - - -def logistic_regression( - T, features, target, steps, learning_rate, sample, add_intercept=False -): - if add_intercept: - intercept = np.ones((features.shape[0], 1), dtype=T) - features = np.hstack((intercept, features)) - - weights = np.zeros(features.shape[1], dtype=T) - - for step in range(steps): - scores = np.dot(features, weights) - predictions = sigmoid(scores) - - error = target - predictions - gradient = np.dot(error, features) - weights += learning_rate * gradient - - if step % sample == 0: - print( - "Log Likelihood of step " - + str(step) - + ": " - + str(log_likelihood(features, target, weights)) - ) - - return weights - - -def run_logistic_regression(N, F, T, I, S, B): # noqa: E741 - print("Running logistic regression...") - print("Number of data points: " + str(N) + "K") - print("Number of features: " + str(F)) - print("Number of iterations: " + str(I)) - start = datetime.datetime.now() - features, target = initialize(N * 1000, F, T) - weights = logistic_regression(T, features, target, I, 1e-5, S, B) - # Check the weights for NaNs to synchronize before stopping timing - assert not math.isnan(np.sum(weights)) - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-b", - "--intercept", - dest="B", - action="store_true", - help="include an intercept in the calculation", - ) - parser.add_argument( - "-f", - "--features", - type=int, - default=32, - dest="F", - help="number of features for each input data point", - ) - parser.add_argument( - "-i", - "--iterations", - type=int, - default=1000, - dest="I", - help="number of iterations to run the algorithm for", - ) - parser.add_argument( - "-n", - "--num", - type=int, - default=10, - dest="N", - help="number of elements in the data set in thousands", - ) - parser.add_argument( - "-p", - "--precision", - type=int, - default=32, - dest="P", - help="precision of the computation in bits", - ) - parser.add_argument( - "-s", - "--sample", - type=int, - default=100, - dest="S", - help="number of iterations between sampling the log likelihood", - ) - parser.add_argument( - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - args = parser.parse_args() - if args.P == 16: - run_benchmark( - run_logistic_regression, - args.benchmark, - "LOGREG(H)", - (args.N, args.F, np.float16, args.I, args.S, args.B), - ) - elif args.P == 32: - run_benchmark( - run_logistic_regression, - args.benchmark, - "LOGREG(S)", - (args.N, args.F, np.float32, args.I, args.S, args.B), - ) - elif args.P == 64: - run_benchmark( - run_logistic_regression, - args.benchmark, - "LOGREG(D)", - (args.N, args.F, np.float64, args.I, args.S, args.B), - ) - else: - raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/lstm_backward.py b/examples/lstm_backward.py deleted file mode 100644 index 45e9b2d29..000000000 --- a/examples/lstm_backward.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime -import math - -from benchmark import run_benchmark - -import legate.numpy as np - - -def run_lstm(batch_size, hidden_size, sentence_length, word_size, timing): - start = datetime.datetime.now() - - WLSTM = np.random.randn( - word_size + hidden_size, 4 * hidden_size - ) / np.sqrt(word_size + hidden_size) - - xphpb = WLSTM.shape[0] - d = hidden_size - n = sentence_length - b = batch_size - - dHout = np.random.randn(n, b, d) - IFOGf = np.random.randn(n, b, d * 4) - C = np.random.randn(n, b, d) - Ct = np.random.randn(n, b, d) - Hin = np.random.randn(n, b, xphpb) - - dIFOG = np.zeros((n, b, d * 4)) - dIFOGf = np.zeros(IFOGf.shape) - dHin = np.zeros(Hin.shape) - dC = np.zeros(C.shape) - dh0 = np.zeros((1, d)) - - for t in reversed(range(n)): - tanhCt = Ct[t] - dIFOGf[t, :, 2 * d : 3 * d] = tanhCt * dHout[t] - # backprop tanh non-linearity first then continue backprop - dC[t] += (1 - tanhCt ** 2) * (IFOGf[t, :, 2 * d : 3 * d] * dHout[t]) - - if t > 0: - dIFOGf[t, :, d : 2 * d] = C[t - 1] * dC[t] - dC[t - 1] += IFOGf[t, :, d : 2 * d] * dC[t] - - dIFOGf[t, :, :d] = IFOGf[t, :, 3 * d :] * dC[t] - dIFOGf[t, :, 3 * d :] = IFOGf[t, :, :d] * dC[t] - - # backprop activation functions - dIFOG[t, :, 3 * d :] = (1 - IFOGf[t, :, 3 * d :] ** 2) * dIFOGf[ - t, :, 3 * d : - ] - y = IFOGf[t, :, : 3 * d] - dIFOG[t, :, : 3 * d] = (y * (1.0 - y)) * dIFOGf[t, :, : 3 * d] - - # backprop matrix multiply - dHin[t] = dIFOG[t].dot(WLSTM.transpose()) - - # backprop the identity transforms into Hin - if t > 0: - dHout[t - 1, :] += dHin[t, :, word_size:] - else: - dh0[0] += np.sum(dHin[t, :, word_size:], 0) - - # Do a little sum to synchronize and check for NaNs - total = np.sum(dh0) - assert not math.isnan(total) - - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - if timing: - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-b", "--batch", type=int, default=32, dest="batch", help="batch size" - ) - parser.add_argument( - "--hidden", type=int, default=10, dest="hidden", help="hidden size" - ) - parser.add_argument( - "-s", - "--sentence", - type=int, - default=4, - dest="sentence", - help="sentence length", - ) - parser.add_argument( - "-w", "--word", type=int, default=10, dest="word", help="word size" - ) - parser.add_argument( - "-t", - "--time", - dest="timing", - action="store_true", - help="perform timing", - ) - parser.add_argument( - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - args = parser.parse_args() - run_benchmark( - run_lstm, - args.benchmark, - "LSTM Backward", - (args.batch, args.hidden, args.sentence, args.word, args.timing), - ) diff --git a/examples/lstm_forward.py b/examples/lstm_forward.py deleted file mode 100644 index c3ac6b779..000000000 --- a/examples/lstm_forward.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime -import math - -from benchmark import run_benchmark - -import legate.numpy as np - - -def run_lstm(batch_size, hidden_size, sentence_length, word_size, timing): - start = datetime.datetime.now() - - X = np.random.randn(sentence_length, batch_size, hidden_size) - h0 = np.random.randn(1, hidden_size) - WLSTM = np.random.randn( - word_size + hidden_size, 4 * hidden_size - ) / np.sqrt(word_size + hidden_size) - - xphpb = WLSTM.shape[0] - d = hidden_size - n = sentence_length - b = batch_size - - Hin = np.zeros((n, b, xphpb)) - Hout = np.zeros((n, b, d)) - IFOG = np.zeros((n, b, d * 4)) - IFOGf = np.zeros((n, b, d * 4)) - C = np.zeros((n, b, d)) - Ct = np.zeros((n, b, d)) - - for t in range(0, n): - if t == 0: - prev = np.tile(h0, (b, 1)) - else: - prev = Hout[t - 1] - - Hin[t, :, :word_size] = X[t] - Hin[t, :, word_size:] = prev - # compute all gate activations. dots: - IFOG[t] = Hin[t].dot(WLSTM) - # non-linearities - IFOGf[t, :, : 3 * d] = 1.0 / ( - 1.0 + np.exp(-IFOG[t, :, : 3 * d]) - ) # sigmoids these are the gates - IFOGf[t, :, 3 * d :] = np.tanh(IFOG[t, :, 3 * d :]) # tanh - # compute the cell activation - C[t] = IFOGf[t, :, :d] * IFOGf[t, :, 3 * d :] - if t > 0: - C[t] += IFOGf[t, :, d : 2 * d] * C[t - 1] - Ct[t] = np.tanh(C[t]) - Hout[t] = IFOGf[t, :, 2 * d : 3 * d] * Ct[t] - - # Do a little sum of the outputs to synchronize and check for NaNs - total = np.sum(Hout) - assert not math.isnan(total) - - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - if timing: - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-b", "--batch", type=int, default=32, dest="batch", help="batch size" - ) - parser.add_argument( - "--hidden", type=int, default=10, dest="hidden", help="hidden size" - ) - parser.add_argument( - "-s", - "--sentence", - type=int, - default=4, - dest="sentence", - help="sentence length", - ) - parser.add_argument( - "-w", "--word", type=int, default=10, dest="word", help="word size" - ) - parser.add_argument( - "-t", - "--time", - dest="timing", - action="store_true", - help="perform timing", - ) - parser.add_argument( - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - args = parser.parse_args() - run_benchmark( - run_lstm, - args.benchmark, - "LSTM Forward", - (args.batch, args.hidden, args.sentence, args.word, args.timing), - ) diff --git a/examples/lstm_full.py b/examples/lstm_full.py deleted file mode 100644 index 071482229..000000000 --- a/examples/lstm_full.py +++ /dev/null @@ -1,429 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime - -from benchmark import run_benchmark - -import legate.numpy as np - - -class Param: - def __init__(self, name, value): - self.name = name - self.v = value # parameter value - self.d = np.zeros_like(value) # derivative - self.m = np.zeros_like(value) # momentum for AdaGrad - - -class Parameters: - def __init__(self, H_size, X_size, z_size, weight_sd): - self.W_f = Param( - "W_f", np.random.randn(H_size, z_size) * weight_sd + 0.5 - ) - self.b_f = Param("b_f", np.zeros((H_size, 1))) - - self.W_i = Param( - "W_i", np.random.randn(H_size, z_size) * weight_sd + 0.5 - ) - self.b_i = Param("b_i", np.zeros((H_size, 1))) - - self.W_C = Param("W_C", np.random.randn(H_size, z_size) * weight_sd) - self.b_C = Param("b_C", np.zeros((H_size, 1))) - - self.W_o = Param( - "W_o", np.random.randn(H_size, z_size) * weight_sd + 0.5 - ) - self.b_o = Param("b_o", np.zeros((H_size, 1))) - - # For final layer to predict the next character - self.W_v = Param("W_v", np.random.randn(X_size, H_size) * weight_sd) - self.b_v = Param("b_v", np.zeros((X_size, 1))) - - def all(self): - return [ - self.W_f, - self.W_i, - self.W_C, - self.W_o, - self.W_v, - self.b_f, - self.b_i, - self.b_C, - self.b_o, - self.b_v, - ] - - -def sigmoid(x): - return 1 / (1 + np.exp(-x)) - - -def dsigmoid(y): - return y * (1 - y) - - -def tanh(x): - return np.tanh(x) - - -def dtanh(y): - return 1 - y * y - - -def forward(x, h_prev, C_prev, H_size, X_size, p): - assert x.shape == (X_size, 1) - assert h_prev.shape == (H_size, 1) - assert C_prev.shape == (H_size, 1) - - z = np.row_stack((h_prev, x)) - f = sigmoid(np.dot(p.W_f.v, z) + p.b_f.v) - i = sigmoid(np.dot(p.W_i.v, z) + p.b_i.v) - C_bar = tanh(np.dot(p.W_C.v, z) + p.b_C.v) - - C = f * C_prev + i * C_bar - o = sigmoid(np.dot(p.W_o.v, z) + p.b_o.v) - h = o * tanh(C) - - v = np.dot(p.W_v.v, h) + p.b_v.v - y = np.exp(v) / np.sum(np.exp(v)) # softmax - - return z, f, i, C_bar, C, o, h, v, y - - -def backward( - target, - dh_next, - dC_next, - C_prev, - H_size, - X_size, - z, - f, - i, - C_bar, - C, - o, - h, - v, - y, - p, -): - - assert z.shape == (X_size + H_size, 1) - assert v.shape == (X_size, 1) - assert y.shape == (X_size, 1) - - for param in [dh_next, dC_next, C_prev, f, i, C_bar, C, o, h]: - assert param.shape == (H_size, 1) - - dv = np.copy(y) - dv[target] -= 1 - - p.W_v.d += np.dot(dv, h.T) - p.b_v.d += dv - - dh = np.dot(p.W_v.v.T, dv) - dh += dh_next - do = dh * tanh(C) - do = dsigmoid(o) * do - p.W_o.d += np.dot(do, z.T) - p.b_o.d += do - - dC = np.copy(dC_next) - dC += dh * o * dtanh(tanh(C)) - dC_bar = dC * i - dC_bar = dtanh(C_bar) * dC_bar - p.W_C.d += np.dot(dC_bar, z.T) - p.b_C.d += dC_bar - - di = dC * C_bar - di = dsigmoid(i) * di - p.W_i.d += np.dot(di, z.T) - p.b_i.d += di - - df = dC * C_prev - df = dsigmoid(f) * df - p.W_f.d += np.dot(df, z.T) - p.b_f.d += df - - dz = ( - np.dot(p.W_f.v.T, df) - + np.dot(p.W_i.v.T, di) - + np.dot(p.W_C.v.T, dC_bar) - + np.dot(p.W_o.v.T, do) - ) - dh_prev = dz[:H_size, :] - dC_prev = f * dC - - return dh_prev, dC_prev - - -def clear_gradients(params): - for p in params.all(): - p.d.fill(0) - - -def clip_gradients(params): - for p in params.all(): - np.clip(p.d, -1, 1, out=p.d) - - -def forward_backward( - inputs, targets, h_prev, C_prev, T_steps, H_size, X_size, parameters -): - # To store the values for each time step - x_s, z_s, f_s, i_s, = ( - {}, - {}, - {}, - {}, - ) - C_bar_s, C_s, o_s, h_s = {}, {}, {}, {} - v_s, y_s = {}, {} - - # Values at t - 1 - h_s[-1] = np.copy(h_prev) - C_s[-1] = np.copy(C_prev) - - loss = 0 - # Loop through time steps - assert len(inputs) == T_steps - for t in range(len(inputs)): - x_s[t] = np.zeros((X_size, 1)) - x_s[t][inputs[t]] = 1 # Input character - - ( - z_s[t], - f_s[t], - i_s[t], - C_bar_s[t], - C_s[t], - o_s[t], - h_s[t], - v_s[t], - y_s[t], - ) = forward( - x_s[t], h_s[t - 1], C_s[t - 1], H_size, X_size, parameters - ) # Forward pass - - loss += -np.log(y_s[t][targets[t], 0]) # Loss for at t - - clear_gradients(parameters) - - dh_next = np.zeros_like(h_s[0]) # dh from the next character - dC_next = np.zeros_like(C_s[0]) # dh from the next character - - for t in reversed(range(len(inputs))): - # Backward pass - dh_next, dC_next = backward( - target=targets[t], - dh_next=dh_next, - dC_next=dC_next, - C_prev=C_s[t - 1], - H_size=H_size, - X_size=X_size, - z=z_s[t], - f=f_s[t], - i=i_s[t], - C_bar=C_bar_s[t], - C=C_s[t], - o=o_s[t], - h=h_s[t], - v=v_s[t], - y=y_s[t], - p=parameters, - ) - - clip_gradients(parameters) - - return loss, h_s[len(inputs) - 1], C_s[len(inputs) - 1] - - -def update_parameters(learning_rate, params): - for p in params.all(): - p.m += p.d * p.d # Calculate sum of gradients - # print(learning_rate * dparam) - p.v += -(learning_rate * p.d / np.sqrt(p.m + 1e-8)) - - -def update_status(iteration, smooth_loss): - print("iter %d, loss %f" % (iteration, smooth_loss)) - - -def run_lstm( - file_name, - H_size, - T_steps, - max_iters, - learning_rate, - weight_sd, - dump, - timing, -): - with open(file_name, "r") as f: - data = f.read() - chars = list(set(data)) - data_size, X_size = len(data), len(chars) - print("data has %d characters, %d unique" % (data_size, X_size)) - char_to_idx = {ch: i for i, ch in enumerate(chars)} - - z_size = H_size + X_size # Size of concatenate(H, X) vector - - parameters = Parameters(H_size, X_size, z_size, weight_sd) - - # Exponential average of loss - # Initialize to a error of a random model - smooth_loss = -np.log(1.0 / X_size) * T_steps - - pointer = 0 - - start = datetime.datetime.now() - - for iteration in range(max_iters): - # Reset - if pointer + T_steps >= len(data) or iteration == 0: - g_h_prev = np.zeros((H_size, 1)) - g_C_prev = np.zeros((H_size, 1)) - pointer = 0 - - inputs = [char_to_idx[ch] for ch in data[pointer : pointer + T_steps]] - targets = [ - char_to_idx[ch] for ch in data[pointer + 1 : pointer + T_steps + 1] - ] - - loss, g_h_prev, g_C_prev = forward_backward( - inputs, - targets, - g_h_prev, - g_C_prev, - T_steps, - H_size, - X_size, - parameters, - ) - smooth_loss = smooth_loss * 0.999 + loss * 0.001 - - # Print every hundred steps - if iteration % dump == 0: - update_status(iteration, smooth_loss) - - update_parameters(learning_rate, parameters) - - pointer += T_steps - update_status(max_iters, smooth_loss) - - stop = datetime.datetime.now() - delta = stop - start - total = delta.total_seconds() * 1000.0 - if timing: - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-d", - "--dump", - type=int, - default=100, - dest="dump", - help="how many iterations of training between dumping output", - ) - parser.add_argument( - "-f", - "--file", - type=str, - default="input.txt", - dest="file_name", - help="input file name", - ) - parser.add_argument( - "--hidden", - type=int, - default=100, - dest="hidden", - help="size of hidden layer", - ) - parser.add_argument( - "-l", - "--loops", - type=int, - default=10000, - dest="loops", - help="maximum number of training loops to run", - ) - parser.add_argument( - "-r", - "--rate", - type=float, - default=1e-1, - dest="rate", - help="learning rate", - ) - parser.add_argument( - "-s", - "--steps", - type=int, - default=25, - dest="steps", - help="number of time steps (length of the sequence) used for training", - ) - parser.add_argument( - "-t", - "--time", - dest="timing", - action="store_true", - help="perform timing", - ) - parser.add_argument( - "-w", - "--weight", - type=float, - default=0.1, - dest="weight", - help="standard deviation of weights for initialization", - ) - parser.add_argument( - "-b", - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 - " - "normal execution)", - ) - args = parser.parse_args() - run_benchmark( - run_lstm, - args.benchmark, - "LSTM Full", - ( - args.file_name, - args.hidden, - args.steps, - args.loops, - args.rate, - args.weight, - args.dump, - args.timing, - ), - ) diff --git a/examples/stencil.py b/examples/stencil.py deleted file mode 100644 index 7794255e4..000000000 --- a/examples/stencil.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime -import math - -from benchmark import run_benchmark - -import legate.numpy as np - - -def initialize(N): - print("Initializing stencil grid...") - grid = np.zeros((N + 2, N + 2)) - grid[:, 0] = -273.15 - grid[:, -1] = -273.15 - grid[-1, :] = -273.15 - grid[0, :] = 40.0 - return grid - - -def run(grid, I, N): # noqa: E741 - print("Running Jacobi stencil...") - center = grid[1:-1, 1:-1] - north = grid[0:-2, 1:-1] - east = grid[1:-1, 2:] - west = grid[1:-1, 0:-2] - south = grid[2:, 1:-1] - for i in range(I): - average = center + north + east + west + south - work = 0.2 * average - # delta = np.sum(np.absolute(work - center)) - center[:] = work - total = np.sum(center) - return total / (N ** 2) - - -def run_stencil(N, I, timing): # noqa: E741 - start = datetime.datetime.now() - grid = initialize(N) - average = run(grid, I, N) - # This will sync the timing because we will need to wait for the result - assert not math.isnan(average) - stop = datetime.datetime.now() - print("Average energy is %.8g" % average) - delta = stop - start - total = delta.total_seconds() * 1000.0 - if timing: - print("Elapsed Time: " + str(total) + " ms") - return total - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-i", - "--iter", - type=int, - default=100, - dest="I", - help="number of iterations to run", - ) - parser.add_argument( - "-n", - "--num", - type=int, - default=100, - dest="N", - help="number of elements in one dimension", - ) - parser.add_argument( - "-t", - "--time", - dest="timing", - action="store_true", - help="perform timing", - ) - parser.add_argument( - "-b", - "--benchmark", - type=int, - default=1, - dest="benchmark", - help="number of times to benchmark this application (default 1 " - "- normal execution)", - ) - args = parser.parse_args() - run_benchmark( - run_stencil, args.benchmark, "Stencil", (args.N, args.I, args.timing) - ) diff --git a/examples/testbench/contrived.py b/examples/testbench/contrived.py deleted file mode 100644 index f9cfed24b..000000000 --- a/examples/testbench/contrived.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime - -#import pdb -#pdb.set_trace() -import legate.numpy as np -import numpy as npo -#import numpy as np -N=6000 -b1 = np.zeros(N) -b2 = np.zeros(N) -b3 = np.zeros(N) -b1.fill(2) -b2.fill(3) -b3.fill(4) - -#dummy ops -# dumb hack so the loop starts at nOps=10 -# so the window/pipe is empty -b3.fill(4) -b3.fill(4) -b3.fill(4) -b3.fill(4) - - -#for i in range(10000): -for i in range(10000): - b3=b1+b2 - -"" diff --git a/examples/testbench/dataflow_legion_python_main_1.pdf b/examples/testbench/dataflow_legion_python_main_1.pdf deleted file mode 100644 index 49ba1be92373ebda1448adea7f5931c32ec07b29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33085 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
iCM|1Hz&i2Vsq}f($|UCg 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 z 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

hT7}!V}nVFcvC?Bxf{HUX1Z)B+s;QHABo{{{O zf$Iia7DgZdoUZXt+6J6B@@pymWPHHu{=A*T3;Q2v5mgw^177w+Dr{h91h4Y{Z4)!7 zoxO;u0rZyvWDWkxvw?n&^G{2|#{XkXaD$6k!H&2vvoZm&YM8;`h<0Yb1V6ggFneil zYWEky1Reu^J;7iw0Di&qF#G&YbHI%J|K|d6!YM0%KRH1l00aX0as5ccA`S-!+*E(x z8v>JYad89S`q+h2B$aQP;H9ZA#bXKoj9@jleGYx8xA2ARSOL0-}L$O>v zaA2B%knJOD0V%Nm$MXJld z76fu%Wc>fp@2_E#hF z%u8mv$j;+OXrmKLLV$jxu3@FhR^3E;c{pdn&t!cqL+Ors-uC5wOxwA)tc=d&!!Y)9 zKoY^w^ws*NrAf3O(_T4q;_A~{`uh9JCJ*BKNp;fL!jEVW1e?JRFM(|ZR?5ll?&;Kp|g5cQbEPx~dS0-SgDoc9VFZw4YXOR^rVEw0)n?vAGG3g=zXt2)3L5 zow6Us`D-Ttfqs*m{ySy=BLKpJANZ$PVUh1=Fb4vdfh-URkPRLeSRmZoAU4>H{NyRY z?;vMj4>g1Hmf#;uV3mKq{Vf0G6tHdJ_k_VCrXtkZ&<^HLzlGwzW9iSJ{&y(-S3qQe z1sgU9tRV}C<7Xeg0ZXuxh2Sm*bBaIW0o;B5@F!UQPuGPLrR;w6BV+aw9(I4k>EFmG z2iP9K_7CR;!8QDK2bd-=9SmVd7ttFUm_e-pY%FXL79fD$)ZX64j)xV-!-7dopawRk zW`=ew)=(3MpF5`r>|i5%GixhRI7^FOlm`R^u>rZjY;2tDoa`_h7RO^Ckl~-5{&yc2 zF@Wu*)+Rp&{zHYoFjz1f`~}Z)h8h`Tz@jP`1Ni#^fN*etIRM6hpE3}HlM}Y$;17V+ zUos#kCp*k)|B^xAdjBZ{!kpsYGENR|*zEjK55xfi!(8J}8H5A=iRBL&kdqrevwz4y z>|h8?^?%E_V7~Y-88`cX>v6-#U;nDd!3op;-!g9ap8DtgIJn{d{-+EA|FoR7sAEZ5Wo!-j;jBO0-_G6uYX8F{K%77}AO - - - - - - - - - - - - - - - - - - -

-
Node Range: :
-
- - -
-
-
-
-
-
- - diff --git a/examples/testbench/decent_band/js/timeline.js b/examples/testbench/decent_band/js/timeline.js deleted file mode 100644 index ba3db5e30..000000000 --- a/examples/testbench/decent_band/js/timeline.js +++ /dev/null @@ -1,2734 +0,0 @@ -// Some of the constants are read in from load_scale_json -var constants = { - margin_left: 350, - margin_right: 75, - margin_bottom: 50, - margin_top: 50, - min_feature_width: 3, - min_gap_width: 1, - util_height: 100, - util_levels: 4, - elem_separation: 2, -} - -var op_dependencies = {}; -var base_map = {}; -var prof_uid_map = {}; - -// Contains the children for each util file -var util_files = {}; - -var state = {}; -var mouseX = 0; -var utilline = d3.svg.line() - .interpolate("step-after") - .x(function(d) { return state.x(+d.time); }) - .y(function(d) { return state.y(+d.count); }); -var timeBisector = d3.bisector(function(d) { return d.time; }).left; -// const num_colors = 20; -// var color = d3.scale.linear() -// .domain([0, num_colors]) -// .range(["green", "blue", "red", "yellow"]); - -String.prototype.hashCode = function() { - var hash = 0; - if (this.length == 0) return hash; - for (i = 0; i < this.length; i++) { - var c = this.charCodeAt(i); - var b = this.charCodeAt(c % this.length); - hash = ((hash<<5)-hash)^c^b; - hash = hash & hash; - } - return Math.abs(hash); -} - -function parseURLParameters() { - var match, - pl = /\+/g, // Regex for replacing addition symbol with a space - search = /([^&=]+)=?([^&]*)/g, - decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, - query = window.location.search.substring(1); - - var urlParams = {}; - while (match = search.exec(query)) - urlParams[decode(match[1])] = decode(match[2]); - - if ("collapseAll" in urlParams) - state.collapseAll = (urlParams["collapseAll"].toLowerCase() === "true"); - - if ("resolution" in urlParams) - state.resolution = Math.max(1, parseFloat(urlParams["resolution"])); - // adjust zoom - var zstart = constants.start; - if ("start" in urlParams) - zstart = Math.max(constants.start, parseFloat(urlParams["start"])); - - var zend = constants.end; - if ("end" in urlParams) - zend = Math.min(constants.end, parseFloat(urlParams["end"])); - - if(zstart < zend) { - // set zoom to get: (zend - start) * zoom * scale = $("#timeline").width() - var newZoom = $("#timeline").width() / state.scale / (zend - zstart); - adjustZoom(newZoom, false); - - // set scrollLeft to get: zstart * zoom * state.scale = scrollLeft() - $("#timeline").scrollLeft(convertToPos(state, zstart)); - } - - if ("search" in urlParams) { - state.searchEnabled = true; - searchRegex = new Array(sizeHistory); - currentPos = 0; - nextPos = 1; - searchRegex[currentPos] = new RegExp(urlParams["search"]); - } -} - -function makeTimelineTransparent() { - state.timelineSvg.select("g#timeline").style("opacity", "0.1"); - $("#timeline").css("overflow-x", "hidden"); - state.timelineSvg.select("g#lines").style("opacity", "0.1"); - state.timelineSvg.select("g.locator").style("opacity", "0.1"); - state.timelineSvg.selectAll("path.util").style("opacity", "0.1"); -} - -function makeTimelineOpaque() { - state.timelineSvg.select("g#timeline").style("opacity", "1.0"); - $("#timeline").css("overflow-x", "scroll"); - state.timelineSvg.select("g#lines").style("opacity", "1.0"); - state.timelineSvg.select("g.locator").style("opacity", "1.0"); - state.timelineSvg.selectAll("path.util").style("opacity", "1.0"); -} - -function mouseMoveHandlerWhenDown() { - var p = d3.mouse(this); - var select_block = state.timelineSvg.select("rect.select-block"); - var select_text = state.timelineSvg.select("text.select-block"); - var newWidth = Math.abs(p[0] - mouseX); - select_block.attr("width", newWidth); - if (p[0] >= mouseX) { - select_block.attr("x", mouseX); - select_text.attr("x", mouseX + (p[0] - mouseX) / 2); - } else { - select_block.attr("x", p[0]); - select_text.attr("x", p[0] + (mouseX - p[0]) / 2); - } - var time = convertToTime(state, newWidth); - select_text.text(getTimeString(time, time)); -} - -function mouseMoveHandlerWhenUp() { - var p = d3.mouse(this); - var x = parseFloat(p[0]); - var scrollLeft = $("#timeline").scrollLeft(); - var paneWidth = $("#timeline").width(); - var currentTime = convertToTime(state, x); - - state.timelineSvg.select("g.locator").remove(); - var locator = state.timelineSvg.append("g").attr("class", "locator"); - locator.insert("line") - .attr({ - x1: p[0], - y1: 0, - x2: p[0], - y2: p[1] - state.thickness / 2, - class: "locator", - }); - locator.append("line") - .attr({ - x1: p[0], - y1: p[1] + state.thickness / 2, - x2: p[0], - y2: state.height, - class: "locator", - }); - var locatorText = locator.append("text"); - var text = getTimeString(currentTime, convertToTime(state, paneWidth)); - locatorText.attr("class", "locator").text(text) - if ((x - scrollLeft) < paneWidth - 100) { - locatorText.attr({x: x + 2, y: $(window).scrollTop() + 10}); - locatorText.attr("anchor", "start"); - } - else { - locatorText.attr({x: x - 2 - text.length * 7, y: $(window).scrollTop() + 10}); - locatorText.attr("anchor", "end"); - } -} - -function mouseDownHandler() { - state.timelineSvg.select("g.locator").remove(); - var p = d3.mouse(this); - state.timelineSvg.append("rect") - .attr({ - x : p[0], - y : 0, - class : "select-block", - width : 0, - height : state.height - }); - state.timelineSvg.append("text") - .attr({ - x : p[0], - y : p[1], - class : "select-block", - anchor : "middle", - "text-anchor" : "middle", - }).text("0 us"); - mouseX = p[0]; - state.timelineSvg.on("mousemove", null); - state.timelineSvg.on("mousemove", mouseMoveHandlerWhenDown); - $(document).off("keydown"); -} - -function get_kind(name) { - var util_regex = /\((.*?)\)/; - var kind_match = util_regex.exec(name); - if (kind_match) { - return kind_match[1]; - } -} - -function getLineColor(elem) { - var kind = get_kind(elem.text); - const colorMap = { - "CPU": "steelblue", - "GPU": "olivedrab", - "Utility": "crimson", - "IO": "orangered", - "Proc Group": "orangered", - "Proc Set": "orangered", - "OpenMP": "orangered", - "Python": "olivedrab", - "System Memory": "olivedrab", - "GASNet Global Memory": "crimson", - "Registered Memory": "darkmagenta", - "Socket Memory": "orangered", - "Zero-Copy Memory": "crimson", - "Framebuffer Memory": "blue", - "Disk Memory": "darkgoldenrod", - "HDF5 Memory": "olivedrab", - "File Memory": "orangered", - "L3 Cache Memory": "crimson", - "L2 Cache Memory": "darkmagenta", - "L1 Cache Memory": "olivedrab", - "Channel": "orangered" - }; - return colorMap[kind]; -} - -function drawUtil() { - // TODO: Add to state - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - var start_time = convertToTime(state, windowStart); - var end_time = convertToTime(state, windowEnd); - var filteredUtilData = []; - for (var i = 0; i < state.flattenedLayoutData.length; i++) { - var elem = state.flattenedLayoutData[i]; - if (elem.type == "util" && elem.enabled && elem.loaded && elem.visible) { - filteredUtilData.push(filterUtilData(elem)); - } - } - - state.x = d3.scale.linear().range([0, convertToPos(state, end_time)]); - state.x.domain([0, end_time]); - state.timelineSvg.selectAll("rect.util").remove(); - state.timelineSvg.selectAll("path.util").remove(); - var paths = state.timelineSvg.selectAll("path") - .data(filteredUtilData); - var totalWidth = windowStart + $("#timeline").width(); - paths.enter().append("rect") - .attr("class", "util") - .attr("base_y", lineLevelCalculator) - .attr("y", lineLevelCalculator) - .attr("x", 0) - .attr("fill", "transparent") - .attr("width", totalWidth) - .attr("height", constants.util_levels * state.thickness) - .on("mouseover", mouseover) - .on("mousemove", mousemove) - .on("mouseout", function() { - state.timelineSvg.select("g.focus").remove(); - state.timelineSvg.select("g.utilDesc").remove(); - }); - paths.enter().append("path") - .attr("base_y", lineLevelCalculator) - .attr("class", "util") - .attr("id", function(d, i) { return "util" + i}) - .attr("d", function (d) { return utilline(d.data); }) - .attr("stroke", getLineColor) - .on("mouseover", mouseover) - .on("mousemove", mousemove) - .on("mouseout", function() { - state.timelineSvg.select("g.focus").remove(); - state.timelineSvg.select("g.utilDesc").remove(); - }) - .attr("transform", - function(d) { - var y = lineLevelCalculator(d); - return "translate(0," + y + ")" - }); -} - - -function mouseUpHandler() { - var p = d3.mouse(this); - var select_block = state.timelineSvg.select("rect.select-block"); - var prevZoom = state.zoom; - var selectWidth = parseInt(select_block.attr("width")); - var svgWidth = state.timelineSvg.attr("width"); - if (state.rangeZoom && selectWidth > 10) { - var x = select_block.attr("x"); - state.zoomHistory.push({zoom: prevZoom, start: $("#timeline").scrollLeft()}); - adjustZoom(svgWidth / selectWidth, false); - $("#timeline").scrollLeft(x / prevZoom * state.zoom); - } - - state.timelineSvg.selectAll("rect.select-block").remove(); - state.timelineSvg.selectAll("text.select-block").remove(); - mouseX = 0; - state.timelineSvg.on("mousemove", null); - state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); - $(document).on("keydown", defaultKeydown); -} - -function turnOffMouseHandlers() { - state.timelineSvg.on("mousedown", null); - state.timelineSvg.on("mouseup", null); - state.timelineSvg.on("mousemove", null); - state.timelineSvg.on("mousemove", null); - // prevent right-click menu - state.timelineSvg.on("contextmenu", function () { - d3.event.preventDefault(); - }); -} - -function turnOnMouseHandlers() { - state.timelineSvg.on("mousedown", mouseDownHandler); - state.timelineSvg.on("mouseup", mouseUpHandler); - state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); - // prevent right-click menu - state.timelineSvg.on("contextmenu", function () { - d3.event.preventDefault(); - }); -} - -function drawLoaderIcon() { - var loaderGroup = state.loaderSvg.append("g") - .attr({ - id: "loader-icon", - }); - loaderGroup.append("path") - .attr({ - opacity: 0.2, - stroke: "steelblue", - fill: "#000", - d: "M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z" - }); - var path = loaderGroup.append("path") - .attr({ - stroke: "steelblue", - fill: "#000", - d: "M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0C22.32,8.481,24.301,9.057,26.013,10.047z" - }); - path.append("animateTransform") - .attr({ - attributeType: "xml", - attributeName: "transform", - type: "rotate", - from: "0 20 20", - to: "360 20 20", - dur: "0.5s", - repeatCount: "indefinite" - }); - state.loaderSvg.select("g").attr("visibility", "hidden"); - state.loaderSvg.attr("width", "0px") - .attr("height", "0px"); -} - -function showLoaderIcon() { - state.numLoading++; - state.loaderSvg.select("g").attr("visibility", "visible"); - state.loaderSvg.attr("width", "40px") - .attr("height", "40px"); -} - -function hideLoaderIcon() { - state.numLoading--; - if (state.numLoading == 0) { - state.loaderSvg.select("g").attr("visibility", "hidden"); - state.loaderSvg.attr("width", "0px") - .attr("height", "0px"); -; - } -} - -function get_time_str(time_val, convert) -{ - if (convert) { - if (time_val >= 1000000) { - var val = time_val/1000000; - val = parseFloat(val.toFixed(3)) - return val.toString() + " sec"; - } - if (time_val >= 1000) { - var val = time_val/1000; - val = parseFloat(val.toFixed(3)) - return val.toString() + " ms"; - } - } - return time_val.toString() + " us"; -} - -function getMouseOver() { - var paneWidth = $("#timeline").width(); - var left = paneWidth / 3; - var right = paneWidth * 2 / 3; - return function(d, i) { - var p = d3.mouse(this); - var x = parseFloat(p[0]); - var y = timelineLevelCalculator(d) - 5; - var descView = state.timelineSvg.append("g") - .attr("id", "desc"); - var text = descView.append("text") - .attr("x", x) - .attr("y", y) - .attr("class", "desc"); - var depElem = prof_uid_map[d.prof_uid][0]; - if ((depElem.in.length != 0) || (depElem.out.length != 0) || - (depElem.children.length !== 0) || (depElem.parents.length !==0 )) { - d3.select(this).style("cursor", "pointer"); - } - // descTexts is an array of Texts we will store in the desc view - var descTexts = []; - var total = d.end - d.start; - var delay = d.start - d.ready; - total = parseFloat(total.toFixed(3)) - delay = parseFloat(delay.toFixed(3)) - var initiation = ""; - // Insert texts in reverse order - if ((d.ready != undefined) && (d.ready != "") && (delay != 0)) { - descTexts.push("Ready State: " + get_time_str(delay,false)); - } - descTexts.push("End: " + get_time_str(d.end, false)); - descTexts.push("Start: " + get_time_str(d.start, false)); - descTexts.push("Total: " + get_time_str(total, true)); - if ((d.initiation != undefined) && d.initiation != "") { - descTexts.push("Initiator: " + state.operations[d.initiation].desc); - } - - // split d.title - var titles = d.title.split("$"); - if (titles.length > 0) { - for (var i = titles.length-1; i >= 0; --i) { - descTexts.push(titles[i]); - } - } - var title = text.append("tspan") - .attr("x", x) - .attr("dy", -12) - .attr("class", "desc") - .text(descTexts[0].replace(/ /g, "\u00A0")); // preserve spacing - - for (var i = 1; i < descTexts.length; ++i) { - var elem = text.append("tspan") - .attr("x", x) - .attr("dy", -12) - .attr("class", "desc") - .text(descTexts[i].replace(/ /g, "\u00A0")); // preserve spacing - } - - var bbox = descView.node().getBBox(); - var padding = 2; - var rect = descView.insert("rect", "text") - .attr("x", bbox.x - 2*padding) - .attr("y", bbox.y - padding) - .attr("width", bbox.width + (padding*4)) - .attr("height", bbox.height + (padding*2)) - .style("fill", "#222") - .style("opacity", "0.7"); - - var bboxRight = bbox.x + bbox.width; - var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); - - // If the box moves off the screen, nudge it back - if (bboxRight > timelineRight) { - var translation = -(bboxRight - timelineRight + 20); - descView.attr("transform", "translate(" + translation + ",0)"); - } - }; -} - -var sizeHistory = 10; -var currentPos; -var nextPos; -var searchRegex = null; - -function showSlider() { - $('#lowerLimit').text($('#node_slider').slider("values", 0)); - $('#upperLimit').text($('#node_slider').slider("values", 1)); -} - -function createMenuList1() { - var memory_kinds = []; - var num_nodes = state.num_nodes; - var num_mems = 0; - var dropdown_options = [ - { value: "ready", - id: "ready_all", - text: "View", - count: 1, - low_range: 0, - high_range: 1 - }, - { value: "memories", - id: "memories_all", - text: "Memories", - count: num_mems, - low_range: 0, - high_range: num_mems -1 - } - ]; - - // memories list - dropdown_options_memories = []; - - // misc items list - var pkind = { - id: "rr", - value: "rdy", - count: 1, - low_range: 0, - high_range: 1, - text: "Ready State" - }; - - dropdown_options_misc = []; - dropdown_options_misc.push(pkind); - - // create the remaining entries - function appendKind(elem) { - var value = state.processor_kinds[elem]; - if (elem.includes("Memory") && (value.count >= 0)) - { - num_mems = num_mems+1; - dropdown_options_memories.push(value); - } - if ((value.count >= 0) && (value.low_range != -1)) { - dropdown_options.push(value); - } - } - Object.keys(state.processor_kinds).forEach(appendKind); - - // main menu - d3.select("#dropdown").selectAll("optgroup") - .data(dropdown_options) - .enter() - .append("optgroup") - .attr('label', function(d) { return d.text;}) - .attr("id", function(d) { return d.id;}) - .attr("value", function(d) { return d.value;}); - - for (var j=0; j val)) - kind_proc.low_range = val; - if (kind_proc.high_range < val) - kind_proc.high_range = val; - } - } - } - - // Util graphs will have processors as their children as well. - if (type == "util") { - // get the children for the util view - var proc_children = getProcessors(text); - var count = 1; - var node_id = get_node_id(text); - var kind = get_kind(text); - // add to processor kinds: union of all processor kinds - if (!(kind in state.processor_kinds)) { - var pkind = { - id: kind, - value: kind, - count: proc_children.length, - low_range: -1, - high_range: -1, - text: kind - }; - state.processor_kinds[kind] = pkind; - } - if (state.processor_kinds[kind].count < proc_children.length) - state.processor_kinds[kind].count = proc_children.length; - - proc_children.forEach(function(proc_child) { - var child_element = getElement(depth + 1, proc_child.text, - proc_child.full_text, "proc", - proc_child.height, load_proc_timeline, - proc_child.tsv, element, undefined, - true, false); - element.children.push(child_element); - }); - } - - return element; -} - - -function calculateLayout() { - - // First element in the layout will be the all_util. All first-level - // elements will start off not enabled, and will be uncollapsed later - // programmatically - var num_nodes = Object.keys(util_files).length; - if (num_nodes > 1) { - var proc_kinds = util_files["all"]; - proc_kinds.forEach(function(name) { - var kind = "(" + get_kind(name) + ")"; - var util_name = "all nodes " + kind; - var kind_element = getElement(0, util_name, undefined, "util", - constants.util_levels, load_util, - "tsv/" + name + "_util.tsv", - undefined, util_files[kind], false, true); - state.layoutData.push(kind_element); - }); - } - - var seen_nodes = []; - state.processors.forEach(function(proc) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - var proc_regex = /(Processor|Memory) 0x1(e|d)([a-fA-f0-9]{4})[a-fA-f0-9]{10}$/; - // Memory Channel - var proc_channel_regex = /(Memory) 0x1(e)([a-fA-f0-9]{4})[a-fA-f0-9]{10}.*Channel/; - var proc_channel_match = proc_channel_regex.exec(proc.full_text); - var proc_match = proc_regex.exec(proc.full_text); - proc_match = proc_match || proc_channel_match; - if (proc_match) { - var node_id = parseInt(proc_match[3], 16); - if (!(node_id in seen_nodes)) { - seen_nodes[node_id] = 1; - if (node_id in util_files) { - var proc_kinds = util_files[node_id]; - proc_kinds.forEach(function(kind) { - var util_name = "node " + kind; - var kind_element = getElement(0, util_name, undefined, "util", - constants.util_levels, load_util, - "tsv/" + kind + "_util.tsv", - undefined, util_files[kind], - false, true); - state.layoutData.push(kind_element); - }); - } - } - } - else { - state.layoutData.push(getElement(0, proc.text, proc.full_text, "proc", - proc.height, load_proc_timeline, - proc.tsv, undefined, undefined, - false, true)); - } - }); - state.num_nodes = seen_nodes.length; -} - -function getElemCoords(elems) { - var proc = elems[0].proc; - var level = elems[0].level; - var startX = convertToPos(state, elems[0].start); - var endX = convertToPos(state, elems[elems.length-1].end); - var endBase = +proc.base; - var endLevel = endBase + level; - var y = dependencyLineLevelCalculator(endLevel); - return {startX: startX, endX: endX, y: y}; -} - - -function addLine(group, x1, x2, y1, y2, color, dashed) { - var line; - if (dashed) { - line = group.append("line") - .attr("x1", x1) - .attr("y1", y1) - .attr("x2", x2) - .attr("y2", y2) - .style("stroke", color) - .style("stroke-dasharray", "3,3") - .style("stroke-width", "1px"); - } else { - line = group.append("line") - .attr("x1", x1) - .attr("y1", y1) - .attr("x2", x2) - .attr("y2", y2) - .style("stroke", color) - .style("stroke-width", "1px"); - } - - var slope = (y2 - y1) / (x2 - x1); - var intercept = y1 - (slope * x1); - var triangleRotation = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI - 90; - - group.append("line") - .attr("x1", x1) - .attr("y1", y1) - .attr("x2", x2) - .attr("y2", y2) - .style("stroke", "transparent") - .style("stroke-width", "20px") - .on("mouseover", function() { - group.append("g") - .attr("class", "marker") - .append("path") - .attr("d", d3.svg.symbol().type("triangle-down").size(20)) - .style("stroke", color) - .style("fill", color); - }) - .on("mousemove", function() { - var marker = group.select("g.marker"); - var px = d3.mouse(this)[0] - 10; - var py = d3.mouse(this)[1] - ((slope > 0 ? 1 : -1) * 20); - if (px < Math.min(x1, x2)) { - px += 20; - } - if (py < Math.min(y1, y2)) { - py += 40; - } - - // some linear algebra here - var cx = (slope * py + px - slope * intercept) / (slope * slope + 1); - var cy = (slope * slope * py + slope * px + intercept) / (slope * slope + 1); - - marker.attr("transform", "translate(" + cx + "," + cy + ") rotate(" + triangleRotation + ")"); - }) - .on("mouseout", function() { - group.select("g.marker").remove(); - }); - - group.append("circle") - .attr("cx", x1) - .attr("cy", y1) - .attr("fill", "white") - .attr("stroke", "black") - .attr("r", 2.5) - .style("stroke-width", "1px"); - - group.append("circle") - .attr("cx", x2) - .attr("cy", y2) - .attr("fill", "white") - .attr("stroke", "black") - .attr("r", 2.5) - .style("stroke-width", "1px"); -} - - -function drawCriticalPath() { - state.timelineSvg.selectAll("g.critical_path_lines").remove(); - if (state.critical_path == undefined || !state.display_critical_path) { - return; - } - var depGroup = state.timelineSvg.append("g") - .attr("class", "critical_path_lines"); - state.critical_path.forEach(function(op) { - var proc = base_map[op[0] + "," + op[1]]; // set in calculateBases - if (proc != undefined && proc.visible && proc.enabled && proc.loaded && proc.selected) { - var elems = prof_uid_map[op[2]]; - if (elems != undefined) { - var coords = getElemCoords(elems) - var startX = coords.startX; - var endX = coords.endX; - var y = coords.y; - elems[0].out.forEach(function(dep) { - if (dep[2] in state.critical_path_prof_uids) { - var depElems = prof_uid_map[dep[2]]; - if (depElems != undefined) { - var depProc = depElems[0].proc; - // is the proc visible? - if (depProc.visible && depProc.enabled && depProc.loaded) { - var depCoords = getElemCoords(depElems); - var depX = depCoords.endX; - var depY = depCoords.y; - addLine(depGroup, depX, startX, depY, y, "grey", false); - } - } - } - }); - // Draw parent-child lines - var lastChildCoords = undefined; - var firstChildCoords = undefined; - elems[0].children.forEach(function(child) { - if (child[2] in state.critical_path_prof_uids) { - var childElems = prof_uid_map[child[2]]; - var childCoords = getElemCoords(childElems); - if (childElems !== undefined) { - if (lastChildCoords === undefined || - childCoords.startX > lastChildCoords.startX) { - lastChildCoords = childCoords; - } - if (firstChildCoords === undefined || - childCoords.endX < firstChildCoords.endX) { - firstChildCoords = childCoords; - } - } - } - }); - if (firstChildCoords !== undefined) { - addLine(depGroup, startX, firstChildCoords.startX, - y, firstChildCoords.y, "grey", true); - } - if (lastChildCoords !== undefined) { - addLine(depGroup, lastChildCoords.endX, endX, - lastChildCoords.y, y, "grey", true); - } - } - } - }); -} - -function drawDependencies() { - state.timelineSvg.select("g.dependencies").remove(); - var timelineEvent = state.dependencyEvent; - if (timelineEvent == undefined || - !timelineEvent.proc.visible || !timelineEvent.proc.enabled) { - return; // don't draw in this case, the src isn't present - } - var srcElems = prof_uid_map[timelineEvent.prof_uid]; - timelineEvent = srcElems[0]; // only the first elem will have deps and children - var srcCoords = getElemCoords(srcElems); - var srcStartX = srcCoords.startX; - var srcEndX = srcCoords.endX; - var srcY = srcCoords.y; - var depGroup = state.timelineSvg.append("g") - .attr("class", "dependencies"); - - var addDependency = function(dep, dir, dashed) { - var depProc = base_map[dep[0] + "," + dep[1]]; // set in calculateBases - if (depProc.visible && depProc.enabled && depProc.selected) { - var depElems = prof_uid_map[dep[2]]; - if (depElems != undefined) { - console.log(dir); - var depCoords = getElemCoords(depElems); - var dstY = depCoords.y; - if (dir === "in") { - addLine(depGroup, srcEndX, depCoords.startX, srcY, dstY, "black", dashed); - } else if (dir === "out") { - addLine(depGroup, depCoords.endX, srcStartX, dstY, srcY, "black", dashed); - } else if (dir === "parent") { - addLine(depGroup, depCoords.startX, srcStartX, dstY, srcY, "black", dashed); - addLine(depGroup, srcEndX, depCoords.endX, srcY, dstY, "black", dashed); - } else if (dir === "child") { - addLine(depGroup, srcStartX, depCoords.startX, srcY, dstY, "black", dashed); - addLine(depGroup, depCoords.endX, srcEndX, dstY, srcY, "black", dashed); - } - - } - } - } - - if (state.drawDeps) { - timelineEvent.in.forEach(function(dep) {addDependency(dep, "in", false)}); - timelineEvent.out.forEach(function(dep) {addDependency(dep, "out", false)}); - } - if (state.drawChildren) { - timelineEvent.parents.forEach(function(dep) {addDependency(dep, "parent", true)}); - timelineEvent.children.forEach(function(dep) {addDependency(dep, "child", true)}); - } -} - -function timelineEventsExistAndEqual(a, b) { - if (a == undefined || b == undefined) { - return false; - } - return (a.proc.base == b.proc.base) && (a.prof_uid == b.prof_uid); -} - -function timelineElementStrokeCalculator(elem) { - if (timelineEventsExistAndEqual(elem, state.dependencyEvent)) { - return true; - } else if (state.display_critical_path && - elem.prof_uid in state.critical_path_prof_uids) { - return true; - } - return false; -} - -function timelineEventMouseDown(_timelineEvent) { - // only the first event of this uid will have information - var timelineEvent = prof_uid_map[_timelineEvent.prof_uid][0]; - var hasDependencies = ((timelineEvent.in.length != 0) || - (timelineEvent.out.length != 0)); - - if (hasDependencies) { - if (timelineEventsExistAndEqual(timelineEvent, state.dependencyEvent)) { - if (d3.event.button === 0) { - state.drawDeps = !state.drawDeps; - } else if (d3.event.button === 2) { - state.drawChildren = !state.drawChildren; - } - if (state.drawDeps === false && state.drawChildren === false) { - state.dependencyEvent = undefined; - } - } else { - timelineEvent.in.concat(timelineEvent.out).forEach(function(dep) { - expandByNodeProc(dep[0], dep[1]) - }); - state.dependencyEvent = timelineEvent; - if (d3.event.button === 0) { - state.drawDeps = true; - } else if (d3.event.button === 2) { - state.drawChildren = true; - } - } - redraw(); - } -} - -function drawTimeline() { - showLoaderIcon() - - updateURL(state.zoom, state.scale); - var timelineGroup = state.timelineSvg.select("g#timeline"); - timelineGroup.selectAll("rect").remove(); - timelineGroup.selectAll("text").remove(); - var timeline = timelineGroup.selectAll("rect") - .data(state.dataToDraw, function(d) { return d.proc.base + "-" + d.id; }); - var timelineText = timelineGroup.selectAll("text") - .data(state.memoryTexts); - var mouseOver = getMouseOver(); - - timeline.enter().append("rect"); - - timeline - .attr("id", function(d) { return "block-" + d.proc.base + "-" + d.id; }) - .attr("x", function(d) { return convertToPos(state, d.start); }) - .attr("y", timelineLevelCalculator) - .style("fill", function(d) { - if (!state.searchEnabled || - searchRegex[currentPos].exec(d.title) == null) - return d.color; - else return "#ff0000"; - }) - .attr("width", function(d) { - return Math.max(constants.min_feature_width, convertToPos(state, d.end - d.start)); - }) - .attr("stroke", function(d) { - if (timelineElementStrokeCalculator(d)) { - return "red"; - } else { - return "black"; - } - }) - .attr("stroke-width", function(d) { - if (timelineElementStrokeCalculator(d)) { - return "1.5"; - } else { - return "0.5"; - } - }) - .attr("height", state.thickness) - .style("opacity", function(d) { - if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) != null || searchRegex[currentPos].exec(d.initiation) != null) { - return d.opacity; - } - else return 0.05; - }) - .on("mouseout", function(d, i) { - if ((d.in.length != 0) || (d.out.length != 0)) { - d3.select(this).style("cursor", "default"); - } - state.timelineSvg.selectAll("#desc").remove(); - }) - .on("mousedown", timelineEventMouseDown) - - - timelineText.enter().append("text"); - - timelineText - .attr("class", "timeline") - .attr("y", timelineTextLevelCalculator) - .attr("text-anchor", "start") - .text(function(d) { - var sizeRegex = /Size=(.*)/; - var match = sizeRegex.exec(d.title); - return match[1]; - }) - .attr("visibility", function(d) { - var textWidth = this.getComputedTextLength(); - var startX = convertToPos(state, d.start); - var endX = convertToPos(state, d.end); - var boxWidth = endX - startX; - return boxWidth > textWidth ? "visible" : "hidden"; - }) - .attr("x", function(d) { - var textWidth = this.getComputedTextLength(); - var midPoint = convertToPos(state, d.start + (d.end - d.start) / 2); - midPoint -= textWidth / 2; - return midPoint - }); - - drawUtil(); - timeline.on("mouseover", mouseOver); - timeline.exit().remove(); - hideLoaderIcon(); -} - -function redraw() { - if (state.numLoading == 0) { - calculateBases(); - filterAndMergeBlocks(state); - constants.max_level = calculateVisibileLevels(); - recalculateHeight(); - drawTimeline(); - drawDependencies(); - drawCriticalPath(); - drawLayout(); - } -} - -function calculateVisibileLevels() { - var levels = 0; - state.flattenedLayoutData.forEach(function(elem) { - if (elem.visible) { - if (elem.enabled) { - if (state.ready_selected && elem.num_levels_ready != undefined) - levels += elem.num_levels_ready; - else - levels += elem.num_levels; - } - levels += constants.elem_separation; - } - }); - return levels; -} - -function is_proc(proc) { - // the full text of this proc should start with 0x1d to be a processor - return /0x1d/.exec(proc.full_text) !== undefined; -} - -function is_proc_string(text) -{ - return /0x1d/.exec(text) != undefined; -} - -function is_mem_string(text) { - return /0x1e/.exec(text) != undefined; -} - -function get_node_val(text) { - var match = /\d+/.exec(text); - if (match) { - var val = parseInt(text.match(/\d+/)); - return val; - } - return match; -} - -function get_node_id(text) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - var proc_regex = /(Memory|Processor) 0x1(e|d)([a-fA-f0-9]{4})/; - var proc_match = proc_regex.exec(text); - // if there's only one node, then per-node graphs are redundant - if (proc_match) { - var node_id = parseInt(proc_match[3], 16); - return node_id - } -} - -function get_proc_in_node(text) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - var proc_regex = /Processor 0x1d[a-fA-f0-9]{11}([a-fA-f0-9]{3})/; - var proc_match = proc_regex.exec(text); - // if there's only one node, then per-node graphs are redundant - if (proc_match) { - var proc_in_node = parseInt(proc_match[1], 16); - return proc_in_node; - } -} - -function calculateBases() { - var base = 0; - state.flattenedLayoutData.forEach(function(elem) { - elem.base = base; - var node_id = get_node_id(elem.full_text); - var proc_in_node = get_proc_in_node(elem.full_text); - if (node_id != undefined && proc_in_node != undefined) { - base_map[(+node_id) + "," + (+proc_in_node)] = elem; - } - if (elem.visible) { - if (elem.enabled) { - if (state.ready_selected && elem.num_levels_ready != undefined) - base += elem.num_levels_ready; - else - base += elem.num_levels; - } - base += constants.elem_separation; - } - }); -} - -function expandHandler(elem, index) { - elem.expanded = !elem.expanded; - - if (elem.expanded) { - function expandChild(child) { - child.visible = true; - //child.enabled = true; - if(!child.loaded) { - showLoaderIcon(); - child.loader(child); // will redraw the timeline once loaded - } else if (child.expanded) { - child.children.forEach(expandChild); - } - } - elem.children.forEach(expandChild); - } else { - function collapseChildren(child) { - child.visible = false; - child.children.forEach(collapseChildren); - } - elem.children.forEach(collapseChildren); - } - redraw(); -} - -// This handler is called when you collapse/uncollapse a row in the -// timeline -function collapseHandler(d, index) { - d.enabled = !d.enabled; - - if (!d.loaded) { - // should always be expanding here - showLoaderIcon(); - //var elem = state.flattenedLayoutData[index]; - d.loader(d); // will redraw the timeline once loaded - } else { - redraw(); - } -} - -// This expands a particular element and its parents if necessary -function expandElementAndParents(elem) { - if (elem !== undefined) { - var elemPath = []; // path up to parent - var curElem = elem; - while (curElem != undefined) { - elemPath.push(curElem); - curElem = curElem.parent; - } - - for (var i = elemPath.length - 1; i >= 0; --i) { - var elem = elemPath[i]; - if (!elem.expanded) { - expandHandler(elem); - } - // uncollapse if necessary - if ((i == 0) && !elem.enabled) { - collapseHandler(elem); - } - } - } -} - - -function expandByNodeProc(node, proc) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - // ugh why isn't there string formatting - var nodeHex = ("0000" + node.toString(16)).slice(-4); - var procHex = ("000" + proc.toString(16)).slice(-3); - var expectedTitle = "0x1d" + nodeHex + "0000000" + procHex; - var matchedElement = undefined; - for (var i = 0; i < state.flattenedLayoutData.length; i++) { - var timelineElement = state.flattenedLayoutData[i]; - if ((timelineElement.full_text != undefined) && - (timelineElement.full_text.indexOf(expectedTitle) !=-1)) { - matchedElement = timelineElement; - break; - } - } - expandElementAndParents(matchedElement) -} - - -function lineLevelCalculator(timelineElement) { - var level = timelineElement.base + 1; - if (timelineElement.enabled) { - if (state.ready_selected && timelineElement.num_levels_ready != undefined) - level += timelineElement.num_levels_ready; - else - level += timelineElement.num_levels; - } - return constants.margin_top + level * state.thickness; -}; - -function utilLevelCalculator(timelineElement) { - var level = timelineElement.base; - if (timelineElement.enabled) { - if (state.ready_selected && timelineElement.num_levels_ready != undefined) - level += timeLineElement.num_levels_ready; - else - level += timeLineElement.num_levels; - } - return constants.margin_top + level * state.thickness; -}; - - -function timelineLevelCalculator(timelineEvent) { - return constants.margin_top + - (timelineEvent.proc.base + timelineEvent.level) * state.thickness; -}; - -function timelineTextLevelCalculator(timelineEvent) { - return constants.margin_top + - (timelineEvent.proc.base + timelineEvent.level + 0.75) * state.thickness; -}; - -function dependencyLineLevelCalculator(level) { - return constants.margin_top + ((level+0.5) * state.thickness); -} - -function drawLayout() { - d3.select("#processors").select("svg").remove(); - state.timelineSvg.select("g#lines").remove(); - - var data = state.flattenedLayoutData; - var svg = d3.select("#processors").append("svg") - .attr("width", constants.margin_left) - .attr("height", state.height); - - var namesGroup = svg.selectAll(".processors") - .data(data) - .enter().append("g"); - - var names = namesGroup.append("text"); - - var thickness = state.thickness; - var xCalculator = function(d) { return (d.depth + 1) * 15; }; - names.attr("text-anchor", "start") - .attr("class", "processor") - .text(function(d) { return d.text; }) - .attr("x", xCalculator) - .attr("y", lineLevelCalculator) - .attr("visibility", function(elem) { - return (elem.visible) ? "visible" : "hidden" - }) - .style("fill", "#000000") - .style("opacity", function(proc) { - return (proc.enabled) ? 1 : 0.5; - }); - - - // names.each(function(d) { - // var elem = d3.select(this); - // var text = d.text; - // var tokens = d.text.split(" to "); - // if (tokens.length == 1) - // elem.append("tspan").text(d.text); - // else { - // var source = tokens[0]; - // var target = tokens[1].replace(" Channel", ""); - // elem.append("tspan").text(source) - // .attr("x", xCalculator) - // .attr("dy", -10); - // elem.append("tspan").text("==> " + target) - // .attr("x", xCalculator) - // .attr("dy", 10); - // } - // }); - names.on({ - "mouseover": function(d) { - d3.select(this).style("cursor", "pointer") - if (d.full_text != undefined) { - var x = xCalculator(d); - var y = lineLevelCalculator(d) - state.thickness; - - var overlaySvg = d3.select("#overlay").append("svg"); - var descView = overlaySvg.append("g").attr("id", "desc"); - - var text = descView.append("text") - .attr("x", x) - .attr("y", y) - .attr("text-anchor", "start") - .attr("class", "desc") - .text(unescape(escape(d.full_text))); - - var bbox = text.node().getBBox(); - var padding = 2; - var rect = descView.insert("rect", "text") - .attr("x", bbox.x - padding) - .attr("y", bbox.y - padding) - .attr("width", bbox.width + (padding*2)) - .attr("height", bbox.height + (padding*2)) - .style("fill", "#222") - .style("opacity", "0.7"); - - overlaySvg.attr("width", bbox.x + bbox.width + (padding*2)) - .attr("height", bbox.y + bbox.height + (padding*2)); - } - }, - "mouseout": function(d) { - d3.select(this).style("cursor", "default") - if (d.full_text != undefined) { - d3.select("#overlay").selectAll("svg").remove(); - } - }, - "click": collapseHandler - }); - - var expandableNodes = namesGroup.filter(function(elem) { - return elem.children.length > 0; - }); - - var expand_group = expandableNodes.append("g"); - - var expand_clickable = expand_group.append("circle") - .attr("fill", "transparent") - .attr("stroke", "transparent") - .attr("r", 8); - var expand_icons = expand_group.append("path"); - var arc = d3.svg.symbol().type('triangle-down') - .size(12); - - - //.attr("transform", function(elem) { - // var x = constants.margin_left - 10; - // var y = lineLevelCalculator(elem); - // return "translate(" + x + "," + y + ")"; - //}) - expand_icons.attr("class", "processor") - .attr("d", arc) - .attr("visibility", function(elem) { - return (elem.visible) ? "visible" : "hidden" - }) - .style("fill", "#000000") - .style("stroke", "#000000") - .style("opacity", function(proc) { - return (proc.enabled) ? 1 : 0.5; - }); - - expand_group.each(function(elem) { - var path = d3.select(this); - var x = elem.depth * 15 + 5; - var y = lineLevelCalculator(elem) - 3; - - if (elem.expanded) { - path.attr("transform", "translate(" + x + ", " + y + ") rotate(0)"); - } else { - path.attr("transform", "translate(" + x + ", " + y + ") rotate(30)"); - } - - }); - - - expand_group.on({ - "mouseover": function(d) { - d3.select(this).style("cursor", "pointer") - }, - "mouseout": function(d) { - d3.select(this).style("cursor", "default") - }, - "click": expandHandler - }); - - - var lines = state.timelineSvg - .append("g") - .attr("id", "lines"); - - var thickness = state.thickness; - lines.selectAll(".lines") - .data(data) - .enter().append("line") - .attr("x1", 0) - .attr("y1", lineLevelCalculator) - .attr("x2", state.zoom * state.width) - .attr("y2", lineLevelCalculator) - .attr("visibility", function(elem) { - return (elem.visible) ? "visible" : "hidden" - }) - .style("stroke", "#000000") - .style("stroke-width", "2px") - .style("opacity", function(proc) { - return (proc.enabled) ? 1 : 0.5; - }); -} - -function drawHelpBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - - var helpBoxGroup = popUpSvg.append("g"); - var helpBoxWidth = Math.min(450, width - 100); - var helpTextOffset = 20; - var helpBoxHeight = Math.min(helpMessage.length * helpTextOffset + 100, - height - 100); - - var boxStartX = (width - helpBoxWidth) / 2; - var boxStartY = (height - helpBoxHeight) / 2; - - helpBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: helpBoxWidth, - height: helpBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var helpText = helpBoxGroup.append("text") - .attr("class", "help-box") - .style("width", helpBoxWidth); - var helpTitle = "Keyboard Shortcuts"; - helpText.append("tspan") - .attr({ x: boxStartX + helpBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text(helpTitle); - var off = 15; - for (var i = 0; i < helpMessage.length; ++i) { - helpText.append("tspan") - .style("font-size", "12pt") - .attr("text-anchor", "start") - .attr({ x: boxStartX + 30, dy: off + helpTextOffset}) - .text(helpMessage[i]); - off = 0; - } -} - -function evalExpandRequest(re) { - var re = new RegExp(re); - state.flattenedLayoutData.forEach(function(elem) { - if (re.exec(elem.text)) { - expandElementAndParents(elem); - } - }); - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); -} - -function drawExpandBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - var expandBoxGroup = popUpSvg.append("g"); - var expandBoxWidth = Math.min(450, width - 100); - var expandBoxHeight = Math.min(220, height - 100); - - var thicknessRatio = state.thickness / state.baseThickness; - var boxStartX = (width - expandBoxWidth) / 2; - var boxStartY = (height - expandBoxHeight) / 2; - - expandBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: expandBoxWidth, - height: expandBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var expandText = expandBoxGroup.append("text") - .attr("class", "expand-box") - .style("width", expandBoxWidth); - expandText.append("tspan") - .attr({ x: boxStartX + expandBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text("expand"); - var expandInputWidth = expandBoxWidth - 40; - var expandInputHeight = 50; - var expandInputStartY = 65; - - - expandBoxGroup.append("foreignObject") - .attr({ x: boxStartX + 20, y: boxStartY + expandInputStartY, - width: expandInputWidth, height: expandBoxHeight - expandInputStartY}) - .attr("text-anchor", "middle") - .html( - "" - + "
" - + "" - + "Presets" - + "" - + "
" - + "
" - + "" - + "" - + "" - + "" - + "" - + "" - + "
" - ); - $("input.expand-box").focus(); -} - -function drawSearchBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - var searchBoxGroup = popUpSvg.append("g"); - var searchBoxWidth = Math.min(450, width - 100); - var searchBoxHeight = Math.min(250, height - 100); - - var thicknessRatio = state.thickness / state.baseThickness; - var boxStartX = (width - searchBoxWidth) / 2; - var boxStartY = (height - searchBoxHeight) / 2; - - searchBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: searchBoxWidth, - height: searchBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var searchText = searchBoxGroup.append("text") - .attr("class", "search-box") - .style("width", searchBoxWidth); - searchText.append("tspan") - .attr({ x: boxStartX + searchBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text("Search"); - var searchInputWidth = searchBoxWidth - 40; - var searchInputHeight = 50; - searchBoxGroup.append("foreignObject") - .attr({ x: boxStartX + 20, y: boxStartY + 150, - width: searchInputWidth, height: searchInputHeight}) - .attr("text-anchor", "middle") - .html(""); - $("input.search-box").focus(); -} - -function drawSearchHistoryBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - - var historyBoxGroup = popUpSvg.append("g"); - var historyBoxWidth = Math.min(450, width - 100); - var historyBoxHeight = Math.min(350, height - 100); - - var boxStartX = (width - historyBoxWidth) / 2; - var boxStartY = (height - historyBoxHeight) / 2; - - historyBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: historyBoxWidth, - height: historyBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var historyText = historyBoxGroup.append("text") - .attr("class", "history-box") - .style("width", historyBoxWidth); - var historyTitle = "Search History"; - historyText.append("tspan") - .attr({ x: boxStartX + historyBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text(historyTitle); - if (searchRegex != null) { - var off = 15; - var id = 1; - for (var i = 0; i < sizeHistory; ++i) { - var pos = (nextPos + i) % sizeHistory; - var regex = searchRegex[pos]; - if (regex != null) { - if (pos == currentPos) prefix = ">>> "; - else prefix = id + " : "; - historyText.append("tspan") - .attr("text-anchor", "start") - .attr({ x: boxStartX + 30, dy: off + 25}) - .text(prefix + regex.source); - off = 0; - id++; - } - } - } -} - -function updateURL() { - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - var start_time = convertToTime(state, windowStart); - var end_time = convertToTime(state, windowEnd); - var url = window.location.href.split('?')[0]; - url += "?start=" + start_time; - url += "&end=" + end_time; - url += "&collapseAll=" + state.collapseAll; - url += "&resolution=" + state.resolution; - if (state.searchEnabled) - url += "&search=" + searchRegex[currentPos].source; - window.history.replaceState("", "", url); -} - -function adjustZoom(newZoom, scroll) { - var prevZoom = state.zoom; - state.zoom = Math.round(newZoom * 10) / 10; - - var svg = d3.select("#timeline").select("svg"); - - svg.attr("width", state.zoom * state.width) - .attr("height", state.height); - - var timelineGroup = svg.select("g#timeline"); - //timelineGroup.selectAll("rect").remove(); - - svg.select("g#lines").selectAll("line") - .attr("x2", state.zoom * state.width); - svg.selectAll("#desc").remove(); - svg.selectAll("g.locator").remove(); - d3.select("#overlay").selectAll("svg").remove(); - - if (scroll) { - var paneWidth = $("#timeline").width(); - var pos = ($("#timeline").scrollLeft() + paneWidth / 2) / prevZoom; - // this will trigger a scroll event which in turn redraws the timeline - $("#timeline").scrollLeft(pos * state.zoom - state.width / 2); - } else { - filterAndMergeBlocks(state); - drawTimeline(); - } - drawDependencies(); - drawCriticalPath(); -} - -function recalculateHeight() { - // adjust the height based on the new thickness and max level - state.height = constants.margin_top + constants.margin_bottom + - (state.thickness * constants.max_level); - var util_height = constants.util_levels * state.thickness; - state.y = d3.scale.linear().range([util_height, 0]); - state.y.domain([0, 1]); - - d3.select("#processors").select("svg").remove(); - var svg = d3.select("#timeline").select("svg"); - svg.attr("width", state.zoom * state.width) - .attr("height", state.height); - var lines = state.timelineSvg.select("g#lines"); - lines.remove(); - - svg.selectAll("#desc").remove(); - svg.selectAll("g.locator").remove(); - d3.select("#overlay").selectAll("svg").remove(); - -} - -function adjustThickness(newThickness) { - state.thickness = newThickness; - recalculateHeight(); - drawTimeline(); - drawLayout(); -} - -function suppressdefault(e) { - if (e.preventDefault) e.preventDefault(); - if (e.stopPropagation) e.stopPropagation(); -} - -function setKeyHandler(handler) { - $(document).off("keydown"); - $(document).on("keydown", handler); -} - -function makeModalKeyHandler(validKeys, callback) { - return function(e) { - if (!e) e = event; - var code = e.keyCode || e.charCode; - if (!(e.ctrlKey || e.metaKey || e.altKey)) { - for (var i = 0; i < validKeys.length; ++i) { - if (keys[code] == validKeys[i]) { - callback(keys[code]); - return false; - } - } - } - return true; - } -} - -function displayPopUp() { - d3.select("#pop-up").append("svg") - .attr("width", $(window).width()) - .attr("height", $(window).height()); -} - -function removePopUp() { - var popUpSvg = d3.select("#pop-up").selectAll("svg").remove(); -} - - -function defaultKeydown(e) { - if (!e) e = event; - - var code = e.keyCode || e.charCode; - var commandType = Command.none; - var modifier = e.ctrlKey || e.metaKey || e.altKey; - var multiFnKeys = e.metaKey && e.ctrlKey || e.altKey && e.ctrlKey; - - var translatedCode = keys[code]; - - if (!modifier) { - commandType = noModifierCommands[translatedCode]; - } else if (!multiFnKeys) { - commandType = modifierCommands[translatedCode]; - } else { - commandType = multipleModifierCommands[translatedCode]; - } - - if (commandType == undefined) { - if (e.metaKey || e.altKey) - state.rangeZoom = false; - return true; - } - - suppressdefault(e); - if (commandType == Command.help) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - // make help box visible - displayPopUp(); - drawHelpBox(); - setKeyHandler(makeModalKeyHandler(['/', 'esc'], function(key) { - // make help box invisible - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - else if (commandType == Command.search) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - displayPopUp(); - drawSearchBox(); - setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { - if (key == 'enter') { - var re = $("input.search-box").val(); - if (re.trim() != "") { - if (searchRegex == null) { - searchRegex = new Array(sizeHistory); - currentPos = -1; - nextPos = 0; - } - currentPos = nextPos; - nextPos = (nextPos + 1) % sizeHistory; - searchRegex[currentPos] = new RegExp(re); - state.searchEnabled = true; - } - } - removePopUp(); - if (state.searchEnabled) { - filterAndMergeBlocks(state); - drawTimeline(); - } - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - else if (commandType == Command.expand) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - displayPopUp(); - drawExpandBox(); - setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { - if (key == 'enter') { - var re = $("input.expand-box").val(); - if (re.trim() != "") { - re = new RegExp(re); - state.flattenedLayoutData.forEach(function(elem) { - if (re.exec(elem.text)) { - expandElementAndParents(elem); - } - }); - } - } - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - else if (commandType == Command.search_history) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - displayPopUp(); - drawSearchHistoryBox(); - setKeyHandler(makeModalKeyHandler(['h', 'esc'], function(key) { - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - - if (commandType == Command.zix) { - var inc = 4.0; - adjustZoom(state.zoom + inc, true); - } else if (commandType == Command.zox) { - var dec = 4.0; - if (state.zoom - dec > 0) - adjustZoom(state.zoom - dec, true); - } else if (commandType == Command.zrx) { - state.zoomHistory = Array(); - adjustZoom(1.0, false); - $("#timeline").scrollLeft(0); - } else if (commandType == Command.zux) { - if (state.zoomHistory.length > 0) { - var previousZoomHistory = state.zoomHistory.pop(); - adjustZoom(previousZoomHistory.zoom, false); - $("#timeline").scrollLeft(previousZoomHistory.start); - } - } else if (commandType == Command.ziy) - adjustThickness(state.thickness * 2); - else if (commandType == Command.zoy) - adjustThickness(state.thickness / 2); - else if (commandType == Command.zry) { - state.height = $(window).height() - constants.margin_bottom - constants.margin_top; - state.thickness = state.height / constants.max_level; - adjustThickness(state.thickness); - } - else if (commandType == Command.clear_search) { - state.searchEnabled = false; - searchRegex = null; - filterAndMergeBlocks(state); - drawTimeline(); - } - else if (commandType == Command.toggle_search) { - if (searchRegex != null) { - state.searchEnabled = !state.searchEnabled; - filterAndMergeBlocks(state); - drawTimeline(); - } - } - else if (commandType == Command.previous_search || - commandType == Command.next_search) { - if (state.searchEnabled) { - var pos = commandType == Command.previous_search ? - (currentPos - 1 + sizeHistory) % sizeHistory : - (currentPos + 1) % sizeHistory; - var sentinel = commandType == Command.previous_search ? - (nextPos - 1 + sizeHistory) % sizeHistory : nextPos; - if (pos != sentinel && searchRegex[pos] != null) { - currentPos = pos; - filterAndMergeBlocks(state); - drawTimeline(); - } - } - } - else if (commandType == Command.toggle_critical_path) { - state.display_critical_path = !state.display_critical_path; - if (state.display_critical_path) { - state.critical_path.forEach(function(op) { - expandByNodeProc(op[0], op[1]); - }); - } - redraw(); - } - return false; -} - -function defaultKeyUp(e) { - if (!e) e = event; - if (!(e.metaKey || e.altKey)) { - state.rangeZoom = true; - } - return true; -} - -function load_proc_timeline(proc) { - var proc_name = proc.full_text; - state.processorData[proc_name] = {}; - var num_levels_ready = proc.num_levels; - if (state.ready_selected) { - proc.num_levels_ready = proc.num_levels; - } - d3.tsv(proc.tsv, - function(d, i) { - var level = +d.level; - var ready = +d.ready; - var start = +d.start; - var end = +d.end; - var level_ready = +d.level_ready; - var total = end - start; - var _in = d.in === "" ? [] : JSON.parse(d.in) - var out = d.out === "" ? [] : JSON.parse(d.out) - var children = d.children === "" ? [] : JSON.parse(d.children) - var parents = d.parents === "" ? [] : JSON.parse(d.parents) - if (total > state.resolution) { - return { - id: i, - level: level, - level_ready: level_ready, - ready: ready, - start: start, - end: end, - color: d.color, - opacity: d.opacity, - initiation: d.initiation, - title: d.title, - in: _in, - out: out, - children: children, - parents: parents, - prof_uid: d.prof_uid, - proc: proc - }; - } - }, - function(data) { - var num_levels_ready=0 - // split profiling items by which level they're on - for(var i = 0; i < data.length; i++) { - var d = data[i]; - var level_sel=d.level; - if (level_sel in state.processorData[proc_name]) { - state.processorData[proc_name][level_sel].push(d); - } else { - state.processorData[proc_name][level_sel] = [d]; - } - if ((d.level_ready != undefined) && (d.level_ready != 0) && - num_levels_ready < d.level_ready) - num_levels_ready = d.level_ready; - - if (d.prof_uid != undefined && d.prof_uid !== "") { - if (d.prof_uid in prof_uid_map) { - prof_uid_map[d.prof_uid].push(d); - } else { - prof_uid_map[d.prof_uid] = [d]; - } - } - } - if (num_levels_ready > proc.num_levels) - proc.num_levels_ready = num_levels_ready; - else - proc.num_levels_ready = proc.num_levels; - proc.loaded = true; - hideLoaderIcon(); - redraw(); - } - ); -} - -function initTimelineElements() { - var timelineGroup = state.timelineSvg.append("g") - .attr("id", "timeline"); - - $("#timeline").scrollLeft(0); - parseURLParameters(); - - var windowCenterY = $(window).height() / 2; - $(window).scroll(function() { - $("#loader-icon").css("top", $(window).scrollTop() + windowCenterY); - $("#pop-up").css("top", $(window).scrollTop()); - }); - - // set scroll callback - var timer = null; - $("#timeline").scroll(function() { - if (timer !== null) { - clearTimeout(timer); - } - timer = setTimeout(function() { - filterAndMergeBlocks(state); - drawTimeline(); - }, 100); - }); - if (!state.collapseAll) { - // initially load in all the cpu processors and the "all util" - var util_regex = /node/; - for (var i = 0; i < state.flattenedLayoutData.length; i++) { - var timelineElement = state.flattenedLayoutData[i]; - if (timelineElement.type == "util" && - util_regex.exec(timelineElement.text) && - timelineElement.depth == 0) { - collapseHandler(timelineElement, i); - } - } - } - turnOnMouseHandlers(); -} - - -function load_ops_and_timeline() { - d3.tsv("legion_prof_ops.tsv", // TODO: move to tsv folder - function(d) { - return d; - }, - function(data) { - data.forEach(function(d) { - state.operations[parseInt(d.op_id)] = d; - }); - // initTimelineElements depends on the ops to be loaded - initTimelineElements(); - } - ); -} - -function load_procs(callback) { - d3.tsv('legion_prof_processor.tsv', - function(d) { - return { - full_text: d.full_text, - text: d.text, - height: +d.levels, - tsv: d.tsv - }; - }, - function(data) { - var prevEnd = 0; - var base = 0; - data.forEach(function(proc) { - proc.enabled = false; - proc.loaded = false; - proc.base = base; - - base += 2; - }); - state.processors = data; - calculateLayout(); - - // flatten the layout and get the new calculated max num levels - flattenLayout(); - calculateBases(); - drawLayout(); - createMenuList1(); - callback(); - - // TODO: fix - load_critical_path(); - } - ); -} - -function getMinElement(arr, mapF) { - if (arr.length === undefined || arr.length == 0) { - throw "invalid array: " + arr; - } - var minElement = arr[0]; - if (mapF === undefined) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] < minElement) { - minElement = arr[i]; - } - } - } else { - minValue = mapF(minElement); - for (var i = 1; i < arr.length; i++) { - var elem = arr[i]; - var value = mapF(elem); - if (value < minValue) { - minElement = elem; - minValue = value; - } - } - } - return minElement; -} - -function filterUtilData(timelineElem) { - var data = state.utilData[timelineElem.tsv]; // TODO: attach to object - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - var start_time = convertToTime(state, windowStart - 100); - var end_time = convertToTime(state, windowEnd + 100); - - var startIndex = timeBisector(data, start_time); - var endIndex = timeBisector(data, end_time); - - startIndex = Math.max(0, startIndex - 1); - endIndex = Math.min(data.length, endIndex + 2); - var length = endIndex - startIndex; - var newData = Array(); - // we will average points together if they are too close together - var resolution = 1; // 3 pixel resolution - var elem = {time: 0, count: 0}; - var startTime = data[startIndex].time; - var startX = convertToPos(state, startTime); - var endTime = 0; - - for (var i = startIndex; i < endIndex - 1; i++) { - endTime = data[i+1].time; - elem.count += data[i].count * (endTime - data[i].time); - //elem.time += data[i].time; - var endX = convertToPos(state, endTime); - if ((endX - startX) >= resolution || i == (endIndex - 2)) { - var totalTime = endTime - startTime; - elem.count /= totalTime; - //avgElem.time /= windowSize; - elem.time = startTime; - newData.push(elem); - elem = {time: 0, count: 0}; - startX = endX; - startTime = endTime; - } - } - - newData.push({time: endTime, count:0}); - - return { - text: timelineElem.text, - base: timelineElem.base, - num_levels: timelineElem.num_levels, - num_levels_ready: timelineElem.num_levels_ready, - data: newData - }; -} - -function mouseover() { - var focus = state.timelineSvg.append("g") - .attr("class", "focus"); - - focus.append("circle") - .attr("fill", "none") - .attr("stroke", "black") - .attr("r", 4.5); - - var utilDescView = state.timelineSvg.append("g") - .attr("class", "utilDesc"); - utilDescView.append("text") - .attr("x", 7) - .attr("y", -4.5) - .attr("class", "desc") - .attr("dy", ".35em"); - utilDescView.insert("rect", "text") - .style("fill", "#222") - .style("opacity", "0.7"); -} - -function mousemove(d, i) { - var line = document.getElementById("util" + i); - - // offset for this particular line grapgh - var base_y = +line.getAttribute("base_y"); - var px = d3.mouse(line)[0]; - var py = d3.mouse(line)[1] + base_y; - - var start = 0; - var end = line.getTotalLength(); - var target = undefined; - var pos = undefined; - - // https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91 - while (true){ - target = Math.floor((start + end) / 2); - pos = line.getPointAtLength(target); - if ((target === end || target === start) && pos.x !== px) { - break; - } - if (pos.x > px) end = target; - else if (pos.x < px) start = target; - else break; //position found - } - - - var cx = pos.x; - var cy = pos.y + base_y; - - var focus = state.timelineSvg.select("g.focus"); - focus.attr("transform", "translate(" + cx + "," + cy + ")"); - - var utilDescView = state.timelineSvg.select("g.utilDesc"); - utilDescView.attr("transform", "translate(" + (px + 10) + "," + (py - 10) + ")"); - var text = utilDescView.select("text") - - text.text(Math.round(state.y.invert(pos.y) * 100) + "% utilization"); - - var bbox = text.node().getBBox(); - var padding = 2; - var rect = utilDescView.select("rect", "text"); - rect.attr("x", bbox.x - padding) - .attr("y", bbox.y - padding) - .attr("width", bbox.width + (padding*2)) - .attr("height", bbox.height + (padding*2)); - - var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); - var bboxRight = px + bbox.x + bbox.width; - // If the box moves off the screen, nudge it back - if (bboxRight > timelineRight) { - var translation = -(bboxRight - timelineRight + 20); - text.attr("transform", "translate(" + translation + ",0)"); - rect.attr("transform", "translate(" + translation + ",0)"); - } -} - -// Get the data -function load_util(elem) { - var util_file = elem.tsv; - - // exit early if we already loaded it - if(state.utilData[util_file]) { - elem.loaded = true; - hideLoaderIcon(); - redraw(); - return; - } - - d3.tsv(util_file, - function(d) { - return { - time: +d.time, - count: +d.count - }; - }, - function(error, data) { - state.utilData[util_file] = data; - elem.loaded = true; - hideLoaderIcon(); - redraw(); - } - ); -} - -function load_critical_path() { - $.getJSON("json/critical_path.json", function(json) { - state.critical_path = json.map(function(p) {return p.tuple}); - state.critical_path_prof_uids = {}; - state.critical_path.forEach(function(p) { - state.critical_path_prof_uids[p[2]] = 1; - }); - }); -} - -function load_data() { - load_procs(load_ops_and_timeline); -} - -function initializeState() { - var margin = constants.margin_left + constants.margin_right; - state.width = $(window).width() - margin; - state.height = $(window).height() - constants.margin_bottom; - state.scale = state.width / (constants.end - constants.start); - state.zoom = 1.0; - state.zoomHistory = Array(); - state.numLoading = 0; - state.dependencyEvent = undefined; - state.drawDeps = false; - state.drawChildren = false; - - state.layoutData = []; - state.flattenedLayoutData = []; - - state.profilingData = {}; - state.processorData = {}; - state.utilData = []; - - state.operations = {}; - state.thickness = 20; //Math.max(state.height / constants.max_level, 20); - state.baseThickness = state.height / constants.max_level; - state.height = constants.max_level * state.thickness; - state.resolution = 10; // time (in us) of the smallest feature we want to load - state.searchEnabled = false; - state.rangeZoom = true; - state.collapseAll = false; - state.display_critical_path = false; - state.processor_kinds = {}; - - // display task ready state? - state.ready_selected = false; - // TODO: change this - state.x = d3.scale.linear().range([0, state.width]); - state.y = d3.scale.linear().range([constants.util_levels * state.thickness, 0]); - state.y.domain([0, 1]); - - setKeyHandler(defaultKeydown); - $(document).on("keyup", defaultKeyUp); - state.timelineSvg = d3.select("#timeline").select("svg").remove(); - state.timelineSvg = d3.select("#timeline").append("svg") - .attr("width", state.zoom * state.width) - .attr("height", state.height); - - state.loaderSvg = d3.select("#loader-icon").select("svg").remove(); - state.loaderSvg = d3.select("#loader-icon").append("svg") - .attr("width", "40px") - .attr("height", "40px"); - - d3.select("#processors").select("svg").remove(); - - drawLoaderIcon(); - drawHelpBox(); - load_data(); -} - -function load_util_json(callback) { - $.getJSON("json/utils.json", function(json) { - util_files = json; - callback(); - }); -} - -// Loads constants such as max_level, start/end time, and number of levels -// of a util view -function load_scale_json(callback) { - $.getJSON("json/scale.json", function(json) { - // add the read-in constants - $.each(json, function(key, val) { - constants[key] = val; - }); - load_util_json(callback); - }); -} - -function load_op_deps_json(callback) { - $.getJSON("json/op_dependencies.json", function(json) { - op_dependencies = json; - load_scale_json(callback); - }); -} - -function load_jsons(callback) { - load_scale_json(callback); -} - -function main() { - load_jsons(initializeState); -} - -main(); diff --git a/examples/testbench/decent_band/js/util.js b/examples/testbench/decent_band/js/util.js deleted file mode 100644 index 16ea770f2..000000000 --- a/examples/testbench/decent_band/js/util.js +++ /dev/null @@ -1,378 +0,0 @@ -//----------------------------------------------------------------------------- -// UTILS -//----------------------------------------------------------------------------- - -var helpMessage = [ - "Zoom-in (x-axis) : Ctrl + / 4", - "Zoom-out (x-axis) : Ctrl - / 3", - "Reset zoom (x-axis): Ctrl 0 / 0", - "Undo zoom (x-axis) : u / U", - "Zoom-in (y-axis) : Ctrl-Alt + / 2", - "Zoom-out (y-axis) : Ctrl-Alt - / 1", - "Reset zoom (y-axis): Ctrl-Alt 0 / `", - "Range Zoom-in : drag-select", - "Measure duration : Alt + drag-select", - "Expand : e / E", - "Draw Critical Path : a / A", - "Search : s / S", - "Search History : h / H", - "Previous Search : p / P", - "Next Search : n / N", - "Clear Search : c / C", - "Toggle Search : t / T", -]; - -var Command = { - none : 0, - help : 1, - zox : 2, - zix : 3, - zrx : 4, - zux : 5, - zoy : 6, - ziy : 7, - zry : 8, - search : 9, - clear_search : 10, - toggle_search : 11, - expand: 12, - toggle_critical_path: 13, - search_history : 14, - previous_search : 15, - next_search : 16 -}; - -// commands without a modifier key pressed -var noModifierCommands = { - '0': Command.zrx, - '1': Command.zoy, - '2': Command.ziy, - '3': Command.zox, - '4': Command.zix, - 'c': Command.clear_search, - 'e': Command.expand, - 'h': Command.search_history, - 'n': Command.next_search, - 'p': Command.previous_search, - 's': Command.search, - 'a': Command.toggle_critical_path, - 't': Command.toggle_search, - 'u': Command.zux, - '/': Command.help -}; - -var modifierCommands = { - '+': Command.zix, - '-': Command.zox, - '0': Command.zrx -} - -var multipleModifierCommands = { - '+': Command.ziy, - '-': Command.zoy, - '0': Command.zry -} - -var keys = { - 13 : 'enter', - 27 : 'esc', - 48 : '0', - 49 : '1', - 50 : '2', - 51 : '3', - 52 : '4', - 61 : '+', // Firefox - 65 : 'a', - 67 : 'c', - 69 : 'e', - 72 : 'h', - 78 : 'n', - 80 : 'p', - 83 : 's', - 84 : 't', - 85 : 'u', - 173 : '-', // Firefox - 187 : '+', - 189 : '-', - 191 : '/', - 192 : '`' -}; - -/** - * Function: convertToTime - * - * Description: - * Takes a value and converts it to time. The input 'x' can either be - * a single position on the timeline, or it can be a width. - */ -function convertToTime(state, x) { - return x / state.zoom / state.scale; -} - -/** - * Function: convertToPos - * - * Description: - * Takes a time and converts it to a position in the window. - * The 'time' parameter MUST BE IN us - */ -function convertToPos(state, time) { - return time * state.zoom * state.scale; -} - -/** - * Function: getTimeString - * - * Description: - * This function takes a time (in us) as well as a 'width' - * field. The 'width' field determines over what interval - * the time is being considered. - * - * If the width is too large, the time will be converted - * to either ms or sec. - * - * The function will return a string representation of the - * (possibly) scaled time at the end of the method - */ -function getTimeString(time, timeWidth) { - var unit = "us"; - var scaledTime = Math.floor(time); - if (timeWidth >= 100000) { - var scaledTime = Math.floor(time / 1000); - unit = "ms"; - } else if (timeWidth >= 100000000) { - var scaledTime = Math.floor(time / 1000000); - unit = "s"; - } - return scaledTime + " " + unit; -} - -// timeField should be 'end' for the left hand side and -// 'start' for the right hand side -function binarySearch(data, level, time, useStart) { - var low = 0; - var high = data[level].length; - while (true) { - // ugh is there a way to do integer division in javascrtipt? - var mid = Math.floor((high - low) / 2) + low; - - // In this case, we haven't found it. This is as close - // as we were able to get. - if (low == high || low == mid) { - return low; - } else if (high == mid) { - return high; - } - var midTime; - if (useStart) { - midTime = data[level][mid].start; - } else { - midTime = data[level][mid].end; - } - - if (midTime > time) { - // need to look below - high = mid; - } else if (midTime < time) { - // need to look above - low = mid; - } else { - // Exact Match - return mid; - } - } -} - -dataReady = {}; -function redoData(proc) { - dataReady = {}; - var items = state.processorData[proc.full_text]; - for (var level in items) { - for (var j = 0; j< items[level].length; j++) { - d = items[level][j]; - // ready state items - if (d.level_ready != undefined && d.level_ready != "" && - d.ready != undefined && d.ready != "") { - // if the level has already been switched, then don't do anything - var level_to_set = d.level_ready; - if (d.level_ready_set != undefined && d.level_ready_set == true) - level_to_set = d.level; - var d_ready = { - id: d.id+items[level].length+1, // unique id - level: level_to_set, - level_ready: d.level, - ready: d.ready, - start: d.ready, - end: d.start, - color: d.color, - opacity: "0.45", - initiation: d.initiation, - title: d.title + " (ready)", - in: d.in, - out: d.out, - children: d.children, - parents: d.parents, - prof_uid: d.prof_uid, - proc: d.proc - }; - // switch levels if we need to - if (d.level_ready_set == undefined || d.level_ready_set == false) - { - var level_tmp = d.level; - d.level = d.level_ready; - d.level_ready = level_tmp; - d.level_ready_set = true; - } - if (d.level_ready in dataReady){ - dataReady[d.level_ready].push(d_ready); - dataReady[d.level_ready].push(d); - } - else { - dataReady[d.level_ready] = [d_ready]; - dataReady[d.level_ready].push(d); - } - } - // add items to the level - else { - if (d.level in dataReady) - dataReady[d.level].push(d); - else - dataReady[d.level] = [d]; - } - } - } -} - -function readyData(proc) { - redoData(proc); -} - -function filterAndMergeBlocks(state) { - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - state.dataToDraw = Array(); - state.memoryTexts = Array(); - var startTime = convertToTime(state, windowStart); - var endTime = convertToTime(state, windowEnd); - var min_feature_time = convertToTime(state, constants.min_feature_width); - var min_gap_time = convertToTime(state, constants.min_gap_width); - for (var index in state.flattenedLayoutData) { - var timelineElement = state.flattenedLayoutData[index]; - if (timelineElement.type == "proc" && timelineElement.enabled && timelineElement.visible) { - var items = state.processorData[timelineElement.full_text]; - var memoryRegex = /Memory/; - var isMemory = memoryRegex.exec(timelineElement.text); - if (state.ready_selected) { - readyData(timelineElement); - items = dataReady; - } - - for (var level in items) { - // gap merging below assumes intervals are sorted - do that first - //items[level].sort(function(a,b) { return a.start - b.start; }); - - // We will use binary search to limit the following section - var startIndex = binarySearch(items, level, startTime, false); - var endIndex = binarySearch(items, level, endTime, true); - for (var i = startIndex; i <= endIndex; ++i) { - var d = items[level][i]; - var start = d.start; - var end = d.end; - // fix the level here - if (state.ready_selected == false && d.level_ready_set != undefined - && d.level_ready_set == true) - { - // switch levels - var level_tmp = d.level; - d.level = d.level_ready; - d.level_ready = level_tmp; - d.level_ready_set = false; - } - // is this block too narrow? - if ((end - start) < min_feature_time) { - // see how many more after this are also too narrow and too close to us - var count = 1; - // don't do this if we're the subject of the current search and don't merge with - // something that is - if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) == null) { - while (((i + count) < items[level].length) && - ((items[level][i + count].start - end) < min_gap_time) && - ((items[level][i + count].end - items[level][i + count].start) < min_feature_time) && - (!state.searchEnabled || searchRegex[currentPos].exec(items[level][i + count].title) == null)) { - end = items[level][i + count].end; - count++; - } - } - // are we still too narrow? if so, bloat, but make sure we don't overlap something later - if ((end - start) < min_feature_time) { - end = start + min_feature_time; - if (((i + count) < items[level].length) && (items[level][i + count].start < end)) - end = items[level][i + count].start; - } - if (count > 1) { - state.dataToDraw.push({ - id: d.id, - prof_uid: d.prof_uid, - proc: timelineElement, - level: d.level, - ready: d.ready, - start: d.start, - end: Math.round(end), - color: "#808080", - title: count + " merged tasks", - in: [], - out: [], - children: [], - parents: [] - }); - i += (count - 1); - } else { - var elem = { - id: d.id, - prof_uid: d.prof_uid, - proc: timelineElement, - level: d.level, - ready: d.ready, - start: d.start, - end: d.end, - color: d.color, - initiation: d.initiation, - title: d.title + " (expanded for visibility)", - in: d.in, - out: d.out, - children: d.children, - parents: d.parents - } - state.dataToDraw.push(elem); - if (isMemory) { - state.memoryTexts.push(elem); - } - } - } else { - var elem = { - id: d.id, - prof_uid: d.prof_uid, - proc: timelineElement, - level: d.level, - ready: d.ready, - start: d.start, - end: d.end, - opacity: d.opacity, - color: d.color, - initiation: d.initiation, - title: d.title, - in: d.in, - out: d.out, - children: d.children, - parents: d.parents - } - state.dataToDraw.push(elem); - if (isMemory) { - state.memoryTexts.push(elem); - } - } - } - } - } - } -} diff --git a/examples/testbench/decent_band/legion_prof_ops.tsv b/examples/testbench/decent_band/legion_prof_ops.tsv deleted file mode 100644 index 281f0c6be..000000000 --- a/examples/testbench/decent_band/legion_prof_ops.tsv +++ /dev/null @@ -1,90 +0,0 @@ -op_id desc proc level -1 legion_python_main <1> Python Processor 0x1d00000000000004 2 -47 legate::numpy::BinaryOpTask [CPU] <47> CPU Processor 0x1d00000000000002 2 -71 legate::numpy::BinaryOpTask [CPU] <71> CPU Processor 0x1d00000000000002 2 -76 legate::numpy::BinaryOpTask [CPU] <76> CPU Processor 0x1d00000000000002 2 -5 Tunable Operation <5> -6 Pending Partition Operation <6> -8 Refinement Operation <8> -7 legate::numpy::FillTask <7> -9 legate::numpy::FillTask <9> -0 Operation <0> -10 legate::numpy::FillTask <10> -12 legate::numpy::FillTask <12> -14 Refinement Operation <14> -15 legate::numpy::FillTask [CPU] <15> CPU Processor 0x1d00000000000003 2 -18 Refinement Operation <18> -17 legate::numpy::FillTask <17> -20 legate::numpy::FillTask <20> -16 legate::numpy::FillTask <16> -19 legate::numpy::FillTask <19> -54 legate::numpy::BinaryOpTask <54> -55 legate::numpy::BinaryOpTask <55> -56 legate::numpy::BinaryOpTask <56> -59 legate::numpy::BinaryOpTask [CPU] <59> CPU Processor 0x1d00000000000003 2 -60 legate::numpy::BinaryOpTask <60> -65 legate::numpy::BinaryOpTask [CPU] <65> CPU Processor 0x1d00000000000002 2 -63 legate::numpy::BinaryOpTask <63> -68 legate::numpy::BinaryOpTask <68> -77 legate::numpy::BinaryOpTask [CPU] <77> CPU Processor 0x1d00000000000003 2 -79 legate::numpy::BinaryOpTask <79> -80 legate::numpy::BinaryOpTask <80> -82 legate::numpy::BinaryOpTask [CPU] <82> CPU Processor 0x1d00000000000002 2 -84 Merge Close Operation <84> -85 legate::numpy::BinaryOpTask [CPU] <85> CPU Processor 0x1d00000000000003 2 -83 Mapping Operation <83> -89 Deletion Operation <89> -87 Deletion Operation <87> -88 Deletion Operation <88> -13 legate::numpy::FillTask [CPU] <13> CPU Processor 0x1d00000000000002 2 -48 legate::numpy::BinaryOpTask [CPU] <48> CPU Processor 0x1d00000000000003 2 -29 legate::numpy::FillTask [CPU] <29> CPU Processor 0x1d00000000000002 2 -38 legate::numpy::FillTask [CPU] <38> CPU Processor 0x1d00000000000002 2 -52 legate::numpy::BinaryOpTask [CPU] <52> CPU Processor 0x1d00000000000002 2 -11 legate::numpy::FillTask <11> -21 legate::numpy::FillTask <21> -25 legate::numpy::FillTask [CPU] <25> CPU Processor 0x1d00000000000003 2 -33 Refinement Operation <33> -34 Refinement Operation <34> -35 legate::numpy::FillTask [CPU] <35> CPU Processor 0x1d00000000000002 2 -36 legate::numpy::FillTask [CPU] <36> CPU Processor 0x1d00000000000003 2 -42 legate::numpy::FillTask [CPU] <42> CPU Processor 0x1d00000000000002 2 -44 legate::numpy::BinaryOpTask <44> -45 legate::numpy::BinaryOpTask <45> -46 legate::numpy::BinaryOpTask <46> -50 legate::numpy::BinaryOpTask <50> -51 legate::numpy::BinaryOpTask <51> -53 legate::numpy::BinaryOpTask [CPU] <53> CPU Processor 0x1d00000000000003 2 -49 legate::numpy::BinaryOpTask <49> -32 legate::numpy::FillTask <32> -31 legate::numpy::FillTask <31> -28 legate::numpy::BinaryOpTask <28> -39 legate::numpy::FillTask [CPU] <39> CPU Processor 0x1d00000000000003 2 -3 Tunable Operation <3> -4 Tunable Operation <4> -22 legate::numpy::FillTask <22> -30 legate::numpy::BinaryOpTask <30> -23 legate::numpy::FillTask <23> -24 legate::numpy::FillTask <24> -26 legate::numpy::FillTask <26> -27 legate::numpy::FillTask <27> -41 legate::numpy::FillTask <41> -40 legate::numpy::FillTask <40> -43 legate::numpy::FillTask [CPU] <43> CPU Processor 0x1d00000000000003 2 -37 legate::numpy::FillTask <37> -64 legate::numpy::BinaryOpTask <64> -70 legate::numpy::BinaryOpTask <70> -78 legate::numpy::BinaryOpTask <78> -86 Fence Operation <86> -58 legate::numpy::BinaryOpTask [CPU] <58> CPU Processor 0x1d00000000000002 2 -57 legate::numpy::BinaryOpTask <57> -66 legate::numpy::BinaryOpTask [CPU] <66> CPU Processor 0x1d00000000000003 2 -72 legate::numpy::BinaryOpTask [CPU] <72> CPU Processor 0x1d00000000000003 2 -81 legate::numpy::BinaryOpTask <81> -62 legate::numpy::BinaryOpTask <62> -73 legate::numpy::BinaryOpTask <73> -74 legate::numpy::BinaryOpTask <74> -75 legate::numpy::BinaryOpTask <75> -61 legate::numpy::BinaryOpTask <61> -67 legate::numpy::BinaryOpTask <67> -69 legate::numpy::BinaryOpTask <69> diff --git a/examples/testbench/decent_band/legion_prof_processor.tsv b/examples/testbench/decent_band/legion_prof_processor.tsv deleted file mode 100644 index 1f9a1fa94..000000000 --- a/examples/testbench/decent_band/legion_prof_processor.tsv +++ /dev/null @@ -1,9 +0,0 @@ -full_text text tsv levels -Utility Processor 0x1d00000000000000 Utility Proc 0 tsv/Proc_0x1d00000000000000.tsv 4 -Utility Processor 0x1d00000000000001 Utility Proc 1 tsv/Proc_0x1d00000000000001.tsv 5 -CPU Processor 0x1d00000000000002 CPU Proc 2 tsv/Proc_0x1d00000000000002.tsv 1 -CPU Processor 0x1d00000000000003 CPU Proc 3 tsv/Proc_0x1d00000000000003.tsv 1 -Python Processor 0x1d00000000000004 Python Proc 4 tsv/Proc_0x1d00000000000004.tsv 1 -Dependent Partition Channel Dependent Partition Channel tsv/None.tsv 3 -System Memory 0x1e00000000000000 to System Memory 0x1e00000000000000 Channel [n0] sys to [n0] sys tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv 3 -System Memory 0x1e00000000000000 [n0] sys tsv/Mem_0x1e00000000000000.tsv 11 diff --git a/examples/testbench/decent_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv b/examples/testbench/decent_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv deleted file mode 100644 index 55e3f448b..000000000 --- a/examples/testbench/decent_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv +++ /dev/null @@ -1,3 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -3 1048681.945 1050273.272 #ff6e00 1.0 size=1.907 MiB, num reqs=1$req[0]: src_inst=0x4000000000000007, dst_inst=0x400000000000000b, fields=1, type=copy, hops=1 83 686 -2 1048752.497 1050266.685 #ff6e00 1.0 size=1.907 MiB, num reqs=1$req[0]: src_inst=0x4000000000000008, dst_inst=0x400000000000000b, fields=1, type=copy, hops=1 83 702 diff --git a/examples/testbench/decent_band/tsv/0 (CPU)_util.tsv b/examples/testbench/decent_band/tsv/0 (CPU)_util.tsv deleted file mode 100644 index 8d75fcdb6..000000000 --- a/examples/testbench/decent_band/tsv/0 (CPU)_util.tsv +++ /dev/null @@ -1,288 +0,0 @@ -time count -0.000 0.00 -962689.824 0.50 -962698.725 0.00 -999427.832 0.50 -999433.367 0.00 -999530.605 0.50 -999537.468 0.00 -999566.582 0.50 -999574.512 0.00 -1019563.499 0.50 -1019569.168 0.00 -1019723.664 0.50 -1019734.354 0.00 -1019976.547 0.50 -1019982.927 0.00 -1020029.859 0.50 -1020035.992 0.00 -1020081.621 0.50 -1020088.315 0.00 -1020133.393 0.50 -1020140.003 0.00 -1020170.226 0.50 -1020176.043 0.00 -1020320.009 0.50 -1020320.096 1.00 -1020326.182 0.50 -1020326.371 0.00 -1020336.073 0.50 -1020344.812 0.00 -1020409.676 0.50 -1020415.356 0.00 -1020465.741 0.50 -1020471.704 0.00 -1020538.912 0.50 -1020544.913 0.00 -1020607.485 0.50 -1020618.851 0.00 -1020683.611 0.50 -1020698.885 1.00 -1020708.696 0.50 -1020718.044 1.00 -1020723.315 0.50 -1020728.635 1.00 -1020732.653 0.50 -1020812.834 1.00 -1020820.679 0.50 -1020841.769 1.00 -1020849.994 0.50 -1020859.100 1.00 -1022061.790 0.50 -1022107.376 1.00 -1022115.335 0.50 -1022125.977 1.00 -1022132.984 0.50 -1022141.854 1.00 -1022148.613 0.50 -1022155.102 1.00 -1022158.592 0.50 -1022164.775 1.00 -1022169.154 0.50 -1022175.085 1.00 -1022178.496 0.50 -1022184.906 1.00 -1022191.677 0.50 -1022198.572 1.00 -1022204.310 0.50 -1022210.953 1.00 -1022211.911 0.50 -1022214.923 0.00 -1022222.553 0.50 -1022227.962 0.00 -1022237.249 0.50 -1022245.039 0.00 -1022245.345 0.50 -1022259.076 1.00 -1023674.045 0.50 -1023674.774 0.00 -1023700.501 0.50 -1023714.788 1.00 -1024165.613 0.50 -1024175.988 0.00 -1024191.329 0.50 -1024212.470 1.00 -1025513.689 0.50 -1025523.689 0.00 -1025541.836 0.50 -1025553.734 1.00 -1025784.682 0.50 -1025793.359 0.00 -1025817.215 0.50 -1025825.619 1.00 -1025838.009 0.50 -1025857.809 1.00 -1027264.327 0.50 -1027267.987 0.00 -1027290.352 0.50 -1027298.588 1.00 -1027310.850 0.50 -1027340.279 1.00 -1028673.325 0.50 -1028683.215 0.00 -1028696.363 0.50 -1028702.589 0.00 -1043099.467 0.50 -1043105.925 0.00 -1043152.725 0.50 -1043162.570 0.00 -1043172.134 0.50 -1043175.780 0.00 -1043313.696 0.50 -1043321.599 0.00 -1043381.693 0.50 -1043389.858 0.00 -1043463.226 0.50 -1043469.407 0.00 -1043478.703 0.50 -1043483.955 0.00 -1043544.444 0.50 -1043550.837 0.00 -1043559.025 0.50 -1043565.584 0.00 -1043780.003 0.50 -1043793.581 0.00 -1043815.587 0.50 -1043823.752 0.00 -1043840.550 0.50 -1043845.419 0.00 -1043885.917 0.50 -1043891.674 1.00 -1043893.078 0.50 -1043899.319 1.00 -1043902.688 0.50 -1043932.016 1.00 -1044741.669 0.50 -1044772.977 1.00 -1044785.500 0.50 -1044786.018 0.00 -1044798.568 0.50 -1044804.821 0.00 -1044816.976 0.50 -1044818.895 1.00 -1044826.305 0.50 -1044832.900 1.00 -1044836.390 0.50 -1044841.026 1.00 -1044846.632 0.50 -1044853.660 1.00 -1044856.914 0.50 -1044903.140 1.00 -1045600.715 0.50 -1045633.063 1.00 -1045640.501 0.50 -1045658.078 1.00 -1045664.840 0.50 -1045674.697 1.00 -1045716.824 0.50 -1045749.414 1.00 -1045757.154 0.50 -1045767.502 1.00 -1045774.232 0.50 -1045783.097 1.00 -1046429.291 0.50 -1046459.143 1.00 -1046466.393 0.50 -1046474.283 1.00 -1046481.896 0.50 -1046509.517 1.00 -1046540.037 0.50 -1046615.744 1.00 -1047234.439 0.50 -1047255.694 1.00 -1047261.622 0.50 -1047267.900 1.00 -1047274.343 0.50 -1047281.641 1.00 -1047298.270 0.50 -1047306.163 1.00 -1047311.434 0.50 -1047316.397 1.00 -1047328.915 0.50 -1047333.748 1.00 -1047336.991 0.50 -1047402.303 0.00 -1047408.539 0.50 -1047414.776 0.00 -1047425.444 0.50 -1047428.177 1.00 -1047430.972 0.50 -1047435.591 0.00 -1047463.197 0.50 -1047485.607 1.00 -1047499.472 0.50 -1047509.224 1.00 -1047515.337 0.50 -1047551.395 1.00 -1047558.273 0.50 -1047583.009 1.00 -1047588.140 0.50 -1047610.844 1.00 -1047614.303 0.50 -1047619.993 1.00 -1047623.284 0.50 -1047656.279 1.00 -1048083.927 0.50 -1048208.167 1.00 -1048215.606 0.50 -1048245.381 1.00 -1048260.714 0.50 -1048281.052 0.00 -1048360.624 0.50 -1048368.336 0.00 -1048392.151 0.50 -1048397.420 0.00 -1048858.236 0.50 -1048865.054 0.00 -1048914.304 0.50 -1048919.582 0.00 -1048927.422 0.50 -1048933.418 0.00 -1183514.868 0.50 -1183526.003 0.00 -1183564.060 0.50 -1183571.389 0.00 -1183586.336 0.50 -1183593.882 0.00 -1183618.998 0.50 -1183627.204 0.00 -1183656.435 0.50 -1183662.395 0.00 -1183716.981 0.50 -1183722.963 0.00 -1183789.778 0.50 -1183796.240 0.00 -1183844.266 0.50 -1183850.453 0.00 -1183876.008 0.50 -1183881.779 0.00 -1183932.594 0.50 -1183961.777 0.00 -1183962.273 0.50 -1183969.461 0.00 -1183990.520 0.50 -1183995.478 0.00 -1184022.320 0.50 -1184027.253 0.00 -1184378.314 0.50 -1184386.071 0.00 -1184410.125 0.50 -1184416.531 0.00 -1184438.252 0.50 -1184446.042 0.00 -1184452.860 0.50 -1184456.362 0.00 -1184482.915 0.50 -1184489.625 0.00 -1184514.238 0.50 -1184519.942 0.00 -1184528.822 0.50 -1184533.676 0.00 -1184557.808 0.50 -1184562.356 0.00 -1184575.260 0.50 -1184578.768 0.00 -1184612.280 0.50 -1184619.851 0.00 -1184649.833 0.50 -1184656.431 0.00 -1184676.751 0.50 -1184683.603 0.00 -1184686.919 0.50 -1184705.292 0.00 -1184711.881 0.50 -1184716.235 1.00 -1184720.164 0.50 -1184722.729 0.00 -1184751.168 0.50 -1184757.069 0.00 -1184788.335 0.50 -1184793.531 0.00 -1184825.080 0.50 -1184831.298 0.00 -1184838.998 0.50 -1184845.978 0.00 -1184846.419 0.50 -1184853.601 0.00 -1184862.211 0.50 -1184865.981 0.00 diff --git a/examples/testbench/decent_band/tsv/0 (Channel)_util.tsv b/examples/testbench/decent_band/tsv/0 (Channel)_util.tsv deleted file mode 100644 index 308fc3280..000000000 --- a/examples/testbench/decent_band/tsv/0 (Channel)_util.tsv +++ /dev/null @@ -1,4 +0,0 @@ -time count -0.000 0.00 -1048681.945 1.00 -1050273.272 0.00 diff --git a/examples/testbench/decent_band/tsv/0 (Python)_util.tsv b/examples/testbench/decent_band/tsv/0 (Python)_util.tsv deleted file mode 100644 index eb57e7853..000000000 --- a/examples/testbench/decent_band/tsv/0 (Python)_util.tsv +++ /dev/null @@ -1,14 +0,0 @@ -time count -0.000 0.00 -478641.174 1.00 -922239.137 0.00 -922497.427 1.00 -922606.850 0.00 -922815.999 1.00 -962519.280 0.00 -962723.661 1.00 -1047360.569 0.00 -1048908.961 1.00 -1048924.893 0.00 -1050359.631 1.00 -1183469.202 0.00 diff --git a/examples/testbench/decent_band/tsv/0 (System Memory)_util.tsv b/examples/testbench/decent_band/tsv/0 (System Memory)_util.tsv deleted file mode 100644 index d2d9245bc..000000000 --- a/examples/testbench/decent_band/tsv/0 (System Memory)_util.tsv +++ /dev/null @@ -1,24 +0,0 @@ -time count -0.000 0.00 -1020277.868 0.00 -1020517.864 0.00 -1021638.640 0.00 -1021896.476 0.00 -1022852.940 0.00 -1023094.891 0.00 -1024127.778 0.00 -1024326.370 0.00 -1025091.417 0.00 -1025243.869 0.00 -1048334.454 0.01 -1183909.479 0.01 -1183973.835 0.00 -1184355.765 0.00 -1184412.082 0.00 -1184466.441 0.00 -1184520.480 0.00 -1184563.664 0.00 -1184616.464 0.00 -1184671.451 0.00 -1184732.637 0.00 -1184825.486 0.00 diff --git a/examples/testbench/decent_band/tsv/0 (Utility)_util.tsv b/examples/testbench/decent_band/tsv/0 (Utility)_util.tsv deleted file mode 100644 index eb2ceb069..000000000 --- a/examples/testbench/decent_band/tsv/0 (Utility)_util.tsv +++ /dev/null @@ -1,924 +0,0 @@ -time count -0.000 0.00 -478125.062 0.50 -478182.035 0.00 -478215.611 0.50 -478215.750 1.00 -478227.571 0.50 -478293.256 0.00 -478321.896 0.50 -478322.038 1.00 -478327.141 0.50 -478364.450 0.00 -478393.250 0.50 -478397.534 1.00 -478398.019 0.50 -478455.013 0.00 -478487.003 0.50 -478488.917 1.00 -478491.783 0.50 -478610.233 0.00 -478651.813 0.50 -478657.222 0.00 -922202.362 0.50 -922257.734 0.00 -922271.051 0.50 -922282.907 1.00 -922293.697 0.50 -922313.422 0.00 -922320.369 0.50 -922352.823 1.00 -922360.236 0.50 -922430.159 0.00 -922485.054 0.50 -922500.295 0.00 -922615.976 0.50 -922651.888 0.00 -922678.906 0.50 -922683.753 0.00 -922685.337 0.50 -922723.942 0.00 -922748.730 0.50 -922752.172 1.00 -922757.292 0.50 -922781.292 0.00 -922821.002 0.50 -922824.608 0.00 -962526.481 0.50 -962567.952 0.00 -962598.963 0.50 -962603.564 0.00 -962606.098 0.50 -962647.123 0.00 -962678.949 0.50 -962723.015 0.00 -962756.169 0.50 -962760.737 0.00 -999297.143 0.50 -999351.129 0.00 -999365.982 0.50 -999372.250 1.00 -999376.414 0.50 -999398.360 0.00 -999406.012 0.50 -999503.615 0.00 -999507.767 0.50 -999524.730 1.00 -999529.853 0.50 -999537.920 0.00 -999551.347 0.50 -999554.898 0.00 -1019311.922 0.50 -1019495.678 1.00 -1019495.815 0.50 -1019516.941 1.00 -1019521.801 0.50 -1019527.822 1.00 -1019531.556 0.50 -1019576.947 1.00 -1019579.130 0.50 -1019594.838 1.00 -1019598.189 0.50 -1019620.039 0.00 -1019628.570 0.50 -1019636.957 1.00 -1019640.979 0.50 -1019699.933 0.00 -1019714.252 0.50 -1019811.952 0.00 -1019827.080 0.50 -1019830.493 1.00 -1019834.164 0.50 -1019933.635 1.00 -1019950.329 0.50 -1019974.821 1.00 -1020004.219 0.50 -1020027.498 1.00 -1020060.964 0.50 -1020081.461 1.00 -1020099.613 0.50 -1020115.715 1.00 -1020149.907 0.50 -1020169.732 1.00 -1020198.015 0.50 -1020215.638 1.00 -1020251.160 0.50 -1020263.069 1.00 -1020281.769 0.50 -1020365.103 1.00 -1020389.610 0.50 -1020411.660 1.00 -1020446.324 0.50 -1020465.390 1.00 -1020580.691 0.50 -1020602.314 1.00 -1020623.469 0.50 -1020634.362 1.00 -1020671.314 0.50 -1020676.289 0.00 -1020691.218 0.50 -1020713.369 0.00 -1020722.173 0.50 -1020750.432 1.00 -1020787.419 0.50 -1020808.922 0.00 -1020810.229 0.50 -1020839.392 1.00 -1020846.307 0.50 -1020864.411 1.00 -1020874.211 0.50 -1020894.975 1.00 -1020913.363 0.50 -1020928.632 1.00 -1020930.984 0.50 -1020952.149 1.00 -1020985.345 0.50 -1020996.549 0.00 -1021013.914 0.50 -1021015.936 1.00 -1021039.622 0.50 -1021048.610 0.00 -1021058.657 0.50 -1021061.000 1.00 -1021089.194 0.50 -1021095.392 0.00 -1021103.473 0.50 -1021113.857 1.00 -1021142.700 0.50 -1021159.797 1.00 -1021175.820 0.50 -1021181.610 0.00 -1021196.702 0.50 -1021219.821 1.00 -1021266.724 0.50 -1021284.322 1.00 -1021292.380 0.50 -1021312.878 1.00 -1021325.094 0.50 -1021339.701 1.00 -1021358.196 0.50 -1021375.545 1.00 -1021396.717 0.50 -1021396.820 0.00 -1021416.548 0.50 -1021427.029 1.00 -1021465.556 0.50 -1021477.105 0.00 -1021485.938 0.50 -1021492.376 1.00 -1021517.858 0.50 -1021535.050 1.00 -1021563.059 0.50 -1021570.371 0.00 -1021585.593 0.50 -1021598.522 1.00 -1021633.743 0.50 -1021650.015 1.00 -1021708.350 0.50 -1021729.660 1.00 -1021748.943 0.50 -1021776.980 0.00 -1021799.332 0.50 -1021800.527 1.00 -1021831.515 0.50 -1021836.851 0.00 -1021856.216 0.50 -1021869.553 1.00 -1021890.510 0.50 -1021906.979 1.00 -1021935.187 0.50 -1021994.272 0.00 -1022016.171 0.50 -1022033.123 1.00 -1022036.573 0.50 -1022059.820 1.00 -1022077.471 0.50 -1022096.587 1.00 -1022115.674 0.50 -1022147.738 0.00 -1022149.566 0.50 -1022163.230 1.00 -1022191.124 0.50 -1022202.817 0.00 -1022220.315 0.50 -1022226.791 1.00 -1022257.425 0.50 -1022276.351 1.00 -1022306.819 0.50 -1022330.425 1.00 -1022345.941 0.50 -1022359.294 1.00 -1022392.149 0.50 -1022402.911 1.00 -1022420.902 0.50 -1022466.782 1.00 -1022494.632 0.50 -1022519.257 1.00 -1022522.165 0.50 -1022536.070 1.00 -1022545.038 0.50 -1022565.474 1.00 -1022572.262 0.50 -1022586.450 1.00 -1022614.121 0.50 -1022625.358 1.00 -1022643.447 0.50 -1022672.695 1.00 -1022681.509 0.50 -1022694.589 1.00 -1022708.855 0.50 -1022721.685 0.00 -1022729.096 0.50 -1022732.564 1.00 -1022761.644 0.50 -1022770.283 0.00 -1022792.567 0.50 -1022795.202 1.00 -1022828.127 0.50 -1022853.928 1.00 -1022898.698 0.50 -1022915.164 1.00 -1022928.362 0.50 -1022953.932 1.00 -1022971.622 0.50 -1022987.959 1.00 -1023010.260 0.50 -1023030.646 0.00 -1023050.877 0.50 -1023051.263 1.00 -1023065.156 0.50 -1023086.962 1.00 -1023113.349 0.50 -1023128.018 1.00 -1023140.111 0.50 -1023152.278 1.00 -1023157.689 0.50 -1023163.973 1.00 -1023168.055 0.50 -1023180.849 0.00 -1023197.049 0.50 -1023208.594 0.00 -1023217.702 0.50 -1023219.200 1.00 -1023224.712 0.50 -1023231.705 1.00 -1023236.361 0.50 -1023243.711 1.00 -1023248.462 0.50 -1023255.017 1.00 -1023259.870 0.50 -1023266.635 1.00 -1023271.371 0.50 -1023278.427 1.00 -1023287.444 0.50 -1023296.822 1.00 -1023297.512 0.50 -1023334.341 0.00 -1023345.970 0.50 -1023357.571 1.00 -1023364.867 0.50 -1023374.111 1.00 -1023376.256 0.50 -1023398.373 1.00 -1023403.459 0.50 -1023435.265 1.00 -1023447.377 0.50 -1023468.882 1.00 -1023524.215 0.50 -1023544.753 1.00 -1023551.388 0.50 -1023567.314 1.00 -1023593.726 0.50 -1023606.937 0.00 -1023608.446 0.50 -1023620.187 1.00 -1023665.627 0.50 -1023676.616 0.00 -1023685.236 0.50 -1023692.044 1.00 -1023718.305 0.50 -1023726.876 0.00 -1023741.592 0.50 -1023746.877 1.00 -1023765.560 0.50 -1023777.870 1.00 -1023800.215 0.50 -1023810.031 0.00 -1023813.667 0.50 -1023824.143 1.00 -1023831.242 0.50 -1023837.657 1.00 -1023842.050 0.50 -1023848.474 1.00 -1023855.887 0.50 -1023864.845 1.00 -1023869.083 0.50 -1023874.606 1.00 -1023879.071 0.50 -1023885.288 1.00 -1023886.789 0.50 -1023900.795 1.00 -1023904.789 0.50 -1023911.051 1.00 -1023919.322 0.50 -1023924.498 1.00 -1023978.079 0.50 -1023982.068 0.00 -1023994.093 0.50 -1024023.781 1.00 -1024050.003 0.50 -1024066.601 1.00 -1024067.567 0.50 -1024083.242 1.00 -1024112.260 0.50 -1024125.702 1.00 -1024142.386 0.50 -1024176.449 1.00 -1024187.245 0.50 -1024197.413 1.00 -1024204.799 0.50 -1024214.037 1.00 -1024298.425 0.50 -1024316.465 1.00 -1024327.960 0.50 -1024336.179 1.00 -1024341.424 0.50 -1024350.467 1.00 -1024359.821 0.50 -1024367.407 1.00 -1024372.548 0.50 -1024380.168 1.00 -1024385.425 0.50 -1024393.264 1.00 -1024397.528 0.50 -1024403.247 1.00 -1024409.951 0.50 -1024415.079 1.00 -1024418.409 0.50 -1024422.747 1.00 -1024425.896 0.50 -1024430.164 1.00 -1024433.324 0.50 -1024437.680 1.00 -1024440.818 0.50 -1024445.675 1.00 -1024450.251 0.50 -1024457.169 1.00 -1024462.152 0.50 -1024468.852 1.00 -1024473.600 0.50 -1024481.925 1.00 -1024488.279 0.50 -1024497.214 1.00 -1024532.506 0.50 -1024551.826 1.00 -1024557.161 0.50 -1024557.310 0.00 -1024564.753 0.50 -1024569.824 0.00 -1024577.086 0.50 -1024582.272 0.00 -1024585.057 0.50 -1024590.350 0.00 -1024597.545 0.50 -1024601.896 0.00 -1024604.599 0.50 -1024607.410 1.00 -1024610.839 0.50 -1024615.132 1.00 -1024619.071 0.50 -1024623.671 1.00 -1024626.791 0.50 -1024631.171 1.00 -1024634.661 0.50 -1024639.219 1.00 -1024642.520 0.50 -1024647.137 1.00 -1024653.786 0.50 -1024658.361 1.00 -1024661.720 0.50 -1024666.000 1.00 -1024669.305 0.50 -1024674.022 1.00 -1024677.281 0.50 -1024682.524 1.00 -1024686.570 0.50 -1024691.334 1.00 -1024694.870 0.50 -1024701.141 1.00 -1024710.027 0.50 -1024725.666 0.00 -1024736.750 0.50 -1024738.342 1.00 -1024762.023 0.50 -1024774.483 1.00 -1024779.744 0.50 -1024804.740 1.00 -1024816.493 0.50 -1024826.612 1.00 -1024833.728 0.50 -1024836.925 0.00 -1024843.783 0.50 -1024849.380 1.00 -1024856.773 0.50 -1024862.364 1.00 -1024865.775 0.50 -1024870.158 1.00 -1024873.470 0.50 -1024878.042 1.00 -1024882.017 0.50 -1024887.041 1.00 -1024891.672 0.50 -1024896.902 1.00 -1024934.671 0.50 -1024954.495 0.00 -1024959.693 0.50 -1024968.486 1.00 -1025006.101 0.50 -1025019.490 1.00 -1025036.615 0.50 -1025052.455 1.00 -1025062.406 0.50 -1025084.356 1.00 -1025136.235 0.50 -1025163.800 1.00 -1025193.188 0.50 -1025214.680 1.00 -1025220.882 0.50 -1025229.189 1.00 -1025233.988 0.50 -1025241.497 1.00 -1025247.221 0.50 -1025257.689 1.00 -1025263.857 0.50 -1025270.770 1.00 -1025275.650 0.50 -1025283.515 1.00 -1025288.725 0.50 -1025296.185 1.00 -1025301.041 0.50 -1025308.726 1.00 -1025315.060 0.50 -1025322.404 1.00 -1025328.213 0.50 -1025336.959 1.00 -1025342.196 0.50 -1025359.303 1.00 -1025364.244 0.50 -1025370.767 1.00 -1025375.170 0.50 -1025381.120 1.00 -1025382.984 0.50 -1025385.474 0.00 -1025391.182 0.50 -1025394.660 0.00 -1025399.314 0.50 -1025402.789 0.00 -1025408.650 0.50 -1025411.987 0.00 -1025424.161 0.50 -1025425.162 1.00 -1025483.181 0.50 -1025498.175 1.00 -1025513.498 0.50 -1025527.688 0.00 -1025539.025 0.50 -1025543.882 1.00 -1025548.382 0.50 -1025558.764 1.00 -1025586.146 0.50 -1025602.869 0.00 -1025611.427 0.50 -1025614.838 1.00 -1025619.617 0.50 -1025622.226 0.00 -1025625.266 0.50 -1025628.726 0.00 -1025633.859 0.50 -1025638.213 1.00 -1025642.194 0.50 -1025647.842 1.00 -1025647.947 0.50 -1025652.082 0.00 -1025656.285 0.50 -1025662.911 0.00 -1025663.084 0.50 -1025668.053 1.00 -1025672.011 0.50 -1025676.517 0.00 -1025677.535 0.50 -1025681.288 0.00 -1025685.439 0.50 -1025689.447 0.00 -1025693.048 0.50 -1025695.077 1.00 -1025699.308 0.50 -1025703.809 0.00 -1025704.517 0.50 -1025708.414 0.00 -1025714.241 0.50 -1025718.680 0.00 -1025721.602 0.50 -1025724.009 1.00 -1025728.305 0.50 -1025731.260 0.00 -1025733.660 0.50 -1025737.322 0.00 -1025743.220 0.50 -1025746.411 1.00 -1025749.866 0.50 -1025755.473 1.00 -1025757.279 0.50 -1025761.694 0.00 -1025766.641 0.50 -1025770.104 1.00 -1025773.447 0.50 -1025779.732 1.00 -1025781.733 0.50 -1025784.983 0.00 -1025792.915 0.50 -1025793.659 1.00 -1025799.588 0.50 -1025800.787 0.00 -1025805.808 0.50 -1025809.659 1.00 -1025811.421 0.50 -1025816.652 0.00 -1025817.749 0.50 -1025826.110 0.00 -1025827.856 0.50 -1025879.400 0.00 -1025906.153 0.50 -1025912.069 0.00 -1027308.633 0.50 -1027310.719 1.00 -1027329.152 0.50 -1027395.869 0.00 -1027416.270 0.50 -1027421.057 0.00 -1028703.178 0.50 -1028712.514 0.00 -1028717.674 0.50 -1028780.475 0.00 -1028818.229 0.50 -1028823.793 0.00 -1042970.205 0.50 -1043065.662 0.00 -1043079.828 0.50 -1043116.150 0.00 -1043117.747 0.50 -1043158.329 0.00 -1043182.818 0.50 -1043276.396 0.00 -1043292.115 0.50 -1043357.314 0.00 -1043363.999 0.50 -1043380.714 1.00 -1043439.363 0.50 -1043456.611 0.00 -1043462.537 0.50 -1043480.043 1.00 -1043521.460 0.50 -1043527.246 0.00 -1043539.388 0.50 -1043543.456 1.00 -1043569.949 0.50 -1043608.194 1.00 -1043755.669 0.50 -1043775.142 0.00 -1043798.301 0.50 -1043801.712 1.00 -1043819.547 0.50 -1043843.446 1.00 -1043856.144 0.50 -1043873.303 0.00 -1043892.005 0.50 -1043895.364 1.00 -1043927.706 0.50 -1043943.742 1.00 -1043944.189 0.50 -1043966.030 0.00 -1043975.777 0.50 -1043979.505 1.00 -1043984.049 0.50 -1043989.105 1.00 -1043993.343 0.50 -1043997.722 1.00 -1044001.005 0.50 -1044064.430 0.00 -1044073.642 0.50 -1044089.069 1.00 -1044098.310 0.50 -1044226.567 0.00 -1044226.872 0.50 -1044247.954 1.00 -1044259.135 0.50 -1044300.172 1.00 -1044329.824 0.50 -1044354.406 1.00 -1044386.707 0.50 -1044410.934 1.00 -1044445.597 0.50 -1044466.872 1.00 -1044480.531 0.50 -1044499.704 1.00 -1044567.279 0.50 -1044587.570 0.00 -1044589.211 0.50 -1044610.308 1.00 -1044652.525 0.50 -1044661.375 0.00 -1044673.215 0.50 -1044681.828 1.00 -1044694.814 0.50 -1044708.340 1.00 -1044713.469 0.50 -1044720.801 1.00 -1044725.565 0.50 -1044733.154 1.00 -1044739.424 0.50 -1044748.470 1.00 -1044753.463 0.50 -1044761.516 1.00 -1044767.193 0.50 -1044780.080 1.00 -1044784.929 0.50 -1044820.621 1.00 -1044825.226 0.50 -1044846.453 1.00 -1044894.401 0.50 -1044900.995 0.00 -1044914.641 0.50 -1044917.922 1.00 -1044921.456 0.50 -1044926.303 1.00 -1044929.620 0.50 -1044956.768 1.00 -1044957.622 0.50 -1044977.578 1.00 -1044983.228 0.50 -1045043.456 0.00 -1045056.568 0.50 -1045063.383 1.00 -1045069.759 0.50 -1045129.604 1.00 -1045161.665 0.50 -1045193.135 1.00 -1045222.693 0.50 -1045244.778 1.00 -1045294.673 0.50 -1045307.601 0.00 -1045319.687 0.50 -1045327.219 1.00 -1045373.960 0.50 -1045394.111 1.00 -1045447.100 0.50 -1045477.587 1.00 -1045506.945 0.50 -1045516.256 0.00 -1045530.483 0.50 -1045538.802 1.00 -1045572.715 0.50 -1045590.083 1.00 -1045596.571 0.50 -1045606.996 1.00 -1045613.389 0.50 -1045623.192 1.00 -1045627.364 0.50 -1045656.151 1.00 -1045675.044 0.50 -1045696.208 1.00 -1045698.593 0.50 -1045723.770 1.00 -1045730.321 0.50 -1045738.104 0.00 -1045740.255 0.50 -1045762.330 1.00 -1045816.314 0.50 -1045829.832 1.00 -1045834.051 0.50 -1045840.224 1.00 -1045845.981 0.50 -1045884.019 1.00 -1045890.352 0.50 -1045899.719 1.00 -1045917.954 0.50 -1045933.357 1.00 -1045982.091 0.50 -1045999.345 0.00 -1046021.175 0.50 -1046041.662 0.00 -1046056.676 0.50 -1046076.892 1.00 -1046091.530 0.50 -1046099.419 1.00 -1046104.230 0.50 -1046111.528 1.00 -1046117.513 0.50 -1046126.367 1.00 -1046135.932 0.50 -1046171.137 1.00 -1046202.563 0.50 -1046217.381 1.00 -1046250.716 0.50 -1046253.709 0.00 -1046267.074 0.50 -1046278.030 1.00 -1046314.988 0.50 -1046339.475 1.00 -1046346.238 0.50 -1046347.300 0.00 -1046356.442 0.50 -1046361.479 1.00 -1046366.368 0.50 -1046371.169 1.00 -1046376.461 0.50 -1046382.603 1.00 -1046386.495 0.50 -1046392.676 1.00 -1046393.607 0.50 -1046397.357 0.00 -1046403.160 0.50 -1046406.375 0.00 -1046413.126 0.50 -1046413.696 1.00 -1046417.530 0.50 -1046420.873 0.00 -1046424.509 0.50 -1046430.009 0.00 -1046432.425 0.50 -1046436.284 1.00 -1046440.982 0.50 -1046441.751 0.00 -1046446.383 0.50 -1046451.457 0.00 -1046452.072 0.50 -1046458.827 0.00 -1046460.896 0.50 -1046470.788 1.00 -1046477.290 0.50 -1046505.755 0.00 -1046529.968 0.50 -1046535.783 0.00 -1046561.498 0.50 -1046574.575 0.00 -1046575.458 0.50 -1046629.117 1.00 -1046632.653 0.50 -1046651.407 1.00 -1046656.178 0.50 -1046661.879 1.00 -1046686.301 0.50 -1046714.430 1.00 -1046725.278 0.50 -1046731.836 0.00 -1046740.944 0.50 -1046745.147 1.00 -1046745.264 0.50 -1046777.346 0.00 -1046791.619 0.50 -1046792.290 1.00 -1046796.714 0.50 -1046847.610 0.00 -1046858.968 0.50 -1046861.463 1.00 -1046865.754 0.50 -1046953.784 0.00 -1046963.523 0.50 -1046968.448 1.00 -1046972.915 0.50 -1047041.315 1.00 -1047045.904 0.50 -1047060.705 1.00 -1047095.389 0.50 -1047157.403 1.00 -1047168.964 0.50 -1047183.873 0.00 -1047197.484 0.50 -1047219.317 1.00 -1047280.431 0.50 -1047296.481 0.00 -1047308.491 0.50 -1047326.874 1.00 -1047380.812 0.50 -1047384.780 0.00 -1047402.395 0.50 -1047409.220 1.00 -1047457.574 0.50 -1047465.051 0.00 -1047478.032 0.50 -1047485.106 1.00 -1047513.167 0.50 -1047531.411 1.00 -1047559.608 0.50 -1047579.867 1.00 -1047591.084 0.50 -1047600.351 0.00 -1047606.599 0.50 -1047617.954 1.00 -1047648.258 0.50 -1047652.121 0.00 -1047667.464 0.50 -1047704.246 1.00 -1047714.252 0.50 -1047727.631 1.00 -1047733.357 0.50 -1047743.823 1.00 -1047767.970 0.50 -1047866.075 1.00 -1047885.816 0.50 -1047892.303 0.00 -1048028.782 0.50 -1048046.924 0.00 -1048073.019 0.50 -1048079.943 0.00 -1048089.840 0.50 -1048102.683 0.00 -1048111.659 0.50 -1048120.678 0.00 -1048129.055 0.50 -1048135.725 1.00 -1048178.094 0.50 -1048202.620 1.00 -1048208.721 0.50 -1048233.751 0.00 -1048240.244 0.50 -1048253.255 1.00 -1048259.273 0.50 -1048303.934 1.00 -1048310.306 0.50 -1048319.181 1.00 -1048367.651 0.50 -1048535.478 1.00 -1048541.225 0.50 -1048570.806 1.00 -1048584.206 0.50 -1048804.548 0.00 -1048841.090 0.50 -1048854.074 1.00 -1048881.903 0.50 -1048904.134 0.00 -1050297.761 0.50 -1050298.787 1.00 -1050315.697 0.50 -1050316.398 0.00 -1144670.598 0.50 -1144703.476 0.00 -1144732.332 0.50 -1144738.433 0.00 -1144879.567 0.50 -1144915.226 0.00 -1144943.824 0.50 -1144961.684 0.00 -1144974.220 0.50 -1144991.831 0.00 -1145003.814 0.50 -1145008.939 0.00 -1145013.909 0.50 -1145017.309 0.00 -1145021.935 0.50 -1145025.293 0.00 -1183447.115 0.50 -1183505.306 1.00 -1183539.347 0.50 -1183556.775 0.00 -1183567.025 0.50 -1183584.044 1.00 -1183592.790 0.50 -1183620.810 1.00 -1183632.883 0.50 -1183682.119 1.00 -1183686.977 0.50 -1183740.807 1.00 -1183767.389 0.50 -1183786.910 1.00 -1183824.028 0.50 -1183846.435 1.00 -1183856.010 0.50 -1183875.602 1.00 -1183938.722 0.50 -1183966.177 1.00 -1183997.470 0.50 -1184344.122 1.00 -1184386.204 0.50 -1184404.214 1.00 -1184437.440 0.50 -1184459.636 1.00 -1184492.880 0.50 -1184513.128 1.00 -1184539.716 0.50 -1184556.087 1.00 -1184588.795 0.50 -1184610.581 1.00 -1184645.091 0.50 -1184665.321 1.00 -1184688.358 0.50 -1184692.744 0.00 -1184717.064 0.50 -1184721.421 1.00 -1184764.287 0.50 -1184788.784 1.00 -1184801.507 0.50 -1184810.844 0.00 -1184818.629 0.50 -1184847.345 0.00 diff --git a/examples/testbench/decent_band/tsv/Mem_0x1e00000000000000.tsv b/examples/testbench/decent_band/tsv/Mem_0x1e00000000000000.tsv deleted file mode 100644 index f432bcea2..000000000 --- a/examples/testbench/decent_band/tsv/Mem_0x1e00000000000000.tsv +++ /dev/null @@ -1,12 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -11 1020277.868 1184412.082 #00fff6 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000001 $Size: 1.907 MiB 13 108 -10 1020517.864 1184732.637 #00fff6 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000002 $Size: 1.907 MiB 15 109 -9 1021638.640 1184825.486 #00fff6 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000003 $Size: 1.907 MiB 25 222 -8 1021896.476 1184466.441 #00fff6 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000004 $Size: 1.907 MiB 29 115 -7 1022852.940 1184520.480 #00fff6 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000005 $Size: 1.907 MiB 38 117 -6 1023094.891 1184616.464 #00fff6 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000006 $Size: 1.907 MiB 39 343 -5 1024127.778 1183973.835 #ff0038 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000007 $Size: 1.907 MiB 47 113 -4 1024326.370 1183909.479 #ff0038 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000008 $Size: 1.907 MiB 48 112 -3 1025091.417 1184563.664 #ff0038 1.0 Region: ispace:1[0:249999] x fspace:1$Fields: [fid:1048581]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000009 $Size: 1.907 MiB 52 119 -2 1025243.869 1184671.451 #ff0038 1.0 Region: ispace:1[250000:499999] x fspace:1$Fields: [fid:1048581]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000a $Size: 1.907 MiB 53 344 -1 1048334.454 1184355.765 #ff6e00 1.0 Region: ispace:1[0:499999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000b $Size: 3.815 MiB 83 110 diff --git a/examples/testbench/decent_band/tsv/None.tsv b/examples/testbench/decent_band/tsv/None.tsv deleted file mode 100644 index fd1ca0fb2..000000000 --- a/examples/testbench/decent_band/tsv/None.tsv +++ /dev/null @@ -1,5 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -3 1047709.207 1047718.548 #ffa700 1.0 Intersection Reduction 84 653 -3 1047764.499 1047773.404 #ffa700 1.0 Intersection Reduction 84 687 -3 1047878.425 1047958.736 #ffa700 1.0 Union Reduction 84 688 -3 1048512.192 1048517.590 #ff6e00 1.0 Difference 83 689 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000000.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000000.tsv deleted file mode 100644 index b13b85e05..000000000 --- a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000000.tsv +++ /dev/null @@ -1,297 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -4 6 478089.159 478125.062 478182.035 #f100ff 1.0 Deferred Enqueue Task 1 [[0, 4, 8]] 223 -4 6 478215.750 478215.750 478227.571 #ffc0cb 1.0 ProfTask <1> 262 -4 6 478280.038 478321.896 478364.450 #3dff00 1.0 Task Physical Dependence Analysis 1 [[0, 4, 8]] 224 -4 6 478393.250 478393.250 478398.019 #ffc0cb 1.0 ProfTask <1> 263 -4 6 478443.497 478488.917 478610.233 #3dff00 1.0 Task Physical Dependence Analysis 1 [[0, 4, 8]] 312 -4 6 922125.469 922202.362 922257.734 #00ff12 1.0 Logical Dependence Analysis 3 226 -4 6 922282.907 922282.907 922293.697 #ffc0cb 1.0 ProfTask <3> 264 -4 6 922301.230 922320.369 922430.159 #007bff 1.0 Operation Physical Dependence Analysis 3 314 -4 6 922573.150 922615.976 922651.888 #00ff12 1.0 Logical Dependence Analysis 4 228 -4 6 922678.906 922678.906 922683.753 #ffc0cb 1.0 ProfTask <4> 265 -4 6 922701.693 922748.730 922781.292 #007bff 1.0 Operation Physical Dependence Analysis 4 229 -4 6 922821.002 922821.002 922824.608 #ffc0cb 1.0 ProfTask <4> 266 -4 6 962476.345 962526.481 962567.952 #00ff12 1.0 Logical Dependence Analysis 5 230 -4 6 962598.963 962598.963 962603.564 #ffc0cb 1.0 ProfTask <5> 267 -4 6 962626.749 962678.949 962723.015 #007bff 1.0 Operation Physical Dependence Analysis 5 316 -4 6 999247.591 999297.143 999351.129 #00ff12 1.0 Logical Dependence Analysis 6 231 -4 6 999372.250 999372.250 999376.414 #ffc0cb 1.0 ProfTask <6> 268 -4 6 999386.903 999406.012 999503.615 #007bff 1.0 Operation Physical Dependence Analysis 6 13 -4 5 999477.933 999524.730 999537.920 #ff00c5 1.0 Tighten Index Space 6 232 -4 6 999551.347 999551.347 999554.898 #ffc0cb 1.0 ProfTask <6> 269 -4 6 1019264.111 1019311.922 1019495.815 #00ff12 1.0 Logical Dependence Analysis 7 233 -4 6 1019516.941 1019516.941 1019521.801 #ffc0cb 1.0 ProfTask <7> 270 -4 5 1019518.805 1019527.822 1019579.130 #007bff 1.0 Operation Physical Dependence Analysis 8 234 -4 6 1019594.838 1019594.838 1019598.189 #ffc0cb 1.0 ProfTask <8> 271 -4 6 1019608.309 1019628.570 1019699.933 #007bff 1.0 Operation Physical Dependence Analysis 7 17 -4 6 1019789.476 1019827.080 1019950.329 #3dff00 1.0 Task Physical Dependence Analysis 9 19 -4 5 1019924.320 1019974.821 1020060.964 #ff7a00 1.0 Scheduler 0 22 -4 6 1020028.245 1020081.461 1020149.907 #00ff12 1.0 Logical Dependence Analysis 12 26 -4 5 1020132.251 1020169.732 1020198.015 #333399 1.0 Deferred Ready Trigger 14 28 -4 4 1020052.647 1020215.638 1020251.160 #3dff00 1.0 Task Physical Dependence Analysis 11 396 -4 5 1020263.069 1020263.069 1020281.769 #cd00ff 1.0 Defer Task Perform Mapping 15 [[0, 3, 470]] 401 -4 5 1020281.769 1020281.769 1020697.773 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 15 401 -4 5 1020697.773 1020697.773 1020722.173 #cd00ff 0.45 Defer Task Perform Mapping (ready) 15 401 -4 5 1020722.173 1020722.173 1020787.419 #cd00ff 1.0 Defer Task Perform Mapping 15 401 -3 6 1020186.739 1020365.103 1020389.610 #007bff 1.0 Operation Physical Dependence Analysis 14 29 -3 4 1020379.795 1020411.660 1020446.324 #333399 1.0 Deferred Ready Trigger 12 30 -3 6 1020465.390 1020465.390 1020545.104 #00b1ff 1.0 Mapper Continuation 15 [[0, 3, 470]] 398 -3 6 1020545.104 1020545.104 1020588.179 #00b1ff 0.15 Mapper Continuation (waiting) 15 398 -3 6 1020588.179 1020588.179 1020618.504 #00b1ff 0.45 Mapper Continuation (ready) 15 398 -3 6 1020618.504 1020618.504 1020671.314 #00b1ff 1.0 Mapper Continuation 15 398 -2 4 1020471.639 1020471.639 1020652.461 #ff3200 1.0 Mapper Call map_task for 15 15 [[0, 3, 470]] 505 -4 6 1020778.521 1020810.229 1020846.307 #ff0098 1.0 Defer Task Launch 15 [[0, 3, 470]] 32 -4 5 1020830.907 1020864.411 1020913.363 #00ff12 1.0 Logical Dependence Analysis 17 36 -4 6 1020916.574 1020928.632 1020996.549 #ff7a00 1.0 Scheduler 0 39 -4 5 1020933.799 1021015.936 1021048.610 #00ff12 1.0 Logical Dependence Analysis 20 42 -4 4 1020973.416 1021061.000 1021089.194 #007bff 1.0 Operation Physical Dependence Analysis 17 43 -4 6 1021103.473 1021103.473 1021142.700 #ff7a00 1.0 Scheduler 0 543 -4 6 1021142.700 1021142.700 1021199.633 #ff7a00 0.15 Scheduler (waiting) 0 543 -4 6 1021199.633 1021199.633 1021219.821 #ff7a00 0.45 Scheduler (ready) 0 543 -4 6 1021219.821 1021219.821 1021266.724 #ff7a00 1.0 Scheduler 0 543 -3 5 1021138.184 1021159.797 1021181.610 #00b1ff 1.0 Mapper Continuation 0 566 -4 5 1021258.764 1021284.322 1021396.717 #ff7a00 1.0 Scheduler 0 547 -4 6 1021278.556 1021416.548 1021465.556 #3dff00 1.0 Task Physical Dependence Analysis 23 548 -4 4 1021453.870 1021485.938 1021570.371 #ff7a00 1.0 Scheduler 0 235 -4 5 1021585.593 1021585.593 1021662.844 #cd00ff 1.0 Defer Task Perform Mapping 25 [[0, 3, 472]] 238 -4 5 1021662.844 1021662.844 1021677.939 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 25 238 -4 5 1021677.939 1021677.939 1021692.768 #cd00ff 0.45 Defer Task Perform Mapping (ready) 25 238 -4 5 1021692.768 1021692.768 1021776.980 #cd00ff 1.0 Defer Task Perform Mapping 25 238 -3 4 1021593.456 1021593.456 1021724.585 #ff3200 1.0 Mapper Call map_task for 25 25 [[0, 3, 472]] 260 -4 4 1021769.429 1021799.332 1021836.851 #ff0098 1.0 Defer Task Launch 25 [[0, 3, 472]] 240 -4 5 1021856.216 1021856.216 1021922.476 #00b1ff 1.0 Mapper Continuation 29 [[0, 2, 471]] 551 -4 5 1021922.476 1021922.476 1021939.770 #00b1ff 0.15 Mapper Continuation (waiting) 29 551 -4 5 1021939.770 1021939.770 1021956.185 #00b1ff 0.45 Mapper Continuation (ready) 29 551 -4 5 1021956.185 1021956.185 1021994.272 #00b1ff 1.0 Mapper Continuation 29 551 -3 4 1021861.823 1021861.823 1021981.244 #ff3200 1.0 Mapper Call map_task for 29 29 [[0, 2, 471]] 261 -4 4 1021986.768 1022016.171 1022036.573 #00b1ff 1.0 Mapper Continuation 0 319 -4 5 1022028.232 1022059.820 1022077.471 #00b1ff 1.0 Mapper Continuation 24 473 -4 5 1022089.923 1022096.587 1022147.738 #006600 1.0 Post-Task Execution 13 [[0, 2, 469]] 475 -4 4 1022093.137 1022163.230 1022202.817 #333399 1.0 Deferred Ready Trigger 20 477 -4 2 1022102.921 1022220.315 1022257.425 #ff0098 1.0 Defer Task Launch 29 [[0, 2, 471]] 478 -4 2 1022266.613 1022276.351 1022345.941 #ff7a00 1.0 Scheduler 0 480 -4 4 1022231.497 1022359.294 1022392.149 #006600 1.0 Post-Task Execution 15 [[0, 3, 470]] 481 -4 6 1021493.653 1022402.911 1022522.165 #00ff12 1.0 Logical Dependence Analysis 28 484 -4 3 1021560.614 1022536.070 1022572.262 #3dff00 1.0 Task Physical Dependence Analysis 26 486 -4 5 1022172.158 1022586.450 1022614.121 #3dff00 1.0 Task Physical Dependence Analysis 27 487 -4 3 1022601.302 1022625.358 1022681.509 #cd00ff 1.0 Defer Task Perform Mapping 36 [[0, 3, 308]] 489 -4 5 1022674.088 1022694.589 1022721.685 #ff0098 1.0 Defer Task Launch 36 [[0, 3, 308]] 320 -4 1 1022335.879 1022732.564 1022770.283 #3dff00 1.0 Task Physical Dependence Analysis 31 322 -4 5 1022792.567 1022792.567 1022828.127 #ff7a00 1.0 Scheduler 0 331 -4 5 1022828.127 1022828.127 1023024.785 #ff7a00 0.15 Scheduler (waiting) 0 331 -4 5 1023024.785 1023024.785 1023051.263 #ff7a00 0.45 Scheduler (ready) 0 331 -4 5 1023051.263 1023051.263 1023065.156 #ff7a00 1.0 Scheduler 0 331 -4 5 1023065.156 1023065.156 1023193.642 #ff7a00 0.15 Scheduler (waiting) 0 331 -4 5 1023193.642 1023193.642 1023345.970 #ff7a00 0.45 Scheduler (ready) 0 331 -4 5 1023345.970 1023345.970 1023376.256 #ff7a00 1.0 Scheduler 0 331 -3 4 1022406.884 1022853.928 1022898.698 #3dff00 1.0 Task Physical Dependence Analysis 32 323 -3 3 1022915.164 1022915.164 1022928.362 #cd00ff 1.0 Defer Task Perform Mapping 39 [[0, 3, 309]] 241 -3 3 1022928.362 1022928.362 1023188.811 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 39 241 -3 3 1023188.811 1023188.811 1023217.702 #cd00ff 0.45 Defer Task Perform Mapping (ready) 39 241 -3 3 1023217.702 1023217.702 1023297.512 #cd00ff 1.0 Defer Task Perform Mapping 39 241 -2 2 1022483.024 1022953.932 1022971.622 #007bff 1.0 Operation Physical Dependence Analysis 33 324 -2 4 1022966.877 1022987.959 1023010.260 #00b1ff 1.0 Mapper Continuation 0 325 -2 4 1023018.399 1023086.962 1023113.349 #ff0098 1.0 Defer Task Launch 38 [[0, 2, 220]] 327 -2 6 1022533.687 1023128.018 1023140.111 #007bff 1.0 Operation Physical Dependence Analysis 34 328 -2 6 1023152.278 1023152.278 1023157.689 #ffc0cb 1.0 ProfTask <0> 569 -2 4 1023155.463 1023163.973 1023180.849 #00b1ff 1.0 Mapper Continuation 0 330 -4 6 1023398.373 1023398.373 1023403.459 #ffc0cb 1.0 ProfTask <0> 272 -4 6 1023415.606 1023435.265 1023524.215 #ff7a00 1.0 Scheduler 0 334 -4 5 1023510.174 1023544.753 1023593.726 #3dff00 1.0 Task Physical Dependence Analysis 40 336 -4 6 1023575.485 1023608.446 1023665.627 #cd00ff 1.0 Defer Task Perform Mapping 42 [[0, 2, 221]] 492 -4 5 1023652.822 1023685.236 1023718.305 #ff0098 1.0 Defer Task Launch 42 [[0, 2, 221]] 494 -4 4 1023664.096 1023741.592 1023765.560 #ff0098 1.0 Defer Task Launch 43 [[0, 3, 389]] 496 -4 6 1023709.363 1023777.870 1023810.031 #007bff 1.0 Operation Physical Dependence Analysis 28 498 -4 6 1023824.143 1023824.143 1023831.242 #ffc0cb 1.0 ProfTask <25> 273 -4 6 1023837.657 1023837.657 1023842.050 #ffc0cb 1.0 ProfTask <22> 274 -4 6 1023848.474 1023848.474 1023855.887 #ffc0cb 1.0 ProfTask <25> 275 -4 6 1023864.845 1023864.845 1023869.083 #ffc0cb 1.0 ProfTask <0> 276 -4 6 1023874.606 1023874.606 1023879.071 #ffc0cb 1.0 ProfTask <25> 277 -4 5 1023876.726 1023885.288 1023978.079 #3dff00 1.0 Task Physical Dependence Analysis 44 501 -4 6 1023971.542 1024023.781 1024067.567 #3dff00 1.0 Task Physical Dependence Analysis 45 503 -4 5 1024040.964 1024083.242 1024112.260 #3dff00 1.0 Task Physical Dependence Analysis 46 504 -4 6 1024125.702 1024125.702 1024142.386 #cd00ff 1.0 Defer Task Perform Mapping 48 [[0, 3, 573]] 337 -4 6 1024142.386 1024142.386 1024577.294 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 48 337 -4 6 1024577.294 1024577.294 1024604.599 #cd00ff 0.45 Defer Task Perform Mapping (ready) 48 337 -4 6 1024604.599 1024604.599 1024710.027 #cd00ff 1.0 Defer Task Perform Mapping 48 337 -3 5 1024176.449 1024176.449 1024187.245 #ffc0cb 1.0 ProfTask <13> 506 -3 4 1024197.413 1024197.413 1024204.799 #ffc0cb 1.0 ProfTask <24> 507 -3 5 1024197.316 1024214.037 1024298.425 #006600 1.0 Post-Task Execution 35 [[0, 2, 219]] 243 -3 5 1024316.465 1024316.465 1024327.960 #ffc0cb 1.0 ProfTask <29> 508 -3 5 1024336.179 1024336.179 1024341.424 #ffc0cb 1.0 ProfTask <13> 509 -3 5 1024350.467 1024350.467 1024359.821 #ffc0cb 1.0 ProfTask <0> 510 -3 5 1024367.407 1024367.407 1024372.548 #ffc0cb 1.0 ProfTask <20> 511 -3 5 1024380.168 1024380.168 1024385.425 #ffc0cb 1.0 ProfTask <15> 512 -3 5 1024393.264 1024393.264 1024397.528 #ffc0cb 1.0 ProfTask <29> 513 -3 5 1024403.247 1024403.247 1024409.951 #ffc0cb 1.0 ProfTask <24> 514 -3 5 1024415.079 1024415.079 1024418.409 #ffc0cb 1.0 ProfTask <0> 515 -3 5 1024422.747 1024422.747 1024425.896 #ffc0cb 1.0 ProfTask <15> 516 -3 5 1024430.164 1024430.164 1024433.324 #ffc0cb 1.0 ProfTask <0> 517 -3 5 1024437.680 1024437.680 1024440.818 #ffc0cb 1.0 ProfTask <33> 518 -3 5 1024445.675 1024445.675 1024450.251 #ffc0cb 1.0 ProfTask <28> 519 -3 5 1024457.169 1024457.169 1024462.152 #ffc0cb 1.0 ProfTask <34> 520 -3 5 1024468.852 1024468.852 1024473.600 #ffc0cb 1.0 ProfTask <26> 521 -3 5 1024481.925 1024481.925 1024488.279 #ffc0cb 1.0 ProfTask <27> 522 -3 4 1024486.316 1024497.214 1024532.506 #ff0098 1.0 Defer Task Launch 47 [[0, 2, 3]] 245 -3 5 1024551.826 1024551.826 1024557.310 #ffc0cb 1.0 ProfTask <35> 523 -3 5 1024564.753 1024564.753 1024569.824 #ffc0cb 1.0 ProfTask <36> 524 -3 5 1024577.086 1024577.086 1024582.272 #ffc0cb 1.0 ProfTask <35> 525 -4 5 1024697.301 1024736.750 1024779.744 #ff0098 1.0 Defer Task Launch 48 [[0, 3, 573]] 250 -4 6 1024804.740 1024804.740 1024816.493 #ffc0cb 1.0 ProfTask <39> 278 -4 6 1024826.612 1024826.612 1024833.728 #ffc0cb 1.0 ProfTask <39> 279 -4 5 1024827.055 1024843.783 1024934.671 #3dff00 1.0 Task Physical Dependence Analysis 49 251 -4 6 1024914.668 1024959.693 1025062.406 #ff7a00 1.0 Scheduler 0 339 -4 5 1025046.686 1025084.356 1025136.235 #3dff00 1.0 Task Physical Dependence Analysis 51 254 -4 6 1025163.800 1025163.800 1025193.188 #cd00ff 1.0 Defer Task Perform Mapping 53 [[0, 3, 390]] 340 -4 6 1025193.188 1025193.188 1025405.718 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 53 340 -4 6 1025405.718 1025405.718 1025425.162 #cd00ff 0.45 Defer Task Perform Mapping (ready) 53 340 -4 6 1025425.162 1025425.162 1025483.181 #cd00ff 1.0 Defer Task Perform Mapping 53 340 -3 5 1025214.680 1025214.680 1025220.882 #ffc0cb 1.0 ProfTask <41> 526 -3 5 1025229.189 1025229.189 1025233.988 #ffc0cb 1.0 ProfTask <42> 527 -3 5 1025241.497 1025241.497 1025247.221 #ffc0cb 1.0 ProfTask <43> 528 -3 5 1025257.689 1025257.689 1025263.857 #ffc0cb 1.0 ProfTask <29> 529 -3 5 1025270.770 1025270.770 1025275.650 #ffc0cb 1.0 ProfTask <25> 530 -3 5 1025283.515 1025283.515 1025288.725 #ffc0cb 1.0 ProfTask <42> 531 -3 5 1025296.185 1025296.185 1025301.041 #ffc0cb 1.0 ProfTask <28> 532 -3 5 1025308.726 1025308.726 1025315.060 #ffc0cb 1.0 ProfTask <43> 533 -3 5 1025322.404 1025322.404 1025328.213 #ffc0cb 1.0 ProfTask <25> 534 -3 5 1025336.959 1025336.959 1025342.196 #ffc0cb 1.0 ProfTask <28> 535 -3 5 1025359.303 1025359.303 1025364.244 #ffc0cb 1.0 ProfTask <0> 536 -3 5 1025370.767 1025370.767 1025375.170 #ffc0cb 1.0 ProfTask <0> 537 -3 5 1025381.120 1025381.120 1025385.474 #ffc0cb 1.0 ProfTask <44> 538 -3 5 1025391.182 1025391.182 1025394.660 #ffc0cb 1.0 ProfTask <0> 539 -3 5 1025399.314 1025399.314 1025402.789 #ffc0cb 1.0 ProfTask <45> 540 -3 5 1025408.650 1025408.650 1025411.987 #ffc0cb 1.0 ProfTask <46> 541 -4 5 1025475.654 1025498.175 1025527.688 #ff0098 1.0 Defer Task Launch 53 [[0, 3, 390]] 258 -4 5 1025543.882 1025543.882 1025548.382 #ffc0cb 1.0 ProfTask <47> 280 -4 6 1025540.699 1025558.764 1025602.869 #006600 1.0 Post-Task Execution 39 [[0, 3, 309]] 341 -4 6 1025614.838 1025614.838 1025619.617 #ffc0cb 1.0 ProfTask <35> 281 -4 6 1025625.266 1025625.266 1025628.726 #ffc0cb 1.0 ProfTask <35> 282 -4 6 1025633.859 1025633.859 1025642.194 #ffc0cb 1.0 ProfTask <47> 283 -4 6 1025647.842 1025647.842 1025652.082 #ffc0cb 1.0 ProfTask <47> 284 -4 6 1025656.285 1025656.285 1025662.911 #ffc0cb 1.0 ProfTask <48> 285 -4 6 1025668.053 1025668.053 1025672.011 #ffc0cb 1.0 ProfTask <30> 286 -4 6 1025677.535 1025677.535 1025681.288 #ffc0cb 1.0 ProfTask <30> 287 -4 6 1025685.439 1025685.439 1025689.447 #ffc0cb 1.0 ProfTask <48> 288 -4 6 1025695.077 1025695.077 1025699.308 #ffc0cb 1.0 ProfTask <49> 289 -4 6 1025704.517 1025704.517 1025708.414 #ffc0cb 1.0 ProfTask <0> 290 -4 6 1025714.241 1025714.241 1025718.680 #ffc0cb 1.0 ProfTask <50> 291 -4 6 1025724.009 1025724.009 1025728.305 #ffc0cb 1.0 ProfTask <52> 292 -4 6 1025733.660 1025733.660 1025737.322 #ffc0cb 1.0 ProfTask <51> 293 -4 6 1025743.220 1025743.220 1025749.866 #ffc0cb 1.0 ProfTask <52> 294 -4 6 1025755.473 1025755.473 1025761.694 #ffc0cb 1.0 ProfTask <53> 295 -4 6 1025766.641 1025766.641 1025773.447 #ffc0cb 1.0 ProfTask <52> 296 -4 6 1025779.732 1025779.732 1025784.983 #ffc0cb 1.0 ProfTask <38> 297 -4 6 1025793.659 1025793.659 1025799.588 #ffc0cb 1.0 ProfTask <53> 298 -4 6 1025805.808 1025805.808 1025811.421 #ffc0cb 1.0 ProfTask <52> 299 -4 6 1025817.749 1025817.749 1025826.110 #ffc0cb 1.0 ProfTask <42> 300 -4 6 1027287.711 1027308.633 1027395.869 #006600 1.0 Post-Task Execution 47 [[0, 2, 3]] 567 -4 6 1027416.270 1027416.270 1027421.057 #ffc0cb 1.0 ProfTask <47> 570 -4 6 1028703.178 1028703.178 1028712.514 #ffc0cb 1.0 ProfTask <52> 571 -4 6 1028818.229 1028818.229 1028823.793 #ffc0cb 1.0 ProfTask <52> 572 -4 6 1042928.225 1042970.205 1043065.662 #00ff12 1.0 Logical Dependence Analysis 54 49 -4 6 1043102.875 1043117.747 1043158.329 #007bff 1.0 Operation Physical Dependence Analysis 54 404 -4 6 1043253.807 1043292.115 1043357.314 #3dff00 1.0 Task Physical Dependence Analysis 55 52 -4 5 1043345.875 1043380.714 1043456.611 #ff7a00 1.0 Scheduler 0 405 -4 6 1043447.447 1043480.043 1043527.246 #3dff00 1.0 Task Physical Dependence Analysis 57 407 -4 5 1043543.456 1043543.456 1043569.949 #cd00ff 1.0 Defer Task Perform Mapping 59 [[0, 3, 393]] 409 -4 5 1043569.949 1043569.949 1043777.305 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 59 409 -4 5 1043777.305 1043777.305 1043798.301 #cd00ff 0.45 Defer Task Perform Mapping (ready) 59 409 -4 5 1043798.301 1043798.301 1043856.144 #cd00ff 1.0 Defer Task Perform Mapping 59 409 -3 6 1043608.194 1043608.194 1043660.704 #00b1ff 1.0 Mapper Continuation 59 [[0, 3, 393]] 57 -3 6 1043660.704 1043660.704 1043708.485 #00b1ff 0.15 Mapper Continuation (waiting) 59 57 -3 6 1043708.485 1043708.485 1043734.260 #00b1ff 0.45 Mapper Continuation (ready) 59 57 -3 6 1043734.260 1043734.260 1043755.669 #00b1ff 1.0 Mapper Continuation 59 57 -2 4 1043613.020 1043613.020 1043738.538 #ff3200 1.0 Mapper Call map_task for 59 59 [[0, 3, 393]] 610 -1 3 1043692.331 1043692.331 1043723.512 #00ff12 1.0 Logical Dependence Analysis 60 575 -1 3 1043723.512 1043723.512 1043836.856 #00ff12 0.15 Logical Dependence Analysis (waiting) 60 575 -1 3 1043836.856 1043836.856 1043895.364 #00ff12 0.45 Logical Dependence Analysis (ready) 60 575 -1 3 1043895.364 1043895.364 1043944.189 #00ff12 1.0 Logical Dependence Analysis 60 575 -4 6 1043959.063 1043975.777 1044064.430 #007bff 1.0 Operation Physical Dependence Analysis 60 633 -4 6 1044089.069 1044089.069 1044098.310 #ffc0cb 1.0 ProfTask <60> 634 -4 6 1044209.907 1044226.872 1044329.824 #3dff00 1.0 Task Physical Dependence Analysis 61 588 -4 5 1044305.651 1044354.406 1044445.597 #ff7a00 1.0 Scheduler 0 590 -4 5 1044452.596 1044466.872 1044587.570 #cd00ff 1.0 Defer Task Perform Mapping 65 [[0, 2, 636]] 593 -4 6 1044433.035 1044610.308 1044661.375 #3dff00 1.0 Task Physical Dependence Analysis 63 63 -4 6 1044681.828 1044681.828 1044694.814 #ffc0cb 1.0 ProfTask <61> 611 -4 6 1044708.340 1044708.340 1044713.469 #ffc0cb 1.0 ProfTask <0> 612 -4 6 1044720.801 1044720.801 1044725.565 #ffc0cb 1.0 ProfTask <0> 613 -4 6 1044733.154 1044733.154 1044739.424 #ffc0cb 1.0 ProfTask <62> 614 -4 6 1044748.470 1044748.470 1044753.463 #ffc0cb 1.0 ProfTask <64> 615 -4 5 1044761.516 1044761.516 1044767.193 #ffc0cb 1.0 ProfTask <65> 616 -4 6 1044756.504 1044780.080 1044825.226 #333399 1.0 Deferred Ready Trigger 64 413 -4 4 1044765.339 1044846.453 1044900.995 #ff0098 1.0 Defer Task Launch 66 [[0, 3, 587]] 595 -4 6 1044917.922 1044917.922 1044921.456 #ffc0cb 1.0 ProfTask <58> 617 -4 6 1044926.303 1044926.303 1044929.620 #ffc0cb 1.0 ProfTask <66> 618 -4 6 1044941.139 1044956.768 1045043.456 #ff7a00 1.0 Scheduler 0 596 -4 6 1045063.383 1045063.383 1045069.759 #ffc0cb 1.0 ProfTask <0> 619 -4 6 1045111.054 1045129.604 1045222.693 #ff7a00 1.0 Scheduler 0 599 -4 5 1045208.449 1045244.778 1045307.601 #3dff00 1.0 Task Physical Dependence Analysis 68 66 -4 6 1045278.958 1045327.219 1045373.960 #3dff00 1.0 Task Physical Dependence Analysis 69 639 -4 5 1045353.422 1045394.111 1045506.945 #cd00ff 1.0 Defer Task Perform Mapping 72 [[0, 3, 672]] 416 -4 6 1045493.944 1045530.483 1045572.715 #ff0098 1.0 Defer Task Launch 72 [[0, 3, 672]] 640 -4 6 1045590.083 1045590.083 1045596.571 #ffc0cb 1.0 ProfTask <67> 620 -4 6 1045606.996 1045606.996 1045613.389 #ffc0cb 1.0 ProfTask <0> 621 -4 5 1045609.591 1045623.192 1045675.044 #333399 1.0 Deferred Ready Trigger 70 642 -4 6 1045660.379 1045696.208 1045738.104 #007bff 1.0 Operation Physical Dependence Analysis 70 601 -4 5 1045736.249 1045762.330 1045816.314 #006600 1.0 Post-Task Execution 66 [[0, 3, 587]] 602 -4 6 1045829.832 1045829.832 1045834.051 #ffc0cb 1.0 ProfTask <71> 622 -4 5 1045830.765 1045840.224 1045917.954 #3dff00 1.0 Task Physical Dependence Analysis 73 604 -4 6 1045933.357 1045933.357 1045982.091 #ff7a00 1.0 Scheduler 0 645 -4 6 1045982.091 1045982.091 1046059.946 #ff7a00 0.15 Scheduler (waiting) 0 645 -4 6 1046059.946 1046059.946 1046171.137 #ff7a00 0.45 Scheduler (ready) 0 645 -4 6 1046171.137 1046171.137 1046202.563 #ff7a00 1.0 Scheduler 0 645 -3 5 1045987.208 1046056.676 1046135.932 #3dff00 1.0 Task Physical Dependence Analysis 74 606 -4 5 1046194.419 1046217.381 1046253.709 #3dff00 1.0 Task Physical Dependence Analysis 75 607 -4 6 1046236.282 1046267.074 1046346.238 #cd00ff 1.0 Defer Task Perform Mapping 77 [[0, 3, 394]] 68 -4 6 1046361.479 1046361.479 1046366.368 #ffc0cb 1.0 ProfTask <66> 623 -4 6 1046371.169 1046371.169 1046376.461 #ffc0cb 1.0 ProfTask <70> 624 -4 6 1046382.603 1046382.603 1046386.495 #ffc0cb 1.0 ProfTask <66> 625 -4 6 1046392.676 1046392.676 1046397.357 #ffc0cb 1.0 ProfTask <0> 626 -4 6 1046403.160 1046403.160 1046406.375 #ffc0cb 1.0 ProfTask <73> 627 -4 6 1046413.126 1046413.126 1046417.530 #ffc0cb 1.0 ProfTask <0> 628 -4 6 1046424.509 1046424.509 1046430.009 #ffc0cb 1.0 ProfTask <74> 629 -4 6 1046436.284 1046436.284 1046440.982 #ffc0cb 1.0 ProfTask <75> 630 -4 6 1046446.383 1046446.383 1046451.457 #ffc0cb 1.0 ProfTask <76> 631 -4 5 1046446.973 1046460.896 1046505.755 #006600 1.0 Post-Task Execution 71 [[0, 2, 5]] 609 -4 6 1046529.968 1046529.968 1046535.783 #ffc0cb 1.0 ProfTask <71> 632 -4 6 1046561.498 1046561.498 1046574.575 #ffc0cb 1.0 ProfTask <72> 677 -4 6 1046612.262 1046629.117 1046686.301 #009900 1.0 Deferred Commit 64 673 -4 6 1046714.430 1046714.430 1046731.836 #ffc0cb 1.0 ProfTask <64> 678 -4 5 1046716.432 1046745.147 1046777.346 #333399 1.0 Deferred Ready Trigger 78 674 -4 6 1046792.290 1046792.290 1046796.714 #ffc0cb 1.0 ProfTask <78> 679 -4 6 1046836.830 1046858.968 1046953.784 #ff7a00 1.0 Scheduler 0 675 -4 6 1046968.448 1046968.448 1046972.915 #ffc0cb 1.0 ProfTask <0> 680 -4 6 1047020.284 1047041.315 1047168.964 #ff7a00 1.0 Scheduler 0 71 -4 5 1047150.882 1047197.484 1047296.481 #3dff00 1.0 Task Physical Dependence Analysis 80 75 -4 6 1047249.015 1047326.874 1047384.780 #006600 1.0 Post-Task Execution 76 [[0, 2, 7]] 78 -4 5 1047302.855 1047402.395 1047465.051 #00ff12 1.0 Logical Dependence Analysis 83 418 -4 6 1047419.961 1047478.032 1047513.167 #006600 1.0 Post-Task Execution 77 [[0, 3, 394]] 419 -4 6 1047523.890 1047531.411 1047600.351 #cd00ff 1.0 Defer Task Perform Mapping 85 [[0, 3, 682]] 423 -4 5 1047592.783 1047617.954 1047652.121 #ff0098 1.0 Defer Task Launch 85 [[0, 3, 682]] 651 -4 6 1047667.464 1047667.464 1047892.303 #007bff 1.0 Operation Physical Dependence Analysis 84 81 -4 6 1047892.303 1047892.303 1048064.832 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 84 81 -4 6 1048064.832 1048064.832 1048135.725 #007bff 0.45 Operation Physical Dependence Analysis (ready) 84 81 -4 6 1048135.725 1048135.725 1048208.721 #007bff 1.0 Operation Physical Dependence Analysis 84 81 -3 5 1047984.153 1048028.782 1048046.924 #ff00c5 1.0 Tighten Index Space 84 683 -4 6 1048240.244 1048240.244 1048371.600 #007bff 1.0 Operation Physical Dependence Analysis 83 86 -4 6 1048371.600 1048371.600 1048388.500 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 83 86 -4 6 1048388.500 1048388.500 1048411.149 #007bff 0.45 Operation Physical Dependence Analysis (ready) 83 86 -4 6 1048411.149 1048411.149 1048584.206 #007bff 1.0 Operation Physical Dependence Analysis 83 86 -4 6 1048584.206 1048584.206 1048783.844 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 83 86 -4 6 1048783.844 1048783.844 1048841.090 #007bff 0.45 Operation Physical Dependence Analysis (ready) 83 86 -4 6 1048841.090 1048841.090 1048904.134 #007bff 1.0 Operation Physical Dependence Analysis 83 86 -3 5 1048253.631 1048253.631 1048443.184 #ff5f00 1.0 Mapper Call map_inline for 83 83 676 -4 6 1050297.761 1050297.761 1050315.697 #ffc0cb 1.0 ProfTask <83> 703 -4 6 1144625.320 1144670.598 1144703.476 #009900 1.0 Deferred Commit 83 685 -4 6 1144860.898 1144879.567 1144915.226 #00ff12 1.0 Logical Dependence Analysis 86 699 -4 5 1144902.125 1144943.824 1144961.684 #333399 1.0 Deferred Ready Trigger 86 700 -4 6 1144954.368 1144974.220 1144991.831 #007bff 1.0 Operation Physical Dependence Analysis 86 701 -4 6 1145003.814 1145003.814 1145008.939 #ffc0cb 1.0 ProfTask <86> 704 -4 6 1145013.909 1145013.909 1145017.309 #ffc0cb 1.0 ProfTask <86> 705 -4 6 1145021.935 1145021.935 1145025.293 #ffc0cb 1.0 ProfTask <86> 706 -4 6 1183406.282 1183447.115 1183556.775 #00ff12 1.0 Logical Dependence Analysis 89 425 -4 5 1183528.104 1183584.044 1183632.883 #007bff 1.0 Operation Physical Dependence Analysis 89 90 -4 6 1183652.384 1183682.119 1184688.358 #007bff 1.0 Operation Physical Dependence Analysis 87 428 -4 5 1184569.758 1184721.421 1184764.287 #009900 1.0 Garbage Collection 87 104 -4 6 1184770.795 1184788.784 1184810.844 #ff8c00 1.0 Top Finish 0 106 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000001.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000001.tsv deleted file mode 100644 index e021bb2f9..000000000 --- a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000001.tsv +++ /dev/null @@ -1,266 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -5 5 478172.693 478215.611 478293.256 #ff7a00 1.0 Scheduler 0 310 -5 5 478322.038 478322.038 478327.141 #ffc0cb 1.0 ProfTask <0> 347 -5 5 478343.946 478397.534 478455.013 #ff7a00 1.0 Scheduler 0 311 -5 5 478487.003 478487.003 478491.783 #ffc0cb 1.0 ProfTask <0> 348 -5 5 478651.813 478651.813 478657.222 #ffc0cb 1.0 ProfTask <1> 349 -5 5 922233.314 922271.051 922313.422 #333399 1.0 Deferred Ready Trigger 3 313 -5 5 922352.823 922352.823 922360.236 #ffc0cb 1.0 ProfTask <3> 350 -5 5 922485.054 922485.054 922500.295 #ffc0cb 1.0 ProfTask <3> 351 -5 5 922630.835 922685.337 922723.942 #333399 1.0 Deferred Ready Trigger 4 315 -5 5 922752.172 922752.172 922757.292 #ffc0cb 1.0 ProfTask <4> 352 -5 5 962545.217 962606.098 962647.123 #333399 1.0 Deferred Ready Trigger 5 10 -5 5 962756.169 962756.169 962760.737 #ffc0cb 1.0 ProfTask <5> 353 -5 5 999327.424 999365.982 999398.360 #333399 1.0 Deferred Ready Trigger 6 12 -5 5 999472.194 999507.767 999529.853 #ff00c5 1.0 Tighten Index Space 6 395 -5 5 1019457.047 1019495.678 1019531.556 #333399 1.0 Deferred Ready Trigger 8 15 -5 5 1019557.401 1019576.947 1019620.039 #333399 1.0 Deferred Ready Trigger 7 317 -5 5 1019636.957 1019636.957 1019640.979 #ffc0cb 1.0 ProfTask <7> 354 -5 5 1019678.408 1019714.252 1019811.952 #ff7a00 1.0 Scheduler 0 318 -5 5 1019830.493 1019830.493 1019834.164 #ffc0cb 1.0 ProfTask <0> 355 -5 5 1019897.852 1019933.635 1020004.219 #ff7a00 1.0 Scheduler 0 21 -5 4 1019992.992 1020027.498 1020099.613 #3dff00 1.0 Task Physical Dependence Analysis 10 24 -5 5 1020115.715 1020115.715 1020307.025 #cd00ff 1.0 Defer Task Perform Mapping 13 [[0, 2, 469]] 397 -5 5 1020307.025 1020307.025 1020352.321 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 13 397 -5 5 1020352.321 1020352.321 1020384.622 #cd00ff 0.45 Defer Task Perform Mapping (ready) 13 397 -5 5 1020384.622 1020384.622 1020580.691 #cd00ff 1.0 Defer Task Perform Mapping 13 397 -4 4 1020128.964 1020128.964 1020436.997 #ff3200 1.0 Mapper Call map_task for 13 13 [[0, 2, 469]] 345 -5 3 1020602.314 1020602.314 1020623.469 #00ff12 1.0 Logical Dependence Analysis 16 402 -5 3 1020623.469 1020623.469 1020734.315 #00ff12 0.15 Logical Dependence Analysis (waiting) 16 402 -5 3 1020734.315 1020734.315 1020750.432 #00ff12 0.45 Logical Dependence Analysis (ready) 16 402 -5 3 1020750.432 1020750.432 1020808.922 #00ff12 1.0 Logical Dependence Analysis 16 402 -4 2 1020573.676 1020634.362 1020676.289 #ff0098 1.0 Defer Task Launch 13 [[0, 2, 469]] 399 -4 5 1020660.088 1020691.218 1020713.369 #00b1ff 1.0 Mapper Continuation 16 400 -5 5 1020789.298 1020839.392 1020874.211 #333399 1.0 Deferred Ready Trigger 18 34 -5 4 1020437.396 1020894.975 1020930.984 #007bff 1.0 Operation Physical Dependence Analysis 12 37 -5 5 1020903.439 1020952.149 1020985.345 #333399 1.0 Deferred Ready Trigger 17 38 -5 3 1020861.093 1021013.914 1021039.622 #007bff 1.0 Operation Physical Dependence Analysis 18 40 -5 4 1021026.234 1021058.657 1021095.392 #333399 1.0 Deferred Ready Trigger 16 45 -5 5 1020987.324 1021113.857 1021175.820 #3dff00 1.0 Task Physical Dependence Analysis 19 47 -5 4 1021158.455 1021196.702 1021292.380 #ff7a00 1.0 Scheduler 0 544 -5 3 1021081.721 1021312.878 1021325.094 #007bff 1.0 Operation Physical Dependence Analysis 16 545 -5 5 1021339.701 1021339.701 1021358.196 #3dff00 1.0 Task Physical Dependence Analysis 21 549 -5 5 1021358.196 1021358.196 1021411.587 #3dff00 0.15 Task Physical Dependence Analysis (waiting) 21 549 -5 5 1021411.587 1021411.587 1021427.029 #3dff00 0.45 Task Physical Dependence Analysis (ready) 21 549 -5 5 1021427.029 1021427.029 1021477.105 #3dff00 1.0 Task Physical Dependence Analysis 21 549 -4 4 1021352.856 1021375.545 1021396.820 #00b1ff 1.0 Mapper Continuation 21 546 -5 4 1021492.376 1021492.376 1021517.858 #ff7a00 1.0 Scheduler 0 476 -5 4 1021517.858 1021517.858 1021580.405 #ff7a00 0.15 Scheduler (waiting) 0 476 -5 4 1021580.405 1021580.405 1021598.522 #ff7a00 0.45 Scheduler (ready) 0 476 -5 4 1021598.522 1021598.522 1021633.743 #ff7a00 1.0 Scheduler 0 476 -5 4 1021633.743 1021633.743 1021852.513 #ff7a00 0.15 Scheduler (waiting) 0 476 -5 4 1021852.513 1021852.513 1021869.553 #ff7a00 0.45 Scheduler (ready) 0 476 -5 4 1021869.553 1021869.553 1021890.510 #ff7a00 1.0 Scheduler 0 476 -5 4 1021890.510 1021890.510 1022054.060 #ff7a00 0.15 Scheduler (waiting) 0 476 -5 4 1022054.060 1022054.060 1022149.566 #ff7a00 0.45 Scheduler (ready) 0 476 -5 4 1022149.566 1022149.566 1022191.124 #ff7a00 1.0 Scheduler 0 476 -4 5 1021519.896 1021535.050 1021563.059 #00b1ff 1.0 Mapper Continuation 0 550 -4 3 1021361.126 1021650.015 1021708.350 #3dff00 1.0 Task Physical Dependence Analysis 22 237 -4 5 1021729.660 1021729.660 1021748.943 #cd00ff 1.0 Defer Task Perform Mapping 29 [[0, 2, 471]] 474 -4 5 1021748.943 1021748.943 1022010.605 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 29 474 -4 5 1022010.605 1022010.605 1022033.123 #cd00ff 0.45 Defer Task Perform Mapping (ready) 29 474 -4 5 1022033.123 1022033.123 1022115.674 #cd00ff 1.0 Defer Task Perform Mapping 29 474 -3 3 1021729.839 1021800.527 1021831.515 #00b1ff 1.0 Mapper Continuation 0 239 -3 2 1021906.979 1021906.979 1021935.187 #3dff00 1.0 Task Physical Dependence Analysis 24 479 -3 2 1021935.187 1021935.187 1022091.376 #3dff00 0.15 Task Physical Dependence Analysis (waiting) 24 479 -3 2 1022091.376 1022091.376 1022226.791 #3dff00 0.45 Task Physical Dependence Analysis (ready) 24 479 -3 2 1022226.791 1022226.791 1022306.819 #3dff00 1.0 Task Physical Dependence Analysis 24 479 -5 4 1022285.594 1022330.425 1022420.902 #ff7a00 1.0 Scheduler 0 482 -5 4 1022452.838 1022466.782 1022494.632 #333399 1.0 Deferred Ready Trigger 33 483 -5 4 1022500.553 1022519.257 1022545.038 #333399 1.0 Deferred Ready Trigger 34 485 -5 4 1022553.538 1022565.474 1022643.447 #cd00ff 1.0 Defer Task Perform Mapping 35 [[0, 2, 219]] 488 -5 3 1022631.033 1022672.695 1022708.855 #ff0098 1.0 Defer Task Launch 35 [[0, 2, 219]] 490 -5 5 1022190.077 1022729.096 1022761.644 #007bff 1.0 Operation Physical Dependence Analysis 20 321 -5 4 1022795.202 1022795.202 1022883.517 #cd00ff 1.0 Defer Task Perform Mapping 38 [[0, 2, 220]] 326 -5 4 1022883.517 1022883.517 1022901.333 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 38 326 -5 4 1022901.333 1022901.333 1022920.608 #cd00ff 0.45 Defer Task Perform Mapping (ready) 38 326 -5 4 1022920.608 1022920.608 1023030.646 #cd00ff 1.0 Defer Task Perform Mapping 38 326 -4 5 1022804.277 1022804.277 1022960.652 #ff3200 1.0 Mapper Call map_task for 38 38 [[0, 2, 220]] 552 -5 5 1023003.439 1023050.877 1023168.055 #00b1ff 1.0 Mapper Continuation 39 [[0, 3, 309]] 329 -5 5 1023197.049 1023197.049 1023208.594 #ffc0cb 1.0 ProfTask <0> 555 -5 5 1023219.200 1023219.200 1023224.712 #ffc0cb 1.0 ProfTask <0> 556 -5 5 1023231.705 1023231.705 1023236.361 #ffc0cb 1.0 ProfTask <16> 557 -5 5 1023243.711 1023243.711 1023248.462 #ffc0cb 1.0 ProfTask <21> 558 -5 5 1023255.017 1023255.017 1023259.870 #ffc0cb 1.0 ProfTask <0> 559 -5 5 1023266.635 1023266.635 1023271.371 #ffc0cb 1.0 ProfTask <23> 560 -5 5 1023278.427 1023278.427 1023287.444 #ffc0cb 1.0 ProfTask <21> 561 -5 4 1023283.147 1023296.822 1023334.341 #ff0098 1.0 Defer Task Launch 39 [[0, 3, 309]] 242 -5 5 1023357.571 1023357.571 1023364.867 #ffc0cb 1.0 ProfTask <0> 562 -5 4 1023364.341 1023374.111 1023447.377 #3dff00 1.0 Task Physical Dependence Analysis 37 333 -5 5 1023430.096 1023468.882 1023551.388 #ff7a00 1.0 Scheduler 0 335 -5 4 1023539.745 1023567.314 1023606.937 #3dff00 1.0 Task Physical Dependence Analysis 41 491 -5 5 1023588.530 1023620.187 1023676.616 #cd00ff 1.0 Defer Task Perform Mapping 43 [[0, 3, 389]] 493 -5 4 1023656.170 1023692.044 1023726.876 #333399 1.0 Deferred Ready Trigger 28 495 -5 5 1023699.394 1023746.877 1023800.215 #006600 1.0 Post-Task Execution 25 [[0, 3, 472]] 497 -5 5 1023801.370 1023813.667 1023886.789 #ff7a00 1.0 Scheduler 0 499 -5 5 1023900.795 1023900.795 1023904.789 #ffc0cb 1.0 ProfTask <29> 563 -5 5 1023911.051 1023911.051 1023919.322 #ffc0cb 1.0 ProfTask <29> 564 -5 4 1023916.347 1023924.498 1023982.068 #ff7a00 1.0 Scheduler 0 500 -5 5 1023952.187 1023994.093 1024050.003 #ff7a00 1.0 Scheduler 0 502 -5 4 1024066.601 1024066.601 1024150.109 #cd00ff 1.0 Defer Task Perform Mapping 47 [[0, 2, 3]] 244 -5 4 1024150.109 1024150.109 1024163.098 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 47 244 -5 4 1024163.098 1024163.098 1024201.405 #cd00ff 0.45 Defer Task Perform Mapping (ready) 47 244 -5 4 1024201.405 1024201.405 1024250.833 #cd00ff 1.0 Defer Task Perform Mapping 47 244 -5 4 1024250.833 1024250.833 1024366.581 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 47 244 -5 4 1024366.581 1024366.581 1024393.117 #cd00ff 0.45 Defer Task Perform Mapping (ready) 47 244 -5 4 1024393.117 1024393.117 1024495.054 #cd00ff 1.0 Defer Task Perform Mapping 47 244 -4 5 1024073.354 1024073.354 1024401.185 #ff3200 1.0 Mapper Call map_task for 47 47 [[0, 2, 3]] 553 -3 3 1024168.921 1024168.921 1024174.931 #ffc0cb 1.0 ProfTask <0> 356 -3 3 1024279.064 1024279.064 1024375.510 #00b1ff 1.0 Mapper Continuation 48 [[0, 3, 573]] 246 -3 3 1024375.510 1024375.510 1024408.679 #00b1ff 0.15 Mapper Continuation (waiting) 48 246 -3 3 1024408.679 1024408.679 1024522.111 #00b1ff 0.45 Mapper Continuation (ready) 48 246 -3 3 1024522.111 1024522.111 1024557.161 #00b1ff 1.0 Mapper Continuation 48 246 -2 2 1024285.192 1024285.192 1024543.162 #ff3200 1.0 Mapper Call map_task for 48 48 [[0, 3, 573]] 346 -5 5 1024585.057 1024585.057 1024590.350 #ffc0cb 1.0 ProfTask <36> 357 -5 5 1024597.545 1024597.545 1024601.896 #ffc0cb 1.0 ProfTask <20> 358 -5 5 1024607.410 1024607.410 1024610.839 #ffc0cb 1.0 ProfTask <31> 359 -5 5 1024615.132 1024615.132 1024619.071 #ffc0cb 1.0 ProfTask <38> 360 -5 5 1024623.671 1024623.671 1024626.791 #ffc0cb 1.0 ProfTask <32> 361 -5 5 1024631.171 1024631.171 1024634.661 #ffc0cb 1.0 ProfTask <33> 362 -5 5 1024639.219 1024639.219 1024642.520 #ffc0cb 1.0 ProfTask <0> 363 -5 5 1024647.137 1024647.137 1024653.786 #ffc0cb 1.0 ProfTask <38> 364 -5 5 1024658.361 1024658.361 1024661.720 #ffc0cb 1.0 ProfTask <39> 365 -5 5 1024666.000 1024666.000 1024669.305 #ffc0cb 1.0 ProfTask <38> 366 -5 5 1024674.022 1024674.022 1024677.281 #ffc0cb 1.0 ProfTask <34> 367 -5 5 1024682.524 1024682.524 1024686.570 #ffc0cb 1.0 ProfTask <39> 368 -5 5 1024691.334 1024691.334 1024694.870 #ffc0cb 1.0 ProfTask <0> 369 -5 4 1024686.172 1024701.141 1024725.666 #333399 1.0 Deferred Ready Trigger 30 248 -5 5 1024717.995 1024738.342 1024762.023 #007bff 1.0 Operation Physical Dependence Analysis 30 249 -5 4 1024753.354 1024774.483 1024836.925 #ff7a00 1.0 Scheduler 0 338 -5 5 1024849.380 1024849.380 1024856.773 #ffc0cb 1.0 ProfTask <0> 370 -5 5 1024862.364 1024862.364 1024865.775 #ffc0cb 1.0 ProfTask <37> 371 -5 5 1024870.158 1024870.158 1024873.470 #ffc0cb 1.0 ProfTask <0> 372 -5 5 1024878.042 1024878.042 1024882.017 #ffc0cb 1.0 ProfTask <0> 373 -5 5 1024887.041 1024887.041 1024891.672 #ffc0cb 1.0 ProfTask <40> 374 -5 4 1024890.447 1024896.902 1024954.495 #ff7a00 1.0 Scheduler 0 252 -5 5 1024946.696 1024968.486 1025006.101 #3dff00 1.0 Task Physical Dependence Analysis 50 253 -5 4 1025019.490 1025019.490 1025036.615 #cd00ff 1.0 Defer Task Perform Mapping 52 [[0, 2, 565]] 257 -5 4 1025036.615 1025036.615 1025346.362 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 52 257 -5 4 1025346.362 1025346.362 1025424.161 #cd00ff 0.45 Defer Task Perform Mapping (ready) 52 257 -5 4 1025424.161 1025424.161 1025513.498 #cd00ff 1.0 Defer Task Perform Mapping 52 257 -4 5 1025052.455 1025052.455 1025110.284 #00b1ff 1.0 Mapper Continuation 52 [[0, 2, 565]] 255 -4 5 1025110.284 1025110.284 1025138.358 #00b1ff 0.15 Mapper Continuation (waiting) 52 255 -4 5 1025138.358 1025138.358 1025163.253 #00b1ff 0.45 Mapper Continuation (ready) 52 255 -4 5 1025163.253 1025163.253 1025184.599 #00b1ff 1.0 Mapper Continuation 52 255 -4 5 1025184.599 1025184.599 1025281.634 #00b1ff 0.15 Mapper Continuation (waiting) 52 255 -4 5 1025281.634 1025281.634 1025305.541 #00b1ff 0.45 Mapper Continuation (ready) 52 255 -4 5 1025305.541 1025305.541 1025331.812 #00b1ff 1.0 Mapper Continuation 52 255 -3 3 1025057.887 1025057.887 1025311.567 #ff3200 1.0 Mapper Call map_task for 52 52 [[0, 2, 565]] 554 -2 2 1025208.469 1025208.469 1025290.866 #00b1ff 1.0 Mapper Continuation 53 [[0, 3, 390]] 256 -2 2 1025290.866 1025290.866 1025317.599 #00b1ff 0.15 Mapper Continuation (waiting) 53 256 -2 2 1025317.599 1025317.599 1025361.797 #00b1ff 0.45 Mapper Continuation (ready) 53 256 -2 2 1025361.797 1025361.797 1025382.984 #00b1ff 1.0 Mapper Continuation 53 256 -1 1 1025213.340 1025213.340 1025369.380 #ff3200 1.0 Mapper Call map_task for 53 53 [[0, 3, 390]] 542 -5 5 1025500.433 1025539.025 1025586.146 #ff0098 1.0 Defer Task Launch 52 [[0, 2, 565]] 259 -5 5 1025611.427 1025611.427 1025622.226 #ffc0cb 1.0 ProfTask <36> 375 -5 5 1025638.213 1025638.213 1025647.947 #ffc0cb 1.0 ProfTask <48> 376 -5 5 1025663.084 1025663.084 1025676.517 #ffc0cb 1.0 ProfTask <48> 377 -5 5 1025693.048 1025693.048 1025703.809 #ffc0cb 1.0 ProfTask <0> 378 -5 5 1025721.602 1025721.602 1025731.260 #ffc0cb 1.0 ProfTask <0> 379 -5 5 1025746.411 1025746.411 1025757.279 #ffc0cb 1.0 ProfTask <53> 380 -5 5 1025770.104 1025770.104 1025781.733 #ffc0cb 1.0 ProfTask <53> 381 -5 5 1025792.915 1025792.915 1025800.787 #ffc0cb 1.0 ProfTask <39> 382 -5 5 1025809.659 1025809.659 1025816.652 #ffc0cb 1.0 ProfTask <39> 383 -5 4 1025812.390 1025827.856 1025879.400 #006600 1.0 Post-Task Execution 43 [[0, 3, 389]] 342 -5 5 1025906.153 1025906.153 1025912.069 #ffc0cb 1.0 ProfTask <43> 384 -5 5 1027310.719 1027310.719 1027329.152 #ffc0cb 1.0 ProfTask <48> 578 -5 5 1028698.765 1028717.674 1028780.475 #006600 1.0 Post-Task Execution 52 [[0, 2, 565]] 568 -5 5 1043041.583 1043079.828 1043116.150 #333399 1.0 Deferred Ready Trigger 54 403 -5 5 1043147.303 1043182.818 1043276.396 #ff7a00 1.0 Scheduler 0 50 -5 5 1043331.296 1043363.999 1043439.363 #ff7a00 1.0 Scheduler 0 53 -5 4 1043429.649 1043462.537 1043521.460 #3dff00 1.0 Task Physical Dependence Analysis 56 55 -5 5 1043539.388 1043539.388 1043563.409 #cd00ff 1.0 Defer Task Perform Mapping 58 [[0, 2, 392]] 408 -5 5 1043563.409 1043563.409 1043637.676 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 58 408 -5 5 1043637.676 1043637.676 1043696.865 #cd00ff 0.45 Defer Task Perform Mapping (ready) 58 408 -5 5 1043696.865 1043696.865 1043775.142 #cd00ff 1.0 Defer Task Perform Mapping 58 408 -4 4 1043548.690 1043548.690 1043702.771 #ff3200 1.0 Mapper Call map_task for 58 58 [[0, 2, 392]] 577 -5 4 1043748.490 1043801.712 1043819.547 #00b1ff 1.0 Mapper Continuation 60 59 -5 3 1043767.658 1043843.446 1043873.303 #ff0098 1.0 Defer Task Launch 58 [[0, 2, 392]] 410 -5 5 1043848.600 1043892.005 1043927.706 #ff0098 1.0 Defer Task Launch 59 [[0, 3, 393]] 574 -5 5 1043929.230 1043943.742 1043966.030 #333399 1.0 Deferred Ready Trigger 60 576 -5 5 1043979.505 1043979.505 1043984.049 #ffc0cb 1.0 ProfTask <59> 579 -5 5 1043989.105 1043989.105 1043993.343 #ffc0cb 1.0 ProfTask <60> 580 -5 5 1043997.722 1043997.722 1044001.005 #ffc0cb 1.0 ProfTask <60> 581 -5 5 1044036.712 1044073.642 1044226.567 #ff7a00 1.0 Scheduler 0 637 -5 5 1044247.954 1044247.954 1044259.135 #ffc0cb 1.0 ProfTask <0> 654 -5 5 1044285.773 1044300.172 1044386.707 #ff7a00 1.0 Scheduler 0 589 -5 4 1044372.250 1044410.934 1044480.531 #3dff00 1.0 Task Physical Dependence Analysis 62 591 -5 5 1044392.301 1044499.704 1044567.279 #00ff12 1.0 Logical Dependence Analysis 64 592 -5 5 1044576.433 1044589.211 1044652.525 #ff0098 1.0 Defer Task Launch 65 [[0, 2, 636]] 61 -5 4 1044637.918 1044673.215 1044784.929 #cd00ff 1.0 Defer Task Perform Mapping 66 [[0, 3, 587]] 412 -5 5 1044758.443 1044820.621 1044894.401 #006600 1.0 Post-Task Execution 58 [[0, 2, 392]] 594 -5 4 1044808.320 1044914.641 1044957.622 #007bff 1.0 Operation Physical Dependence Analysis 64 638 -5 5 1044977.578 1044977.578 1044983.228 #ffc0cb 1.0 ProfTask <64> 655 -5 5 1045027.536 1045056.568 1045161.665 #3dff00 1.0 Task Physical Dependence Analysis 67 598 -5 4 1045139.449 1045193.135 1045294.673 #ff7a00 1.0 Scheduler 0 64 -5 5 1045276.168 1045319.687 1045447.100 #cd00ff 1.0 Defer Task Perform Mapping 71 [[0, 2, 5]] 414 -5 4 1045436.237 1045477.587 1045516.256 #ff0098 1.0 Defer Task Launch 71 [[0, 2, 5]] 600 -5 3 1045283.908 1045538.802 1045627.364 #00ff12 1.0 Logical Dependence Analysis 70 641 -5 5 1045619.478 1045656.151 1045698.593 #006600 1.0 Post-Task Execution 65 [[0, 2, 636]] 643 -5 4 1045723.770 1045723.770 1045730.321 #ffc0cb 1.0 ProfTask <69> 656 -5 5 1045721.386 1045740.255 1045845.981 #ff7a00 1.0 Scheduler 0 603 -5 5 1045884.019 1045884.019 1045890.352 #ffc0cb 1.0 ProfTask <72> 657 -5 4 1045885.201 1045899.719 1045999.345 #ff7a00 1.0 Scheduler 0 644 -5 5 1045976.234 1046021.175 1046041.662 #00b1ff 1.0 Mapper Continuation 0 605 -5 5 1046076.892 1046076.892 1046091.530 #ffc0cb 1.0 ProfTask <65> 658 -5 5 1046099.419 1046099.419 1046104.230 #ffc0cb 1.0 ProfTask <70> 659 -5 5 1046111.528 1046111.528 1046117.513 #ffc0cb 1.0 ProfTask <70> 660 -5 4 1046113.992 1046126.367 1046250.716 #cd00ff 1.0 Defer Task Perform Mapping 76 [[0, 2, 7]] 608 -5 5 1046237.537 1046278.030 1046314.988 #ff0098 1.0 Defer Task Launch 76 [[0, 2, 7]] 646 -5 4 1046339.475 1046339.475 1046347.300 #ffc0cb 1.0 ProfTask <65> 661 -5 5 1046337.015 1046356.442 1046393.607 #ff0098 1.0 Defer Task Launch 77 [[0, 3, 394]] 647 -5 5 1046413.696 1046413.696 1046420.873 #ffc0cb 1.0 ProfTask <0> 662 -5 5 1046432.425 1046432.425 1046441.751 #ffc0cb 1.0 ProfTask <0> 663 -5 5 1046452.072 1046452.072 1046458.827 #ffc0cb 1.0 ProfTask <76> 664 -5 5 1046470.788 1046470.788 1046477.290 #ffc0cb 1.0 ProfTask <77> 665 -5 5 1046560.606 1046575.458 1046632.653 #006600 1.0 Post-Task Execution 72 [[0, 3, 672]] 648 -5 5 1046651.407 1046651.407 1046656.178 #ffc0cb 1.0 ProfTask <72> 666 -5 4 1046653.371 1046661.879 1046725.278 #00ff12 1.0 Logical Dependence Analysis 78 649 -5 5 1046740.944 1046740.944 1046745.264 #ffc0cb 1.0 ProfTask <78> 667 -5 5 1046766.391 1046791.619 1046847.610 #007bff 1.0 Operation Physical Dependence Analysis 78 650 -5 5 1046861.463 1046861.463 1046865.754 #ffc0cb 1.0 ProfTask <78> 668 -5 5 1046943.149 1046963.523 1047045.904 #3dff00 1.0 Task Physical Dependence Analysis 79 70 -5 4 1047060.705 1047060.705 1047095.389 #ff7a00 1.0 Scheduler 0 73 -5 4 1047095.389 1047095.389 1047197.337 #ff7a00 0.15 Scheduler (waiting) 0 73 -5 4 1047197.337 1047197.337 1047219.317 #ff7a00 0.45 Scheduler (ready) 0 73 -5 4 1047219.317 1047219.317 1047280.431 #ff7a00 1.0 Scheduler 0 73 -4 5 1047090.004 1047157.403 1047183.873 #00b1ff 1.0 Mapper Continuation 0 72 -5 5 1047242.202 1047308.491 1047380.812 #cd00ff 1.0 Defer Task Perform Mapping 82 [[0, 2, 681]] 77 -5 4 1047372.876 1047409.220 1047457.574 #ff0098 1.0 Defer Task Launch 82 [[0, 2, 681]] 417 -5 3 1047265.656 1047485.106 1047559.608 #3dff00 1.0 Task Physical Dependence Analysis 81 421 -5 2 1047276.966 1047579.867 1047591.084 #2500ff 1.0 Prepipeline Stage 83 422 -5 5 1047585.357 1047606.599 1047648.258 #333399 1.0 Deferred Ready Trigger 84 652 -5 5 1047704.246 1047704.246 1047714.252 #ffc0cb 1.0 ProfTask <85> 669 -5 5 1047727.631 1047727.631 1047733.357 #ffc0cb 1.0 ProfTask <84> 670 -5 5 1047743.823 1047743.823 1047767.970 #ffc0cb 1.0 ProfTask <84> 671 -5 5 1047866.075 1047866.075 1047885.816 #ffc0cb 1.0 ProfTask <84> 690 -5 5 1048073.019 1048073.019 1048079.943 #ffc0cb 1.0 ProfTask <84> 691 -5 5 1048089.840 1048089.840 1048102.683 #ffc0cb 1.0 ProfTask <84> 692 -5 4 1048111.659 1048111.659 1048120.678 #ffc0cb 1.0 ProfTask <82> 693 -5 5 1048106.806 1048129.055 1048178.094 #006600 1.0 Post-Task Execution 82 [[0, 2, 681]] 79 -5 4 1048177.813 1048202.620 1048233.751 #333399 1.0 Deferred Ready Trigger 83 684 -5 5 1048253.255 1048253.255 1048259.273 #ffc0cb 1.0 ProfTask <83> 694 -5 5 1048303.934 1048303.934 1048310.306 #ffc0cb 1.0 ProfTask <85> 695 -5 4 1048304.146 1048319.181 1048367.651 #006600 1.0 Post-Task Execution 85 [[0, 3, 682]] 83 -5 5 1048535.478 1048535.478 1048541.225 #ffc0cb 1.0 ProfTask <83> 696 -5 5 1048557.987 1048570.806 1048804.548 #1f00ff 1.0 Copy Fill Aggregation 83 424 -5 4 1048794.518 1048854.074 1048881.903 #00ff0f 1.0 Copy Fill Deletion 83 85 -5 5 1050298.787 1050298.787 1050316.398 #ffc0cb 1.0 ProfTask <83> 697 -5 5 1144732.332 1144732.332 1144738.433 #ffc0cb 1.0 ProfTask <83> 698 -5 5 1183469.750 1183505.306 1183539.347 #333399 1.0 Deferred Ready Trigger 89 88 -5 4 1183509.249 1183567.025 1183592.790 #006600 1.0 Post-Task Execution 1 [[0, 4, 8]] 89 -5 5 1183591.689 1183620.810 1183686.977 #333399 1.0 Deferred Ready Trigger 87 92 -5 5 1183723.784 1183740.807 1183767.389 #333399 1.0 Deferred Ready Trigger 88 94 -5 4 1183759.243 1183786.910 1183824.028 #007bff 1.0 Operation Physical Dependence Analysis 88 95 -5 4 1183795.438 1183846.435 1183856.010 #f7ff00 1.0 Trigger Complete 1 [[0, 4, 8]] 96 -5 5 1183790.134 1183875.602 1183938.722 #009900 1.0 Garbage Collection 87 426 -5 3 1183810.754 1183966.177 1183997.470 #009900 1.0 Garbage Collection 87 97 -5 5 1184311.353 1184344.122 1184386.204 #009900 1.0 Garbage Collection 87 427 -5 4 1184377.864 1184404.214 1184437.440 #009900 1.0 Garbage Collection 87 98 -5 5 1184398.593 1184459.636 1184492.880 #009900 1.0 Garbage Collection 87 99 -5 3 1184418.693 1184513.128 1184539.716 #009900 1.0 Garbage Collection 87 100 -5 4 1184443.049 1184556.087 1184588.795 #009900 1.0 Garbage Collection 87 101 -5 5 1184537.181 1184610.581 1184645.091 #009900 1.0 Garbage Collection 87 102 -5 3 1184552.029 1184665.321 1184692.744 #009900 1.0 Garbage Collection 87 103 -5 5 1184670.914 1184717.064 1184801.507 #990000 1.0 Deferred Execute 88 105 -5 4 1184592.607 1184818.629 1184847.345 #009900 1.0 Garbage Collection 87 429 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000002.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000002.tsv deleted file mode 100644 index b43bebebf..000000000 --- a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000002.tsv +++ /dev/null @@ -1,93 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -1 3 962689.824 962689.824 962698.725 #ffc0cb 1.0 ProfTask <5> 120 -1 3 999427.832 999427.832 999433.367 #ffc0cb 1.0 ProfTask <6> 121 -1 3 999530.605 999530.605 999537.468 #ffc0cb 1.0 ProfTask <6> 122 -1 3 1019563.499 1019563.499 1019569.168 #ffc0cb 1.0 ProfTask <8> 123 -1 3 1019723.664 1019723.664 1019734.354 #ffc0cb 1.0 ProfTask <7> 124 -1 3 1019976.547 1019976.547 1019982.927 #ffc0cb 1.0 ProfTask <9> 125 -1 3 1020029.859 1020029.859 1020035.992 #ffc0cb 1.0 ProfTask <0> 126 -1 3 1020081.621 1020081.621 1020088.315 #ffc0cb 1.0 ProfTask <0> 127 -1 3 1020133.393 1020133.393 1020140.003 #ffc0cb 1.0 ProfTask <10> 128 -1 3 1020170.226 1020170.226 1020176.043 #ffc0cb 1.0 ProfTask <12> 129 -1 3 1020320.009 1020320.009 1020326.182 #ffc0cb 1.0 ProfTask <14> 130 -1 3 1020336.073 1020336.073 1020344.812 #ffc0cb 1.0 ProfTask <13> 131 -1 3 1020409.676 1020409.676 1020415.356 #ffc0cb 1.0 ProfTask <14> 132 -1 3 1020465.741 1020465.741 1020471.704 #ffc0cb 1.0 ProfTask <12> 133 -1 3 1020538.912 1020538.912 1020544.913 #ffc0cb 1.0 ProfTask <15> 134 -1 3 1020662.935 1020683.611 1022061.790 #00fff6 1.0 legate::numpy::FillTask [CPU] <13> [[0, 3, 308], [0, 0, 475]] [[0, 1, 345], [0, 1, 397], [0, 1, 399]] [[0, 4, 8]] 469 -1 3 1022107.376 1022107.376 1022115.335 #ffc0cb 1.0 ProfTask <15> 135 -1 3 1022125.977 1022125.977 1022132.984 #ffc0cb 1.0 ProfTask <18> 136 -1 3 1022141.854 1022141.854 1022148.613 #ffc0cb 1.0 ProfTask <17> 137 -1 3 1022155.102 1022155.102 1022158.592 #ffc0cb 1.0 ProfTask <12> 138 -1 3 1022164.775 1022164.775 1022169.154 #ffc0cb 1.0 ProfTask <17> 139 -1 3 1022175.085 1022175.085 1022178.496 #ffc0cb 1.0 ProfTask <0> 140 -1 3 1022184.906 1022184.906 1022191.677 #ffc0cb 1.0 ProfTask <18> 141 -1 3 1022198.572 1022198.572 1022204.310 #ffc0cb 1.0 ProfTask <20> 142 -1 3 1022210.953 1022210.953 1022214.923 #ffc0cb 1.0 ProfTask <17> 143 -1 3 1022222.553 1022222.553 1022227.962 #ffc0cb 1.0 ProfTask <16> 144 -1 3 1022237.249 1022237.249 1022245.039 #ffc0cb 1.0 ProfTask <19> 145 -1 2 1022238.538 1022259.076 1023674.045 #00fff6 1.0 legate::numpy::FillTask [CPU] <29> [[0, 1, 474], [0, 0, 551], [0, 0, 478], [0, 0, 261]] 471 -1 3 1022696.533 1023700.501 1024175.988 #00fff6 1.0 legate::numpy::FillTask [CPU] <35> [[0, 0, 243]] [[0, 2, 565], [0, 1, 488], [0, 3, 390], [0, 1, 490]] [[0, 4, 8]] 219 -1 1 1023104.640 1024212.470 1025513.689 #00fff6 1.0 legate::numpy::FillTask [CPU] <38> [[0, 2, 221], [0, 1, 326], [0, 0, 327], [0, 1, 552], [0, 3, 389]] 220 -1 2 1023703.011 1025541.836 1025784.682 #00fff6 1.0 legate::numpy::FillTask [CPU] <42> [[0, 2, 220], [0, 3, 573]] [[0, 0, 494], [0, 3, 472], [0, 0, 492]] [[0, 4, 8]] 221 -1 3 1025808.403 1025817.215 1027264.327 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <47> [[0, 0, 567], [0, 2, 565]] [[0, 3, 308], [0, 1, 553], [0, 1, 244], [0, 3, 389], [0, 0, 245]] [[0, 4, 8]] 3 -1 3 1027298.588 1027298.588 1027310.850 #ffc0cb 1.0 ProfTask <47> 146 -1 3 1027323.700 1027340.279 1028683.215 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <52> [[0, 3, 393], [0, 1, 568], [0, 2, 219]] [[0, 1, 255], [0, 1, 554], [0, 1, 259], [0, 1, 257], [0, 2, 3]] [[0, 4, 8]] 565 -1 3 1043099.467 1043099.467 1043105.925 #ffc0cb 1.0 ProfTask <54> 147 -1 3 1043313.696 1043313.696 1043321.599 #ffc0cb 1.0 ProfTask <0> 148 -1 3 1043381.693 1043381.693 1043389.858 #ffc0cb 1.0 ProfTask <55> 149 -1 3 1043463.226 1043463.226 1043469.407 #ffc0cb 1.0 ProfTask <0> 150 -1 3 1043544.444 1043544.444 1043550.837 #ffc0cb 1.0 ProfTask <56> 151 -1 3 1043780.003 1043780.003 1043793.581 #ffc0cb 1.0 ProfTask <59> 152 -1 3 1043840.550 1043840.550 1043845.419 #ffc0cb 1.0 ProfTask <60> 153 -1 3 1043865.362 1043891.674 1044741.669 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <58> [[0, 2, 636], [0, 1, 594]] [[0, 1, 408], [0, 1, 410], [0, 1, 577], [0, 3, 390]] [[0, 4, 8]] 392 -1 3 1044772.977 1044772.977 1044785.500 #ffc0cb 1.0 ProfTask <65> 154 -1 3 1044798.568 1044798.568 1044804.821 #ffc0cb 1.0 ProfTask <63> 155 -1 2 1044801.631 1044816.976 1045600.715 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <65> [[0, 1, 643], [0, 2, 5]] [[0, 1, 61], [0, 2, 392], [0, 0, 593]] [[0, 4, 8]] 636 -1 3 1045633.063 1045633.063 1045640.501 #ffc0cb 1.0 ProfTask <0> 156 -1 2 1045658.078 1045658.078 1045664.840 #ffc0cb 1.0 ProfTask <68> 157 -1 3 1045655.819 1045674.697 1046429.291 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <71> [[0, 0, 609], [0, 2, 7], [0, 3, 587]] [[0, 2, 636], [0, 1, 414], [0, 1, 600]] [[0, 4, 8]] 5 -1 3 1046459.143 1046459.143 1046466.393 #ffc0cb 1.0 ProfTask <77> 158 -1 3 1046474.283 1046474.283 1046481.896 #ffc0cb 1.0 ProfTask <71> 159 -1 3 1046483.645 1046509.517 1047234.439 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <76> [[0, 0, 78], [0, 3, 672]] [[0, 1, 646], [0, 1, 608], [0, 2, 5]] [[0, 4, 8]] 7 -1 3 1047255.694 1047255.694 1047261.622 #ffc0cb 1.0 ProfTask <79> 160 -1 3 1047267.900 1047267.900 1047274.343 #ffc0cb 1.0 ProfTask <0> 161 -1 3 1047281.641 1047281.641 1047298.270 #ffc0cb 1.0 ProfTask <0> 162 -1 3 1047306.163 1047306.163 1047311.434 #ffc0cb 1.0 ProfTask <76> 163 -1 3 1047316.397 1047316.397 1047328.915 #ffc0cb 1.0 ProfTask <0> 164 -1 3 1047333.748 1047333.748 1047336.991 #ffc0cb 1.0 ProfTask <80> 165 -1 3 1047408.539 1047408.539 1047414.776 #ffc0cb 1.0 ProfTask <82> 166 -1 3 1047425.444 1047425.444 1047430.972 #ffc0cb 1.0 ProfTask <76> 167 -1 3 1047440.173 1047463.197 1048083.927 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <82> [[0, 1, 79]] [[0, 3, 394], [0, 1, 417], [0, 1, 77]] [[0, 4, 8]] 681 -1 3 1048208.167 1048208.167 1048215.606 #ffc0cb 1.0 ProfTask <82> 168 -1 3 1048245.381 1048245.381 1048260.714 #ffc0cb 1.0 ProfTask <84> 169 -1 3 1048360.624 1048360.624 1048368.336 #ffc0cb 1.0 ProfTask <83> 170 -1 3 1048392.151 1048392.151 1048397.420 #ffc0cb 1.0 ProfTask <85> 171 -1 3 1048914.304 1048914.304 1048919.582 #ffc0cb 1.0 ProfTask <83> 172 -1 3 1048927.422 1048927.422 1048933.418 #ffc0cb 1.0 ProfTask <83> 173 -1 3 1183514.868 1183514.868 1183526.003 #ffc0cb 1.0 ProfTask <1> 174 -1 3 1183564.060 1183564.060 1183571.389 #ffc0cb 1.0 ProfTask <89> 175 -1 3 1183618.998 1183618.998 1183627.204 #ffc0cb 1.0 ProfTask <1> 176 -1 3 1183656.435 1183656.435 1183662.395 #ffc0cb 1.0 ProfTask <89> 177 -1 3 1183716.981 1183716.981 1183722.963 #ffc0cb 1.0 ProfTask <87> 178 -1 3 1183789.778 1183789.778 1183796.240 #ffc0cb 1.0 ProfTask <88> 179 -1 3 1183844.266 1183844.266 1183850.453 #ffc0cb 1.0 ProfTask <88> 180 -1 3 1183876.008 1183876.008 1183881.779 #ffc0cb 1.0 ProfTask <1> 181 -1 3 1183932.594 1183932.594 1183961.777 #ffc0cb 1.0 ProfTask <48> 182 -1 3 1183990.520 1183990.520 1183995.478 #ffc0cb 1.0 ProfTask <47> 183 -1 3 1184022.320 1184022.320 1184027.253 #ffc0cb 1.0 ProfTask <87> 184 -1 3 1184378.314 1184378.314 1184386.071 #ffc0cb 1.0 ProfTask <83> 185 -1 3 1184438.252 1184438.252 1184446.042 #ffc0cb 1.0 ProfTask <13> 186 -1 3 1184452.860 1184452.860 1184456.362 #ffc0cb 1.0 ProfTask <87> 187 -1 3 1184482.915 1184482.915 1184489.625 #ffc0cb 1.0 ProfTask <29> 188 -1 3 1184514.238 1184514.238 1184519.942 #ffc0cb 1.0 ProfTask <87> 189 -1 3 1184528.822 1184528.822 1184533.676 #ffc0cb 1.0 ProfTask <38> 190 -1 3 1184557.808 1184557.808 1184562.356 #ffc0cb 1.0 ProfTask <87> 191 -1 3 1184575.260 1184575.260 1184578.768 #ffc0cb 1.0 ProfTask <52> 192 -1 3 1184612.280 1184612.280 1184619.851 #ffc0cb 1.0 ProfTask <87> 193 -1 3 1184676.751 1184676.751 1184683.603 #ffc0cb 1.0 ProfTask <87> 194 -1 3 1184711.881 1184711.881 1184720.164 #ffc0cb 1.0 ProfTask <87> 195 -1 3 1184751.168 1184751.168 1184757.069 #ffc0cb 1.0 ProfTask <15> 196 -1 3 1184788.335 1184788.335 1184793.531 #ffc0cb 1.0 ProfTask <87> 197 -1 3 1184825.080 1184825.080 1184831.298 #ffc0cb 1.0 ProfTask <88> 198 -1 3 1184838.998 1184838.998 1184845.978 #ffc0cb 1.0 ProfTask <0> 199 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000003.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000003.tsv deleted file mode 100644 index 3224fd8ff..000000000 --- a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000003.tsv +++ /dev/null @@ -1,52 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -1 3 999566.582 999566.582 999574.512 #ffc0cb 1.0 ProfTask <6> 430 -1 3 1020320.096 1020320.096 1020326.371 #ffc0cb 1.0 ProfTask <11> 431 -1 3 1020607.485 1020607.485 1020618.851 #ffc0cb 1.0 ProfTask <13> 432 -1 3 1020698.885 1020698.885 1020708.696 #ffc0cb 1.0 ProfTask <15> 433 -1 3 1020718.044 1020718.044 1020723.315 #ffc0cb 1.0 ProfTask <13> 434 -1 3 1020728.635 1020728.635 1020732.653 #ffc0cb 1.0 ProfTask <16> 435 -1 3 1020812.834 1020812.834 1020820.679 #ffc0cb 1.0 ProfTask <15> 436 -1 2 1020841.769 1020841.769 1020849.994 #ffc0cb 1.0 ProfTask <16> 437 -1 3 1020836.247 1020859.100 1022211.911 #00fff6 1.0 legate::numpy::FillTask [CPU] <15> [[0, 0, 481]] [[0, 0, 32], [0, 0, 398], [0, 0, 401], [0, 0, 505]] [[0, 4, 8]] 470 -1 2 1021824.225 1022245.345 1023674.774 #00fff6 1.0 legate::numpy::FillTask [CPU] <25> [[0, 1, 497], [0, 2, 221]] [[0, 0, 240], [0, 0, 260], [0, 0, 238]] [[0, 4, 8]] 472 -1 3 1022713.176 1023714.788 1024165.613 #00fff6 1.0 legate::numpy::FillTask [CPU] <36> [[0, 2, 3]] [[0, 0, 320], [0, 2, 469], [0, 0, 489]] [[0, 4, 8]] 308 -1 1 1023323.068 1024191.329 1025523.689 #00fff6 1.0 legate::numpy::FillTask [CPU] <39> [[0, 0, 341]] [[0, 0, 241], [0, 1, 329], [0, 1, 242]] [[0, 4, 8]] 309 -1 2 1023757.906 1025553.734 1025793.359 #00fff6 1.0 legate::numpy::FillTask [CPU] <43> [[0, 2, 220], [0, 2, 3], [0, 1, 342]] [[0, 1, 493], [0, 0, 496]] [[0, 4, 8]] 389 -1 3 1025825.619 1025825.619 1025838.009 #ffc0cb 1.0 ProfTask <43> 438 -1 3 1025842.865 1025857.809 1027267.987 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <48> [[0, 3, 390]] [[0, 2, 221], [0, 1, 346], [0, 0, 337], [0, 1, 246], [0, 0, 250]] [[0, 4, 8]] 573 -1 3 1027284.385 1027290.352 1028673.325 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <53> [[0, 2, 392], [0, 2, 219]] [[0, 0, 258], [0, 3, 573], [0, 1, 256], [0, 1, 542], [0, 0, 340]] [[0, 4, 8]] 390 -1 3 1028696.363 1028696.363 1028702.589 #ffc0cb 1.0 ProfTask <53> 439 -1 3 1043152.725 1043152.725 1043162.570 #ffc0cb 1.0 ProfTask <54> 440 -1 3 1043172.134 1043172.134 1043175.780 #ffc0cb 1.0 ProfTask <54> 441 -1 3 1043478.703 1043478.703 1043483.955 #ffc0cb 1.0 ProfTask <0> 442 -1 3 1043559.025 1043559.025 1043565.584 #ffc0cb 1.0 ProfTask <57> 443 -1 3 1043815.587 1043815.587 1043823.752 #ffc0cb 1.0 ProfTask <58> 444 -1 3 1043885.917 1043885.917 1043893.078 #ffc0cb 1.0 ProfTask <59> 445 -1 3 1043899.319 1043899.319 1043902.688 #ffc0cb 1.0 ProfTask <58> 446 -1 3 1043915.164 1043932.016 1044786.018 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <59> [[0, 3, 394], [0, 3, 587]] [[0, 0, 409], [0, 2, 565], [0, 1, 574], [0, 0, 57], [0, 0, 610]] [[0, 4, 8]] 393 -1 3 1044818.895 1044818.895 1044826.305 #ffc0cb 1.0 ProfTask <58> 447 -1 3 1044832.900 1044832.900 1044836.390 #ffc0cb 1.0 ProfTask <59> 448 -1 3 1044841.026 1044841.026 1044846.632 #ffc0cb 1.0 ProfTask <66> 449 -1 3 1044853.660 1044853.660 1044856.914 #ffc0cb 1.0 ProfTask <64> 450 -1 3 1044886.088 1044903.140 1045716.824 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <66> [[0, 0, 602]] [[0, 0, 595], [0, 3, 393], [0, 1, 412], [0, 2, 5]] [[0, 4, 8]] 587 -1 3 1045749.414 1045749.414 1045757.154 #ffc0cb 1.0 ProfTask <71> 451 -1 3 1045767.502 1045767.502 1045774.232 #ffc0cb 1.0 ProfTask <72> 452 -1 2 1045769.705 1045783.097 1046540.037 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <72> [[0, 1, 648]] [[0, 0, 640], [0, 0, 416], [0, 3, 394], [0, 2, 7]] [[0, 4, 8]] 672 -1 3 1046599.653 1046615.744 1047402.303 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <77> [[0, 2, 681], [0, 0, 419], [0, 3, 672]] [[0, 3, 393], [0, 0, 68], [0, 1, 647]] [[0, 4, 8]] 394 -1 3 1047428.177 1047428.177 1047435.591 #ffc0cb 1.0 ProfTask <77> 453 -1 3 1047485.607 1047485.607 1047499.472 #ffc0cb 1.0 ProfTask <82> 454 -1 3 1047509.224 1047509.224 1047515.337 #ffc0cb 1.0 ProfTask <83> 455 -1 3 1047551.395 1047551.395 1047558.273 #ffc0cb 1.0 ProfTask <77> 456 -1 3 1047583.009 1047583.009 1047588.140 #ffc0cb 1.0 ProfTask <81> 457 -1 3 1047610.844 1047610.844 1047614.303 #ffc0cb 1.0 ProfTask <83> 458 -1 3 1047619.993 1047619.993 1047623.284 #ffc0cb 1.0 ProfTask <85> 459 -1 3 1047638.420 1047656.279 1048281.052 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <85> [[0, 1, 83]] [[0, 0, 651], [0, 0, 423]] [[0, 4, 8]] 682 -1 3 1048858.236 1048858.236 1048865.054 #ffc0cb 1.0 ProfTask <83> 460 -1 3 1183586.336 1183586.336 1183593.882 #ffc0cb 1.0 ProfTask <89> 461 -1 3 1183962.273 1183962.273 1183969.461 #ffc0cb 1.0 ProfTask <87> 462 -1 3 1184410.125 1184410.125 1184416.531 #ffc0cb 1.0 ProfTask <87> 463 -1 3 1184649.833 1184649.833 1184656.431 #ffc0cb 1.0 ProfTask <39> 464 -1 3 1184686.919 1184686.919 1184705.292 #ffc0cb 1.0 ProfTask <53> 465 -1 3 1184716.235 1184716.235 1184722.729 #ffc0cb 1.0 ProfTask <87> 466 -1 3 1184846.419 1184846.419 1184853.601 #ffc0cb 1.0 ProfTask <25> 467 -1 3 1184862.211 1184862.211 1184865.981 #ffc0cb 1.0 ProfTask <87> 468 diff --git a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000004.tsv b/examples/testbench/decent_band/tsv/Proc_0x1d00000000000004.tsv deleted file mode 100644 index 6c823e943..000000000 --- a/examples/testbench/decent_band/tsv/Proc_0x1d00000000000004.tsv +++ /dev/null @@ -1,17 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -1 1 478641.174 478641.174 922239.137 #eb00ff 1.0 legion_python_main <1> [[0, 1, 89], [0, 1, 96]] [[0, 0, 223], [0, 0, 224], [0, 0, 312]] [[0, 3, 682], [0, 3, 470], [0, 3, 389], [0, 2, 392], [0, 2, 3], [0, 2, 636], [0, 3, 308], [0, 2, 221], [0, 3, 587], [0, 3, 573], [0, 3, 393], [0, 2, 7], [0, 3, 390], [0, 2, 219], [0, 3, 309], [0, 2, 469], [0, 3, 672], [0, 2, 681], [0, 3, 472], [0, 2, 565], [0, 2, 5], [0, 3, 394]] 8 -1 1 922239.137 922239.137 922397.410 #eb00ff 0.15 legion_python_main <1> (waiting) 8 -1 1 922397.410 922397.410 922497.427 #eb00ff 0.45 legion_python_main <1> (ready) 8 -1 1 922497.427 922497.427 922606.850 #eb00ff 1.0 legion_python_main <1> 8 -1 1 922606.850 922606.850 922766.603 #eb00ff 0.15 legion_python_main <1> (waiting) 8 -1 1 922766.603 922766.603 922815.999 #eb00ff 0.45 legion_python_main <1> (ready) 8 -1 1 922815.999 922815.999 962519.280 #eb00ff 1.0 legion_python_main <1> 8 -1 1 962519.280 962519.280 962704.926 #eb00ff 0.15 legion_python_main <1> (waiting) 8 -1 1 962704.926 962704.926 962723.661 #eb00ff 0.45 legion_python_main <1> (ready) 8 -1 1 962723.661 962723.661 1047360.569 #eb00ff 1.0 legion_python_main <1> 8 -1 1 1047360.569 1047360.569 1048868.455 #eb00ff 0.15 legion_python_main <1> (waiting) 8 -1 1 1048868.455 1048868.455 1048908.961 #eb00ff 0.45 legion_python_main <1> (ready) 8 -1 1 1048908.961 1048908.961 1048924.893 #eb00ff 1.0 legion_python_main <1> 8 -1 1 1048924.893 1048924.893 1050325.359 #eb00ff 0.15 legion_python_main <1> (waiting) 8 -1 1 1050325.359 1050325.359 1050359.631 #eb00ff 0.45 legion_python_main <1> (ready) 8 -1 1 1050359.631 1050359.631 1183469.202 #eb00ff 1.0 legion_python_main <1> 8 diff --git a/examples/testbench/decent_band/tsv/all (CPU)_util.tsv b/examples/testbench/decent_band/tsv/all (CPU)_util.tsv deleted file mode 100644 index 8d75fcdb6..000000000 --- a/examples/testbench/decent_band/tsv/all (CPU)_util.tsv +++ /dev/null @@ -1,288 +0,0 @@ -time count -0.000 0.00 -962689.824 0.50 -962698.725 0.00 -999427.832 0.50 -999433.367 0.00 -999530.605 0.50 -999537.468 0.00 -999566.582 0.50 -999574.512 0.00 -1019563.499 0.50 -1019569.168 0.00 -1019723.664 0.50 -1019734.354 0.00 -1019976.547 0.50 -1019982.927 0.00 -1020029.859 0.50 -1020035.992 0.00 -1020081.621 0.50 -1020088.315 0.00 -1020133.393 0.50 -1020140.003 0.00 -1020170.226 0.50 -1020176.043 0.00 -1020320.009 0.50 -1020320.096 1.00 -1020326.182 0.50 -1020326.371 0.00 -1020336.073 0.50 -1020344.812 0.00 -1020409.676 0.50 -1020415.356 0.00 -1020465.741 0.50 -1020471.704 0.00 -1020538.912 0.50 -1020544.913 0.00 -1020607.485 0.50 -1020618.851 0.00 -1020683.611 0.50 -1020698.885 1.00 -1020708.696 0.50 -1020718.044 1.00 -1020723.315 0.50 -1020728.635 1.00 -1020732.653 0.50 -1020812.834 1.00 -1020820.679 0.50 -1020841.769 1.00 -1020849.994 0.50 -1020859.100 1.00 -1022061.790 0.50 -1022107.376 1.00 -1022115.335 0.50 -1022125.977 1.00 -1022132.984 0.50 -1022141.854 1.00 -1022148.613 0.50 -1022155.102 1.00 -1022158.592 0.50 -1022164.775 1.00 -1022169.154 0.50 -1022175.085 1.00 -1022178.496 0.50 -1022184.906 1.00 -1022191.677 0.50 -1022198.572 1.00 -1022204.310 0.50 -1022210.953 1.00 -1022211.911 0.50 -1022214.923 0.00 -1022222.553 0.50 -1022227.962 0.00 -1022237.249 0.50 -1022245.039 0.00 -1022245.345 0.50 -1022259.076 1.00 -1023674.045 0.50 -1023674.774 0.00 -1023700.501 0.50 -1023714.788 1.00 -1024165.613 0.50 -1024175.988 0.00 -1024191.329 0.50 -1024212.470 1.00 -1025513.689 0.50 -1025523.689 0.00 -1025541.836 0.50 -1025553.734 1.00 -1025784.682 0.50 -1025793.359 0.00 -1025817.215 0.50 -1025825.619 1.00 -1025838.009 0.50 -1025857.809 1.00 -1027264.327 0.50 -1027267.987 0.00 -1027290.352 0.50 -1027298.588 1.00 -1027310.850 0.50 -1027340.279 1.00 -1028673.325 0.50 -1028683.215 0.00 -1028696.363 0.50 -1028702.589 0.00 -1043099.467 0.50 -1043105.925 0.00 -1043152.725 0.50 -1043162.570 0.00 -1043172.134 0.50 -1043175.780 0.00 -1043313.696 0.50 -1043321.599 0.00 -1043381.693 0.50 -1043389.858 0.00 -1043463.226 0.50 -1043469.407 0.00 -1043478.703 0.50 -1043483.955 0.00 -1043544.444 0.50 -1043550.837 0.00 -1043559.025 0.50 -1043565.584 0.00 -1043780.003 0.50 -1043793.581 0.00 -1043815.587 0.50 -1043823.752 0.00 -1043840.550 0.50 -1043845.419 0.00 -1043885.917 0.50 -1043891.674 1.00 -1043893.078 0.50 -1043899.319 1.00 -1043902.688 0.50 -1043932.016 1.00 -1044741.669 0.50 -1044772.977 1.00 -1044785.500 0.50 -1044786.018 0.00 -1044798.568 0.50 -1044804.821 0.00 -1044816.976 0.50 -1044818.895 1.00 -1044826.305 0.50 -1044832.900 1.00 -1044836.390 0.50 -1044841.026 1.00 -1044846.632 0.50 -1044853.660 1.00 -1044856.914 0.50 -1044903.140 1.00 -1045600.715 0.50 -1045633.063 1.00 -1045640.501 0.50 -1045658.078 1.00 -1045664.840 0.50 -1045674.697 1.00 -1045716.824 0.50 -1045749.414 1.00 -1045757.154 0.50 -1045767.502 1.00 -1045774.232 0.50 -1045783.097 1.00 -1046429.291 0.50 -1046459.143 1.00 -1046466.393 0.50 -1046474.283 1.00 -1046481.896 0.50 -1046509.517 1.00 -1046540.037 0.50 -1046615.744 1.00 -1047234.439 0.50 -1047255.694 1.00 -1047261.622 0.50 -1047267.900 1.00 -1047274.343 0.50 -1047281.641 1.00 -1047298.270 0.50 -1047306.163 1.00 -1047311.434 0.50 -1047316.397 1.00 -1047328.915 0.50 -1047333.748 1.00 -1047336.991 0.50 -1047402.303 0.00 -1047408.539 0.50 -1047414.776 0.00 -1047425.444 0.50 -1047428.177 1.00 -1047430.972 0.50 -1047435.591 0.00 -1047463.197 0.50 -1047485.607 1.00 -1047499.472 0.50 -1047509.224 1.00 -1047515.337 0.50 -1047551.395 1.00 -1047558.273 0.50 -1047583.009 1.00 -1047588.140 0.50 -1047610.844 1.00 -1047614.303 0.50 -1047619.993 1.00 -1047623.284 0.50 -1047656.279 1.00 -1048083.927 0.50 -1048208.167 1.00 -1048215.606 0.50 -1048245.381 1.00 -1048260.714 0.50 -1048281.052 0.00 -1048360.624 0.50 -1048368.336 0.00 -1048392.151 0.50 -1048397.420 0.00 -1048858.236 0.50 -1048865.054 0.00 -1048914.304 0.50 -1048919.582 0.00 -1048927.422 0.50 -1048933.418 0.00 -1183514.868 0.50 -1183526.003 0.00 -1183564.060 0.50 -1183571.389 0.00 -1183586.336 0.50 -1183593.882 0.00 -1183618.998 0.50 -1183627.204 0.00 -1183656.435 0.50 -1183662.395 0.00 -1183716.981 0.50 -1183722.963 0.00 -1183789.778 0.50 -1183796.240 0.00 -1183844.266 0.50 -1183850.453 0.00 -1183876.008 0.50 -1183881.779 0.00 -1183932.594 0.50 -1183961.777 0.00 -1183962.273 0.50 -1183969.461 0.00 -1183990.520 0.50 -1183995.478 0.00 -1184022.320 0.50 -1184027.253 0.00 -1184378.314 0.50 -1184386.071 0.00 -1184410.125 0.50 -1184416.531 0.00 -1184438.252 0.50 -1184446.042 0.00 -1184452.860 0.50 -1184456.362 0.00 -1184482.915 0.50 -1184489.625 0.00 -1184514.238 0.50 -1184519.942 0.00 -1184528.822 0.50 -1184533.676 0.00 -1184557.808 0.50 -1184562.356 0.00 -1184575.260 0.50 -1184578.768 0.00 -1184612.280 0.50 -1184619.851 0.00 -1184649.833 0.50 -1184656.431 0.00 -1184676.751 0.50 -1184683.603 0.00 -1184686.919 0.50 -1184705.292 0.00 -1184711.881 0.50 -1184716.235 1.00 -1184720.164 0.50 -1184722.729 0.00 -1184751.168 0.50 -1184757.069 0.00 -1184788.335 0.50 -1184793.531 0.00 -1184825.080 0.50 -1184831.298 0.00 -1184838.998 0.50 -1184845.978 0.00 -1184846.419 0.50 -1184853.601 0.00 -1184862.211 0.50 -1184865.981 0.00 diff --git a/examples/testbench/decent_band/tsv/all (Channel)_util.tsv b/examples/testbench/decent_band/tsv/all (Channel)_util.tsv deleted file mode 100644 index 308fc3280..000000000 --- a/examples/testbench/decent_band/tsv/all (Channel)_util.tsv +++ /dev/null @@ -1,4 +0,0 @@ -time count -0.000 0.00 -1048681.945 1.00 -1050273.272 0.00 diff --git a/examples/testbench/decent_band/tsv/all (Python)_util.tsv b/examples/testbench/decent_band/tsv/all (Python)_util.tsv deleted file mode 100644 index eb57e7853..000000000 --- a/examples/testbench/decent_band/tsv/all (Python)_util.tsv +++ /dev/null @@ -1,14 +0,0 @@ -time count -0.000 0.00 -478641.174 1.00 -922239.137 0.00 -922497.427 1.00 -922606.850 0.00 -922815.999 1.00 -962519.280 0.00 -962723.661 1.00 -1047360.569 0.00 -1048908.961 1.00 -1048924.893 0.00 -1050359.631 1.00 -1183469.202 0.00 diff --git a/examples/testbench/decent_band/tsv/all (System Memory)_util.tsv b/examples/testbench/decent_band/tsv/all (System Memory)_util.tsv deleted file mode 100644 index d2d9245bc..000000000 --- a/examples/testbench/decent_band/tsv/all (System Memory)_util.tsv +++ /dev/null @@ -1,24 +0,0 @@ -time count -0.000 0.00 -1020277.868 0.00 -1020517.864 0.00 -1021638.640 0.00 -1021896.476 0.00 -1022852.940 0.00 -1023094.891 0.00 -1024127.778 0.00 -1024326.370 0.00 -1025091.417 0.00 -1025243.869 0.00 -1048334.454 0.01 -1183909.479 0.01 -1183973.835 0.00 -1184355.765 0.00 -1184412.082 0.00 -1184466.441 0.00 -1184520.480 0.00 -1184563.664 0.00 -1184616.464 0.00 -1184671.451 0.00 -1184732.637 0.00 -1184825.486 0.00 diff --git a/examples/testbench/decent_band/tsv/all (Utility)_util.tsv b/examples/testbench/decent_band/tsv/all (Utility)_util.tsv deleted file mode 100644 index eb2ceb069..000000000 --- a/examples/testbench/decent_band/tsv/all (Utility)_util.tsv +++ /dev/null @@ -1,924 +0,0 @@ -time count -0.000 0.00 -478125.062 0.50 -478182.035 0.00 -478215.611 0.50 -478215.750 1.00 -478227.571 0.50 -478293.256 0.00 -478321.896 0.50 -478322.038 1.00 -478327.141 0.50 -478364.450 0.00 -478393.250 0.50 -478397.534 1.00 -478398.019 0.50 -478455.013 0.00 -478487.003 0.50 -478488.917 1.00 -478491.783 0.50 -478610.233 0.00 -478651.813 0.50 -478657.222 0.00 -922202.362 0.50 -922257.734 0.00 -922271.051 0.50 -922282.907 1.00 -922293.697 0.50 -922313.422 0.00 -922320.369 0.50 -922352.823 1.00 -922360.236 0.50 -922430.159 0.00 -922485.054 0.50 -922500.295 0.00 -922615.976 0.50 -922651.888 0.00 -922678.906 0.50 -922683.753 0.00 -922685.337 0.50 -922723.942 0.00 -922748.730 0.50 -922752.172 1.00 -922757.292 0.50 -922781.292 0.00 -922821.002 0.50 -922824.608 0.00 -962526.481 0.50 -962567.952 0.00 -962598.963 0.50 -962603.564 0.00 -962606.098 0.50 -962647.123 0.00 -962678.949 0.50 -962723.015 0.00 -962756.169 0.50 -962760.737 0.00 -999297.143 0.50 -999351.129 0.00 -999365.982 0.50 -999372.250 1.00 -999376.414 0.50 -999398.360 0.00 -999406.012 0.50 -999503.615 0.00 -999507.767 0.50 -999524.730 1.00 -999529.853 0.50 -999537.920 0.00 -999551.347 0.50 -999554.898 0.00 -1019311.922 0.50 -1019495.678 1.00 -1019495.815 0.50 -1019516.941 1.00 -1019521.801 0.50 -1019527.822 1.00 -1019531.556 0.50 -1019576.947 1.00 -1019579.130 0.50 -1019594.838 1.00 -1019598.189 0.50 -1019620.039 0.00 -1019628.570 0.50 -1019636.957 1.00 -1019640.979 0.50 -1019699.933 0.00 -1019714.252 0.50 -1019811.952 0.00 -1019827.080 0.50 -1019830.493 1.00 -1019834.164 0.50 -1019933.635 1.00 -1019950.329 0.50 -1019974.821 1.00 -1020004.219 0.50 -1020027.498 1.00 -1020060.964 0.50 -1020081.461 1.00 -1020099.613 0.50 -1020115.715 1.00 -1020149.907 0.50 -1020169.732 1.00 -1020198.015 0.50 -1020215.638 1.00 -1020251.160 0.50 -1020263.069 1.00 -1020281.769 0.50 -1020365.103 1.00 -1020389.610 0.50 -1020411.660 1.00 -1020446.324 0.50 -1020465.390 1.00 -1020580.691 0.50 -1020602.314 1.00 -1020623.469 0.50 -1020634.362 1.00 -1020671.314 0.50 -1020676.289 0.00 -1020691.218 0.50 -1020713.369 0.00 -1020722.173 0.50 -1020750.432 1.00 -1020787.419 0.50 -1020808.922 0.00 -1020810.229 0.50 -1020839.392 1.00 -1020846.307 0.50 -1020864.411 1.00 -1020874.211 0.50 -1020894.975 1.00 -1020913.363 0.50 -1020928.632 1.00 -1020930.984 0.50 -1020952.149 1.00 -1020985.345 0.50 -1020996.549 0.00 -1021013.914 0.50 -1021015.936 1.00 -1021039.622 0.50 -1021048.610 0.00 -1021058.657 0.50 -1021061.000 1.00 -1021089.194 0.50 -1021095.392 0.00 -1021103.473 0.50 -1021113.857 1.00 -1021142.700 0.50 -1021159.797 1.00 -1021175.820 0.50 -1021181.610 0.00 -1021196.702 0.50 -1021219.821 1.00 -1021266.724 0.50 -1021284.322 1.00 -1021292.380 0.50 -1021312.878 1.00 -1021325.094 0.50 -1021339.701 1.00 -1021358.196 0.50 -1021375.545 1.00 -1021396.717 0.50 -1021396.820 0.00 -1021416.548 0.50 -1021427.029 1.00 -1021465.556 0.50 -1021477.105 0.00 -1021485.938 0.50 -1021492.376 1.00 -1021517.858 0.50 -1021535.050 1.00 -1021563.059 0.50 -1021570.371 0.00 -1021585.593 0.50 -1021598.522 1.00 -1021633.743 0.50 -1021650.015 1.00 -1021708.350 0.50 -1021729.660 1.00 -1021748.943 0.50 -1021776.980 0.00 -1021799.332 0.50 -1021800.527 1.00 -1021831.515 0.50 -1021836.851 0.00 -1021856.216 0.50 -1021869.553 1.00 -1021890.510 0.50 -1021906.979 1.00 -1021935.187 0.50 -1021994.272 0.00 -1022016.171 0.50 -1022033.123 1.00 -1022036.573 0.50 -1022059.820 1.00 -1022077.471 0.50 -1022096.587 1.00 -1022115.674 0.50 -1022147.738 0.00 -1022149.566 0.50 -1022163.230 1.00 -1022191.124 0.50 -1022202.817 0.00 -1022220.315 0.50 -1022226.791 1.00 -1022257.425 0.50 -1022276.351 1.00 -1022306.819 0.50 -1022330.425 1.00 -1022345.941 0.50 -1022359.294 1.00 -1022392.149 0.50 -1022402.911 1.00 -1022420.902 0.50 -1022466.782 1.00 -1022494.632 0.50 -1022519.257 1.00 -1022522.165 0.50 -1022536.070 1.00 -1022545.038 0.50 -1022565.474 1.00 -1022572.262 0.50 -1022586.450 1.00 -1022614.121 0.50 -1022625.358 1.00 -1022643.447 0.50 -1022672.695 1.00 -1022681.509 0.50 -1022694.589 1.00 -1022708.855 0.50 -1022721.685 0.00 -1022729.096 0.50 -1022732.564 1.00 -1022761.644 0.50 -1022770.283 0.00 -1022792.567 0.50 -1022795.202 1.00 -1022828.127 0.50 -1022853.928 1.00 -1022898.698 0.50 -1022915.164 1.00 -1022928.362 0.50 -1022953.932 1.00 -1022971.622 0.50 -1022987.959 1.00 -1023010.260 0.50 -1023030.646 0.00 -1023050.877 0.50 -1023051.263 1.00 -1023065.156 0.50 -1023086.962 1.00 -1023113.349 0.50 -1023128.018 1.00 -1023140.111 0.50 -1023152.278 1.00 -1023157.689 0.50 -1023163.973 1.00 -1023168.055 0.50 -1023180.849 0.00 -1023197.049 0.50 -1023208.594 0.00 -1023217.702 0.50 -1023219.200 1.00 -1023224.712 0.50 -1023231.705 1.00 -1023236.361 0.50 -1023243.711 1.00 -1023248.462 0.50 -1023255.017 1.00 -1023259.870 0.50 -1023266.635 1.00 -1023271.371 0.50 -1023278.427 1.00 -1023287.444 0.50 -1023296.822 1.00 -1023297.512 0.50 -1023334.341 0.00 -1023345.970 0.50 -1023357.571 1.00 -1023364.867 0.50 -1023374.111 1.00 -1023376.256 0.50 -1023398.373 1.00 -1023403.459 0.50 -1023435.265 1.00 -1023447.377 0.50 -1023468.882 1.00 -1023524.215 0.50 -1023544.753 1.00 -1023551.388 0.50 -1023567.314 1.00 -1023593.726 0.50 -1023606.937 0.00 -1023608.446 0.50 -1023620.187 1.00 -1023665.627 0.50 -1023676.616 0.00 -1023685.236 0.50 -1023692.044 1.00 -1023718.305 0.50 -1023726.876 0.00 -1023741.592 0.50 -1023746.877 1.00 -1023765.560 0.50 -1023777.870 1.00 -1023800.215 0.50 -1023810.031 0.00 -1023813.667 0.50 -1023824.143 1.00 -1023831.242 0.50 -1023837.657 1.00 -1023842.050 0.50 -1023848.474 1.00 -1023855.887 0.50 -1023864.845 1.00 -1023869.083 0.50 -1023874.606 1.00 -1023879.071 0.50 -1023885.288 1.00 -1023886.789 0.50 -1023900.795 1.00 -1023904.789 0.50 -1023911.051 1.00 -1023919.322 0.50 -1023924.498 1.00 -1023978.079 0.50 -1023982.068 0.00 -1023994.093 0.50 -1024023.781 1.00 -1024050.003 0.50 -1024066.601 1.00 -1024067.567 0.50 -1024083.242 1.00 -1024112.260 0.50 -1024125.702 1.00 -1024142.386 0.50 -1024176.449 1.00 -1024187.245 0.50 -1024197.413 1.00 -1024204.799 0.50 -1024214.037 1.00 -1024298.425 0.50 -1024316.465 1.00 -1024327.960 0.50 -1024336.179 1.00 -1024341.424 0.50 -1024350.467 1.00 -1024359.821 0.50 -1024367.407 1.00 -1024372.548 0.50 -1024380.168 1.00 -1024385.425 0.50 -1024393.264 1.00 -1024397.528 0.50 -1024403.247 1.00 -1024409.951 0.50 -1024415.079 1.00 -1024418.409 0.50 -1024422.747 1.00 -1024425.896 0.50 -1024430.164 1.00 -1024433.324 0.50 -1024437.680 1.00 -1024440.818 0.50 -1024445.675 1.00 -1024450.251 0.50 -1024457.169 1.00 -1024462.152 0.50 -1024468.852 1.00 -1024473.600 0.50 -1024481.925 1.00 -1024488.279 0.50 -1024497.214 1.00 -1024532.506 0.50 -1024551.826 1.00 -1024557.161 0.50 -1024557.310 0.00 -1024564.753 0.50 -1024569.824 0.00 -1024577.086 0.50 -1024582.272 0.00 -1024585.057 0.50 -1024590.350 0.00 -1024597.545 0.50 -1024601.896 0.00 -1024604.599 0.50 -1024607.410 1.00 -1024610.839 0.50 -1024615.132 1.00 -1024619.071 0.50 -1024623.671 1.00 -1024626.791 0.50 -1024631.171 1.00 -1024634.661 0.50 -1024639.219 1.00 -1024642.520 0.50 -1024647.137 1.00 -1024653.786 0.50 -1024658.361 1.00 -1024661.720 0.50 -1024666.000 1.00 -1024669.305 0.50 -1024674.022 1.00 -1024677.281 0.50 -1024682.524 1.00 -1024686.570 0.50 -1024691.334 1.00 -1024694.870 0.50 -1024701.141 1.00 -1024710.027 0.50 -1024725.666 0.00 -1024736.750 0.50 -1024738.342 1.00 -1024762.023 0.50 -1024774.483 1.00 -1024779.744 0.50 -1024804.740 1.00 -1024816.493 0.50 -1024826.612 1.00 -1024833.728 0.50 -1024836.925 0.00 -1024843.783 0.50 -1024849.380 1.00 -1024856.773 0.50 -1024862.364 1.00 -1024865.775 0.50 -1024870.158 1.00 -1024873.470 0.50 -1024878.042 1.00 -1024882.017 0.50 -1024887.041 1.00 -1024891.672 0.50 -1024896.902 1.00 -1024934.671 0.50 -1024954.495 0.00 -1024959.693 0.50 -1024968.486 1.00 -1025006.101 0.50 -1025019.490 1.00 -1025036.615 0.50 -1025052.455 1.00 -1025062.406 0.50 -1025084.356 1.00 -1025136.235 0.50 -1025163.800 1.00 -1025193.188 0.50 -1025214.680 1.00 -1025220.882 0.50 -1025229.189 1.00 -1025233.988 0.50 -1025241.497 1.00 -1025247.221 0.50 -1025257.689 1.00 -1025263.857 0.50 -1025270.770 1.00 -1025275.650 0.50 -1025283.515 1.00 -1025288.725 0.50 -1025296.185 1.00 -1025301.041 0.50 -1025308.726 1.00 -1025315.060 0.50 -1025322.404 1.00 -1025328.213 0.50 -1025336.959 1.00 -1025342.196 0.50 -1025359.303 1.00 -1025364.244 0.50 -1025370.767 1.00 -1025375.170 0.50 -1025381.120 1.00 -1025382.984 0.50 -1025385.474 0.00 -1025391.182 0.50 -1025394.660 0.00 -1025399.314 0.50 -1025402.789 0.00 -1025408.650 0.50 -1025411.987 0.00 -1025424.161 0.50 -1025425.162 1.00 -1025483.181 0.50 -1025498.175 1.00 -1025513.498 0.50 -1025527.688 0.00 -1025539.025 0.50 -1025543.882 1.00 -1025548.382 0.50 -1025558.764 1.00 -1025586.146 0.50 -1025602.869 0.00 -1025611.427 0.50 -1025614.838 1.00 -1025619.617 0.50 -1025622.226 0.00 -1025625.266 0.50 -1025628.726 0.00 -1025633.859 0.50 -1025638.213 1.00 -1025642.194 0.50 -1025647.842 1.00 -1025647.947 0.50 -1025652.082 0.00 -1025656.285 0.50 -1025662.911 0.00 -1025663.084 0.50 -1025668.053 1.00 -1025672.011 0.50 -1025676.517 0.00 -1025677.535 0.50 -1025681.288 0.00 -1025685.439 0.50 -1025689.447 0.00 -1025693.048 0.50 -1025695.077 1.00 -1025699.308 0.50 -1025703.809 0.00 -1025704.517 0.50 -1025708.414 0.00 -1025714.241 0.50 -1025718.680 0.00 -1025721.602 0.50 -1025724.009 1.00 -1025728.305 0.50 -1025731.260 0.00 -1025733.660 0.50 -1025737.322 0.00 -1025743.220 0.50 -1025746.411 1.00 -1025749.866 0.50 -1025755.473 1.00 -1025757.279 0.50 -1025761.694 0.00 -1025766.641 0.50 -1025770.104 1.00 -1025773.447 0.50 -1025779.732 1.00 -1025781.733 0.50 -1025784.983 0.00 -1025792.915 0.50 -1025793.659 1.00 -1025799.588 0.50 -1025800.787 0.00 -1025805.808 0.50 -1025809.659 1.00 -1025811.421 0.50 -1025816.652 0.00 -1025817.749 0.50 -1025826.110 0.00 -1025827.856 0.50 -1025879.400 0.00 -1025906.153 0.50 -1025912.069 0.00 -1027308.633 0.50 -1027310.719 1.00 -1027329.152 0.50 -1027395.869 0.00 -1027416.270 0.50 -1027421.057 0.00 -1028703.178 0.50 -1028712.514 0.00 -1028717.674 0.50 -1028780.475 0.00 -1028818.229 0.50 -1028823.793 0.00 -1042970.205 0.50 -1043065.662 0.00 -1043079.828 0.50 -1043116.150 0.00 -1043117.747 0.50 -1043158.329 0.00 -1043182.818 0.50 -1043276.396 0.00 -1043292.115 0.50 -1043357.314 0.00 -1043363.999 0.50 -1043380.714 1.00 -1043439.363 0.50 -1043456.611 0.00 -1043462.537 0.50 -1043480.043 1.00 -1043521.460 0.50 -1043527.246 0.00 -1043539.388 0.50 -1043543.456 1.00 -1043569.949 0.50 -1043608.194 1.00 -1043755.669 0.50 -1043775.142 0.00 -1043798.301 0.50 -1043801.712 1.00 -1043819.547 0.50 -1043843.446 1.00 -1043856.144 0.50 -1043873.303 0.00 -1043892.005 0.50 -1043895.364 1.00 -1043927.706 0.50 -1043943.742 1.00 -1043944.189 0.50 -1043966.030 0.00 -1043975.777 0.50 -1043979.505 1.00 -1043984.049 0.50 -1043989.105 1.00 -1043993.343 0.50 -1043997.722 1.00 -1044001.005 0.50 -1044064.430 0.00 -1044073.642 0.50 -1044089.069 1.00 -1044098.310 0.50 -1044226.567 0.00 -1044226.872 0.50 -1044247.954 1.00 -1044259.135 0.50 -1044300.172 1.00 -1044329.824 0.50 -1044354.406 1.00 -1044386.707 0.50 -1044410.934 1.00 -1044445.597 0.50 -1044466.872 1.00 -1044480.531 0.50 -1044499.704 1.00 -1044567.279 0.50 -1044587.570 0.00 -1044589.211 0.50 -1044610.308 1.00 -1044652.525 0.50 -1044661.375 0.00 -1044673.215 0.50 -1044681.828 1.00 -1044694.814 0.50 -1044708.340 1.00 -1044713.469 0.50 -1044720.801 1.00 -1044725.565 0.50 -1044733.154 1.00 -1044739.424 0.50 -1044748.470 1.00 -1044753.463 0.50 -1044761.516 1.00 -1044767.193 0.50 -1044780.080 1.00 -1044784.929 0.50 -1044820.621 1.00 -1044825.226 0.50 -1044846.453 1.00 -1044894.401 0.50 -1044900.995 0.00 -1044914.641 0.50 -1044917.922 1.00 -1044921.456 0.50 -1044926.303 1.00 -1044929.620 0.50 -1044956.768 1.00 -1044957.622 0.50 -1044977.578 1.00 -1044983.228 0.50 -1045043.456 0.00 -1045056.568 0.50 -1045063.383 1.00 -1045069.759 0.50 -1045129.604 1.00 -1045161.665 0.50 -1045193.135 1.00 -1045222.693 0.50 -1045244.778 1.00 -1045294.673 0.50 -1045307.601 0.00 -1045319.687 0.50 -1045327.219 1.00 -1045373.960 0.50 -1045394.111 1.00 -1045447.100 0.50 -1045477.587 1.00 -1045506.945 0.50 -1045516.256 0.00 -1045530.483 0.50 -1045538.802 1.00 -1045572.715 0.50 -1045590.083 1.00 -1045596.571 0.50 -1045606.996 1.00 -1045613.389 0.50 -1045623.192 1.00 -1045627.364 0.50 -1045656.151 1.00 -1045675.044 0.50 -1045696.208 1.00 -1045698.593 0.50 -1045723.770 1.00 -1045730.321 0.50 -1045738.104 0.00 -1045740.255 0.50 -1045762.330 1.00 -1045816.314 0.50 -1045829.832 1.00 -1045834.051 0.50 -1045840.224 1.00 -1045845.981 0.50 -1045884.019 1.00 -1045890.352 0.50 -1045899.719 1.00 -1045917.954 0.50 -1045933.357 1.00 -1045982.091 0.50 -1045999.345 0.00 -1046021.175 0.50 -1046041.662 0.00 -1046056.676 0.50 -1046076.892 1.00 -1046091.530 0.50 -1046099.419 1.00 -1046104.230 0.50 -1046111.528 1.00 -1046117.513 0.50 -1046126.367 1.00 -1046135.932 0.50 -1046171.137 1.00 -1046202.563 0.50 -1046217.381 1.00 -1046250.716 0.50 -1046253.709 0.00 -1046267.074 0.50 -1046278.030 1.00 -1046314.988 0.50 -1046339.475 1.00 -1046346.238 0.50 -1046347.300 0.00 -1046356.442 0.50 -1046361.479 1.00 -1046366.368 0.50 -1046371.169 1.00 -1046376.461 0.50 -1046382.603 1.00 -1046386.495 0.50 -1046392.676 1.00 -1046393.607 0.50 -1046397.357 0.00 -1046403.160 0.50 -1046406.375 0.00 -1046413.126 0.50 -1046413.696 1.00 -1046417.530 0.50 -1046420.873 0.00 -1046424.509 0.50 -1046430.009 0.00 -1046432.425 0.50 -1046436.284 1.00 -1046440.982 0.50 -1046441.751 0.00 -1046446.383 0.50 -1046451.457 0.00 -1046452.072 0.50 -1046458.827 0.00 -1046460.896 0.50 -1046470.788 1.00 -1046477.290 0.50 -1046505.755 0.00 -1046529.968 0.50 -1046535.783 0.00 -1046561.498 0.50 -1046574.575 0.00 -1046575.458 0.50 -1046629.117 1.00 -1046632.653 0.50 -1046651.407 1.00 -1046656.178 0.50 -1046661.879 1.00 -1046686.301 0.50 -1046714.430 1.00 -1046725.278 0.50 -1046731.836 0.00 -1046740.944 0.50 -1046745.147 1.00 -1046745.264 0.50 -1046777.346 0.00 -1046791.619 0.50 -1046792.290 1.00 -1046796.714 0.50 -1046847.610 0.00 -1046858.968 0.50 -1046861.463 1.00 -1046865.754 0.50 -1046953.784 0.00 -1046963.523 0.50 -1046968.448 1.00 -1046972.915 0.50 -1047041.315 1.00 -1047045.904 0.50 -1047060.705 1.00 -1047095.389 0.50 -1047157.403 1.00 -1047168.964 0.50 -1047183.873 0.00 -1047197.484 0.50 -1047219.317 1.00 -1047280.431 0.50 -1047296.481 0.00 -1047308.491 0.50 -1047326.874 1.00 -1047380.812 0.50 -1047384.780 0.00 -1047402.395 0.50 -1047409.220 1.00 -1047457.574 0.50 -1047465.051 0.00 -1047478.032 0.50 -1047485.106 1.00 -1047513.167 0.50 -1047531.411 1.00 -1047559.608 0.50 -1047579.867 1.00 -1047591.084 0.50 -1047600.351 0.00 -1047606.599 0.50 -1047617.954 1.00 -1047648.258 0.50 -1047652.121 0.00 -1047667.464 0.50 -1047704.246 1.00 -1047714.252 0.50 -1047727.631 1.00 -1047733.357 0.50 -1047743.823 1.00 -1047767.970 0.50 -1047866.075 1.00 -1047885.816 0.50 -1047892.303 0.00 -1048028.782 0.50 -1048046.924 0.00 -1048073.019 0.50 -1048079.943 0.00 -1048089.840 0.50 -1048102.683 0.00 -1048111.659 0.50 -1048120.678 0.00 -1048129.055 0.50 -1048135.725 1.00 -1048178.094 0.50 -1048202.620 1.00 -1048208.721 0.50 -1048233.751 0.00 -1048240.244 0.50 -1048253.255 1.00 -1048259.273 0.50 -1048303.934 1.00 -1048310.306 0.50 -1048319.181 1.00 -1048367.651 0.50 -1048535.478 1.00 -1048541.225 0.50 -1048570.806 1.00 -1048584.206 0.50 -1048804.548 0.00 -1048841.090 0.50 -1048854.074 1.00 -1048881.903 0.50 -1048904.134 0.00 -1050297.761 0.50 -1050298.787 1.00 -1050315.697 0.50 -1050316.398 0.00 -1144670.598 0.50 -1144703.476 0.00 -1144732.332 0.50 -1144738.433 0.00 -1144879.567 0.50 -1144915.226 0.00 -1144943.824 0.50 -1144961.684 0.00 -1144974.220 0.50 -1144991.831 0.00 -1145003.814 0.50 -1145008.939 0.00 -1145013.909 0.50 -1145017.309 0.00 -1145021.935 0.50 -1145025.293 0.00 -1183447.115 0.50 -1183505.306 1.00 -1183539.347 0.50 -1183556.775 0.00 -1183567.025 0.50 -1183584.044 1.00 -1183592.790 0.50 -1183620.810 1.00 -1183632.883 0.50 -1183682.119 1.00 -1183686.977 0.50 -1183740.807 1.00 -1183767.389 0.50 -1183786.910 1.00 -1183824.028 0.50 -1183846.435 1.00 -1183856.010 0.50 -1183875.602 1.00 -1183938.722 0.50 -1183966.177 1.00 -1183997.470 0.50 -1184344.122 1.00 -1184386.204 0.50 -1184404.214 1.00 -1184437.440 0.50 -1184459.636 1.00 -1184492.880 0.50 -1184513.128 1.00 -1184539.716 0.50 -1184556.087 1.00 -1184588.795 0.50 -1184610.581 1.00 -1184645.091 0.50 -1184665.321 1.00 -1184688.358 0.50 -1184692.744 0.00 -1184717.064 0.50 -1184721.421 1.00 -1184764.287 0.50 -1184788.784 1.00 -1184801.507 0.50 -1184810.844 0.00 -1184818.629 0.50 -1184847.345 0.00 diff --git a/examples/testbench/event_graph_legion_python_main_1.pdf b/examples/testbench/event_graph_legion_python_main_1.pdf deleted file mode 100644 index d90eedb33ee10433f47317a54fa9ae92f6148cf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25345 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 WjUAoOEdm1N<>w=0Vv<&oA^bnr2%($+ diff --git a/examples/testbench/go.sh b/examples/testbench/go.sh deleted file mode 100644 index e851f13d0..000000000 --- a/examples/testbench/go.sh +++ /dev/null @@ -1,15 +0,0 @@ -rm -rf prof* -rm -rf spy* -rm -rf legion_prof* -#prof -../../../legate.core/install/bin/legate --cpus 1 test.py -lg:prof 1 -lg:prof_logfile prof_%.gz - -#spy -../../../legate.core/install/bin/legate --cpus 1 test.py -lg:spy -logfile spy_%.log -../../../legate.core/legion/tools/legion_spy.py -dez spy_*.log - -#both -../../../legate.core/legion/tools/legion_prof.py prof_*.gz spy_*.log -cp dataflow_legion_python* legion_prof/ -cp event_graph_legion_python* legion_prof/ -echo "done" diff --git a/examples/testbench/good_band/dataflow_legion_python_main_1.pdf b/examples/testbench/good_band/dataflow_legion_python_main_1.pdf deleted file mode 100644 index 26c905f13c9399024e89ed427c01a5865fa7f38f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31522 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 diff --git a/examples/testbench/good_band/event_graph_legion_python_main_1.pdf b/examples/testbench/good_band/event_graph_legion_python_main_1.pdf deleted file mode 100644 index 08c5b7d64537c700fd23892164e97f23506cc063..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27545 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 - - - - - - - - - - - - - - - - - - -
-
Node Range: :
-
- - -
-
-
-
-
-
- - diff --git a/examples/testbench/good_band/js/timeline.js b/examples/testbench/good_band/js/timeline.js deleted file mode 100644 index ba3db5e30..000000000 --- a/examples/testbench/good_band/js/timeline.js +++ /dev/null @@ -1,2734 +0,0 @@ -// Some of the constants are read in from load_scale_json -var constants = { - margin_left: 350, - margin_right: 75, - margin_bottom: 50, - margin_top: 50, - min_feature_width: 3, - min_gap_width: 1, - util_height: 100, - util_levels: 4, - elem_separation: 2, -} - -var op_dependencies = {}; -var base_map = {}; -var prof_uid_map = {}; - -// Contains the children for each util file -var util_files = {}; - -var state = {}; -var mouseX = 0; -var utilline = d3.svg.line() - .interpolate("step-after") - .x(function(d) { return state.x(+d.time); }) - .y(function(d) { return state.y(+d.count); }); -var timeBisector = d3.bisector(function(d) { return d.time; }).left; -// const num_colors = 20; -// var color = d3.scale.linear() -// .domain([0, num_colors]) -// .range(["green", "blue", "red", "yellow"]); - -String.prototype.hashCode = function() { - var hash = 0; - if (this.length == 0) return hash; - for (i = 0; i < this.length; i++) { - var c = this.charCodeAt(i); - var b = this.charCodeAt(c % this.length); - hash = ((hash<<5)-hash)^c^b; - hash = hash & hash; - } - return Math.abs(hash); -} - -function parseURLParameters() { - var match, - pl = /\+/g, // Regex for replacing addition symbol with a space - search = /([^&=]+)=?([^&]*)/g, - decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, - query = window.location.search.substring(1); - - var urlParams = {}; - while (match = search.exec(query)) - urlParams[decode(match[1])] = decode(match[2]); - - if ("collapseAll" in urlParams) - state.collapseAll = (urlParams["collapseAll"].toLowerCase() === "true"); - - if ("resolution" in urlParams) - state.resolution = Math.max(1, parseFloat(urlParams["resolution"])); - // adjust zoom - var zstart = constants.start; - if ("start" in urlParams) - zstart = Math.max(constants.start, parseFloat(urlParams["start"])); - - var zend = constants.end; - if ("end" in urlParams) - zend = Math.min(constants.end, parseFloat(urlParams["end"])); - - if(zstart < zend) { - // set zoom to get: (zend - start) * zoom * scale = $("#timeline").width() - var newZoom = $("#timeline").width() / state.scale / (zend - zstart); - adjustZoom(newZoom, false); - - // set scrollLeft to get: zstart * zoom * state.scale = scrollLeft() - $("#timeline").scrollLeft(convertToPos(state, zstart)); - } - - if ("search" in urlParams) { - state.searchEnabled = true; - searchRegex = new Array(sizeHistory); - currentPos = 0; - nextPos = 1; - searchRegex[currentPos] = new RegExp(urlParams["search"]); - } -} - -function makeTimelineTransparent() { - state.timelineSvg.select("g#timeline").style("opacity", "0.1"); - $("#timeline").css("overflow-x", "hidden"); - state.timelineSvg.select("g#lines").style("opacity", "0.1"); - state.timelineSvg.select("g.locator").style("opacity", "0.1"); - state.timelineSvg.selectAll("path.util").style("opacity", "0.1"); -} - -function makeTimelineOpaque() { - state.timelineSvg.select("g#timeline").style("opacity", "1.0"); - $("#timeline").css("overflow-x", "scroll"); - state.timelineSvg.select("g#lines").style("opacity", "1.0"); - state.timelineSvg.select("g.locator").style("opacity", "1.0"); - state.timelineSvg.selectAll("path.util").style("opacity", "1.0"); -} - -function mouseMoveHandlerWhenDown() { - var p = d3.mouse(this); - var select_block = state.timelineSvg.select("rect.select-block"); - var select_text = state.timelineSvg.select("text.select-block"); - var newWidth = Math.abs(p[0] - mouseX); - select_block.attr("width", newWidth); - if (p[0] >= mouseX) { - select_block.attr("x", mouseX); - select_text.attr("x", mouseX + (p[0] - mouseX) / 2); - } else { - select_block.attr("x", p[0]); - select_text.attr("x", p[0] + (mouseX - p[0]) / 2); - } - var time = convertToTime(state, newWidth); - select_text.text(getTimeString(time, time)); -} - -function mouseMoveHandlerWhenUp() { - var p = d3.mouse(this); - var x = parseFloat(p[0]); - var scrollLeft = $("#timeline").scrollLeft(); - var paneWidth = $("#timeline").width(); - var currentTime = convertToTime(state, x); - - state.timelineSvg.select("g.locator").remove(); - var locator = state.timelineSvg.append("g").attr("class", "locator"); - locator.insert("line") - .attr({ - x1: p[0], - y1: 0, - x2: p[0], - y2: p[1] - state.thickness / 2, - class: "locator", - }); - locator.append("line") - .attr({ - x1: p[0], - y1: p[1] + state.thickness / 2, - x2: p[0], - y2: state.height, - class: "locator", - }); - var locatorText = locator.append("text"); - var text = getTimeString(currentTime, convertToTime(state, paneWidth)); - locatorText.attr("class", "locator").text(text) - if ((x - scrollLeft) < paneWidth - 100) { - locatorText.attr({x: x + 2, y: $(window).scrollTop() + 10}); - locatorText.attr("anchor", "start"); - } - else { - locatorText.attr({x: x - 2 - text.length * 7, y: $(window).scrollTop() + 10}); - locatorText.attr("anchor", "end"); - } -} - -function mouseDownHandler() { - state.timelineSvg.select("g.locator").remove(); - var p = d3.mouse(this); - state.timelineSvg.append("rect") - .attr({ - x : p[0], - y : 0, - class : "select-block", - width : 0, - height : state.height - }); - state.timelineSvg.append("text") - .attr({ - x : p[0], - y : p[1], - class : "select-block", - anchor : "middle", - "text-anchor" : "middle", - }).text("0 us"); - mouseX = p[0]; - state.timelineSvg.on("mousemove", null); - state.timelineSvg.on("mousemove", mouseMoveHandlerWhenDown); - $(document).off("keydown"); -} - -function get_kind(name) { - var util_regex = /\((.*?)\)/; - var kind_match = util_regex.exec(name); - if (kind_match) { - return kind_match[1]; - } -} - -function getLineColor(elem) { - var kind = get_kind(elem.text); - const colorMap = { - "CPU": "steelblue", - "GPU": "olivedrab", - "Utility": "crimson", - "IO": "orangered", - "Proc Group": "orangered", - "Proc Set": "orangered", - "OpenMP": "orangered", - "Python": "olivedrab", - "System Memory": "olivedrab", - "GASNet Global Memory": "crimson", - "Registered Memory": "darkmagenta", - "Socket Memory": "orangered", - "Zero-Copy Memory": "crimson", - "Framebuffer Memory": "blue", - "Disk Memory": "darkgoldenrod", - "HDF5 Memory": "olivedrab", - "File Memory": "orangered", - "L3 Cache Memory": "crimson", - "L2 Cache Memory": "darkmagenta", - "L1 Cache Memory": "olivedrab", - "Channel": "orangered" - }; - return colorMap[kind]; -} - -function drawUtil() { - // TODO: Add to state - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - var start_time = convertToTime(state, windowStart); - var end_time = convertToTime(state, windowEnd); - var filteredUtilData = []; - for (var i = 0; i < state.flattenedLayoutData.length; i++) { - var elem = state.flattenedLayoutData[i]; - if (elem.type == "util" && elem.enabled && elem.loaded && elem.visible) { - filteredUtilData.push(filterUtilData(elem)); - } - } - - state.x = d3.scale.linear().range([0, convertToPos(state, end_time)]); - state.x.domain([0, end_time]); - state.timelineSvg.selectAll("rect.util").remove(); - state.timelineSvg.selectAll("path.util").remove(); - var paths = state.timelineSvg.selectAll("path") - .data(filteredUtilData); - var totalWidth = windowStart + $("#timeline").width(); - paths.enter().append("rect") - .attr("class", "util") - .attr("base_y", lineLevelCalculator) - .attr("y", lineLevelCalculator) - .attr("x", 0) - .attr("fill", "transparent") - .attr("width", totalWidth) - .attr("height", constants.util_levels * state.thickness) - .on("mouseover", mouseover) - .on("mousemove", mousemove) - .on("mouseout", function() { - state.timelineSvg.select("g.focus").remove(); - state.timelineSvg.select("g.utilDesc").remove(); - }); - paths.enter().append("path") - .attr("base_y", lineLevelCalculator) - .attr("class", "util") - .attr("id", function(d, i) { return "util" + i}) - .attr("d", function (d) { return utilline(d.data); }) - .attr("stroke", getLineColor) - .on("mouseover", mouseover) - .on("mousemove", mousemove) - .on("mouseout", function() { - state.timelineSvg.select("g.focus").remove(); - state.timelineSvg.select("g.utilDesc").remove(); - }) - .attr("transform", - function(d) { - var y = lineLevelCalculator(d); - return "translate(0," + y + ")" - }); -} - - -function mouseUpHandler() { - var p = d3.mouse(this); - var select_block = state.timelineSvg.select("rect.select-block"); - var prevZoom = state.zoom; - var selectWidth = parseInt(select_block.attr("width")); - var svgWidth = state.timelineSvg.attr("width"); - if (state.rangeZoom && selectWidth > 10) { - var x = select_block.attr("x"); - state.zoomHistory.push({zoom: prevZoom, start: $("#timeline").scrollLeft()}); - adjustZoom(svgWidth / selectWidth, false); - $("#timeline").scrollLeft(x / prevZoom * state.zoom); - } - - state.timelineSvg.selectAll("rect.select-block").remove(); - state.timelineSvg.selectAll("text.select-block").remove(); - mouseX = 0; - state.timelineSvg.on("mousemove", null); - state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); - $(document).on("keydown", defaultKeydown); -} - -function turnOffMouseHandlers() { - state.timelineSvg.on("mousedown", null); - state.timelineSvg.on("mouseup", null); - state.timelineSvg.on("mousemove", null); - state.timelineSvg.on("mousemove", null); - // prevent right-click menu - state.timelineSvg.on("contextmenu", function () { - d3.event.preventDefault(); - }); -} - -function turnOnMouseHandlers() { - state.timelineSvg.on("mousedown", mouseDownHandler); - state.timelineSvg.on("mouseup", mouseUpHandler); - state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); - // prevent right-click menu - state.timelineSvg.on("contextmenu", function () { - d3.event.preventDefault(); - }); -} - -function drawLoaderIcon() { - var loaderGroup = state.loaderSvg.append("g") - .attr({ - id: "loader-icon", - }); - loaderGroup.append("path") - .attr({ - opacity: 0.2, - stroke: "steelblue", - fill: "#000", - d: "M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z" - }); - var path = loaderGroup.append("path") - .attr({ - stroke: "steelblue", - fill: "#000", - d: "M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0C22.32,8.481,24.301,9.057,26.013,10.047z" - }); - path.append("animateTransform") - .attr({ - attributeType: "xml", - attributeName: "transform", - type: "rotate", - from: "0 20 20", - to: "360 20 20", - dur: "0.5s", - repeatCount: "indefinite" - }); - state.loaderSvg.select("g").attr("visibility", "hidden"); - state.loaderSvg.attr("width", "0px") - .attr("height", "0px"); -} - -function showLoaderIcon() { - state.numLoading++; - state.loaderSvg.select("g").attr("visibility", "visible"); - state.loaderSvg.attr("width", "40px") - .attr("height", "40px"); -} - -function hideLoaderIcon() { - state.numLoading--; - if (state.numLoading == 0) { - state.loaderSvg.select("g").attr("visibility", "hidden"); - state.loaderSvg.attr("width", "0px") - .attr("height", "0px"); -; - } -} - -function get_time_str(time_val, convert) -{ - if (convert) { - if (time_val >= 1000000) { - var val = time_val/1000000; - val = parseFloat(val.toFixed(3)) - return val.toString() + " sec"; - } - if (time_val >= 1000) { - var val = time_val/1000; - val = parseFloat(val.toFixed(3)) - return val.toString() + " ms"; - } - } - return time_val.toString() + " us"; -} - -function getMouseOver() { - var paneWidth = $("#timeline").width(); - var left = paneWidth / 3; - var right = paneWidth * 2 / 3; - return function(d, i) { - var p = d3.mouse(this); - var x = parseFloat(p[0]); - var y = timelineLevelCalculator(d) - 5; - var descView = state.timelineSvg.append("g") - .attr("id", "desc"); - var text = descView.append("text") - .attr("x", x) - .attr("y", y) - .attr("class", "desc"); - var depElem = prof_uid_map[d.prof_uid][0]; - if ((depElem.in.length != 0) || (depElem.out.length != 0) || - (depElem.children.length !== 0) || (depElem.parents.length !==0 )) { - d3.select(this).style("cursor", "pointer"); - } - // descTexts is an array of Texts we will store in the desc view - var descTexts = []; - var total = d.end - d.start; - var delay = d.start - d.ready; - total = parseFloat(total.toFixed(3)) - delay = parseFloat(delay.toFixed(3)) - var initiation = ""; - // Insert texts in reverse order - if ((d.ready != undefined) && (d.ready != "") && (delay != 0)) { - descTexts.push("Ready State: " + get_time_str(delay,false)); - } - descTexts.push("End: " + get_time_str(d.end, false)); - descTexts.push("Start: " + get_time_str(d.start, false)); - descTexts.push("Total: " + get_time_str(total, true)); - if ((d.initiation != undefined) && d.initiation != "") { - descTexts.push("Initiator: " + state.operations[d.initiation].desc); - } - - // split d.title - var titles = d.title.split("$"); - if (titles.length > 0) { - for (var i = titles.length-1; i >= 0; --i) { - descTexts.push(titles[i]); - } - } - var title = text.append("tspan") - .attr("x", x) - .attr("dy", -12) - .attr("class", "desc") - .text(descTexts[0].replace(/ /g, "\u00A0")); // preserve spacing - - for (var i = 1; i < descTexts.length; ++i) { - var elem = text.append("tspan") - .attr("x", x) - .attr("dy", -12) - .attr("class", "desc") - .text(descTexts[i].replace(/ /g, "\u00A0")); // preserve spacing - } - - var bbox = descView.node().getBBox(); - var padding = 2; - var rect = descView.insert("rect", "text") - .attr("x", bbox.x - 2*padding) - .attr("y", bbox.y - padding) - .attr("width", bbox.width + (padding*4)) - .attr("height", bbox.height + (padding*2)) - .style("fill", "#222") - .style("opacity", "0.7"); - - var bboxRight = bbox.x + bbox.width; - var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); - - // If the box moves off the screen, nudge it back - if (bboxRight > timelineRight) { - var translation = -(bboxRight - timelineRight + 20); - descView.attr("transform", "translate(" + translation + ",0)"); - } - }; -} - -var sizeHistory = 10; -var currentPos; -var nextPos; -var searchRegex = null; - -function showSlider() { - $('#lowerLimit').text($('#node_slider').slider("values", 0)); - $('#upperLimit').text($('#node_slider').slider("values", 1)); -} - -function createMenuList1() { - var memory_kinds = []; - var num_nodes = state.num_nodes; - var num_mems = 0; - var dropdown_options = [ - { value: "ready", - id: "ready_all", - text: "View", - count: 1, - low_range: 0, - high_range: 1 - }, - { value: "memories", - id: "memories_all", - text: "Memories", - count: num_mems, - low_range: 0, - high_range: num_mems -1 - } - ]; - - // memories list - dropdown_options_memories = []; - - // misc items list - var pkind = { - id: "rr", - value: "rdy", - count: 1, - low_range: 0, - high_range: 1, - text: "Ready State" - }; - - dropdown_options_misc = []; - dropdown_options_misc.push(pkind); - - // create the remaining entries - function appendKind(elem) { - var value = state.processor_kinds[elem]; - if (elem.includes("Memory") && (value.count >= 0)) - { - num_mems = num_mems+1; - dropdown_options_memories.push(value); - } - if ((value.count >= 0) && (value.low_range != -1)) { - dropdown_options.push(value); - } - } - Object.keys(state.processor_kinds).forEach(appendKind); - - // main menu - d3.select("#dropdown").selectAll("optgroup") - .data(dropdown_options) - .enter() - .append("optgroup") - .attr('label', function(d) { return d.text;}) - .attr("id", function(d) { return d.id;}) - .attr("value", function(d) { return d.value;}); - - for (var j=0; j val)) - kind_proc.low_range = val; - if (kind_proc.high_range < val) - kind_proc.high_range = val; - } - } - } - - // Util graphs will have processors as their children as well. - if (type == "util") { - // get the children for the util view - var proc_children = getProcessors(text); - var count = 1; - var node_id = get_node_id(text); - var kind = get_kind(text); - // add to processor kinds: union of all processor kinds - if (!(kind in state.processor_kinds)) { - var pkind = { - id: kind, - value: kind, - count: proc_children.length, - low_range: -1, - high_range: -1, - text: kind - }; - state.processor_kinds[kind] = pkind; - } - if (state.processor_kinds[kind].count < proc_children.length) - state.processor_kinds[kind].count = proc_children.length; - - proc_children.forEach(function(proc_child) { - var child_element = getElement(depth + 1, proc_child.text, - proc_child.full_text, "proc", - proc_child.height, load_proc_timeline, - proc_child.tsv, element, undefined, - true, false); - element.children.push(child_element); - }); - } - - return element; -} - - -function calculateLayout() { - - // First element in the layout will be the all_util. All first-level - // elements will start off not enabled, and will be uncollapsed later - // programmatically - var num_nodes = Object.keys(util_files).length; - if (num_nodes > 1) { - var proc_kinds = util_files["all"]; - proc_kinds.forEach(function(name) { - var kind = "(" + get_kind(name) + ")"; - var util_name = "all nodes " + kind; - var kind_element = getElement(0, util_name, undefined, "util", - constants.util_levels, load_util, - "tsv/" + name + "_util.tsv", - undefined, util_files[kind], false, true); - state.layoutData.push(kind_element); - }); - } - - var seen_nodes = []; - state.processors.forEach(function(proc) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - var proc_regex = /(Processor|Memory) 0x1(e|d)([a-fA-f0-9]{4})[a-fA-f0-9]{10}$/; - // Memory Channel - var proc_channel_regex = /(Memory) 0x1(e)([a-fA-f0-9]{4})[a-fA-f0-9]{10}.*Channel/; - var proc_channel_match = proc_channel_regex.exec(proc.full_text); - var proc_match = proc_regex.exec(proc.full_text); - proc_match = proc_match || proc_channel_match; - if (proc_match) { - var node_id = parseInt(proc_match[3], 16); - if (!(node_id in seen_nodes)) { - seen_nodes[node_id] = 1; - if (node_id in util_files) { - var proc_kinds = util_files[node_id]; - proc_kinds.forEach(function(kind) { - var util_name = "node " + kind; - var kind_element = getElement(0, util_name, undefined, "util", - constants.util_levels, load_util, - "tsv/" + kind + "_util.tsv", - undefined, util_files[kind], - false, true); - state.layoutData.push(kind_element); - }); - } - } - } - else { - state.layoutData.push(getElement(0, proc.text, proc.full_text, "proc", - proc.height, load_proc_timeline, - proc.tsv, undefined, undefined, - false, true)); - } - }); - state.num_nodes = seen_nodes.length; -} - -function getElemCoords(elems) { - var proc = elems[0].proc; - var level = elems[0].level; - var startX = convertToPos(state, elems[0].start); - var endX = convertToPos(state, elems[elems.length-1].end); - var endBase = +proc.base; - var endLevel = endBase + level; - var y = dependencyLineLevelCalculator(endLevel); - return {startX: startX, endX: endX, y: y}; -} - - -function addLine(group, x1, x2, y1, y2, color, dashed) { - var line; - if (dashed) { - line = group.append("line") - .attr("x1", x1) - .attr("y1", y1) - .attr("x2", x2) - .attr("y2", y2) - .style("stroke", color) - .style("stroke-dasharray", "3,3") - .style("stroke-width", "1px"); - } else { - line = group.append("line") - .attr("x1", x1) - .attr("y1", y1) - .attr("x2", x2) - .attr("y2", y2) - .style("stroke", color) - .style("stroke-width", "1px"); - } - - var slope = (y2 - y1) / (x2 - x1); - var intercept = y1 - (slope * x1); - var triangleRotation = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI - 90; - - group.append("line") - .attr("x1", x1) - .attr("y1", y1) - .attr("x2", x2) - .attr("y2", y2) - .style("stroke", "transparent") - .style("stroke-width", "20px") - .on("mouseover", function() { - group.append("g") - .attr("class", "marker") - .append("path") - .attr("d", d3.svg.symbol().type("triangle-down").size(20)) - .style("stroke", color) - .style("fill", color); - }) - .on("mousemove", function() { - var marker = group.select("g.marker"); - var px = d3.mouse(this)[0] - 10; - var py = d3.mouse(this)[1] - ((slope > 0 ? 1 : -1) * 20); - if (px < Math.min(x1, x2)) { - px += 20; - } - if (py < Math.min(y1, y2)) { - py += 40; - } - - // some linear algebra here - var cx = (slope * py + px - slope * intercept) / (slope * slope + 1); - var cy = (slope * slope * py + slope * px + intercept) / (slope * slope + 1); - - marker.attr("transform", "translate(" + cx + "," + cy + ") rotate(" + triangleRotation + ")"); - }) - .on("mouseout", function() { - group.select("g.marker").remove(); - }); - - group.append("circle") - .attr("cx", x1) - .attr("cy", y1) - .attr("fill", "white") - .attr("stroke", "black") - .attr("r", 2.5) - .style("stroke-width", "1px"); - - group.append("circle") - .attr("cx", x2) - .attr("cy", y2) - .attr("fill", "white") - .attr("stroke", "black") - .attr("r", 2.5) - .style("stroke-width", "1px"); -} - - -function drawCriticalPath() { - state.timelineSvg.selectAll("g.critical_path_lines").remove(); - if (state.critical_path == undefined || !state.display_critical_path) { - return; - } - var depGroup = state.timelineSvg.append("g") - .attr("class", "critical_path_lines"); - state.critical_path.forEach(function(op) { - var proc = base_map[op[0] + "," + op[1]]; // set in calculateBases - if (proc != undefined && proc.visible && proc.enabled && proc.loaded && proc.selected) { - var elems = prof_uid_map[op[2]]; - if (elems != undefined) { - var coords = getElemCoords(elems) - var startX = coords.startX; - var endX = coords.endX; - var y = coords.y; - elems[0].out.forEach(function(dep) { - if (dep[2] in state.critical_path_prof_uids) { - var depElems = prof_uid_map[dep[2]]; - if (depElems != undefined) { - var depProc = depElems[0].proc; - // is the proc visible? - if (depProc.visible && depProc.enabled && depProc.loaded) { - var depCoords = getElemCoords(depElems); - var depX = depCoords.endX; - var depY = depCoords.y; - addLine(depGroup, depX, startX, depY, y, "grey", false); - } - } - } - }); - // Draw parent-child lines - var lastChildCoords = undefined; - var firstChildCoords = undefined; - elems[0].children.forEach(function(child) { - if (child[2] in state.critical_path_prof_uids) { - var childElems = prof_uid_map[child[2]]; - var childCoords = getElemCoords(childElems); - if (childElems !== undefined) { - if (lastChildCoords === undefined || - childCoords.startX > lastChildCoords.startX) { - lastChildCoords = childCoords; - } - if (firstChildCoords === undefined || - childCoords.endX < firstChildCoords.endX) { - firstChildCoords = childCoords; - } - } - } - }); - if (firstChildCoords !== undefined) { - addLine(depGroup, startX, firstChildCoords.startX, - y, firstChildCoords.y, "grey", true); - } - if (lastChildCoords !== undefined) { - addLine(depGroup, lastChildCoords.endX, endX, - lastChildCoords.y, y, "grey", true); - } - } - } - }); -} - -function drawDependencies() { - state.timelineSvg.select("g.dependencies").remove(); - var timelineEvent = state.dependencyEvent; - if (timelineEvent == undefined || - !timelineEvent.proc.visible || !timelineEvent.proc.enabled) { - return; // don't draw in this case, the src isn't present - } - var srcElems = prof_uid_map[timelineEvent.prof_uid]; - timelineEvent = srcElems[0]; // only the first elem will have deps and children - var srcCoords = getElemCoords(srcElems); - var srcStartX = srcCoords.startX; - var srcEndX = srcCoords.endX; - var srcY = srcCoords.y; - var depGroup = state.timelineSvg.append("g") - .attr("class", "dependencies"); - - var addDependency = function(dep, dir, dashed) { - var depProc = base_map[dep[0] + "," + dep[1]]; // set in calculateBases - if (depProc.visible && depProc.enabled && depProc.selected) { - var depElems = prof_uid_map[dep[2]]; - if (depElems != undefined) { - console.log(dir); - var depCoords = getElemCoords(depElems); - var dstY = depCoords.y; - if (dir === "in") { - addLine(depGroup, srcEndX, depCoords.startX, srcY, dstY, "black", dashed); - } else if (dir === "out") { - addLine(depGroup, depCoords.endX, srcStartX, dstY, srcY, "black", dashed); - } else if (dir === "parent") { - addLine(depGroup, depCoords.startX, srcStartX, dstY, srcY, "black", dashed); - addLine(depGroup, srcEndX, depCoords.endX, srcY, dstY, "black", dashed); - } else if (dir === "child") { - addLine(depGroup, srcStartX, depCoords.startX, srcY, dstY, "black", dashed); - addLine(depGroup, depCoords.endX, srcEndX, dstY, srcY, "black", dashed); - } - - } - } - } - - if (state.drawDeps) { - timelineEvent.in.forEach(function(dep) {addDependency(dep, "in", false)}); - timelineEvent.out.forEach(function(dep) {addDependency(dep, "out", false)}); - } - if (state.drawChildren) { - timelineEvent.parents.forEach(function(dep) {addDependency(dep, "parent", true)}); - timelineEvent.children.forEach(function(dep) {addDependency(dep, "child", true)}); - } -} - -function timelineEventsExistAndEqual(a, b) { - if (a == undefined || b == undefined) { - return false; - } - return (a.proc.base == b.proc.base) && (a.prof_uid == b.prof_uid); -} - -function timelineElementStrokeCalculator(elem) { - if (timelineEventsExistAndEqual(elem, state.dependencyEvent)) { - return true; - } else if (state.display_critical_path && - elem.prof_uid in state.critical_path_prof_uids) { - return true; - } - return false; -} - -function timelineEventMouseDown(_timelineEvent) { - // only the first event of this uid will have information - var timelineEvent = prof_uid_map[_timelineEvent.prof_uid][0]; - var hasDependencies = ((timelineEvent.in.length != 0) || - (timelineEvent.out.length != 0)); - - if (hasDependencies) { - if (timelineEventsExistAndEqual(timelineEvent, state.dependencyEvent)) { - if (d3.event.button === 0) { - state.drawDeps = !state.drawDeps; - } else if (d3.event.button === 2) { - state.drawChildren = !state.drawChildren; - } - if (state.drawDeps === false && state.drawChildren === false) { - state.dependencyEvent = undefined; - } - } else { - timelineEvent.in.concat(timelineEvent.out).forEach(function(dep) { - expandByNodeProc(dep[0], dep[1]) - }); - state.dependencyEvent = timelineEvent; - if (d3.event.button === 0) { - state.drawDeps = true; - } else if (d3.event.button === 2) { - state.drawChildren = true; - } - } - redraw(); - } -} - -function drawTimeline() { - showLoaderIcon() - - updateURL(state.zoom, state.scale); - var timelineGroup = state.timelineSvg.select("g#timeline"); - timelineGroup.selectAll("rect").remove(); - timelineGroup.selectAll("text").remove(); - var timeline = timelineGroup.selectAll("rect") - .data(state.dataToDraw, function(d) { return d.proc.base + "-" + d.id; }); - var timelineText = timelineGroup.selectAll("text") - .data(state.memoryTexts); - var mouseOver = getMouseOver(); - - timeline.enter().append("rect"); - - timeline - .attr("id", function(d) { return "block-" + d.proc.base + "-" + d.id; }) - .attr("x", function(d) { return convertToPos(state, d.start); }) - .attr("y", timelineLevelCalculator) - .style("fill", function(d) { - if (!state.searchEnabled || - searchRegex[currentPos].exec(d.title) == null) - return d.color; - else return "#ff0000"; - }) - .attr("width", function(d) { - return Math.max(constants.min_feature_width, convertToPos(state, d.end - d.start)); - }) - .attr("stroke", function(d) { - if (timelineElementStrokeCalculator(d)) { - return "red"; - } else { - return "black"; - } - }) - .attr("stroke-width", function(d) { - if (timelineElementStrokeCalculator(d)) { - return "1.5"; - } else { - return "0.5"; - } - }) - .attr("height", state.thickness) - .style("opacity", function(d) { - if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) != null || searchRegex[currentPos].exec(d.initiation) != null) { - return d.opacity; - } - else return 0.05; - }) - .on("mouseout", function(d, i) { - if ((d.in.length != 0) || (d.out.length != 0)) { - d3.select(this).style("cursor", "default"); - } - state.timelineSvg.selectAll("#desc").remove(); - }) - .on("mousedown", timelineEventMouseDown) - - - timelineText.enter().append("text"); - - timelineText - .attr("class", "timeline") - .attr("y", timelineTextLevelCalculator) - .attr("text-anchor", "start") - .text(function(d) { - var sizeRegex = /Size=(.*)/; - var match = sizeRegex.exec(d.title); - return match[1]; - }) - .attr("visibility", function(d) { - var textWidth = this.getComputedTextLength(); - var startX = convertToPos(state, d.start); - var endX = convertToPos(state, d.end); - var boxWidth = endX - startX; - return boxWidth > textWidth ? "visible" : "hidden"; - }) - .attr("x", function(d) { - var textWidth = this.getComputedTextLength(); - var midPoint = convertToPos(state, d.start + (d.end - d.start) / 2); - midPoint -= textWidth / 2; - return midPoint - }); - - drawUtil(); - timeline.on("mouseover", mouseOver); - timeline.exit().remove(); - hideLoaderIcon(); -} - -function redraw() { - if (state.numLoading == 0) { - calculateBases(); - filterAndMergeBlocks(state); - constants.max_level = calculateVisibileLevels(); - recalculateHeight(); - drawTimeline(); - drawDependencies(); - drawCriticalPath(); - drawLayout(); - } -} - -function calculateVisibileLevels() { - var levels = 0; - state.flattenedLayoutData.forEach(function(elem) { - if (elem.visible) { - if (elem.enabled) { - if (state.ready_selected && elem.num_levels_ready != undefined) - levels += elem.num_levels_ready; - else - levels += elem.num_levels; - } - levels += constants.elem_separation; - } - }); - return levels; -} - -function is_proc(proc) { - // the full text of this proc should start with 0x1d to be a processor - return /0x1d/.exec(proc.full_text) !== undefined; -} - -function is_proc_string(text) -{ - return /0x1d/.exec(text) != undefined; -} - -function is_mem_string(text) { - return /0x1e/.exec(text) != undefined; -} - -function get_node_val(text) { - var match = /\d+/.exec(text); - if (match) { - var val = parseInt(text.match(/\d+/)); - return val; - } - return match; -} - -function get_node_id(text) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - var proc_regex = /(Memory|Processor) 0x1(e|d)([a-fA-f0-9]{4})/; - var proc_match = proc_regex.exec(text); - // if there's only one node, then per-node graphs are redundant - if (proc_match) { - var node_id = parseInt(proc_match[3], 16); - return node_id - } -} - -function get_proc_in_node(text) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - var proc_regex = /Processor 0x1d[a-fA-f0-9]{11}([a-fA-f0-9]{3})/; - var proc_match = proc_regex.exec(text); - // if there's only one node, then per-node graphs are redundant - if (proc_match) { - var proc_in_node = parseInt(proc_match[1], 16); - return proc_in_node; - } -} - -function calculateBases() { - var base = 0; - state.flattenedLayoutData.forEach(function(elem) { - elem.base = base; - var node_id = get_node_id(elem.full_text); - var proc_in_node = get_proc_in_node(elem.full_text); - if (node_id != undefined && proc_in_node != undefined) { - base_map[(+node_id) + "," + (+proc_in_node)] = elem; - } - if (elem.visible) { - if (elem.enabled) { - if (state.ready_selected && elem.num_levels_ready != undefined) - base += elem.num_levels_ready; - else - base += elem.num_levels; - } - base += constants.elem_separation; - } - }); -} - -function expandHandler(elem, index) { - elem.expanded = !elem.expanded; - - if (elem.expanded) { - function expandChild(child) { - child.visible = true; - //child.enabled = true; - if(!child.loaded) { - showLoaderIcon(); - child.loader(child); // will redraw the timeline once loaded - } else if (child.expanded) { - child.children.forEach(expandChild); - } - } - elem.children.forEach(expandChild); - } else { - function collapseChildren(child) { - child.visible = false; - child.children.forEach(collapseChildren); - } - elem.children.forEach(collapseChildren); - } - redraw(); -} - -// This handler is called when you collapse/uncollapse a row in the -// timeline -function collapseHandler(d, index) { - d.enabled = !d.enabled; - - if (!d.loaded) { - // should always be expanding here - showLoaderIcon(); - //var elem = state.flattenedLayoutData[index]; - d.loader(d); // will redraw the timeline once loaded - } else { - redraw(); - } -} - -// This expands a particular element and its parents if necessary -function expandElementAndParents(elem) { - if (elem !== undefined) { - var elemPath = []; // path up to parent - var curElem = elem; - while (curElem != undefined) { - elemPath.push(curElem); - curElem = curElem.parent; - } - - for (var i = elemPath.length - 1; i >= 0; --i) { - var elem = elemPath[i]; - if (!elem.expanded) { - expandHandler(elem); - } - // uncollapse if necessary - if ((i == 0) && !elem.enabled) { - collapseHandler(elem); - } - } - } -} - - -function expandByNodeProc(node, proc) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - // ugh why isn't there string formatting - var nodeHex = ("0000" + node.toString(16)).slice(-4); - var procHex = ("000" + proc.toString(16)).slice(-3); - var expectedTitle = "0x1d" + nodeHex + "0000000" + procHex; - var matchedElement = undefined; - for (var i = 0; i < state.flattenedLayoutData.length; i++) { - var timelineElement = state.flattenedLayoutData[i]; - if ((timelineElement.full_text != undefined) && - (timelineElement.full_text.indexOf(expectedTitle) !=-1)) { - matchedElement = timelineElement; - break; - } - } - expandElementAndParents(matchedElement) -} - - -function lineLevelCalculator(timelineElement) { - var level = timelineElement.base + 1; - if (timelineElement.enabled) { - if (state.ready_selected && timelineElement.num_levels_ready != undefined) - level += timelineElement.num_levels_ready; - else - level += timelineElement.num_levels; - } - return constants.margin_top + level * state.thickness; -}; - -function utilLevelCalculator(timelineElement) { - var level = timelineElement.base; - if (timelineElement.enabled) { - if (state.ready_selected && timelineElement.num_levels_ready != undefined) - level += timeLineElement.num_levels_ready; - else - level += timeLineElement.num_levels; - } - return constants.margin_top + level * state.thickness; -}; - - -function timelineLevelCalculator(timelineEvent) { - return constants.margin_top + - (timelineEvent.proc.base + timelineEvent.level) * state.thickness; -}; - -function timelineTextLevelCalculator(timelineEvent) { - return constants.margin_top + - (timelineEvent.proc.base + timelineEvent.level + 0.75) * state.thickness; -}; - -function dependencyLineLevelCalculator(level) { - return constants.margin_top + ((level+0.5) * state.thickness); -} - -function drawLayout() { - d3.select("#processors").select("svg").remove(); - state.timelineSvg.select("g#lines").remove(); - - var data = state.flattenedLayoutData; - var svg = d3.select("#processors").append("svg") - .attr("width", constants.margin_left) - .attr("height", state.height); - - var namesGroup = svg.selectAll(".processors") - .data(data) - .enter().append("g"); - - var names = namesGroup.append("text"); - - var thickness = state.thickness; - var xCalculator = function(d) { return (d.depth + 1) * 15; }; - names.attr("text-anchor", "start") - .attr("class", "processor") - .text(function(d) { return d.text; }) - .attr("x", xCalculator) - .attr("y", lineLevelCalculator) - .attr("visibility", function(elem) { - return (elem.visible) ? "visible" : "hidden" - }) - .style("fill", "#000000") - .style("opacity", function(proc) { - return (proc.enabled) ? 1 : 0.5; - }); - - - // names.each(function(d) { - // var elem = d3.select(this); - // var text = d.text; - // var tokens = d.text.split(" to "); - // if (tokens.length == 1) - // elem.append("tspan").text(d.text); - // else { - // var source = tokens[0]; - // var target = tokens[1].replace(" Channel", ""); - // elem.append("tspan").text(source) - // .attr("x", xCalculator) - // .attr("dy", -10); - // elem.append("tspan").text("==> " + target) - // .attr("x", xCalculator) - // .attr("dy", 10); - // } - // }); - names.on({ - "mouseover": function(d) { - d3.select(this).style("cursor", "pointer") - if (d.full_text != undefined) { - var x = xCalculator(d); - var y = lineLevelCalculator(d) - state.thickness; - - var overlaySvg = d3.select("#overlay").append("svg"); - var descView = overlaySvg.append("g").attr("id", "desc"); - - var text = descView.append("text") - .attr("x", x) - .attr("y", y) - .attr("text-anchor", "start") - .attr("class", "desc") - .text(unescape(escape(d.full_text))); - - var bbox = text.node().getBBox(); - var padding = 2; - var rect = descView.insert("rect", "text") - .attr("x", bbox.x - padding) - .attr("y", bbox.y - padding) - .attr("width", bbox.width + (padding*2)) - .attr("height", bbox.height + (padding*2)) - .style("fill", "#222") - .style("opacity", "0.7"); - - overlaySvg.attr("width", bbox.x + bbox.width + (padding*2)) - .attr("height", bbox.y + bbox.height + (padding*2)); - } - }, - "mouseout": function(d) { - d3.select(this).style("cursor", "default") - if (d.full_text != undefined) { - d3.select("#overlay").selectAll("svg").remove(); - } - }, - "click": collapseHandler - }); - - var expandableNodes = namesGroup.filter(function(elem) { - return elem.children.length > 0; - }); - - var expand_group = expandableNodes.append("g"); - - var expand_clickable = expand_group.append("circle") - .attr("fill", "transparent") - .attr("stroke", "transparent") - .attr("r", 8); - var expand_icons = expand_group.append("path"); - var arc = d3.svg.symbol().type('triangle-down') - .size(12); - - - //.attr("transform", function(elem) { - // var x = constants.margin_left - 10; - // var y = lineLevelCalculator(elem); - // return "translate(" + x + "," + y + ")"; - //}) - expand_icons.attr("class", "processor") - .attr("d", arc) - .attr("visibility", function(elem) { - return (elem.visible) ? "visible" : "hidden" - }) - .style("fill", "#000000") - .style("stroke", "#000000") - .style("opacity", function(proc) { - return (proc.enabled) ? 1 : 0.5; - }); - - expand_group.each(function(elem) { - var path = d3.select(this); - var x = elem.depth * 15 + 5; - var y = lineLevelCalculator(elem) - 3; - - if (elem.expanded) { - path.attr("transform", "translate(" + x + ", " + y + ") rotate(0)"); - } else { - path.attr("transform", "translate(" + x + ", " + y + ") rotate(30)"); - } - - }); - - - expand_group.on({ - "mouseover": function(d) { - d3.select(this).style("cursor", "pointer") - }, - "mouseout": function(d) { - d3.select(this).style("cursor", "default") - }, - "click": expandHandler - }); - - - var lines = state.timelineSvg - .append("g") - .attr("id", "lines"); - - var thickness = state.thickness; - lines.selectAll(".lines") - .data(data) - .enter().append("line") - .attr("x1", 0) - .attr("y1", lineLevelCalculator) - .attr("x2", state.zoom * state.width) - .attr("y2", lineLevelCalculator) - .attr("visibility", function(elem) { - return (elem.visible) ? "visible" : "hidden" - }) - .style("stroke", "#000000") - .style("stroke-width", "2px") - .style("opacity", function(proc) { - return (proc.enabled) ? 1 : 0.5; - }); -} - -function drawHelpBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - - var helpBoxGroup = popUpSvg.append("g"); - var helpBoxWidth = Math.min(450, width - 100); - var helpTextOffset = 20; - var helpBoxHeight = Math.min(helpMessage.length * helpTextOffset + 100, - height - 100); - - var boxStartX = (width - helpBoxWidth) / 2; - var boxStartY = (height - helpBoxHeight) / 2; - - helpBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: helpBoxWidth, - height: helpBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var helpText = helpBoxGroup.append("text") - .attr("class", "help-box") - .style("width", helpBoxWidth); - var helpTitle = "Keyboard Shortcuts"; - helpText.append("tspan") - .attr({ x: boxStartX + helpBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text(helpTitle); - var off = 15; - for (var i = 0; i < helpMessage.length; ++i) { - helpText.append("tspan") - .style("font-size", "12pt") - .attr("text-anchor", "start") - .attr({ x: boxStartX + 30, dy: off + helpTextOffset}) - .text(helpMessage[i]); - off = 0; - } -} - -function evalExpandRequest(re) { - var re = new RegExp(re); - state.flattenedLayoutData.forEach(function(elem) { - if (re.exec(elem.text)) { - expandElementAndParents(elem); - } - }); - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); -} - -function drawExpandBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - var expandBoxGroup = popUpSvg.append("g"); - var expandBoxWidth = Math.min(450, width - 100); - var expandBoxHeight = Math.min(220, height - 100); - - var thicknessRatio = state.thickness / state.baseThickness; - var boxStartX = (width - expandBoxWidth) / 2; - var boxStartY = (height - expandBoxHeight) / 2; - - expandBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: expandBoxWidth, - height: expandBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var expandText = expandBoxGroup.append("text") - .attr("class", "expand-box") - .style("width", expandBoxWidth); - expandText.append("tspan") - .attr({ x: boxStartX + expandBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text("expand"); - var expandInputWidth = expandBoxWidth - 40; - var expandInputHeight = 50; - var expandInputStartY = 65; - - - expandBoxGroup.append("foreignObject") - .attr({ x: boxStartX + 20, y: boxStartY + expandInputStartY, - width: expandInputWidth, height: expandBoxHeight - expandInputStartY}) - .attr("text-anchor", "middle") - .html( - "" - + "
" - + "" - + "Presets" - + "" - + "
" - + "
" - + "" - + "" - + "" - + "" - + "" - + "" - + "
" - ); - $("input.expand-box").focus(); -} - -function drawSearchBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - var searchBoxGroup = popUpSvg.append("g"); - var searchBoxWidth = Math.min(450, width - 100); - var searchBoxHeight = Math.min(250, height - 100); - - var thicknessRatio = state.thickness / state.baseThickness; - var boxStartX = (width - searchBoxWidth) / 2; - var boxStartY = (height - searchBoxHeight) / 2; - - searchBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: searchBoxWidth, - height: searchBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var searchText = searchBoxGroup.append("text") - .attr("class", "search-box") - .style("width", searchBoxWidth); - searchText.append("tspan") - .attr({ x: boxStartX + searchBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text("Search"); - var searchInputWidth = searchBoxWidth - 40; - var searchInputHeight = 50; - searchBoxGroup.append("foreignObject") - .attr({ x: boxStartX + 20, y: boxStartY + 150, - width: searchInputWidth, height: searchInputHeight}) - .attr("text-anchor", "middle") - .html(""); - $("input.search-box").focus(); -} - -function drawSearchHistoryBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - - var historyBoxGroup = popUpSvg.append("g"); - var historyBoxWidth = Math.min(450, width - 100); - var historyBoxHeight = Math.min(350, height - 100); - - var boxStartX = (width - historyBoxWidth) / 2; - var boxStartY = (height - historyBoxHeight) / 2; - - historyBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: historyBoxWidth, - height: historyBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var historyText = historyBoxGroup.append("text") - .attr("class", "history-box") - .style("width", historyBoxWidth); - var historyTitle = "Search History"; - historyText.append("tspan") - .attr({ x: boxStartX + historyBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text(historyTitle); - if (searchRegex != null) { - var off = 15; - var id = 1; - for (var i = 0; i < sizeHistory; ++i) { - var pos = (nextPos + i) % sizeHistory; - var regex = searchRegex[pos]; - if (regex != null) { - if (pos == currentPos) prefix = ">>> "; - else prefix = id + " : "; - historyText.append("tspan") - .attr("text-anchor", "start") - .attr({ x: boxStartX + 30, dy: off + 25}) - .text(prefix + regex.source); - off = 0; - id++; - } - } - } -} - -function updateURL() { - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - var start_time = convertToTime(state, windowStart); - var end_time = convertToTime(state, windowEnd); - var url = window.location.href.split('?')[0]; - url += "?start=" + start_time; - url += "&end=" + end_time; - url += "&collapseAll=" + state.collapseAll; - url += "&resolution=" + state.resolution; - if (state.searchEnabled) - url += "&search=" + searchRegex[currentPos].source; - window.history.replaceState("", "", url); -} - -function adjustZoom(newZoom, scroll) { - var prevZoom = state.zoom; - state.zoom = Math.round(newZoom * 10) / 10; - - var svg = d3.select("#timeline").select("svg"); - - svg.attr("width", state.zoom * state.width) - .attr("height", state.height); - - var timelineGroup = svg.select("g#timeline"); - //timelineGroup.selectAll("rect").remove(); - - svg.select("g#lines").selectAll("line") - .attr("x2", state.zoom * state.width); - svg.selectAll("#desc").remove(); - svg.selectAll("g.locator").remove(); - d3.select("#overlay").selectAll("svg").remove(); - - if (scroll) { - var paneWidth = $("#timeline").width(); - var pos = ($("#timeline").scrollLeft() + paneWidth / 2) / prevZoom; - // this will trigger a scroll event which in turn redraws the timeline - $("#timeline").scrollLeft(pos * state.zoom - state.width / 2); - } else { - filterAndMergeBlocks(state); - drawTimeline(); - } - drawDependencies(); - drawCriticalPath(); -} - -function recalculateHeight() { - // adjust the height based on the new thickness and max level - state.height = constants.margin_top + constants.margin_bottom + - (state.thickness * constants.max_level); - var util_height = constants.util_levels * state.thickness; - state.y = d3.scale.linear().range([util_height, 0]); - state.y.domain([0, 1]); - - d3.select("#processors").select("svg").remove(); - var svg = d3.select("#timeline").select("svg"); - svg.attr("width", state.zoom * state.width) - .attr("height", state.height); - var lines = state.timelineSvg.select("g#lines"); - lines.remove(); - - svg.selectAll("#desc").remove(); - svg.selectAll("g.locator").remove(); - d3.select("#overlay").selectAll("svg").remove(); - -} - -function adjustThickness(newThickness) { - state.thickness = newThickness; - recalculateHeight(); - drawTimeline(); - drawLayout(); -} - -function suppressdefault(e) { - if (e.preventDefault) e.preventDefault(); - if (e.stopPropagation) e.stopPropagation(); -} - -function setKeyHandler(handler) { - $(document).off("keydown"); - $(document).on("keydown", handler); -} - -function makeModalKeyHandler(validKeys, callback) { - return function(e) { - if (!e) e = event; - var code = e.keyCode || e.charCode; - if (!(e.ctrlKey || e.metaKey || e.altKey)) { - for (var i = 0; i < validKeys.length; ++i) { - if (keys[code] == validKeys[i]) { - callback(keys[code]); - return false; - } - } - } - return true; - } -} - -function displayPopUp() { - d3.select("#pop-up").append("svg") - .attr("width", $(window).width()) - .attr("height", $(window).height()); -} - -function removePopUp() { - var popUpSvg = d3.select("#pop-up").selectAll("svg").remove(); -} - - -function defaultKeydown(e) { - if (!e) e = event; - - var code = e.keyCode || e.charCode; - var commandType = Command.none; - var modifier = e.ctrlKey || e.metaKey || e.altKey; - var multiFnKeys = e.metaKey && e.ctrlKey || e.altKey && e.ctrlKey; - - var translatedCode = keys[code]; - - if (!modifier) { - commandType = noModifierCommands[translatedCode]; - } else if (!multiFnKeys) { - commandType = modifierCommands[translatedCode]; - } else { - commandType = multipleModifierCommands[translatedCode]; - } - - if (commandType == undefined) { - if (e.metaKey || e.altKey) - state.rangeZoom = false; - return true; - } - - suppressdefault(e); - if (commandType == Command.help) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - // make help box visible - displayPopUp(); - drawHelpBox(); - setKeyHandler(makeModalKeyHandler(['/', 'esc'], function(key) { - // make help box invisible - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - else if (commandType == Command.search) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - displayPopUp(); - drawSearchBox(); - setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { - if (key == 'enter') { - var re = $("input.search-box").val(); - if (re.trim() != "") { - if (searchRegex == null) { - searchRegex = new Array(sizeHistory); - currentPos = -1; - nextPos = 0; - } - currentPos = nextPos; - nextPos = (nextPos + 1) % sizeHistory; - searchRegex[currentPos] = new RegExp(re); - state.searchEnabled = true; - } - } - removePopUp(); - if (state.searchEnabled) { - filterAndMergeBlocks(state); - drawTimeline(); - } - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - else if (commandType == Command.expand) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - displayPopUp(); - drawExpandBox(); - setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { - if (key == 'enter') { - var re = $("input.expand-box").val(); - if (re.trim() != "") { - re = new RegExp(re); - state.flattenedLayoutData.forEach(function(elem) { - if (re.exec(elem.text)) { - expandElementAndParents(elem); - } - }); - } - } - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - else if (commandType == Command.search_history) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - displayPopUp(); - drawSearchHistoryBox(); - setKeyHandler(makeModalKeyHandler(['h', 'esc'], function(key) { - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - - if (commandType == Command.zix) { - var inc = 4.0; - adjustZoom(state.zoom + inc, true); - } else if (commandType == Command.zox) { - var dec = 4.0; - if (state.zoom - dec > 0) - adjustZoom(state.zoom - dec, true); - } else if (commandType == Command.zrx) { - state.zoomHistory = Array(); - adjustZoom(1.0, false); - $("#timeline").scrollLeft(0); - } else if (commandType == Command.zux) { - if (state.zoomHistory.length > 0) { - var previousZoomHistory = state.zoomHistory.pop(); - adjustZoom(previousZoomHistory.zoom, false); - $("#timeline").scrollLeft(previousZoomHistory.start); - } - } else if (commandType == Command.ziy) - adjustThickness(state.thickness * 2); - else if (commandType == Command.zoy) - adjustThickness(state.thickness / 2); - else if (commandType == Command.zry) { - state.height = $(window).height() - constants.margin_bottom - constants.margin_top; - state.thickness = state.height / constants.max_level; - adjustThickness(state.thickness); - } - else if (commandType == Command.clear_search) { - state.searchEnabled = false; - searchRegex = null; - filterAndMergeBlocks(state); - drawTimeline(); - } - else if (commandType == Command.toggle_search) { - if (searchRegex != null) { - state.searchEnabled = !state.searchEnabled; - filterAndMergeBlocks(state); - drawTimeline(); - } - } - else if (commandType == Command.previous_search || - commandType == Command.next_search) { - if (state.searchEnabled) { - var pos = commandType == Command.previous_search ? - (currentPos - 1 + sizeHistory) % sizeHistory : - (currentPos + 1) % sizeHistory; - var sentinel = commandType == Command.previous_search ? - (nextPos - 1 + sizeHistory) % sizeHistory : nextPos; - if (pos != sentinel && searchRegex[pos] != null) { - currentPos = pos; - filterAndMergeBlocks(state); - drawTimeline(); - } - } - } - else if (commandType == Command.toggle_critical_path) { - state.display_critical_path = !state.display_critical_path; - if (state.display_critical_path) { - state.critical_path.forEach(function(op) { - expandByNodeProc(op[0], op[1]); - }); - } - redraw(); - } - return false; -} - -function defaultKeyUp(e) { - if (!e) e = event; - if (!(e.metaKey || e.altKey)) { - state.rangeZoom = true; - } - return true; -} - -function load_proc_timeline(proc) { - var proc_name = proc.full_text; - state.processorData[proc_name] = {}; - var num_levels_ready = proc.num_levels; - if (state.ready_selected) { - proc.num_levels_ready = proc.num_levels; - } - d3.tsv(proc.tsv, - function(d, i) { - var level = +d.level; - var ready = +d.ready; - var start = +d.start; - var end = +d.end; - var level_ready = +d.level_ready; - var total = end - start; - var _in = d.in === "" ? [] : JSON.parse(d.in) - var out = d.out === "" ? [] : JSON.parse(d.out) - var children = d.children === "" ? [] : JSON.parse(d.children) - var parents = d.parents === "" ? [] : JSON.parse(d.parents) - if (total > state.resolution) { - return { - id: i, - level: level, - level_ready: level_ready, - ready: ready, - start: start, - end: end, - color: d.color, - opacity: d.opacity, - initiation: d.initiation, - title: d.title, - in: _in, - out: out, - children: children, - parents: parents, - prof_uid: d.prof_uid, - proc: proc - }; - } - }, - function(data) { - var num_levels_ready=0 - // split profiling items by which level they're on - for(var i = 0; i < data.length; i++) { - var d = data[i]; - var level_sel=d.level; - if (level_sel in state.processorData[proc_name]) { - state.processorData[proc_name][level_sel].push(d); - } else { - state.processorData[proc_name][level_sel] = [d]; - } - if ((d.level_ready != undefined) && (d.level_ready != 0) && - num_levels_ready < d.level_ready) - num_levels_ready = d.level_ready; - - if (d.prof_uid != undefined && d.prof_uid !== "") { - if (d.prof_uid in prof_uid_map) { - prof_uid_map[d.prof_uid].push(d); - } else { - prof_uid_map[d.prof_uid] = [d]; - } - } - } - if (num_levels_ready > proc.num_levels) - proc.num_levels_ready = num_levels_ready; - else - proc.num_levels_ready = proc.num_levels; - proc.loaded = true; - hideLoaderIcon(); - redraw(); - } - ); -} - -function initTimelineElements() { - var timelineGroup = state.timelineSvg.append("g") - .attr("id", "timeline"); - - $("#timeline").scrollLeft(0); - parseURLParameters(); - - var windowCenterY = $(window).height() / 2; - $(window).scroll(function() { - $("#loader-icon").css("top", $(window).scrollTop() + windowCenterY); - $("#pop-up").css("top", $(window).scrollTop()); - }); - - // set scroll callback - var timer = null; - $("#timeline").scroll(function() { - if (timer !== null) { - clearTimeout(timer); - } - timer = setTimeout(function() { - filterAndMergeBlocks(state); - drawTimeline(); - }, 100); - }); - if (!state.collapseAll) { - // initially load in all the cpu processors and the "all util" - var util_regex = /node/; - for (var i = 0; i < state.flattenedLayoutData.length; i++) { - var timelineElement = state.flattenedLayoutData[i]; - if (timelineElement.type == "util" && - util_regex.exec(timelineElement.text) && - timelineElement.depth == 0) { - collapseHandler(timelineElement, i); - } - } - } - turnOnMouseHandlers(); -} - - -function load_ops_and_timeline() { - d3.tsv("legion_prof_ops.tsv", // TODO: move to tsv folder - function(d) { - return d; - }, - function(data) { - data.forEach(function(d) { - state.operations[parseInt(d.op_id)] = d; - }); - // initTimelineElements depends on the ops to be loaded - initTimelineElements(); - } - ); -} - -function load_procs(callback) { - d3.tsv('legion_prof_processor.tsv', - function(d) { - return { - full_text: d.full_text, - text: d.text, - height: +d.levels, - tsv: d.tsv - }; - }, - function(data) { - var prevEnd = 0; - var base = 0; - data.forEach(function(proc) { - proc.enabled = false; - proc.loaded = false; - proc.base = base; - - base += 2; - }); - state.processors = data; - calculateLayout(); - - // flatten the layout and get the new calculated max num levels - flattenLayout(); - calculateBases(); - drawLayout(); - createMenuList1(); - callback(); - - // TODO: fix - load_critical_path(); - } - ); -} - -function getMinElement(arr, mapF) { - if (arr.length === undefined || arr.length == 0) { - throw "invalid array: " + arr; - } - var minElement = arr[0]; - if (mapF === undefined) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] < minElement) { - minElement = arr[i]; - } - } - } else { - minValue = mapF(minElement); - for (var i = 1; i < arr.length; i++) { - var elem = arr[i]; - var value = mapF(elem); - if (value < minValue) { - minElement = elem; - minValue = value; - } - } - } - return minElement; -} - -function filterUtilData(timelineElem) { - var data = state.utilData[timelineElem.tsv]; // TODO: attach to object - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - var start_time = convertToTime(state, windowStart - 100); - var end_time = convertToTime(state, windowEnd + 100); - - var startIndex = timeBisector(data, start_time); - var endIndex = timeBisector(data, end_time); - - startIndex = Math.max(0, startIndex - 1); - endIndex = Math.min(data.length, endIndex + 2); - var length = endIndex - startIndex; - var newData = Array(); - // we will average points together if they are too close together - var resolution = 1; // 3 pixel resolution - var elem = {time: 0, count: 0}; - var startTime = data[startIndex].time; - var startX = convertToPos(state, startTime); - var endTime = 0; - - for (var i = startIndex; i < endIndex - 1; i++) { - endTime = data[i+1].time; - elem.count += data[i].count * (endTime - data[i].time); - //elem.time += data[i].time; - var endX = convertToPos(state, endTime); - if ((endX - startX) >= resolution || i == (endIndex - 2)) { - var totalTime = endTime - startTime; - elem.count /= totalTime; - //avgElem.time /= windowSize; - elem.time = startTime; - newData.push(elem); - elem = {time: 0, count: 0}; - startX = endX; - startTime = endTime; - } - } - - newData.push({time: endTime, count:0}); - - return { - text: timelineElem.text, - base: timelineElem.base, - num_levels: timelineElem.num_levels, - num_levels_ready: timelineElem.num_levels_ready, - data: newData - }; -} - -function mouseover() { - var focus = state.timelineSvg.append("g") - .attr("class", "focus"); - - focus.append("circle") - .attr("fill", "none") - .attr("stroke", "black") - .attr("r", 4.5); - - var utilDescView = state.timelineSvg.append("g") - .attr("class", "utilDesc"); - utilDescView.append("text") - .attr("x", 7) - .attr("y", -4.5) - .attr("class", "desc") - .attr("dy", ".35em"); - utilDescView.insert("rect", "text") - .style("fill", "#222") - .style("opacity", "0.7"); -} - -function mousemove(d, i) { - var line = document.getElementById("util" + i); - - // offset for this particular line grapgh - var base_y = +line.getAttribute("base_y"); - var px = d3.mouse(line)[0]; - var py = d3.mouse(line)[1] + base_y; - - var start = 0; - var end = line.getTotalLength(); - var target = undefined; - var pos = undefined; - - // https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91 - while (true){ - target = Math.floor((start + end) / 2); - pos = line.getPointAtLength(target); - if ((target === end || target === start) && pos.x !== px) { - break; - } - if (pos.x > px) end = target; - else if (pos.x < px) start = target; - else break; //position found - } - - - var cx = pos.x; - var cy = pos.y + base_y; - - var focus = state.timelineSvg.select("g.focus"); - focus.attr("transform", "translate(" + cx + "," + cy + ")"); - - var utilDescView = state.timelineSvg.select("g.utilDesc"); - utilDescView.attr("transform", "translate(" + (px + 10) + "," + (py - 10) + ")"); - var text = utilDescView.select("text") - - text.text(Math.round(state.y.invert(pos.y) * 100) + "% utilization"); - - var bbox = text.node().getBBox(); - var padding = 2; - var rect = utilDescView.select("rect", "text"); - rect.attr("x", bbox.x - padding) - .attr("y", bbox.y - padding) - .attr("width", bbox.width + (padding*2)) - .attr("height", bbox.height + (padding*2)); - - var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); - var bboxRight = px + bbox.x + bbox.width; - // If the box moves off the screen, nudge it back - if (bboxRight > timelineRight) { - var translation = -(bboxRight - timelineRight + 20); - text.attr("transform", "translate(" + translation + ",0)"); - rect.attr("transform", "translate(" + translation + ",0)"); - } -} - -// Get the data -function load_util(elem) { - var util_file = elem.tsv; - - // exit early if we already loaded it - if(state.utilData[util_file]) { - elem.loaded = true; - hideLoaderIcon(); - redraw(); - return; - } - - d3.tsv(util_file, - function(d) { - return { - time: +d.time, - count: +d.count - }; - }, - function(error, data) { - state.utilData[util_file] = data; - elem.loaded = true; - hideLoaderIcon(); - redraw(); - } - ); -} - -function load_critical_path() { - $.getJSON("json/critical_path.json", function(json) { - state.critical_path = json.map(function(p) {return p.tuple}); - state.critical_path_prof_uids = {}; - state.critical_path.forEach(function(p) { - state.critical_path_prof_uids[p[2]] = 1; - }); - }); -} - -function load_data() { - load_procs(load_ops_and_timeline); -} - -function initializeState() { - var margin = constants.margin_left + constants.margin_right; - state.width = $(window).width() - margin; - state.height = $(window).height() - constants.margin_bottom; - state.scale = state.width / (constants.end - constants.start); - state.zoom = 1.0; - state.zoomHistory = Array(); - state.numLoading = 0; - state.dependencyEvent = undefined; - state.drawDeps = false; - state.drawChildren = false; - - state.layoutData = []; - state.flattenedLayoutData = []; - - state.profilingData = {}; - state.processorData = {}; - state.utilData = []; - - state.operations = {}; - state.thickness = 20; //Math.max(state.height / constants.max_level, 20); - state.baseThickness = state.height / constants.max_level; - state.height = constants.max_level * state.thickness; - state.resolution = 10; // time (in us) of the smallest feature we want to load - state.searchEnabled = false; - state.rangeZoom = true; - state.collapseAll = false; - state.display_critical_path = false; - state.processor_kinds = {}; - - // display task ready state? - state.ready_selected = false; - // TODO: change this - state.x = d3.scale.linear().range([0, state.width]); - state.y = d3.scale.linear().range([constants.util_levels * state.thickness, 0]); - state.y.domain([0, 1]); - - setKeyHandler(defaultKeydown); - $(document).on("keyup", defaultKeyUp); - state.timelineSvg = d3.select("#timeline").select("svg").remove(); - state.timelineSvg = d3.select("#timeline").append("svg") - .attr("width", state.zoom * state.width) - .attr("height", state.height); - - state.loaderSvg = d3.select("#loader-icon").select("svg").remove(); - state.loaderSvg = d3.select("#loader-icon").append("svg") - .attr("width", "40px") - .attr("height", "40px"); - - d3.select("#processors").select("svg").remove(); - - drawLoaderIcon(); - drawHelpBox(); - load_data(); -} - -function load_util_json(callback) { - $.getJSON("json/utils.json", function(json) { - util_files = json; - callback(); - }); -} - -// Loads constants such as max_level, start/end time, and number of levels -// of a util view -function load_scale_json(callback) { - $.getJSON("json/scale.json", function(json) { - // add the read-in constants - $.each(json, function(key, val) { - constants[key] = val; - }); - load_util_json(callback); - }); -} - -function load_op_deps_json(callback) { - $.getJSON("json/op_dependencies.json", function(json) { - op_dependencies = json; - load_scale_json(callback); - }); -} - -function load_jsons(callback) { - load_scale_json(callback); -} - -function main() { - load_jsons(initializeState); -} - -main(); diff --git a/examples/testbench/good_band/js/util.js b/examples/testbench/good_band/js/util.js deleted file mode 100644 index 16ea770f2..000000000 --- a/examples/testbench/good_band/js/util.js +++ /dev/null @@ -1,378 +0,0 @@ -//----------------------------------------------------------------------------- -// UTILS -//----------------------------------------------------------------------------- - -var helpMessage = [ - "Zoom-in (x-axis) : Ctrl + / 4", - "Zoom-out (x-axis) : Ctrl - / 3", - "Reset zoom (x-axis): Ctrl 0 / 0", - "Undo zoom (x-axis) : u / U", - "Zoom-in (y-axis) : Ctrl-Alt + / 2", - "Zoom-out (y-axis) : Ctrl-Alt - / 1", - "Reset zoom (y-axis): Ctrl-Alt 0 / `", - "Range Zoom-in : drag-select", - "Measure duration : Alt + drag-select", - "Expand : e / E", - "Draw Critical Path : a / A", - "Search : s / S", - "Search History : h / H", - "Previous Search : p / P", - "Next Search : n / N", - "Clear Search : c / C", - "Toggle Search : t / T", -]; - -var Command = { - none : 0, - help : 1, - zox : 2, - zix : 3, - zrx : 4, - zux : 5, - zoy : 6, - ziy : 7, - zry : 8, - search : 9, - clear_search : 10, - toggle_search : 11, - expand: 12, - toggle_critical_path: 13, - search_history : 14, - previous_search : 15, - next_search : 16 -}; - -// commands without a modifier key pressed -var noModifierCommands = { - '0': Command.zrx, - '1': Command.zoy, - '2': Command.ziy, - '3': Command.zox, - '4': Command.zix, - 'c': Command.clear_search, - 'e': Command.expand, - 'h': Command.search_history, - 'n': Command.next_search, - 'p': Command.previous_search, - 's': Command.search, - 'a': Command.toggle_critical_path, - 't': Command.toggle_search, - 'u': Command.zux, - '/': Command.help -}; - -var modifierCommands = { - '+': Command.zix, - '-': Command.zox, - '0': Command.zrx -} - -var multipleModifierCommands = { - '+': Command.ziy, - '-': Command.zoy, - '0': Command.zry -} - -var keys = { - 13 : 'enter', - 27 : 'esc', - 48 : '0', - 49 : '1', - 50 : '2', - 51 : '3', - 52 : '4', - 61 : '+', // Firefox - 65 : 'a', - 67 : 'c', - 69 : 'e', - 72 : 'h', - 78 : 'n', - 80 : 'p', - 83 : 's', - 84 : 't', - 85 : 'u', - 173 : '-', // Firefox - 187 : '+', - 189 : '-', - 191 : '/', - 192 : '`' -}; - -/** - * Function: convertToTime - * - * Description: - * Takes a value and converts it to time. The input 'x' can either be - * a single position on the timeline, or it can be a width. - */ -function convertToTime(state, x) { - return x / state.zoom / state.scale; -} - -/** - * Function: convertToPos - * - * Description: - * Takes a time and converts it to a position in the window. - * The 'time' parameter MUST BE IN us - */ -function convertToPos(state, time) { - return time * state.zoom * state.scale; -} - -/** - * Function: getTimeString - * - * Description: - * This function takes a time (in us) as well as a 'width' - * field. The 'width' field determines over what interval - * the time is being considered. - * - * If the width is too large, the time will be converted - * to either ms or sec. - * - * The function will return a string representation of the - * (possibly) scaled time at the end of the method - */ -function getTimeString(time, timeWidth) { - var unit = "us"; - var scaledTime = Math.floor(time); - if (timeWidth >= 100000) { - var scaledTime = Math.floor(time / 1000); - unit = "ms"; - } else if (timeWidth >= 100000000) { - var scaledTime = Math.floor(time / 1000000); - unit = "s"; - } - return scaledTime + " " + unit; -} - -// timeField should be 'end' for the left hand side and -// 'start' for the right hand side -function binarySearch(data, level, time, useStart) { - var low = 0; - var high = data[level].length; - while (true) { - // ugh is there a way to do integer division in javascrtipt? - var mid = Math.floor((high - low) / 2) + low; - - // In this case, we haven't found it. This is as close - // as we were able to get. - if (low == high || low == mid) { - return low; - } else if (high == mid) { - return high; - } - var midTime; - if (useStart) { - midTime = data[level][mid].start; - } else { - midTime = data[level][mid].end; - } - - if (midTime > time) { - // need to look below - high = mid; - } else if (midTime < time) { - // need to look above - low = mid; - } else { - // Exact Match - return mid; - } - } -} - -dataReady = {}; -function redoData(proc) { - dataReady = {}; - var items = state.processorData[proc.full_text]; - for (var level in items) { - for (var j = 0; j< items[level].length; j++) { - d = items[level][j]; - // ready state items - if (d.level_ready != undefined && d.level_ready != "" && - d.ready != undefined && d.ready != "") { - // if the level has already been switched, then don't do anything - var level_to_set = d.level_ready; - if (d.level_ready_set != undefined && d.level_ready_set == true) - level_to_set = d.level; - var d_ready = { - id: d.id+items[level].length+1, // unique id - level: level_to_set, - level_ready: d.level, - ready: d.ready, - start: d.ready, - end: d.start, - color: d.color, - opacity: "0.45", - initiation: d.initiation, - title: d.title + " (ready)", - in: d.in, - out: d.out, - children: d.children, - parents: d.parents, - prof_uid: d.prof_uid, - proc: d.proc - }; - // switch levels if we need to - if (d.level_ready_set == undefined || d.level_ready_set == false) - { - var level_tmp = d.level; - d.level = d.level_ready; - d.level_ready = level_tmp; - d.level_ready_set = true; - } - if (d.level_ready in dataReady){ - dataReady[d.level_ready].push(d_ready); - dataReady[d.level_ready].push(d); - } - else { - dataReady[d.level_ready] = [d_ready]; - dataReady[d.level_ready].push(d); - } - } - // add items to the level - else { - if (d.level in dataReady) - dataReady[d.level].push(d); - else - dataReady[d.level] = [d]; - } - } - } -} - -function readyData(proc) { - redoData(proc); -} - -function filterAndMergeBlocks(state) { - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - state.dataToDraw = Array(); - state.memoryTexts = Array(); - var startTime = convertToTime(state, windowStart); - var endTime = convertToTime(state, windowEnd); - var min_feature_time = convertToTime(state, constants.min_feature_width); - var min_gap_time = convertToTime(state, constants.min_gap_width); - for (var index in state.flattenedLayoutData) { - var timelineElement = state.flattenedLayoutData[index]; - if (timelineElement.type == "proc" && timelineElement.enabled && timelineElement.visible) { - var items = state.processorData[timelineElement.full_text]; - var memoryRegex = /Memory/; - var isMemory = memoryRegex.exec(timelineElement.text); - if (state.ready_selected) { - readyData(timelineElement); - items = dataReady; - } - - for (var level in items) { - // gap merging below assumes intervals are sorted - do that first - //items[level].sort(function(a,b) { return a.start - b.start; }); - - // We will use binary search to limit the following section - var startIndex = binarySearch(items, level, startTime, false); - var endIndex = binarySearch(items, level, endTime, true); - for (var i = startIndex; i <= endIndex; ++i) { - var d = items[level][i]; - var start = d.start; - var end = d.end; - // fix the level here - if (state.ready_selected == false && d.level_ready_set != undefined - && d.level_ready_set == true) - { - // switch levels - var level_tmp = d.level; - d.level = d.level_ready; - d.level_ready = level_tmp; - d.level_ready_set = false; - } - // is this block too narrow? - if ((end - start) < min_feature_time) { - // see how many more after this are also too narrow and too close to us - var count = 1; - // don't do this if we're the subject of the current search and don't merge with - // something that is - if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) == null) { - while (((i + count) < items[level].length) && - ((items[level][i + count].start - end) < min_gap_time) && - ((items[level][i + count].end - items[level][i + count].start) < min_feature_time) && - (!state.searchEnabled || searchRegex[currentPos].exec(items[level][i + count].title) == null)) { - end = items[level][i + count].end; - count++; - } - } - // are we still too narrow? if so, bloat, but make sure we don't overlap something later - if ((end - start) < min_feature_time) { - end = start + min_feature_time; - if (((i + count) < items[level].length) && (items[level][i + count].start < end)) - end = items[level][i + count].start; - } - if (count > 1) { - state.dataToDraw.push({ - id: d.id, - prof_uid: d.prof_uid, - proc: timelineElement, - level: d.level, - ready: d.ready, - start: d.start, - end: Math.round(end), - color: "#808080", - title: count + " merged tasks", - in: [], - out: [], - children: [], - parents: [] - }); - i += (count - 1); - } else { - var elem = { - id: d.id, - prof_uid: d.prof_uid, - proc: timelineElement, - level: d.level, - ready: d.ready, - start: d.start, - end: d.end, - color: d.color, - initiation: d.initiation, - title: d.title + " (expanded for visibility)", - in: d.in, - out: d.out, - children: d.children, - parents: d.parents - } - state.dataToDraw.push(elem); - if (isMemory) { - state.memoryTexts.push(elem); - } - } - } else { - var elem = { - id: d.id, - prof_uid: d.prof_uid, - proc: timelineElement, - level: d.level, - ready: d.ready, - start: d.start, - end: d.end, - opacity: d.opacity, - color: d.color, - initiation: d.initiation, - title: d.title, - in: d.in, - out: d.out, - children: d.children, - parents: d.parents - } - state.dataToDraw.push(elem); - if (isMemory) { - state.memoryTexts.push(elem); - } - } - } - } - } - } -} diff --git a/examples/testbench/good_band/legion_prof_ops.tsv b/examples/testbench/good_band/legion_prof_ops.tsv deleted file mode 100644 index 399ea7717..000000000 --- a/examples/testbench/good_band/legion_prof_ops.tsv +++ /dev/null @@ -1,90 +0,0 @@ -op_id desc proc level -1 legion_python_main <1> Python Processor 0x1d00000000000004 2 -42 legate::numpy::FillTask [CPU] <42> CPU Processor 0x1d00000000000002 2 -47 legate::numpy::BinaryOpTask [CPU] <47> CPU Processor 0x1d00000000000002 2 -58 legate::numpy::BinaryOpTask [CPU] <58> CPU Processor 0x1d00000000000002 2 -71 legate::numpy::BinaryOpTask [CPU] <71> CPU Processor 0x1d00000000000002 2 -77 legate::numpy::BinaryOpTask [CPU] <77> CPU Processor 0x1d00000000000002 2 -3 Tunable Operation <3> -4 Tunable Operation <4> -5 Tunable Operation <5> -6 Pending Partition Operation <6> -8 Refinement Operation <8> -7 legate::numpy::FillTask <7> -0 Operation <0> -9 legate::numpy::FillTask <9> -12 legate::numpy::FillTask <12> -11 legate::numpy::FillTask <11> -14 Refinement Operation <14> -13 legate::numpy::FillTask [CPU] <13> CPU Processor 0x1d00000000000002 2 -86 Fence Operation <86> -89 Deletion Operation <89> -88 Deletion Operation <88> -87 Deletion Operation <87> -15 legate::numpy::FillTask [CPU] <15> CPU Processor 0x1d00000000000003 2 -48 legate::numpy::BinaryOpTask [CPU] <48> CPU Processor 0x1d00000000000003 2 -79 Mapping Operation <79> -23 legate::numpy::FillTask [CPU] <23> CPU Processor 0x1d00000000000002 2 -24 legate::numpy::FillTask [CPU] <24> CPU Processor 0x1d00000000000003 2 -38 legate::numpy::FillTask [CPU] <38> CPU Processor 0x1d00000000000003 2 -10 legate::numpy::FillTask <10> -21 legate::numpy::FillTask <21> -22 legate::numpy::FillTask <22> -30 legate::numpy::FillTask <30> -31 legate::numpy::FillTask <31> -34 legate::numpy::FillTask <34> -36 legate::numpy::FillTask [CPU] <36> CPU Processor 0x1d00000000000002 2 -39 Refinement Operation <39> -16 legate::numpy::FillTask <16> -26 legate::numpy::FillTask <26> -20 legate::numpy::FillTask <20> -53 legate::numpy::BinaryOpTask [CPU] <53> CPU Processor 0x1d00000000000003 2 -27 legate::numpy::FillTask <27> -40 legate::numpy::FillTask <40> -41 legate::numpy::FillTask <41> -43 legate::numpy::FillTask [CPU] <43> CPU Processor 0x1d00000000000003 2 -19 Refinement Operation <19> -28 legate::numpy::FillTask <28> -32 Refinement Operation <32> -33 legate::numpy::FillTask [CPU] <33> CPU Processor 0x1d00000000000002 2 -35 legate::numpy::FillTask [CPU] <35> CPU Processor 0x1d00000000000003 2 -44 legate::numpy::BinaryOpTask <44> -45 legate::numpy::BinaryOpTask <45> -46 legate::numpy::BinaryOpTask <46> -25 legate::numpy::FillTask <25> -17 legate::numpy::FillTask <17> -29 legate::numpy::BinaryOpTask <29> -18 legate::numpy::FillTask <18> -37 legate::numpy::BinaryOpTask <37> -54 legate::numpy::BinaryOpTask <54> -59 legate::numpy::BinaryOpTask <59> -62 legate::numpy::BinaryOpTask <62> -68 legate::numpy::BinaryOpTask <68> -73 legate::numpy::BinaryOpTask <73> -60 legate::numpy::BinaryOpTask [CPU] <60> CPU Processor 0x1d00000000000003 2 -66 legate::numpy::BinaryOpTask [CPU] <66> CPU Processor 0x1d00000000000003 2 -72 legate::numpy::BinaryOpTask [CPU] <72> CPU Processor 0x1d00000000000003 2 -78 legate::numpy::BinaryOpTask [CPU] <78> CPU Processor 0x1d00000000000003 2 -52 legate::numpy::BinaryOpTask [CPU] <52> CPU Processor 0x1d00000000000002 2 -49 legate::numpy::BinaryOpTask <49> -50 legate::numpy::BinaryOpTask <50> -51 legate::numpy::BinaryOpTask <51> -61 legate::numpy::BinaryOpTask <61> -63 legate::numpy::BinaryOpTask <63> -64 legate::numpy::BinaryOpTask <64> -65 legate::numpy::BinaryOpTask [CPU] <65> CPU Processor 0x1d00000000000002 2 -67 legate::numpy::BinaryOpTask <67> -80 Merge Close Operation <80> -81 legate::numpy::BinaryOpTask <81> -82 legate::numpy::BinaryOpTask <82> -83 legate::numpy::BinaryOpTask <83> -55 legate::numpy::BinaryOpTask <55> -57 legate::numpy::BinaryOpTask <57> -69 legate::numpy::BinaryOpTask <69> -70 legate::numpy::BinaryOpTask <70> -84 legate::numpy::BinaryOpTask [CPU] <84> CPU Processor 0x1d00000000000002 2 -85 legate::numpy::BinaryOpTask [CPU] <85> CPU Processor 0x1d00000000000003 2 -56 legate::numpy::BinaryOpTask <56> -74 legate::numpy::BinaryOpTask <74> -75 legate::numpy::BinaryOpTask <75> -76 legate::numpy::BinaryOpTask <76> diff --git a/examples/testbench/good_band/legion_prof_processor.tsv b/examples/testbench/good_band/legion_prof_processor.tsv deleted file mode 100644 index 4773ccb73..000000000 --- a/examples/testbench/good_band/legion_prof_processor.tsv +++ /dev/null @@ -1,9 +0,0 @@ -full_text text tsv levels -Utility Processor 0x1d00000000000000 Utility Proc 0 tsv/Proc_0x1d00000000000000.tsv 5 -Utility Processor 0x1d00000000000001 Utility Proc 1 tsv/Proc_0x1d00000000000001.tsv 4 -CPU Processor 0x1d00000000000002 CPU Proc 2 tsv/Proc_0x1d00000000000002.tsv 1 -CPU Processor 0x1d00000000000003 CPU Proc 3 tsv/Proc_0x1d00000000000003.tsv 1 -Python Processor 0x1d00000000000004 Python Proc 4 tsv/Proc_0x1d00000000000004.tsv 1 -Dependent Partition Channel Dependent Partition Channel tsv/None.tsv 3 -System Memory 0x1e00000000000000 to System Memory 0x1e00000000000000 Channel [n0] sys to [n0] sys tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv 3 -System Memory 0x1e00000000000000 [n0] sys tsv/Mem_0x1e00000000000000.tsv 11 diff --git a/examples/testbench/good_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv b/examples/testbench/good_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv deleted file mode 100644 index 4203867b4..000000000 --- a/examples/testbench/good_band/tsv/(System_Memory_0x1e00000000000000,_System_Memory_0x1e00000000000000).tsv +++ /dev/null @@ -1,3 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -3 1373371.458 1387229.451 #ff6e00 1.0 size=19.073 MiB, num reqs=1$req[0]: src_inst=0x4000000000000007, dst_inst=0x400000000000000b, fields=1, type=copy, hops=1 79 647 -2 1373846.460 1387561.869 #ff6e00 1.0 size=19.073 MiB, num reqs=1$req[0]: src_inst=0x4000000000000008, dst_inst=0x400000000000000b, fields=1, type=copy, hops=1 79 648 diff --git a/examples/testbench/good_band/tsv/0 (CPU)_util.tsv b/examples/testbench/good_band/tsv/0 (CPU)_util.tsv deleted file mode 100644 index 4fe28da97..000000000 --- a/examples/testbench/good_band/tsv/0 (CPU)_util.tsv +++ /dev/null @@ -1,208 +0,0 @@ -time count -0.000 0.00 -1164390.880 0.50 -1164404.064 0.00 -1164431.041 0.50 -1164436.216 0.00 -1164746.447 0.50 -1164753.372 0.00 -1164794.721 0.50 -1164801.321 0.00 -1207340.857 0.50 -1207348.217 0.00 -1207357.779 0.50 -1207362.525 0.00 -1257468.208 0.50 -1257475.225 0.00 -1257512.563 0.50 -1257518.405 0.00 -1257612.061 0.50 -1257621.839 0.00 -1257633.588 0.50 -1257640.573 0.00 -1278088.519 0.50 -1278094.369 0.00 -1278227.506 0.50 -1278250.584 0.00 -1278329.460 0.50 -1278341.946 0.00 -1278465.635 0.50 -1278473.130 0.00 -1278531.783 0.50 -1278539.848 0.00 -1278559.197 0.50 -1278563.854 0.00 -1278647.025 0.50 -1278654.038 0.00 -1278661.355 0.50 -1278670.464 0.00 -1278677.818 0.50 -1278682.210 0.00 -1278732.052 0.50 -1278737.425 0.00 -1278822.472 0.50 -1278827.664 0.00 -1278836.004 0.50 -1278846.984 0.00 -1278863.656 0.50 -1278867.667 0.00 -1278941.853 0.50 -1278947.582 0.00 -1279087.247 0.50 -1279093.462 0.00 -1279119.581 0.50 -1279132.688 0.00 -1279195.488 0.50 -1279381.573 1.00 -1279387.931 0.50 -1279397.429 1.00 -1279409.712 0.50 -1279450.771 1.00 -1279457.216 0.50 -1279491.926 1.00 -1279502.598 0.50 -1279554.996 1.00 -1279565.486 0.50 -1279612.008 1.00 -1279618.651 0.50 -1279629.022 1.00 -1279637.142 0.50 -1279646.909 1.00 -1290530.227 0.50 -1290575.311 1.00 -1290673.584 0.50 -1290724.634 1.00 -1301160.372 0.50 -1301205.707 1.00 -1301522.032 0.50 -1301559.534 1.00 -1312999.079 0.50 -1313041.542 1.00 -1313329.507 0.50 -1313364.414 1.00 -1316508.577 0.50 -1316545.328 1.00 -1316831.920 0.50 -1316862.415 1.00 -1319918.397 0.50 -1319957.314 1.00 -1319964.781 0.50 -1320009.542 1.00 -1320182.092 0.50 -1320208.211 1.00 -1333283.719 0.50 -1333326.173 1.00 -1333334.715 0.50 -1333381.736 1.00 -1333389.695 0.50 -1333450.382 1.00 -1346503.982 0.50 -1346589.948 1.00 -1347048.850 0.50 -1347087.138 1.00 -1347098.437 0.50 -1347145.449 1.00 -1353143.177 0.50 -1353185.134 1.00 -1353193.257 0.50 -1353240.213 1.00 -1353587.731 0.50 -1353620.664 1.00 -1353625.527 0.50 -1353676.454 1.00 -1358415.641 0.50 -1358516.042 1.00 -1358922.645 0.50 -1358955.630 1.00 -1358961.897 0.50 -1359020.346 1.00 -1363745.920 0.50 -1363795.948 1.00 -1363805.182 0.50 -1363869.877 1.00 -1364298.334 0.50 -1364340.083 1.00 -1364346.914 0.50 -1364383.652 1.00 -1368701.245 0.50 -1368739.249 1.00 -1368746.421 0.50 -1368793.530 1.00 -1369149.144 0.50 -1369188.043 1.00 -1369203.231 0.50 -1369248.466 1.00 -1373328.678 0.50 -1373764.764 0.00 -1805328.138 0.50 -1805337.533 0.00 -1805375.803 0.50 -1805382.225 0.00 -1843775.371 0.50 -1843805.275 0.00 -1843817.171 0.50 -1843824.922 0.00 -1843844.761 0.50 -1843861.109 0.00 -1843886.263 0.50 -1843893.154 0.00 -1843937.108 0.50 -1843943.529 0.00 -1843951.637 0.50 -1843966.439 0.00 -1844034.676 0.50 -1844041.454 0.00 -1844091.466 0.50 -1844097.428 0.00 -1844123.736 0.50 -1844129.659 0.00 -1844167.643 0.50 -1844182.143 0.00 -1844214.123 0.50 -1844221.266 0.00 -1844257.222 0.50 -1844263.836 0.00 -1844301.260 0.50 -1844305.938 0.00 -1844676.874 0.50 -1844697.739 0.00 -1844723.767 0.50 -1844730.441 0.00 -1844738.308 0.50 -1844743.158 0.00 -1844770.899 0.50 -1844776.660 0.00 -1844809.980 0.50 -1844816.809 0.00 -1844857.582 0.50 -1844865.890 0.00 -1844874.628 0.50 -1844891.521 0.00 -1844898.768 0.50 -1844902.397 0.00 -1844935.962 0.50 -1844943.256 0.00 -1844963.598 0.50 -1844966.386 1.00 -1844971.617 0.50 -1844973.976 0.00 -1845015.224 0.50 -1845023.543 0.00 -1845051.132 0.50 -1845067.224 0.00 -1845079.615 0.50 -1845085.862 0.00 -1845092.849 0.50 -1845096.644 0.00 -1845103.389 0.50 -1845108.412 0.00 -1845129.295 0.50 -1845132.386 1.00 -1845137.136 0.50 -1845139.801 0.00 -1845147.332 0.50 -1845163.365 0.00 -1845168.715 0.50 -1845171.090 1.00 -1845175.087 0.50 -1845177.515 0.00 diff --git a/examples/testbench/good_band/tsv/0 (Channel)_util.tsv b/examples/testbench/good_band/tsv/0 (Channel)_util.tsv deleted file mode 100644 index e13bb0242..000000000 --- a/examples/testbench/good_band/tsv/0 (Channel)_util.tsv +++ /dev/null @@ -1,4 +0,0 @@ -time count -0.000 0.00 -1373371.458 1.00 -1387561.869 0.00 diff --git a/examples/testbench/good_band/tsv/0 (Python)_util.tsv b/examples/testbench/good_band/tsv/0 (Python)_util.tsv deleted file mode 100644 index 9d87a3d5a..000000000 --- a/examples/testbench/good_band/tsv/0 (Python)_util.tsv +++ /dev/null @@ -1,16 +0,0 @@ -time count -0.000 0.00 -494356.555 1.00 -1164322.429 0.00 -1164554.852 1.00 -1164686.388 0.00 -1164823.261 1.00 -1207258.637 0.00 -1207422.856 1.00 -1305677.005 0.00 -1307537.619 1.00 -1307553.652 0.00 -1387655.987 1.00 -1805303.104 0.00 -1805398.321 1.00 -1843718.831 0.00 diff --git a/examples/testbench/good_band/tsv/0 (System Memory)_util.tsv b/examples/testbench/good_band/tsv/0 (System Memory)_util.tsv deleted file mode 100644 index c46245cd8..000000000 --- a/examples/testbench/good_band/tsv/0 (System Memory)_util.tsv +++ /dev/null @@ -1,24 +0,0 @@ -time count -0.000 0.00 -1278823.735 0.00 -1279061.877 0.01 -1280061.606 0.01 -1280246.078 0.02 -1281367.754 0.02 -1281572.958 0.03 -1282612.241 0.03 -1282784.125 0.04 -1283563.847 0.04 -1283746.860 0.05 -1307133.149 0.06 -1844151.087 0.05 -1844240.657 0.05 -1844651.511 0.04 -1844726.221 0.03 -1844793.065 0.03 -1844857.709 0.02 -1844919.518 0.02 -1844985.437 0.01 -1845081.180 0.01 -1845119.817 0.00 -1845134.718 0.00 diff --git a/examples/testbench/good_band/tsv/0 (Utility)_util.tsv b/examples/testbench/good_band/tsv/0 (Utility)_util.tsv deleted file mode 100644 index e697ba587..000000000 --- a/examples/testbench/good_band/tsv/0 (Utility)_util.tsv +++ /dev/null @@ -1,992 +0,0 @@ -time count -0.000 0.00 -493837.510 0.50 -493896.375 0.00 -493931.102 0.50 -493931.677 1.00 -493944.124 0.50 -494029.929 0.00 -494058.742 0.50 -494058.910 1.00 -494064.325 0.50 -494101.567 0.00 -494125.428 0.50 -494130.615 1.00 -494135.463 0.50 -494193.707 0.00 -494208.875 0.50 -494210.784 1.00 -494214.839 0.50 -494348.350 0.00 -494368.000 0.50 -494371.632 0.00 -1164265.110 0.50 -1164304.048 0.00 -1164313.229 0.50 -1164405.071 1.00 -1164407.217 0.50 -1164511.519 0.00 -1164541.448 0.50 -1164549.085 0.00 -1164682.320 0.50 -1164714.593 0.00 -1164725.526 0.50 -1164772.567 0.00 -1164778.390 0.50 -1164819.329 0.00 -1164842.752 0.50 -1164848.390 0.00 -1207271.028 0.50 -1207305.822 1.00 -1207307.344 0.50 -1207337.594 0.00 -1207339.179 0.50 -1207399.159 0.00 -1207424.454 0.50 -1207430.784 0.00 -1257389.335 0.50 -1257422.422 0.00 -1257444.005 0.50 -1257484.492 0.00 -1257499.072 0.50 -1257585.815 0.00 -1257595.549 0.50 -1257609.470 1.00 -1257615.167 0.50 -1257624.283 0.00 -1257640.055 0.50 -1257646.736 0.00 -1277848.542 0.50 -1278028.704 1.00 -1278028.841 0.50 -1278051.446 1.00 -1278056.549 0.50 -1278061.916 0.00 -1278063.442 0.50 -1278109.764 1.00 -1278119.561 0.50 -1278137.033 1.00 -1278141.642 0.50 -1278162.126 0.00 -1278163.934 0.50 -1278180.326 1.00 -1278186.455 0.50 -1278205.113 0.00 -1278209.774 0.50 -1278308.664 0.00 -1278323.593 0.50 -1278426.961 1.00 -1278440.201 0.50 -1278461.160 1.00 -1278505.618 0.50 -1278538.494 1.00 -1278541.424 0.50 -1278559.476 1.00 -1278619.622 0.50 -1278620.037 0.00 -1278638.486 0.50 -1278641.562 1.00 -1278664.513 0.50 -1278680.314 1.00 -1278712.234 0.50 -1278726.859 1.00 -1278745.693 0.50 -1278783.666 1.00 -1278801.586 0.50 -1278818.753 1.00 -1278849.780 0.50 -1278893.781 1.00 -1278918.912 0.50 -1278940.842 1.00 -1278989.270 0.50 -1279017.443 1.00 -1279099.959 0.50 -1279133.630 1.00 -1279160.544 0.50 -1279231.730 1.00 -1279251.865 0.50 -1279320.699 1.00 -1279351.834 0.50 -1279375.598 0.00 -1279389.655 0.50 -1279418.725 1.00 -1279426.309 0.50 -1279467.951 0.00 -1279479.418 0.50 -1279508.879 1.00 -1279536.461 0.50 -1279561.577 1.00 -1279580.044 0.50 -1279591.038 0.00 -1279611.199 0.50 -1279616.772 1.00 -1279651.982 0.50 -1279674.758 1.00 -1279698.571 0.50 -1279718.086 1.00 -1279761.109 0.50 -1279774.382 0.00 -1279777.897 0.50 -1279792.958 1.00 -1279794.261 0.50 -1279823.597 1.00 -1279866.659 0.50 -1279872.496 0.00 -1279883.399 0.50 -1279895.526 1.00 -1279907.765 0.50 -1279921.310 1.00 -1279925.030 0.50 -1279945.362 0.00 -1279947.145 0.50 -1279958.591 1.00 -1279997.784 0.50 -1280008.249 0.00 -1280011.334 0.50 -1280036.518 1.00 -1280057.763 0.50 -1280076.936 1.00 -1280123.017 0.50 -1280137.759 1.00 -1280175.444 0.50 -1280192.631 1.00 -1280237.601 0.50 -1280252.240 1.00 -1280278.040 0.50 -1280290.082 1.00 -1280302.458 0.50 -1280314.319 1.00 -1280319.182 0.50 -1280324.665 1.00 -1280328.013 0.50 -1280332.985 1.00 -1280336.186 0.50 -1280340.596 1.00 -1280345.027 0.50 -1280349.935 1.00 -1280354.507 0.50 -1280360.608 1.00 -1280368.275 0.50 -1280379.031 0.00 -1280397.006 0.50 -1280404.093 0.00 -1280408.793 0.50 -1280412.723 0.00 -1280415.218 0.50 -1280418.215 1.00 -1280422.494 0.50 -1280427.978 1.00 -1280432.194 0.50 -1280436.774 1.00 -1280440.821 0.50 -1280446.196 1.00 -1280450.961 0.50 -1280456.534 1.00 -1280480.415 0.50 -1280500.201 0.00 -1280517.657 0.50 -1280519.467 1.00 -1280590.069 0.50 -1280618.696 1.00 -1280620.373 0.50 -1280640.616 1.00 -1280675.589 0.50 -1280695.112 1.00 -1280704.966 0.50 -1280724.974 1.00 -1280731.408 0.50 -1280750.931 1.00 -1280799.920 0.50 -1280819.690 1.00 -1280845.001 0.50 -1280864.265 1.00 -1280903.705 0.50 -1280923.262 1.00 -1280948.444 0.50 -1280949.533 0.00 -1280969.101 0.50 -1280975.106 1.00 -1281006.901 0.50 -1281020.886 0.00 -1281026.198 0.50 -1281040.746 1.00 -1281082.549 0.50 -1281102.897 1.00 -1281117.395 0.50 -1281128.249 0.00 -1281133.593 0.50 -1281156.030 0.00 -1281168.256 0.50 -1281168.977 1.00 -1281202.632 0.50 -1281216.424 1.00 -1281221.133 0.50 -1281244.468 1.00 -1281263.117 0.50 -1281278.236 1.00 -1281304.887 0.50 -1281307.180 0.00 -1281323.992 0.50 -1281331.290 1.00 -1281352.380 0.50 -1281369.623 1.00 -1281426.948 0.50 -1281441.165 1.00 -1281453.949 0.50 -1281469.680 1.00 -1281491.546 0.50 -1281511.464 1.00 -1281524.905 0.50 -1281540.900 1.00 -1281542.779 0.50 -1281578.718 1.00 -1281646.649 0.50 -1281662.778 1.00 -1281672.107 0.50 -1281687.437 0.00 -1281702.413 0.50 -1281711.894 1.00 -1281728.933 0.50 -1281747.438 1.00 -1281795.038 0.50 -1281819.066 1.00 -1281833.954 0.50 -1281854.322 1.00 -1281914.727 0.50 -1281935.560 1.00 -1281962.837 0.50 -1281968.754 0.00 -1281982.725 0.50 -1281987.215 1.00 -1281997.474 0.50 -1282022.385 1.00 -1282052.736 0.50 -1282073.815 1.00 -1282075.305 0.50 -1282094.433 1.00 -1282135.609 0.50 -1282156.222 0.00 -1282156.494 0.50 -1282176.348 1.00 -1282184.635 0.50 -1282204.439 1.00 -1282213.490 0.50 -1282231.574 0.00 -1282232.852 0.50 -1282247.509 1.00 -1282254.507 0.50 -1282263.334 1.00 -1282265.809 0.50 -1282284.700 1.00 -1282290.552 0.50 -1282298.502 1.00 -1282305.272 0.50 -1282312.818 1.00 -1282321.895 0.50 -1282329.352 1.00 -1282334.523 0.50 -1282342.111 1.00 -1282347.445 0.50 -1282350.095 0.00 -1282355.476 0.50 -1282370.051 1.00 -1282376.626 0.50 -1282383.996 1.00 -1282390.851 0.50 -1282398.511 1.00 -1282404.761 0.50 -1282412.358 1.00 -1282431.565 0.50 -1282451.010 1.00 -1282495.982 0.50 -1282517.522 1.00 -1282537.356 0.50 -1282560.296 1.00 -1282570.883 0.50 -1282589.505 1.00 -1282637.613 0.50 -1282666.567 1.00 -1282670.256 0.50 -1282676.118 1.00 -1282682.844 0.50 -1282687.683 1.00 -1282691.027 0.50 -1282695.682 1.00 -1282699.349 0.50 -1282704.941 1.00 -1282708.191 0.50 -1282712.962 1.00 -1282717.209 0.50 -1282721.947 1.00 -1282725.259 0.50 -1282729.621 1.00 -1282732.909 0.50 -1282738.061 1.00 -1282742.186 0.50 -1282747.803 1.00 -1282880.412 0.50 -1282895.492 1.00 -1282898.743 0.50 -1282903.269 1.00 -1282906.398 0.50 -1282911.963 1.00 -1282915.130 0.50 -1282919.738 1.00 -1282922.982 0.50 -1282928.128 1.00 -1282935.817 0.50 -1282942.383 1.00 -1282942.785 0.50 -1282966.964 0.00 -1282980.146 0.50 -1282986.367 1.00 -1282991.345 0.50 -1282998.561 1.00 -1283003.565 0.50 -1283010.418 1.00 -1283015.397 0.50 -1283022.770 1.00 -1283027.895 0.50 -1283034.875 1.00 -1283040.014 0.50 -1283046.978 1.00 -1283052.050 0.50 -1283059.186 1.00 -1283065.631 0.50 -1283073.383 1.00 -1283076.987 0.50 -1283098.801 1.00 -1283110.127 0.50 -1283130.304 1.00 -1283130.494 0.50 -1283150.656 1.00 -1283156.284 0.50 -1283163.621 0.00 -1283164.014 0.50 -1283182.622 1.00 -1283188.104 0.50 -1283195.694 1.00 -1283204.944 0.50 -1283211.677 1.00 -1283220.390 0.50 -1283227.561 1.00 -1283232.886 0.50 -1283239.761 1.00 -1283244.909 0.50 -1283251.950 0.00 -1283252.211 0.50 -1283272.054 1.00 -1283278.592 0.50 -1283285.846 1.00 -1283291.196 0.50 -1283298.174 1.00 -1283303.562 0.50 -1283311.221 1.00 -1283324.969 0.50 -1283344.437 1.00 -1283395.670 0.50 -1283414.744 1.00 -1283430.716 0.50 -1283450.278 1.00 -1283480.049 0.50 -1283500.017 1.00 -1283500.409 0.50 -1283519.252 1.00 -1283537.974 0.50 -1283621.832 1.00 -1283626.988 0.50 -1283634.116 1.00 -1283639.765 0.50 -1283647.210 1.00 -1283652.142 0.50 -1283658.525 1.00 -1283663.327 0.50 -1283669.788 1.00 -1283674.776 0.50 -1283681.015 1.00 -1283687.272 0.50 -1283695.521 1.00 -1283891.905 0.50 -1283930.408 1.00 -1283931.392 0.50 -1283956.807 1.00 -1283991.577 0.50 -1283996.266 0.00 -1284006.864 0.50 -1284019.731 1.00 -1284026.542 0.50 -1284031.957 0.00 -1284037.065 0.50 -1284043.643 0.00 -1284046.066 0.50 -1284050.070 0.00 -1284052.387 0.50 -1284055.707 1.00 -1284059.289 0.50 -1284060.505 0.00 -1284067.513 0.50 -1284070.087 1.00 -1284074.595 0.50 -1284076.801 0.00 -1284080.228 0.50 -1284085.420 1.00 -1284086.541 0.50 -1284091.929 0.00 -1284092.440 0.50 -1284096.296 0.00 -1284100.863 0.50 -1284101.982 1.00 -1284106.383 0.50 -1284107.585 0.00 -1284111.488 0.50 -1284115.765 0.00 -1284116.830 0.50 -1284121.233 1.00 -1284123.552 0.50 -1284125.707 0.00 -1284131.344 0.50 -1284132.489 1.00 -1284135.349 0.50 -1284139.516 0.00 -1284140.596 0.50 -1284144.671 0.00 -1284148.163 0.50 -1284149.723 1.00 -1284154.638 0.50 -1284156.310 0.00 -1284161.552 0.50 -1284163.452 1.00 -1284167.611 0.50 -1284172.102 1.00 -1284175.585 0.50 -1284177.046 0.00 -1284182.497 0.50 -1284189.542 0.00 -1290561.994 0.50 -1290575.892 1.00 -1290581.206 0.50 -1290645.947 0.00 -1290672.470 0.50 -1290682.613 0.00 -1290706.341 0.50 -1290712.299 0.00 -1290721.686 0.50 -1290776.945 1.00 -1290793.748 0.50 -1290814.031 1.00 -1290821.356 0.50 -1290821.681 0.00 -1290851.820 0.50 -1290857.268 0.00 -1301189.824 0.50 -1301196.603 0.00 -1301211.605 0.50 -1301251.876 0.00 -1301276.326 0.50 -1301282.541 0.00 -1301544.868 0.50 -1301552.926 0.00 -1301559.661 0.50 -1301606.151 1.00 -1301629.806 0.50 -1301641.799 0.00 -1301646.722 0.50 -1301651.116 0.00 -1301693.731 0.50 -1301697.364 0.00 -1303168.646 0.50 -1303281.263 1.00 -1303283.977 0.50 -1303305.777 1.00 -1303312.883 0.50 -1303320.693 0.00 -1303321.376 0.50 -1303344.045 1.00 -1303349.993 0.50 -1303396.088 0.00 -1303396.962 0.50 -1303414.273 1.00 -1303418.400 0.50 -1303482.714 0.00 -1303483.722 0.50 -1303497.656 1.00 -1303502.117 0.50 -1303545.046 1.00 -1303558.517 0.50 -1303573.877 1.00 -1303624.181 0.50 -1303642.161 0.00 -1303670.965 0.50 -1303671.094 1.00 -1303704.125 0.50 -1303718.836 0.00 -1303732.487 0.50 -1303745.784 1.00 -1303770.128 0.50 -1303786.168 1.00 -1303805.810 0.50 -1303811.406 0.00 -1303820.840 0.50 -1303844.177 0.00 -1303845.931 0.50 -1303856.281 1.00 -1303879.903 0.50 -1303908.169 0.00 -1303909.035 0.50 -1303922.034 1.00 -1303925.681 0.50 -1303931.496 1.00 -1303935.527 0.50 -1303940.923 1.00 -1303944.758 0.50 -1303950.746 1.00 -1303965.082 0.50 -1303983.695 1.00 -1303988.852 0.50 -1303996.469 1.00 -1304002.083 0.50 -1304010.979 1.00 -1304016.012 0.50 -1304034.134 1.00 -1304053.638 0.50 -1304057.203 0.00 -1304070.131 0.50 -1304076.332 1.00 -1304082.034 0.50 -1304089.969 1.00 -1304095.865 0.50 -1304099.441 0.00 -1304104.636 0.50 -1304120.480 1.00 -1304128.900 0.50 -1304137.321 1.00 -1304143.536 0.50 -1304151.481 1.00 -1304158.130 0.50 -1304166.492 1.00 -1304172.116 0.50 -1304179.541 1.00 -1304185.478 0.50 -1304194.596 1.00 -1304201.779 0.50 -1304225.353 1.00 -1304268.486 0.50 -1304287.341 1.00 -1304297.327 0.50 -1304317.260 1.00 -1304378.464 0.50 -1304388.941 0.00 -1304398.660 0.50 -1304402.496 1.00 -1304436.193 0.50 -1304450.099 1.00 -1304450.999 0.50 -1304470.099 1.00 -1304504.123 0.50 -1304516.057 1.00 -1304538.039 0.50 -1304551.018 1.00 -1304564.826 0.50 -1304575.121 0.00 -1304586.431 0.50 -1304587.656 1.00 -1304609.345 0.50 -1304619.350 0.00 -1304622.305 0.50 -1304637.141 1.00 -1304643.365 0.50 -1304651.780 1.00 -1304658.683 0.50 -1304666.550 1.00 -1304672.388 0.50 -1304680.459 1.00 -1304688.024 0.50 -1304690.689 0.00 -1304698.019 0.50 -1304706.331 1.00 -1304723.689 0.50 -1304762.829 1.00 -1304772.128 0.50 -1304783.673 0.00 -1304792.515 0.50 -1304816.987 1.00 -1304856.819 0.50 -1304888.752 0.00 -1304897.074 0.50 -1304903.629 1.00 -1304949.175 0.50 -1304964.588 1.00 -1305012.316 0.50 -1305034.947 1.00 -1305056.498 0.50 -1305071.433 0.00 -1305078.479 0.50 -1305086.886 1.00 -1305111.303 0.50 -1305123.950 1.00 -1305127.879 0.50 -1305132.242 1.00 -1305135.716 0.50 -1305140.603 1.00 -1305144.069 0.50 -1305148.825 1.00 -1305152.880 0.50 -1305158.699 1.00 -1305162.057 0.50 -1305168.106 1.00 -1305176.877 0.50 -1305192.136 0.00 -1305199.516 0.50 -1305206.007 1.00 -1305232.334 0.50 -1305234.115 0.00 -1305245.411 0.50 -1305252.611 1.00 -1305308.677 0.50 -1305319.714 0.00 -1305327.160 0.50 -1305339.765 1.00 -1305345.502 0.50 -1305353.891 1.00 -1305360.727 0.50 -1305370.367 1.00 -1305382.614 0.50 -1305404.041 1.00 -1305480.738 0.50 -1305504.378 1.00 -1305514.951 0.50 -1305536.821 1.00 -1305567.074 0.50 -1305594.413 1.00 -1305610.959 0.50 -1305631.496 1.00 -1305686.197 0.50 -1305712.259 1.00 -1305727.618 0.50 -1305742.024 1.00 -1305770.369 0.50 -1305783.995 1.00 -1305807.428 0.50 -1305813.329 0.00 -1305832.088 0.50 -1305888.240 1.00 -1305893.515 0.50 -1305920.984 1.00 -1305922.460 0.50 -1305952.530 1.00 -1305961.048 0.50 -1305972.370 1.00 -1305975.704 0.50 -1305994.539 1.00 -1306000.231 0.50 -1306007.662 1.00 -1306012.745 0.50 -1306018.660 1.00 -1306024.251 0.50 -1306031.062 1.00 -1306036.169 0.50 -1306042.053 1.00 -1306046.201 0.50 -1306051.923 1.00 -1306055.204 0.50 -1306061.397 1.00 -1306068.757 0.50 -1306077.209 1.00 -1306082.911 0.50 -1306089.960 1.00 -1306095.305 0.50 -1306102.116 1.00 -1306106.899 0.50 -1306113.792 1.00 -1306118.325 0.50 -1306125.177 1.00 -1306129.472 0.50 -1306135.484 1.00 -1306139.885 0.50 -1306146.163 1.00 -1306151.014 0.50 -1306157.922 1.00 -1306162.843 0.50 -1306169.196 1.00 -1306173.805 0.50 -1306180.863 1.00 -1306186.221 0.50 -1306192.428 1.00 -1306198.940 0.50 -1306207.747 1.00 -1306213.896 0.50 -1306224.076 1.00 -1306224.570 0.50 -1306244.535 1.00 -1306251.719 0.50 -1306258.625 1.00 -1306262.340 0.50 -1306266.639 1.00 -1306269.915 0.50 -1306274.647 1.00 -1306278.288 0.50 -1306284.148 1.00 -1306288.891 0.50 -1306295.085 1.00 -1306316.875 0.50 -1306337.294 1.00 -1306373.980 0.50 -1306390.469 1.00 -1306410.407 0.50 -1306431.241 0.00 -1306438.072 0.50 -1306444.023 1.00 -1306475.533 0.50 -1306487.743 1.00 -1306501.791 0.50 -1306520.623 1.00 -1306546.595 0.50 -1306556.205 0.00 -1306561.231 0.50 -1306570.551 1.00 -1306596.581 0.50 -1306597.755 0.00 -1306609.046 0.50 -1306616.486 1.00 -1306620.257 0.50 -1306625.100 1.00 -1306628.442 0.50 -1306633.053 1.00 -1306638.535 0.50 -1306643.545 1.00 -1306647.468 0.50 -1306651.973 1.00 -1306655.289 0.50 -1306659.951 1.00 -1306663.338 0.50 -1306667.811 1.00 -1306671.169 0.50 -1306676.051 1.00 -1306680.523 0.50 -1306685.372 1.00 -1306688.634 0.50 -1306692.987 1.00 -1306696.272 0.50 -1306701.710 1.00 -1306706.054 0.50 -1306710.872 1.00 -1306714.195 0.50 -1306719.516 1.00 -1306723.164 0.50 -1306727.419 1.00 -1306730.709 0.50 -1306739.454 1.00 -1306745.991 0.50 -1306751.542 1.00 -1306756.065 0.50 -1306756.354 0.00 -1306761.979 0.50 -1306766.736 0.00 -1306773.560 0.50 -1306776.655 1.00 -1306781.569 0.50 -1306790.612 0.00 -1306792.355 0.50 -1306802.720 1.00 -1306806.557 0.50 -1306811.402 0.00 -1306869.300 0.50 -1306875.443 0.00 -1306886.823 0.50 -1306898.727 0.00 -1306924.051 0.50 -1306929.726 0.00 -1306948.288 0.50 -1306999.684 1.00 -1307020.185 0.50 -1307038.067 0.00 -1307056.365 0.50 -1307059.257 1.00 -1307084.938 0.50 -1307095.699 1.00 -1307099.265 0.50 -1307154.918 1.00 -1307163.906 0.50 -1307269.010 1.00 -1307275.994 0.50 -1307300.490 1.00 -1307307.680 0.50 -1307478.161 0.00 -1307484.883 0.50 -1307497.332 1.00 -1307515.476 0.50 -1307531.573 1.00 -1307536.897 0.50 -1307545.301 1.00 -1307547.707 0.50 -1307551.859 0.00 -1307575.711 0.50 -1307583.147 0.00 -1313028.908 0.50 -1313043.492 0.00 -1313044.487 0.50 -1313088.907 0.00 -1313107.910 0.50 -1313112.001 0.00 -1313377.313 0.50 -1313383.481 0.00 -1313415.699 0.50 -1313465.770 0.00 -1313482.463 0.50 -1313486.229 0.00 -1316552.854 0.50 -1316569.677 0.00 -1316583.573 0.50 -1316625.438 0.00 -1316644.297 0.50 -1316648.163 0.00 -1316874.269 0.50 -1316881.752 0.00 -1316912.943 0.50 -1316958.130 0.00 -1316974.511 0.50 -1316978.142 0.00 -1319995.186 0.50 -1320025.818 0.00 -1320040.609 0.50 -1320044.432 0.00 -1320214.501 0.50 -1320214.870 1.00 -1320221.281 0.50 -1320270.219 0.00 -1320297.734 0.50 -1320303.704 0.00 -1333333.783 0.50 -1333386.811 0.00 -1333412.514 0.50 -1333412.634 1.00 -1333418.805 0.50 -1333418.933 0.00 -1333430.989 0.50 -1333469.596 0.00 -1333486.409 0.50 -1333490.897 0.00 -1346545.220 0.50 -1346551.558 1.00 -1346557.434 0.50 -1346606.273 0.00 -1346633.938 0.50 -1346640.148 0.00 -1347130.799 0.50 -1347181.604 0.00 -1347201.196 0.50 -1347205.096 0.00 -1353197.202 0.50 -1353243.345 0.00 -1353265.362 0.50 -1353269.535 0.00 -1353631.730 0.50 -1353696.535 0.00 -1353696.939 0.50 -1353712.876 1.00 -1353716.802 0.50 -1353730.416 0.00 -1353754.700 0.50 -1353758.956 0.00 -1358452.236 0.50 -1358458.994 0.00 -1358473.590 0.50 -1358523.159 0.00 -1358542.082 0.50 -1358545.952 0.00 -1358967.387 0.50 -1359027.712 0.00 -1359051.943 0.50 -1359070.658 0.00 -1363809.927 0.50 -1363860.938 0.00 -1363885.600 0.50 -1363890.292 0.00 -1364374.287 0.50 -1364433.513 0.00 -1364452.289 0.50 -1364456.250 0.00 -1368751.598 0.50 -1368796.172 0.00 -1368816.259 0.50 -1368820.470 0.00 -1369233.364 0.50 -1369285.700 0.00 -1369303.293 0.50 -1369306.996 0.00 -1373388.953 0.50 -1373389.096 1.00 -1373396.919 0.50 -1373442.745 0.00 -1373498.990 0.50 -1373505.271 0.00 -1373792.113 0.50 -1373798.465 0.00 -1373807.331 0.50 -1373852.739 0.00 -1373877.596 0.50 -1373884.279 0.00 -1373892.118 0.50 -1373914.139 0.00 -1373935.631 0.50 -1373948.425 0.00 -1387284.123 0.50 -1387301.770 0.00 -1387620.271 0.50 -1387635.470 0.00 -1804975.977 0.50 -1805012.283 0.00 -1805063.076 0.50 -1805068.493 0.00 -1805259.310 0.50 -1805292.870 0.00 -1805312.310 0.50 -1805350.358 1.00 -1805350.562 0.50 -1805386.009 0.00 -1805425.680 0.50 -1805431.066 0.00 -1843677.054 0.50 -1843737.041 1.00 -1843768.695 0.50 -1843815.161 0.00 -1843827.225 0.50 -1843860.017 1.00 -1843861.862 0.50 -1843891.732 1.00 -1843907.874 0.50 -1843922.152 0.00 -1843936.415 0.50 -1843992.420 1.00 -1844012.594 0.50 -1844033.640 1.00 -1844072.396 0.50 -1844093.056 1.00 -1844104.457 0.50 -1844126.888 1.00 -1844192.738 0.50 -1844231.819 1.00 -1844276.782 0.50 -1844639.970 1.00 -1844690.377 0.50 -1844718.199 1.00 -1844750.254 0.50 -1844782.026 1.00 -1844822.422 0.50 -1844849.633 1.00 -1844884.140 0.50 -1844910.803 1.00 -1844942.276 0.50 -1844947.737 0.00 -1844965.071 0.50 -1844970.793 1.00 -1845017.478 0.50 -1845051.566 0.00 -1845052.547 0.50 -1845069.252 1.00 -1845086.468 0.50 -1845104.383 0.00 -1845110.994 0.50 -1845126.065 1.00 -1845146.179 0.50 -1845155.068 0.00 diff --git a/examples/testbench/good_band/tsv/Mem_0x1e00000000000000.tsv b/examples/testbench/good_band/tsv/Mem_0x1e00000000000000.tsv deleted file mode 100644 index 1e1740690..000000000 --- a/examples/testbench/good_band/tsv/Mem_0x1e00000000000000.tsv +++ /dev/null @@ -1,12 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -11 1278823.735 1844793.065 #00fff6 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000001 $Size: 19.073 MiB 13 68 -10 1279061.877 1845081.180 #00fff6 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000002 $Size: 19.073 MiB 15 70 -9 1280061.606 1844985.437 #00fff6 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000003 $Size: 19.073 MiB 24 79 -8 1280246.078 1844919.518 #00fff6 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000004 $Size: 19.073 MiB 23 77 -7 1281367.754 1844726.221 #00fff6 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000005 $Size: 19.073 MiB 36 191 -6 1281572.958 1845134.718 #00fff6 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000006 $Size: 19.073 MiB 38 81 -5 1282612.241 1844151.087 #ff0038 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000007 $Size: 19.073 MiB 47 71 -4 1282784.125 1844240.657 #ff0038 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000008 $Size: 19.073 MiB 48 73 -3 1283563.847 1844857.709 #ff0038 1.0 Region: ispace:1[0:2499999] x fspace:1$Fields: [fid:1048581]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000009 $Size: 19.073 MiB 52 291 -2 1283746.860 1845119.817 #ff0038 1.0 Region: ispace:1[2500000:4999999] x fspace:1$Fields: [fid:1048581]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000a $Size: 19.073 MiB 53 148 -1 1307133.149 1844651.511 #ff6e00 1.0 Region: ispace:1[0:4999999] x fspace:1$Fields: [fid:1048580]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000b $Size: 38.147 MiB 79 75 diff --git a/examples/testbench/good_band/tsv/None.tsv b/examples/testbench/good_band/tsv/None.tsv deleted file mode 100644 index cc466a54c..000000000 --- a/examples/testbench/good_band/tsv/None.tsv +++ /dev/null @@ -1,5 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -3 1306638.074 1306645.058 #ffa700 1.0 Intersection Reduction 80 506 -3 1306677.611 1306682.376 #ffa700 1.0 Intersection Reduction 80 649 -3 1306758.499 1306839.247 #ffa700 1.0 Union Reduction 80 650 -3 1307245.719 1307250.230 #ff6e00 1.0 Difference 79 696 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000000.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000000.tsv deleted file mode 100644 index 568ef7a40..000000000 --- a/examples/testbench/good_band/tsv/Proc_0x1d00000000000000.tsv +++ /dev/null @@ -1,304 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -5 5 493801.174 493837.510 493896.375 #f100ff 1.0 Deferred Enqueue Task 1 [[0, 4, 12]] 149 -5 5 493931.677 493931.677 493944.124 #ffc0cb 1.0 ProfTask <1> 167 -5 5 494015.963 494058.742 494101.567 #3dff00 1.0 Task Physical Dependence Analysis 1 [[0, 4, 12]] 150 -5 5 494130.615 494130.615 494135.463 #ffc0cb 1.0 ProfTask <1> 168 -5 5 494172.288 494208.875 494348.350 #3dff00 1.0 Task Physical Dependence Analysis 1 [[0, 4, 12]] 194 -5 5 1164217.469 1164265.110 1164304.048 #00ff12 1.0 Logical Dependence Analysis 3 14 -5 5 1164388.574 1164405.071 1164511.519 #007bff 1.0 Operation Physical Dependence Analysis 3 195 -5 5 1164663.131 1164682.320 1164714.593 #00ff12 1.0 Logical Dependence Analysis 4 17 -5 5 1164756.861 1164778.390 1164819.329 #007bff 1.0 Operation Physical Dependence Analysis 4 196 -5 5 1207223.090 1207271.028 1207307.344 #00ff12 1.0 Logical Dependence Analysis 5 20 -5 5 1207325.288 1207339.179 1207399.159 #007bff 1.0 Operation Physical Dependence Analysis 5 197 -5 5 1257350.514 1257389.335 1257422.422 #00ff12 1.0 Logical Dependence Analysis 6 23 -5 5 1257467.484 1257499.072 1257585.815 #007bff 1.0 Operation Physical Dependence Analysis 6 25 -5 4 1257570.248 1257609.470 1257624.283 #ff00c5 1.0 Tighten Index Space 6 151 -5 5 1257640.055 1257640.055 1257646.736 #ffc0cb 1.0 ProfTask <6> 169 -5 5 1277801.597 1277848.542 1278028.841 #00ff12 1.0 Logical Dependence Analysis 7 152 -5 4 1278051.446 1278051.446 1278056.549 #ffc0cb 1.0 ProfTask <7> 170 -5 5 1278050.047 1278063.442 1278119.561 #007bff 1.0 Operation Physical Dependence Analysis 8 153 -5 5 1278137.033 1278137.033 1278141.642 #ffc0cb 1.0 ProfTask <8> 171 -5 4 1278141.192 1278163.934 1278205.113 #007bff 1.0 Operation Physical Dependence Analysis 7 30 -5 5 1278287.286 1278323.593 1278440.201 #3dff00 1.0 Task Physical Dependence Analysis 9 34 -5 4 1278415.518 1278461.160 1278541.424 #ff7a00 1.0 Scheduler 0 36 -5 4 1278546.753 1278559.476 1278619.622 #00ff12 1.0 Logical Dependence Analysis 12 38 -5 3 1278596.469 1278638.486 1278664.513 #333399 1.0 Deferred Ready Trigger 14 275 -5 5 1278523.822 1278680.314 1278712.234 #3dff00 1.0 Task Physical Dependence Analysis 11 40 -5 3 1278726.859 1278726.859 1278745.693 #cd00ff 1.0 Defer Task Perform Mapping 15 [[0, 3, 567]] 282 -5 3 1278745.693 1278745.693 1279400.852 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 15 282 -5 3 1279400.852 1279400.852 1279508.879 #cd00ff 0.45 Defer Task Perform Mapping (ready) 15 282 -5 3 1279508.879 1279508.879 1279580.044 #cd00ff 1.0 Defer Task Perform Mapping 15 282 -4 4 1278654.209 1278783.666 1278801.586 #007bff 1.0 Operation Physical Dependence Analysis 14 42 -4 5 1278792.897 1278818.753 1278849.780 #333399 1.0 Deferred Ready Trigger 12 43 -4 4 1278839.559 1278893.781 1278918.912 #007bff 1.0 Operation Physical Dependence Analysis 12 44 -4 5 1278940.842 1278940.842 1278989.270 #ff7a00 1.0 Scheduler 0 279 -4 5 1278989.270 1278989.270 1279378.141 #ff7a00 0.15 Scheduler (waiting) 0 279 -4 5 1279378.141 1279378.141 1279418.725 #ff7a00 0.45 Scheduler (ready) 0 279 -4 5 1279418.725 1279418.725 1279467.951 #ff7a00 1.0 Scheduler 0 279 -3 4 1279017.443 1279017.443 1279092.823 #00b1ff 1.0 Mapper Continuation 15 [[0, 3, 567]] 277 -3 4 1279092.823 1279092.823 1279124.275 #00b1ff 0.15 Mapper Continuation (waiting) 15 277 -3 4 1279124.275 1279124.275 1279256.387 #00b1ff 0.45 Mapper Continuation (ready) 15 277 -3 4 1279256.387 1279256.387 1279375.598 #00b1ff 1.0 Mapper Continuation 15 277 -2 2 1279021.995 1279021.995 1279292.319 #ff3200 1.0 Mapper Call map_task for 15 15 [[0, 3, 567]] 406 -1 1 1279090.815 1279127.934 1279198.924 #ff0098 1.0 Defer Task Launch 13 [[0, 2, 566]] 409 -5 4 1279454.633 1279616.772 1279698.571 #3dff00 1.0 Task Physical Dependence Analysis 16 200 -5 3 1279718.086 1279718.086 1279761.109 #ff7a00 1.0 Scheduler 0 205 -5 3 1279761.109 1279761.109 1279808.204 #ff7a00 0.15 Scheduler (waiting) 0 205 -5 3 1279808.204 1279808.204 1279823.597 #ff7a00 0.45 Scheduler (ready) 0 205 -5 3 1279823.597 1279823.597 1279872.496 #ff7a00 1.0 Scheduler 0 205 -4 4 1279755.896 1279777.897 1279794.261 #00b1ff 1.0 Mapper Continuation 0 202 -5 5 1279581.924 1279895.526 1279925.030 #007bff 1.0 Operation Physical Dependence Analysis 19 207 -5 2 1279765.397 1279947.145 1280008.249 #3dff00 1.0 Task Physical Dependence Analysis 21 210 -5 5 1280036.518 1280036.518 1280057.763 #cd00ff 1.0 Defer Task Perform Mapping 23 [[0, 2, 568]] 324 -5 5 1280057.763 1280057.763 1280397.540 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 23 324 -5 5 1280397.540 1280397.540 1280519.467 #cd00ff 0.45 Defer Task Perform Mapping (ready) 23 324 -5 5 1280519.467 1280519.467 1280590.069 #cd00ff 1.0 Defer Task Perform Mapping 23 324 -4 4 1279899.473 1280076.936 1280123.017 #007bff 1.0 Operation Physical Dependence Analysis 18 211 -4 3 1280137.759 1280137.759 1280175.444 #ff7a00 1.0 Scheduler 0 322 -4 3 1280175.444 1280175.444 1280388.340 #ff7a00 0.15 Scheduler (waiting) 0 322 -4 3 1280388.340 1280388.340 1280415.218 #ff7a00 0.45 Scheduler (ready) 0 322 -4 3 1280415.218 1280415.218 1280480.415 #ff7a00 1.0 Scheduler 0 322 -3 4 1280192.631 1280192.631 1280273.101 #00b1ff 1.0 Mapper Continuation 23 [[0, 2, 568]] 321 -3 4 1280273.101 1280273.101 1280295.077 #00b1ff 0.15 Mapper Continuation (waiting) 23 321 -3 4 1280295.077 1280295.077 1280320.312 #00b1ff 0.45 Mapper Continuation (ready) 23 321 -3 4 1280320.312 1280320.312 1280368.275 #00b1ff 1.0 Mapper Continuation 23 321 -2 2 1280198.716 1280198.716 1280346.233 #ff3200 1.0 Mapper Call map_task for 23 23 [[0, 2, 568]] 407 -5 4 1280489.436 1280618.696 1280704.966 #ff7a00 1.0 Scheduler 0 327 -5 3 1280589.954 1280724.974 1280799.920 #3dff00 1.0 Task Physical Dependence Analysis 26 329 -5 4 1280766.907 1280819.690 1280903.705 #ff7a00 1.0 Scheduler 0 331 -5 3 1280815.462 1280923.262 1280949.533 #333399 1.0 Deferred Ready Trigger 32 447 -5 5 1280664.164 1280975.106 1281006.901 #007bff 1.0 Operation Physical Dependence Analysis 20 154 -5 3 1281026.198 1281026.198 1281082.549 #ff7a00 1.0 Scheduler 0 336 -5 3 1281082.549 1281082.549 1281148.698 #ff7a00 0.15 Scheduler (waiting) 0 336 -5 3 1281148.698 1281148.698 1281168.977 #ff7a00 0.45 Scheduler (ready) 0 336 -5 3 1281168.977 1281168.977 1281221.133 #ff7a00 1.0 Scheduler 0 336 -4 5 1281075.860 1281102.897 1281128.249 #00b1ff 1.0 Mapper Continuation 0 333 -5 2 1280891.200 1281244.468 1281304.887 #3dff00 1.0 Task Physical Dependence Analysis 30 339 -5 5 1281331.290 1281331.290 1281352.380 #00ff12 1.0 Logical Dependence Analysis 37 343 -5 5 1281352.380 1281352.380 1281562.024 #00ff12 0.15 Logical Dependence Analysis (waiting) 37 343 -5 5 1281562.024 1281562.024 1281578.718 #00ff12 0.45 Logical Dependence Analysis (ready) 37 343 -5 5 1281578.718 1281578.718 1281646.649 #00ff12 1.0 Logical Dependence Analysis 37 343 -4 4 1280936.111 1281369.623 1281426.948 #3dff00 1.0 Task Physical Dependence Analysis 31 340 -4 3 1281441.165 1281441.165 1281453.949 #cd00ff 1.0 Defer Task Perform Mapping 38 [[0, 3, 624]] 411 -4 3 1281453.949 1281453.949 1281693.157 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 38 411 -4 3 1281693.157 1281693.157 1281711.894 #cd00ff 0.45 Defer Task Perform Mapping (ready) 38 411 -4 3 1281711.894 1281711.894 1281795.038 #cd00ff 1.0 Defer Task Perform Mapping 38 411 -3 1 1280938.299 1281469.680 1281491.546 #007bff 1.0 Operation Physical Dependence Analysis 32 341 -3 4 1281477.968 1281511.464 1281542.779 #00b1ff 1.0 Mapper Continuation 37 410 -5 2 1281516.045 1281662.778 1281687.437 #ff0098 1.0 Defer Task Launch 36 [[0, 2, 623]] 345 -5 4 1281801.212 1281819.066 1281914.727 #ff7a00 1.0 Scheduler 0 413 -5 5 1281774.812 1281935.560 1281968.754 #ff0098 1.0 Defer Task Launch 38 [[0, 3, 624]] 157 -5 3 1281901.157 1281987.215 1282052.736 #3dff00 1.0 Task Physical Dependence Analysis 40 160 -5 5 1282030.295 1282073.815 1282135.609 #cd00ff 1.0 Defer Task Perform Mapping 42 [[0, 2, 3]] 163 -5 4 1282124.752 1282156.494 1282184.635 #ff0098 1.0 Defer Task Launch 42 [[0, 2, 3]] 216 -5 5 1282145.674 1282204.439 1282231.574 #ff0098 1.0 Defer Task Launch 43 [[0, 3, 626]] 218 -5 5 1282247.509 1282247.509 1282254.507 #ffc0cb 1.0 ProfTask <24> 361 -5 4 1282253.820 1282263.334 1282350.095 #ff7a00 1.0 Scheduler 0 220 -5 5 1282370.051 1282370.051 1282376.626 #ffc0cb 1.0 ProfTask <0> 362 -5 5 1282383.996 1282383.996 1282390.851 #ffc0cb 1.0 ProfTask <23> 363 -5 4 1282398.511 1282398.511 1282404.761 #ffc0cb 1.0 ProfTask <0> 364 -5 5 1282397.684 1282412.358 1282495.982 #ff7a00 1.0 Scheduler 0 222 -5 4 1282483.446 1282517.522 1282570.883 #3dff00 1.0 Task Physical Dependence Analysis 45 414 -5 5 1282524.958 1282589.505 1282637.613 #3dff00 1.0 Task Physical Dependence Analysis 46 347 -5 5 1282666.567 1282666.567 1282670.256 #ffc0cb 1.0 ProfTask <25> 365 -5 5 1282676.118 1282676.118 1282682.844 #ffc0cb 1.0 ProfTask <23> 366 -5 5 1282687.683 1282687.683 1282691.027 #ffc0cb 1.0 ProfTask <0> 367 -5 5 1282695.682 1282695.682 1282699.349 #ffc0cb 1.0 ProfTask <20> 368 -5 5 1282704.941 1282704.941 1282708.191 #ffc0cb 1.0 ProfTask <0> 369 -5 5 1282712.962 1282712.962 1282717.209 #ffc0cb 1.0 ProfTask <23> 370 -5 5 1282721.947 1282721.947 1282725.259 #ffc0cb 1.0 ProfTask <26> 371 -5 5 1282729.621 1282729.621 1282732.909 #ffc0cb 1.0 ProfTask <29> 372 -5 5 1282738.061 1282738.061 1282742.186 #ffc0cb 1.0 ProfTask <0> 373 -5 4 1282747.803 1282747.803 1282829.910 #00b1ff 1.0 Mapper Continuation 48 [[0, 3, 627]] 348 -5 4 1282829.910 1282829.910 1282854.537 #00b1ff 0.15 Mapper Continuation (waiting) 48 348 -5 4 1282854.537 1282854.537 1282869.073 #00b1ff 0.45 Mapper Continuation (ready) 48 348 -5 4 1282869.073 1282869.073 1282880.412 #00b1ff 1.0 Mapper Continuation 48 348 -4 5 1282752.164 1282752.164 1282873.147 #ff3200 1.0 Mapper Call map_task for 48 48 [[0, 3, 627]] 360 -3 3 1282844.366 1282844.366 1282849.739 #ffc0cb 1.0 ProfTask <20> 172 -3 3 1282856.291 1282856.291 1282859.931 #ffc0cb 1.0 ProfTask <27> 173 -5 5 1282895.492 1282895.492 1282898.743 #ffc0cb 1.0 ProfTask <33> 374 -5 5 1282903.269 1282903.269 1282906.398 #ffc0cb 1.0 ProfTask <0> 375 -5 5 1282911.963 1282911.963 1282915.130 #ffc0cb 1.0 ProfTask <33> 376 -5 5 1282919.738 1282919.738 1282922.982 #ffc0cb 1.0 ProfTask <28> 377 -5 5 1282928.128 1282928.128 1282935.817 #ffc0cb 1.0 ProfTask <0> 378 -5 4 1282928.718 1282942.383 1282966.964 #ff0098 1.0 Defer Task Launch 47 [[0, 2, 5]] 415 -5 5 1282986.367 1282986.367 1282991.345 #ffc0cb 1.0 ProfTask <35> 379 -5 5 1282998.561 1282998.561 1283003.565 #ffc0cb 1.0 ProfTask <35> 380 -5 5 1283010.418 1283010.418 1283015.397 #ffc0cb 1.0 ProfTask <30> 381 -5 5 1283022.770 1283022.770 1283027.895 #ffc0cb 1.0 ProfTask <36> 382 -5 5 1283034.875 1283034.875 1283040.014 #ffc0cb 1.0 ProfTask <31> 383 -5 5 1283046.978 1283046.978 1283052.050 #ffc0cb 1.0 ProfTask <32> 384 -5 4 1283059.186 1283059.186 1283065.631 #ffc0cb 1.0 ProfTask <36> 385 -5 5 1283057.281 1283073.383 1283110.127 #333399 1.0 Deferred Ready Trigger 37 416 -5 4 1283098.619 1283130.304 1283163.621 #007bff 1.0 Operation Physical Dependence Analysis 37 417 -5 5 1283182.622 1283182.622 1283188.104 #ffc0cb 1.0 ProfTask <38> 386 -5 5 1283195.694 1283195.694 1283204.944 #ffc0cb 1.0 ProfTask <37> 387 -5 5 1283211.677 1283211.677 1283220.390 #ffc0cb 1.0 ProfTask <38> 388 -5 5 1283227.561 1283227.561 1283232.886 #ffc0cb 1.0 ProfTask <36> 389 -5 4 1283239.761 1283239.761 1283244.909 #ffc0cb 1.0 ProfTask <39> 390 -5 5 1283238.880 1283252.211 1283324.969 #3dff00 1.0 Task Physical Dependence Analysis 49 353 -5 4 1283309.549 1283344.437 1283430.716 #ff7a00 1.0 Scheduler 0 354 -5 5 1283418.585 1283450.278 1283500.409 #3dff00 1.0 Task Physical Dependence Analysis 51 355 -5 4 1283519.252 1283519.252 1283537.974 #cd00ff 1.0 Defer Task Perform Mapping 53 [[0, 3, 265]] 357 -5 4 1283537.974 1283537.974 1283903.575 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 53 357 -5 4 1283903.575 1283903.575 1283930.408 #cd00ff 0.45 Defer Task Perform Mapping (ready) 53 357 -5 4 1283930.408 1283930.408 1283991.577 #cd00ff 1.0 Defer Task Perform Mapping 53 357 -4 5 1283621.832 1283621.832 1283626.988 #ffc0cb 1.0 ProfTask <38> 174 -4 5 1283634.116 1283634.116 1283639.765 #ffc0cb 1.0 ProfTask <39> 175 -4 5 1283647.210 1283647.210 1283652.142 #ffc0cb 1.0 ProfTask <40> 176 -4 5 1283658.525 1283658.525 1283663.327 #ffc0cb 1.0 ProfTask <41> 177 -4 5 1283669.788 1283669.788 1283674.776 #ffc0cb 1.0 ProfTask <42> 178 -4 5 1283681.015 1283681.015 1283687.272 #ffc0cb 1.0 ProfTask <43> 179 -4 3 1283695.521 1283695.521 1283809.423 #00b1ff 1.0 Mapper Continuation 53 [[0, 3, 265]] 356 -4 3 1283809.423 1283809.423 1283835.904 #00b1ff 0.15 Mapper Continuation (waiting) 53 356 -4 3 1283835.904 1283835.904 1283879.069 #00b1ff 0.45 Mapper Continuation (ready) 53 356 -4 3 1283879.069 1283879.069 1283891.905 #00b1ff 1.0 Mapper Continuation 53 356 -3 5 1283702.060 1283702.060 1283883.843 #ff3200 1.0 Mapper Call map_task for 53 53 [[0, 3, 265]] 166 -2 2 1283839.563 1283839.563 1283846.958 #ffc0cb 1.0 ProfTask <0> 408 -5 5 1283982.687 1284006.864 1284031.957 #ff0098 1.0 Defer Task Launch 53 [[0, 3, 265]] 359 -5 5 1284046.066 1284046.066 1284050.070 #ffc0cb 1.0 ProfTask <46> 391 -5 5 1284055.707 1284055.707 1284060.505 #ffc0cb 1.0 ProfTask <48> 392 -5 5 1284067.513 1284067.513 1284074.595 #ffc0cb 1.0 ProfTask <47> 393 -5 5 1284080.228 1284080.228 1284086.541 #ffc0cb 1.0 ProfTask <48> 394 -5 5 1284092.440 1284092.440 1284096.296 #ffc0cb 1.0 ProfTask <48> 395 -5 5 1284101.982 1284101.982 1284106.383 #ffc0cb 1.0 ProfTask <0> 396 -5 5 1284111.488 1284111.488 1284115.765 #ffc0cb 1.0 ProfTask <49> 397 -5 5 1284121.233 1284121.233 1284125.707 #ffc0cb 1.0 ProfTask <0> 398 -5 5 1284131.344 1284131.344 1284135.349 #ffc0cb 1.0 ProfTask <51> 399 -5 5 1284140.596 1284140.596 1284144.671 #ffc0cb 1.0 ProfTask <52> 400 -5 5 1284149.723 1284149.723 1284156.310 #ffc0cb 1.0 ProfTask <53> 401 -5 5 1284161.552 1284161.552 1284167.611 #ffc0cb 1.0 ProfTask <53> 402 -5 5 1284172.102 1284172.102 1284177.046 #ffc0cb 1.0 ProfTask <52> 403 -5 5 1284182.497 1284182.497 1284189.542 #ffc0cb 1.0 ProfTask <53> 404 -5 5 1290561.994 1290561.994 1290581.206 #ffc0cb 1.0 ProfTask <13> 595 -5 5 1290672.470 1290672.470 1290682.613 #ffc0cb 1.0 ProfTask <13> 596 -5 5 1290706.341 1290706.341 1290712.299 #ffc0cb 1.0 ProfTask <15> 597 -5 4 1290710.670 1290721.686 1290793.748 #006600 1.0 Post-Task Execution 15 [[0, 3, 567]] 571 -5 5 1290814.031 1290814.031 1290821.681 #ffc0cb 1.0 ProfTask <15> 598 -5 5 1290851.820 1290851.820 1290857.268 #ffc0cb 1.0 ProfTask <7> 599 -5 5 1301189.824 1301189.824 1301196.603 #ffc0cb 1.0 ProfTask <23> 600 -5 5 1301544.868 1301544.868 1301552.926 #ffc0cb 1.0 ProfTask <24> 601 -5 5 1301590.084 1301606.151 1301641.799 #009900 1.0 Deferred Commit 12 450 -5 5 1303148.986 1303168.646 1303283.977 #00ff12 1.0 Logical Dependence Analysis 54 573 -5 5 1303305.777 1303305.777 1303312.883 #ffc0cb 1.0 ProfTask <54> 602 -5 4 1303306.411 1303321.376 1303396.088 #007bff 1.0 Operation Physical Dependence Analysis 54 574 -5 5 1303414.273 1303414.273 1303418.400 #ffc0cb 1.0 ProfTask <54> 603 -5 5 1303469.495 1303483.722 1303558.517 #3dff00 1.0 Task Physical Dependence Analysis 55 454 -5 4 1303573.877 1303573.877 1303624.181 #ff7a00 1.0 Scheduler 0 457 -5 4 1303624.181 1303624.181 1303725.332 #ff7a00 0.15 Scheduler (waiting) 0 457 -5 4 1303725.332 1303725.332 1303745.784 #ff7a00 0.45 Scheduler (ready) 0 457 -5 4 1303745.784 1303745.784 1303770.128 #ff7a00 1.0 Scheduler 0 457 -5 4 1303770.128 1303770.128 1303829.434 #ff7a00 0.15 Scheduler (waiting) 0 457 -5 4 1303829.434 1303829.434 1303845.931 #ff7a00 0.45 Scheduler (ready) 0 457 -5 4 1303845.931 1303845.931 1303879.903 #ff7a00 1.0 Scheduler 0 457 -4 5 1303618.687 1303670.965 1303704.125 #00b1ff 1.0 Mapper Continuation 0 456 -4 5 1303762.868 1303786.168 1303811.406 #00b1ff 1.0 Mapper Continuation 0 577 -5 5 1303866.667 1303909.035 1303965.082 #3dff00 1.0 Task Physical Dependence Analysis 57 460 -5 5 1303983.695 1303983.695 1303988.852 #ffc0cb 1.0 ProfTask <56> 604 -5 5 1303996.469 1303996.469 1304002.083 #ffc0cb 1.0 ProfTask <58> 605 -5 4 1304001.260 1304010.979 1304053.638 #333399 1.0 Deferred Ready Trigger 59 579 -5 5 1304076.332 1304076.332 1304082.034 #ffc0cb 1.0 ProfTask <0> 606 -5 4 1304089.969 1304089.969 1304095.865 #ffc0cb 1.0 ProfTask <58> 607 -5 5 1304085.798 1304104.636 1304201.779 #ff7a00 1.0 Scheduler 0 581 -5 4 1304200.689 1304225.353 1304297.327 #00ff12 1.0 Logical Dependence Analysis 62 583 -5 5 1304252.409 1304317.260 1304388.941 #ff7a00 1.0 Scheduler 0 585 -5 4 1304379.607 1304402.496 1304450.999 #3dff00 1.0 Task Physical Dependence Analysis 64 587 -5 5 1304428.149 1304470.099 1304564.826 #cd00ff 1.0 Defer Task Perform Mapping 66 [[0, 3, 269]] 588 -5 4 1304553.849 1304586.431 1304619.350 #ff0098 1.0 Defer Task Launch 66 [[0, 3, 269]] 467 -5 5 1304637.141 1304637.141 1304643.365 #ffc0cb 1.0 ProfTask <59> 608 -5 5 1304651.780 1304651.780 1304658.683 #ffc0cb 1.0 ProfTask <59> 609 -5 5 1304666.550 1304666.550 1304672.388 #ffc0cb 1.0 ProfTask <0> 610 -5 4 1304680.459 1304680.459 1304688.024 #ffc0cb 1.0 ProfTask <61> 611 -5 5 1304679.583 1304698.019 1304772.128 #3dff00 1.0 Task Physical Dependence Analysis 67 469 -5 4 1304740.079 1304792.515 1304888.752 #ff7a00 1.0 Scheduler 0 472 -5 5 1304879.093 1304903.629 1304949.175 #3dff00 1.0 Task Physical Dependence Analysis 69 474 -5 4 1304928.889 1304964.588 1305056.498 #cd00ff 1.0 Defer Task Perform Mapping 71 [[0, 2, 9]] 476 -5 5 1305043.193 1305078.479 1305111.303 #ff0098 1.0 Defer Task Launch 71 [[0, 2, 9]] 479 -5 5 1305123.950 1305123.950 1305127.879 #ffc0cb 1.0 ProfTask <62> 612 -5 5 1305132.242 1305132.242 1305135.716 #ffc0cb 1.0 ProfTask <0> 613 -5 5 1305140.603 1305140.603 1305144.069 #ffc0cb 1.0 ProfTask <0> 614 -5 5 1305148.825 1305148.825 1305152.880 #ffc0cb 1.0 ProfTask <63> 615 -5 4 1305158.699 1305158.699 1305162.057 #ffc0cb 1.0 ProfTask <64> 616 -5 5 1305156.383 1305168.106 1305192.136 #333399 1.0 Deferred Ready Trigger 68 481 -5 4 1305184.035 1305206.007 1305232.334 #007bff 1.0 Operation Physical Dependence Analysis 68 482 -5 5 1305222.067 1305245.411 1305308.677 #ff7a00 1.0 Scheduler 0 484 -5 4 1305299.926 1305327.160 1305382.614 #3dff00 1.0 Task Physical Dependence Analysis 74 589 -5 5 1305369.809 1305404.041 1305514.951 #ff7a00 1.0 Scheduler 0 591 -5 4 1305500.072 1305536.821 1305610.959 #3dff00 1.0 Task Physical Dependence Analysis 76 593 -5 5 1305574.749 1305631.496 1305727.618 #cd00ff 1.0 Defer Task Perform Mapping 78 [[0, 3, 273]] 487 -5 4 1305674.252 1305742.024 1305770.369 #ff0098 1.0 Defer Task Launch 77 [[0, 2, 11]] 488 -5 2 1305711.951 1305783.995 1305813.329 #333399 1.0 Deferred Ready Trigger 73 490 -5 3 1305590.048 1305888.240 1305922.460 #2500ff 1.0 Prepipeline Stage 79 492 -5 5 1305952.530 1305952.530 1305961.048 #ffc0cb 1.0 ProfTask <66> 617 -5 4 1305960.182 1305972.370 1306224.570 #ff7a00 1.0 Scheduler 0 494 -5 5 1306244.535 1306244.535 1306251.719 #ffc0cb 1.0 ProfTask <74> 618 -5 5 1306258.625 1306258.625 1306262.340 #ffc0cb 1.0 ProfTask <0> 619 -5 5 1306266.639 1306266.639 1306269.915 #ffc0cb 1.0 ProfTask <0> 620 -5 5 1306274.647 1306274.647 1306278.288 #ffc0cb 1.0 ProfTask <75> 621 -5 5 1306284.148 1306284.148 1306288.891 #ffc0cb 1.0 ProfTask <76> 622 -5 4 1306287.059 1306295.085 1306373.980 #ff7a00 1.0 Scheduler 0 496 -5 5 1306361.416 1306390.469 1306431.241 #3dff00 1.0 Task Physical Dependence Analysis 82 498 -5 4 1306399.822 1306444.023 1306475.533 #3dff00 1.0 Task Physical Dependence Analysis 83 499 -5 5 1306461.902 1306487.743 1306556.205 #cd00ff 1.0 Defer Task Perform Mapping 85 [[0, 3, 630]] 504 -5 4 1306548.549 1306570.551 1306596.581 #ff0098 1.0 Defer Task Launch 85 [[0, 3, 630]] 631 -5 5 1306609.046 1306609.046 1306756.065 #007bff 1.0 Operation Physical Dependence Analysis 80 681 -5 5 1306756.065 1306756.065 1306919.478 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 80 681 -5 5 1306919.478 1306919.478 1306948.288 #007bff 0.45 Operation Physical Dependence Analysis (ready) 80 681 -5 5 1306948.288 1306948.288 1307020.185 #007bff 1.0 Operation Physical Dependence Analysis 80 681 -4 4 1306776.655 1306776.655 1306790.612 #ffc0cb 1.0 ProfTask <85> 651 -4 4 1306802.720 1306802.720 1306811.402 #ffc0cb 1.0 ProfTask <80> 652 -4 4 1306869.300 1306869.300 1306875.443 #ffc0cb 1.0 ProfTask <80> 653 -4 4 1306924.051 1306924.051 1306929.726 #ffc0cb 1.0 ProfTask <80> 654 -5 5 1307056.365 1307056.365 1307307.680 #007bff 1.0 Operation Physical Dependence Analysis 79 685 -5 5 1307307.680 1307307.680 1307458.321 #007bff 0.15 Operation Physical Dependence Analysis (waiting) 79 685 -5 5 1307458.321 1307458.321 1307484.883 #007bff 0.45 Operation Physical Dependence Analysis (ready) 79 685 -5 5 1307484.883 1307484.883 1307547.707 #007bff 1.0 Operation Physical Dependence Analysis 79 685 -4 4 1307070.233 1307070.233 1307183.723 #ff5f00 1.0 Mapper Call map_inline for 79 79 594 -5 5 1313028.908 1313028.908 1313043.492 #ffc0cb 1.0 ProfTask <36> 655 -5 5 1313377.313 1313377.313 1313383.481 #ffc0cb 1.0 ProfTask <38> 656 -5 5 1313400.373 1313415.699 1313465.770 #006600 1.0 Post-Task Execution 38 [[0, 3, 624]] 633 -5 5 1313482.463 1313482.463 1313486.229 #ffc0cb 1.0 ProfTask <38> 657 -5 5 1316874.269 1316874.269 1316881.752 #ffc0cb 1.0 ProfTask <35> 658 -5 5 1316889.537 1316912.943 1316958.130 #006600 1.0 Post-Task Execution 35 [[0, 3, 625]] 634 -5 5 1316974.511 1316974.511 1316978.142 #ffc0cb 1.0 ProfTask <35> 659 -5 5 1319981.003 1319995.186 1320025.818 #006600 1.0 Post-Task Execution 42 [[0, 2, 3]] 635 -5 5 1320040.609 1320040.609 1320044.432 #ffc0cb 1.0 ProfTask <42> 660 -5 5 1320214.870 1320214.870 1320221.281 #ffc0cb 1.0 ProfTask <43> 661 -5 5 1333311.079 1333333.783 1333386.811 #006600 1.0 Post-Task Execution 47 [[0, 2, 5]] 689 -5 4 1333412.514 1333412.514 1333418.805 #ffc0cb 1.0 ProfTask <48> 662 -5 5 1333407.103 1333430.989 1333469.596 #006600 1.0 Post-Task Execution 48 [[0, 3, 627]] 636 -5 5 1333486.409 1333486.409 1333490.897 #ffc0cb 1.0 ProfTask <48> 663 -5 5 1346545.220 1346545.220 1346557.434 #ffc0cb 1.0 ProfTask <52> 664 -5 5 1346633.938 1346633.938 1346640.148 #ffc0cb 1.0 ProfTask <52> 665 -5 5 1347111.988 1347130.799 1347181.604 #006600 1.0 Post-Task Execution 53 [[0, 3, 265]] 638 -5 5 1347201.196 1347201.196 1347205.096 #ffc0cb 1.0 ProfTask <53> 666 -5 5 1353173.197 1353197.202 1353243.345 #006600 1.0 Post-Task Execution 58 [[0, 2, 7]] 639 -5 5 1353265.362 1353265.362 1353269.535 #ffc0cb 1.0 ProfTask <58> 667 -5 5 1353611.015 1353631.730 1353696.535 #006600 1.0 Post-Task Execution 60 [[0, 3, 267]] 640 -5 5 1353712.876 1353712.876 1353716.802 #ffc0cb 1.0 ProfTask <60> 668 -5 5 1358452.236 1358452.236 1358458.994 #ffc0cb 1.0 ProfTask <65> 669 -5 5 1358946.400 1358967.387 1359027.712 #006600 1.0 Post-Task Execution 66 [[0, 3, 269]] 692 -5 5 1363780.521 1363809.927 1363860.938 #006600 1.0 Post-Task Execution 71 [[0, 2, 9]] 641 -5 5 1363885.600 1363885.600 1363890.292 #ffc0cb 1.0 ProfTask <71> 670 -5 5 1364357.583 1364374.287 1364433.513 #006600 1.0 Post-Task Execution 72 [[0, 3, 271]] 642 -5 5 1364452.289 1364452.289 1364456.250 #ffc0cb 1.0 ProfTask <72> 671 -5 5 1368727.688 1368751.598 1368796.172 #006600 1.0 Post-Task Execution 77 [[0, 2, 11]] 643 -5 5 1368816.259 1368816.259 1368820.470 #ffc0cb 1.0 ProfTask <77> 672 -5 5 1369208.235 1369233.364 1369285.700 #006600 1.0 Post-Task Execution 78 [[0, 3, 273]] 644 -5 5 1369303.293 1369303.293 1369306.996 #ffc0cb 1.0 ProfTask <78> 673 -5 5 1373352.694 1373388.953 1373442.745 #006600 1.0 Post-Task Execution 84 [[0, 2, 680]] 645 -5 5 1373498.990 1373498.990 1373505.271 #ffc0cb 1.0 ProfTask <84> 674 -5 5 1373792.113 1373792.113 1373798.465 #ffc0cb 1.0 ProfTask <85> 675 -5 5 1373877.596 1373877.596 1373884.279 #ffc0cb 1.0 ProfTask <85> 676 -5 4 1373882.218 1373892.118 1373914.139 #009900 1.0 Deferred Commit 73 693 -5 5 1387284.123 1387284.123 1387301.770 #ffc0cb 1.0 ProfTask <79> 677 -5 5 1387620.271 1387620.271 1387635.470 #ffc0cb 1.0 ProfTask <79> 678 -5 5 1804925.007 1804975.977 1805012.283 #009900 1.0 Deferred Commit 79 694 -5 5 1805222.737 1805259.310 1805292.870 #00ff12 1.0 Logical Dependence Analysis 86 48 -5 5 1805332.667 1805350.358 1805386.009 #007bff 1.0 Operation Physical Dependence Analysis 86 695 -5 5 1843649.095 1843677.054 1843815.161 #00ff12 1.0 Logical Dependence Analysis 89 52 -5 4 1843756.306 1843860.017 1843907.874 #007bff 1.0 Operation Physical Dependence Analysis 89 54 -5 5 1843910.102 1843936.415 1844942.276 #007bff 1.0 Operation Physical Dependence Analysis 87 64 -5 2 1844929.285 1844965.071 1845051.566 #990000 1.0 Deferred Execute 88 287 -5 4 1844821.434 1845069.252 1845104.383 #009900 1.0 Garbage Collection 87 66 -5 3 1844852.242 1845126.065 1845155.068 #009900 1.0 Garbage Collection 87 67 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000001.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000001.tsv deleted file mode 100644 index 6b5ce879a..000000000 --- a/examples/testbench/good_band/tsv/Proc_0x1d00000000000001.tsv +++ /dev/null @@ -1,287 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -4 5 493886.718 493931.102 494029.929 #ff7a00 1.0 Scheduler 0 192 -4 5 494058.910 494058.910 494064.325 #ffc0cb 1.0 ProfTask <0> 228 -4 5 494080.457 494125.428 494193.707 #ff7a00 1.0 Scheduler 0 193 -4 5 494210.784 494210.784 494214.839 #ffc0cb 1.0 ProfTask <0> 229 -4 5 494368.000 494368.000 494371.632 #ffc0cb 1.0 ProfTask <1> 230 -4 5 1164287.507 1164313.229 1164407.217 #333399 1.0 Deferred Ready Trigger 3 15 -4 5 1164541.448 1164541.448 1164549.085 #ffc0cb 1.0 ProfTask <3> 231 -4 5 1164701.605 1164725.526 1164772.567 #333399 1.0 Deferred Ready Trigger 4 18 -4 5 1164842.752 1164842.752 1164848.390 #ffc0cb 1.0 ProfTask <4> 232 -4 5 1207290.361 1207305.822 1207337.594 #333399 1.0 Deferred Ready Trigger 5 21 -4 5 1207424.454 1207424.454 1207430.784 #ffc0cb 1.0 ProfTask <5> 233 -4 5 1257408.526 1257444.005 1257484.492 #333399 1.0 Deferred Ready Trigger 6 24 -4 5 1257563.718 1257595.549 1257615.167 #ff00c5 1.0 Tighten Index Space 6 26 -4 5 1277991.028 1278028.704 1278061.916 #333399 1.0 Deferred Ready Trigger 8 28 -4 5 1278097.793 1278109.764 1278162.126 #333399 1.0 Deferred Ready Trigger 7 198 -4 5 1278180.326 1278180.326 1278186.455 #ffc0cb 1.0 ProfTask <7> 234 -4 5 1278195.856 1278209.774 1278308.664 #ff7a00 1.0 Scheduler 0 32 -4 5 1278390.540 1278426.961 1278505.618 #ff7a00 1.0 Scheduler 0 35 -4 4 1278494.858 1278538.494 1278620.037 #3dff00 1.0 Task Physical Dependence Analysis 10 274 -4 5 1278641.562 1278641.562 1278855.517 #cd00ff 1.0 Defer Task Perform Mapping 13 [[0, 2, 566]] 46 -4 5 1278855.517 1278855.517 1278868.886 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 13 46 -4 5 1278868.886 1278868.886 1278899.184 #cd00ff 0.45 Defer Task Perform Mapping (ready) 13 46 -4 5 1278899.184 1278899.184 1279099.959 #cd00ff 1.0 Defer Task Perform Mapping 13 46 -3 4 1278659.569 1278659.569 1278953.292 #ff3200 1.0 Mapper Call map_task for 13 13 [[0, 2, 566]] 223 -4 3 1279133.630 1279133.630 1279160.544 #00ff12 1.0 Logical Dependence Analysis 17 280 -4 3 1279160.544 1279160.544 1279450.908 #00ff12 0.15 Logical Dependence Analysis (waiting) 17 280 -4 3 1279450.908 1279450.908 1279479.418 #00ff12 0.45 Logical Dependence Analysis (ready) 17 280 -4 3 1279479.418 1279479.418 1279536.461 #00ff12 1.0 Logical Dependence Analysis 17 280 -3 5 1279231.730 1279231.730 1279251.865 #ffc0cb 1.0 ProfTask <13> 422 -3 5 1279300.720 1279320.699 1279351.834 #00b1ff 1.0 Mapper Continuation 0 276 -3 4 1279342.106 1279389.655 1279426.309 #00b1ff 1.0 Mapper Continuation 17 278 -4 5 1279519.469 1279561.577 1279591.038 #333399 1.0 Deferred Ready Trigger 19 281 -4 3 1279568.066 1279611.199 1279651.982 #ff0098 1.0 Defer Task Launch 15 [[0, 3, 567]] 199 -4 5 1279666.777 1279674.758 1279774.382 #ff7a00 1.0 Scheduler 0 201 -4 4 1279554.634 1279792.958 1279866.659 #00ff12 1.0 Logical Dependence Analysis 18 204 -4 5 1279833.746 1279883.399 1279907.765 #333399 1.0 Deferred Ready Trigger 18 206 -4 5 1279909.666 1279921.310 1279945.362 #333399 1.0 Deferred Ready Trigger 17 208 -4 3 1279857.000 1279958.591 1279997.784 #3dff00 1.0 Task Physical Dependence Analysis 22 209 -4 5 1280011.334 1280011.334 1280086.285 #cd00ff 1.0 Defer Task Perform Mapping 24 [[0, 3, 569]] 212 -4 5 1280086.285 1280086.285 1280105.447 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 24 212 -4 5 1280105.447 1280105.447 1280128.872 #cd00ff 0.45 Defer Task Perform Mapping (ready) 24 212 -4 5 1280128.872 1280128.872 1280237.601 #cd00ff 1.0 Defer Task Perform Mapping 24 212 -3 3 1280018.950 1280018.950 1280162.081 #ff3200 1.0 Mapper Call map_task for 24 24 [[0, 3, 569]] 224 -4 3 1280230.049 1280252.240 1280278.040 #ff0098 1.0 Defer Task Launch 24 [[0, 3, 569]] 213 -4 4 1279937.260 1280290.082 1280302.458 #007bff 1.0 Operation Physical Dependence Analysis 17 214 -4 5 1280314.319 1280314.319 1280319.182 #ffc0cb 1.0 ProfTask <15> 235 -4 5 1280324.665 1280324.665 1280328.013 #ffc0cb 1.0 ProfTask <16> 236 -4 5 1280332.985 1280332.985 1280336.186 #ffc0cb 1.0 ProfTask <0> 237 -4 5 1280340.596 1280340.596 1280345.027 #ffc0cb 1.0 ProfTask <0> 238 -4 5 1280349.935 1280349.935 1280354.507 #ffc0cb 1.0 ProfTask <18> 239 -4 4 1280354.292 1280360.608 1280379.031 #00b1ff 1.0 Mapper Continuation 0 320 -4 5 1280397.006 1280397.006 1280404.093 #ffc0cb 1.0 ProfTask <0> 240 -4 5 1280408.793 1280408.793 1280412.723 #ffc0cb 1.0 ProfTask <18> 241 -4 5 1280418.215 1280418.215 1280422.494 #ffc0cb 1.0 ProfTask <19> 242 -4 5 1280427.978 1280427.978 1280432.194 #ffc0cb 1.0 ProfTask <17> 243 -4 5 1280436.774 1280436.774 1280440.821 #ffc0cb 1.0 ProfTask <22> 244 -4 5 1280446.196 1280446.196 1280450.961 #ffc0cb 1.0 ProfTask <21> 245 -4 4 1280450.394 1280456.534 1280500.201 #3dff00 1.0 Task Physical Dependence Analysis 25 323 -4 5 1280469.627 1280517.657 1280620.373 #ff7a00 1.0 Scheduler 0 325 -4 4 1280569.671 1280640.616 1280675.589 #333399 1.0 Deferred Ready Trigger 20 326 -4 3 1280578.972 1280695.112 1280731.408 #ff0098 1.0 Defer Task Launch 23 [[0, 2, 568]] 328 -4 2 1280605.210 1280750.931 1280845.001 #00ff12 1.0 Logical Dependence Analysis 29 330 -4 4 1280785.560 1280864.265 1280948.444 #ff7a00 1.0 Scheduler 0 446 -4 1 1280606.881 1280969.101 1281020.886 #3dff00 1.0 Task Physical Dependence Analysis 27 156 -4 4 1280999.402 1281040.746 1281117.395 #cd00ff 1.0 Defer Task Perform Mapping 33 [[0, 2, 679]] 332 -4 3 1281107.769 1281133.593 1281156.030 #ff0098 1.0 Defer Task Launch 33 [[0, 2, 679]] 334 -4 5 1280692.339 1281168.256 1281202.632 #3dff00 1.0 Task Physical Dependence Analysis 28 335 -4 4 1281185.590 1281216.424 1281263.117 #cd00ff 1.0 Defer Task Perform Mapping 35 [[0, 3, 625]] 337 -4 3 1281256.063 1281278.236 1281307.180 #ff0098 1.0 Defer Task Launch 35 [[0, 3, 625]] 338 -4 4 1281323.992 1281323.992 1281389.743 #cd00ff 1.0 Defer Task Perform Mapping 36 [[0, 2, 623]] 342 -4 4 1281389.743 1281389.743 1281408.233 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 36 342 -4 4 1281408.233 1281408.233 1281431.771 #cd00ff 0.45 Defer Task Perform Mapping (ready) 36 342 -4 4 1281431.771 1281431.771 1281524.905 #cd00ff 1.0 Defer Task Perform Mapping 36 342 -3 3 1281330.745 1281330.745 1281473.517 #ff3200 1.0 Mapper Call map_task for 36 36 [[0, 2, 623]] 225 -4 4 1281540.900 1281540.900 1281592.395 #00b1ff 1.0 Mapper Continuation 38 [[0, 3, 624]] 344 -4 4 1281592.395 1281592.395 1281613.947 #00b1ff 0.15 Mapper Continuation (waiting) 38 344 -4 4 1281613.947 1281613.947 1281635.375 #00b1ff 0.45 Mapper Continuation (ready) 38 344 -4 4 1281635.375 1281635.375 1281672.107 #00b1ff 1.0 Mapper Continuation 38 344 -3 3 1281545.926 1281545.926 1281660.734 #ff3200 1.0 Mapper Call map_task for 38 38 [[0, 3, 624]] 226 -4 2 1281620.289 1281702.413 1281728.933 #333399 1.0 Deferred Ready Trigger 39 346 -4 5 1281206.486 1281747.438 1281833.954 #3dff00 1.0 Task Physical Dependence Analysis 34 412 -4 3 1281816.726 1281854.322 1281962.837 #ff7a00 1.0 Scheduler 0 215 -4 4 1281718.810 1281982.725 1281997.474 #007bff 1.0 Operation Physical Dependence Analysis 39 158 -4 5 1281937.145 1282022.385 1282075.305 #3dff00 1.0 Task Physical Dependence Analysis 41 162 -4 4 1282053.287 1282094.433 1282156.222 #cd00ff 1.0 Defer Task Perform Mapping 43 [[0, 3, 626]] 165 -4 5 1282137.435 1282176.348 1282213.490 #333399 1.0 Deferred Ready Trigger 29 217 -4 4 1282201.355 1282232.852 1282265.809 #007bff 1.0 Operation Physical Dependence Analysis 29 219 -4 5 1282284.700 1282284.700 1282290.552 #ffc0cb 1.0 ProfTask <18> 246 -4 5 1282298.502 1282298.502 1282305.272 #ffc0cb 1.0 ProfTask <24> 247 -4 5 1282312.818 1282312.818 1282321.895 #ffc0cb 1.0 ProfTask <23> 248 -4 5 1282329.352 1282329.352 1282334.523 #ffc0cb 1.0 ProfTask <24> 249 -4 4 1282342.111 1282342.111 1282347.445 #ffc0cb 1.0 ProfTask <17> 250 -4 5 1282337.210 1282355.476 1282431.565 #3dff00 1.0 Task Physical Dependence Analysis 44 221 -4 4 1282416.515 1282451.010 1282537.356 #ff7a00 1.0 Scheduler 0 405 -4 5 1282560.296 1282560.296 1282643.907 #cd00ff 1.0 Defer Task Perform Mapping 47 [[0, 2, 5]] 349 -4 5 1282643.907 1282643.907 1282659.879 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 47 349 -4 5 1282659.879 1282659.879 1282716.702 #cd00ff 0.45 Defer Task Perform Mapping (ready) 47 349 -4 5 1282716.702 1282716.702 1282746.859 #cd00ff 1.0 Defer Task Perform Mapping 47 349 -4 5 1282746.859 1282746.859 1282821.799 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 47 349 -4 5 1282821.799 1282821.799 1282841.705 #cd00ff 0.45 Defer Task Perform Mapping (ready) 47 349 -4 5 1282841.705 1282841.705 1282942.785 #cd00ff 1.0 Defer Task Perform Mapping 47 349 -3 4 1282569.138 1282569.138 1282847.965 #ff3200 1.0 Mapper Call map_task for 47 47 [[0, 2, 5]] 227 -2 3 1282663.993 1282663.993 1282701.439 #cd00ff 1.0 Defer Task Perform Mapping 48 [[0, 3, 627]] 350 -2 3 1282701.439 1282701.439 1282890.865 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 48 350 -2 3 1282890.865 1282890.865 1282980.146 #cd00ff 0.45 Defer Task Perform Mapping (ready) 48 350 -2 3 1282980.146 1282980.146 1283076.987 #cd00ff 1.0 Defer Task Perform Mapping 48 350 -1 2 1282805.518 1282805.518 1282813.694 #ffc0cb 1.0 ProfTask <0> 507 -1 2 1282822.188 1282822.188 1282826.005 #ffc0cb 1.0 ProfTask <32> 508 -4 5 1283066.079 1283098.801 1283130.494 #ff0098 1.0 Defer Task Launch 48 [[0, 3, 627]] 351 -4 5 1283150.656 1283150.656 1283156.284 #ffc0cb 1.0 ProfTask <37> 423 -4 4 1283151.820 1283164.014 1283251.950 #ff7a00 1.0 Scheduler 0 352 -4 5 1283272.054 1283272.054 1283278.592 #ffc0cb 1.0 ProfTask <38> 424 -4 5 1283285.846 1283285.846 1283291.196 #ffc0cb 1.0 ProfTask <34> 425 -4 4 1283298.174 1283298.174 1283303.562 #ffc0cb 1.0 ProfTask <0> 426 -4 5 1283293.821 1283311.221 1283395.670 #ff7a00 1.0 Scheduler 0 418 -4 4 1283383.048 1283414.744 1283480.049 #3dff00 1.0 Task Physical Dependence Analysis 50 419 -4 5 1283500.017 1283500.017 1283591.367 #cd00ff 1.0 Defer Task Perform Mapping 52 [[0, 2, 628]] 420 -4 5 1283591.367 1283591.367 1283611.308 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 52 420 -4 5 1283611.308 1283611.308 1283641.409 #cd00ff 0.45 Defer Task Perform Mapping (ready) 52 420 -4 5 1283641.409 1283641.409 1283697.539 #cd00ff 1.0 Defer Task Perform Mapping 52 420 -4 5 1283697.539 1283697.539 1283797.270 #cd00ff 0.15 Defer Task Perform Mapping (waiting) 52 420 -4 5 1283797.270 1283797.270 1283820.015 #cd00ff 0.45 Defer Task Perform Mapping (ready) 52 420 -4 5 1283820.015 1283820.015 1283931.392 #cd00ff 1.0 Defer Task Perform Mapping 52 420 -3 4 1283509.012 1283509.012 1283827.962 #ff3200 1.0 Mapper Call map_task for 52 52 [[0, 2, 628]] 421 -2 3 1283610.289 1283610.289 1283616.905 #ffc0cb 1.0 ProfTask <0> 251 -2 3 1283719.137 1283719.137 1283724.225 #ffc0cb 1.0 ProfTask <42> 252 -2 3 1283731.492 1283731.492 1283736.181 #ffc0cb 1.0 ProfTask <29> 253 -2 3 1283742.804 1283742.804 1283748.666 #ffc0cb 1.0 ProfTask <43> 254 -2 3 1283755.389 1283755.389 1283761.016 #ffc0cb 1.0 ProfTask <29> 255 -2 3 1283770.827 1283770.827 1283775.640 #ffc0cb 1.0 ProfTask <0> 256 -2 3 1283781.939 1283781.939 1283786.622 #ffc0cb 1.0 ProfTask <44> 257 -2 3 1283793.118 1283793.118 1283799.645 #ffc0cb 1.0 ProfTask <0> 258 -4 4 1283918.483 1283956.807 1283996.266 #ff0098 1.0 Defer Task Launch 52 [[0, 2, 628]] 358 -4 5 1284019.731 1284019.731 1284026.542 #ffc0cb 1.0 ProfTask <45> 427 -4 5 1284037.065 1284037.065 1284043.643 #ffc0cb 1.0 ProfTask <47> 428 -4 5 1284052.387 1284052.387 1284059.289 #ffc0cb 1.0 ProfTask <48> 429 -4 5 1284070.087 1284070.087 1284076.801 #ffc0cb 1.0 ProfTask <47> 430 -4 5 1284085.420 1284085.420 1284091.929 #ffc0cb 1.0 ProfTask <37> 431 -4 5 1284100.863 1284100.863 1284107.585 #ffc0cb 1.0 ProfTask <37> 432 -4 5 1284116.830 1284116.830 1284123.552 #ffc0cb 1.0 ProfTask <0> 433 -4 5 1284132.489 1284132.489 1284139.516 #ffc0cb 1.0 ProfTask <50> 434 -4 5 1284148.163 1284148.163 1284154.638 #ffc0cb 1.0 ProfTask <53> 435 -4 5 1284163.452 1284163.452 1284175.585 #ffc0cb 1.0 ProfTask <52> 436 -4 5 1290560.504 1290575.892 1290645.947 #006600 1.0 Post-Task Execution 13 [[0, 2, 566]] 570 -4 5 1290758.990 1290776.945 1290821.356 #009900 1.0 Deferred Commit 7 572 -4 5 1301188.653 1301211.605 1301251.876 #006600 1.0 Post-Task Execution 23 [[0, 2, 568]] 448 -4 5 1301276.326 1301276.326 1301282.541 #ffc0cb 1.0 ProfTask <23> 509 -4 5 1301545.784 1301559.661 1301629.806 #006600 1.0 Post-Task Execution 24 [[0, 3, 569]] 449 -4 5 1301646.722 1301646.722 1301651.116 #ffc0cb 1.0 ProfTask <24> 510 -4 5 1301693.731 1301693.731 1301697.364 #ffc0cb 1.0 ProfTask <12> 511 -4 5 1303264.188 1303281.263 1303320.693 #333399 1.0 Deferred Ready Trigger 54 451 -4 5 1303344.045 1303344.045 1303349.993 #ffc0cb 1.0 ProfTask <54> 512 -4 5 1303381.432 1303396.962 1303482.714 #ff7a00 1.0 Scheduler 0 452 -4 5 1303497.656 1303497.656 1303502.117 #ffc0cb 1.0 ProfTask <0> 513 -4 5 1303531.059 1303545.046 1303642.161 #ff7a00 1.0 Scheduler 0 455 -4 4 1303629.723 1303671.094 1303718.836 #3dff00 1.0 Task Physical Dependence Analysis 56 575 -4 5 1303700.660 1303732.487 1303805.810 #cd00ff 1.0 Defer Task Perform Mapping 58 [[0, 2, 7]] 576 -4 4 1303796.494 1303820.840 1303844.177 #ff0098 1.0 Defer Task Launch 58 [[0, 2, 7]] 578 -4 3 1303712.940 1303856.281 1303908.169 #00ff12 1.0 Logical Dependence Analysis 59 458 -4 5 1303922.034 1303922.034 1303925.681 #ffc0cb 1.0 ProfTask <55> 514 -4 5 1303931.496 1303931.496 1303935.527 #ffc0cb 1.0 ProfTask <0> 515 -4 4 1303940.923 1303940.923 1303944.758 #ffc0cb 1.0 ProfTask <0> 516 -4 5 1303940.359 1303950.746 1304016.012 #cd00ff 1.0 Defer Task Perform Mapping 60 [[0, 3, 267]] 461 -4 4 1304007.690 1304034.134 1304057.203 #ff0098 1.0 Defer Task Launch 60 [[0, 3, 267]] 462 -4 5 1304040.859 1304070.131 1304099.441 #007bff 1.0 Operation Physical Dependence Analysis 59 580 -4 5 1304120.480 1304120.480 1304128.900 #ffc0cb 1.0 ProfTask <0> 517 -4 5 1304137.321 1304137.321 1304143.536 #ffc0cb 1.0 ProfTask <59> 518 -4 5 1304151.481 1304151.481 1304158.130 #ffc0cb 1.0 ProfTask <57> 519 -4 5 1304166.492 1304166.492 1304172.116 #ffc0cb 1.0 ProfTask <60> 520 -4 5 1304179.541 1304179.541 1304185.478 #ffc0cb 1.0 ProfTask <60> 521 -4 5 1304186.066 1304194.596 1304268.486 #3dff00 1.0 Task Physical Dependence Analysis 61 582 -4 4 1304237.028 1304287.341 1304378.464 #ff7a00 1.0 Scheduler 0 584 -4 5 1304364.597 1304398.660 1304436.193 #3dff00 1.0 Task Physical Dependence Analysis 63 586 -4 4 1304419.994 1304450.099 1304504.123 #cd00ff 1.0 Defer Task Perform Mapping 65 [[0, 2, 629]] 463 -4 5 1304497.044 1304516.057 1304538.039 #ff0098 1.0 Defer Task Launch 65 [[0, 2, 629]] 464 -4 5 1304544.115 1304551.018 1304575.121 #333399 1.0 Deferred Ready Trigger 62 465 -4 4 1304566.458 1304587.656 1304609.345 #007bff 1.0 Operation Physical Dependence Analysis 62 466 -4 5 1304600.491 1304622.305 1304690.689 #ff7a00 1.0 Scheduler 0 468 -4 5 1304706.331 1304706.331 1304723.689 #00ff12 1.0 Logical Dependence Analysis 68 471 -4 5 1304723.689 1304723.689 1304798.895 #00ff12 0.15 Logical Dependence Analysis (waiting) 68 471 -4 5 1304798.895 1304798.895 1304816.987 #00ff12 0.45 Logical Dependence Analysis (ready) 68 471 -4 5 1304816.987 1304816.987 1304856.819 #00ff12 1.0 Logical Dependence Analysis 68 471 -3 4 1304719.513 1304762.829 1304783.673 #00b1ff 1.0 Mapper Continuation 68 470 -4 3 1304755.187 1304897.074 1305012.316 #ff7a00 1.0 Scheduler 0 475 -4 5 1305000.679 1305034.947 1305071.433 #3dff00 1.0 Task Physical Dependence Analysis 70 478 -4 4 1305056.724 1305086.886 1305176.877 #cd00ff 1.0 Defer Task Perform Mapping 72 [[0, 3, 271]] 480 -4 5 1305165.964 1305199.516 1305234.115 #ff0098 1.0 Defer Task Launch 72 [[0, 3, 271]] 483 -4 4 1305207.658 1305252.611 1305319.714 #00ff12 1.0 Logical Dependence Analysis 73 485 -4 5 1305339.765 1305339.765 1305345.502 #ffc0cb 1.0 ProfTask <65> 522 -4 5 1305353.891 1305353.891 1305360.727 #ffc0cb 1.0 ProfTask <65> 523 -4 4 1305357.954 1305370.367 1305480.738 #ff7a00 1.0 Scheduler 0 590 -4 5 1305465.200 1305504.378 1305567.074 #3dff00 1.0 Task Physical Dependence Analysis 75 592 -4 4 1305543.778 1305594.413 1305686.197 #cd00ff 1.0 Defer Task Perform Mapping 77 [[0, 2, 11]] 486 -4 5 1305605.824 1305712.259 1305807.428 #00ff12 1.0 Logical Dependence Analysis 79 489 -4 4 1305720.839 1305832.088 1305893.515 #ff0098 1.0 Defer Task Launch 78 [[0, 3, 273]] 491 -4 3 1305802.946 1305920.984 1305975.704 #007bff 1.0 Operation Physical Dependence Analysis 73 493 -4 5 1305994.539 1305994.539 1306000.231 #ffc0cb 1.0 ProfTask <62> 524 -4 5 1306007.662 1306007.662 1306012.745 #ffc0cb 1.0 ProfTask <62> 525 -4 5 1306018.660 1306018.660 1306024.251 #ffc0cb 1.0 ProfTask <66> 526 -4 5 1306031.062 1306031.062 1306036.169 #ffc0cb 1.0 ProfTask <0> 527 -4 5 1306042.053 1306042.053 1306046.201 #ffc0cb 1.0 ProfTask <67> 528 -4 5 1306051.923 1306051.923 1306055.204 #ffc0cb 1.0 ProfTask <68> 529 -4 5 1306061.397 1306061.397 1306068.757 #ffc0cb 1.0 ProfTask <68> 530 -4 5 1306077.209 1306077.209 1306082.911 #ffc0cb 1.0 ProfTask <0> 531 -4 5 1306089.960 1306089.960 1306095.305 #ffc0cb 1.0 ProfTask <69> 532 -4 5 1306102.116 1306102.116 1306106.899 #ffc0cb 1.0 ProfTask <0> 533 -4 5 1306113.792 1306113.792 1306118.325 #ffc0cb 1.0 ProfTask <71> 534 -4 5 1306125.177 1306125.177 1306129.472 #ffc0cb 1.0 ProfTask <70> 535 -4 5 1306135.484 1306135.484 1306139.885 #ffc0cb 1.0 ProfTask <71> 536 -4 5 1306146.163 1306146.163 1306151.014 #ffc0cb 1.0 ProfTask <72> 537 -4 5 1306157.922 1306157.922 1306162.843 #ffc0cb 1.0 ProfTask <68> 538 -4 5 1306169.196 1306169.196 1306173.805 #ffc0cb 1.0 ProfTask <68> 539 -4 5 1306180.863 1306180.863 1306186.221 #ffc0cb 1.0 ProfTask <72> 540 -4 5 1306192.428 1306192.428 1306198.940 #ffc0cb 1.0 ProfTask <0> 541 -4 5 1306207.747 1306207.747 1306213.896 #ffc0cb 1.0 ProfTask <73> 542 -4 4 1306209.300 1306224.076 1306316.875 #3dff00 1.0 Task Physical Dependence Analysis 81 495 -4 5 1306301.406 1306337.294 1306410.407 #ff7a00 1.0 Scheduler 0 497 -4 4 1306409.916 1306438.072 1306501.791 #cd00ff 1.0 Defer Task Perform Mapping 84 [[0, 2, 680]] 501 -4 5 1306493.051 1306520.623 1306546.595 #ff0098 1.0 Defer Task Launch 84 [[0, 2, 680]] 502 -4 4 1306541.621 1306561.231 1306597.755 #333399 1.0 Deferred Ready Trigger 80 505 -4 5 1306616.486 1306616.486 1306620.257 #ffc0cb 1.0 ProfTask <77> 543 -4 5 1306625.100 1306625.100 1306628.442 #ffc0cb 1.0 ProfTask <78> 544 -4 5 1306633.053 1306633.053 1306638.535 #ffc0cb 1.0 ProfTask <77> 545 -4 5 1306643.545 1306643.545 1306647.468 #ffc0cb 1.0 ProfTask <79> 546 -4 5 1306651.973 1306651.973 1306655.289 #ffc0cb 1.0 ProfTask <73> 547 -4 5 1306659.951 1306659.951 1306663.338 #ffc0cb 1.0 ProfTask <78> 548 -4 5 1306667.811 1306667.811 1306671.169 #ffc0cb 1.0 ProfTask <79> 549 -4 5 1306676.051 1306676.051 1306680.523 #ffc0cb 1.0 ProfTask <73> 550 -4 5 1306685.372 1306685.372 1306688.634 #ffc0cb 1.0 ProfTask <0> 551 -4 5 1306692.987 1306692.987 1306696.272 #ffc0cb 1.0 ProfTask <81> 552 -4 5 1306701.710 1306701.710 1306706.054 #ffc0cb 1.0 ProfTask <0> 553 -4 5 1306710.872 1306710.872 1306714.195 #ffc0cb 1.0 ProfTask <0> 554 -4 5 1306719.516 1306719.516 1306723.164 #ffc0cb 1.0 ProfTask <82> 555 -4 5 1306727.419 1306727.419 1306730.709 #ffc0cb 1.0 ProfTask <83> 556 -4 5 1306739.454 1306739.454 1306745.991 #ffc0cb 1.0 ProfTask <84> 557 -4 5 1306751.542 1306751.542 1306756.354 #ffc0cb 1.0 ProfTask <84> 558 -4 5 1306761.979 1306761.979 1306766.736 #ffc0cb 1.0 ProfTask <85> 559 -4 5 1306773.560 1306773.560 1306781.569 #ffc0cb 1.0 ProfTask <80> 560 -4 5 1306792.355 1306792.355 1306806.557 #ffc0cb 1.0 ProfTask <80> 561 -4 5 1306869.972 1306886.823 1306898.727 #ff00c5 1.0 Tighten Index Space 80 632 -4 5 1306982.462 1306999.684 1307038.067 #333399 1.0 Deferred Ready Trigger 79 682 -4 5 1307059.257 1307059.257 1307084.938 #ffc0cb 1.0 ProfTask <80> 697 -4 5 1307095.699 1307095.699 1307099.265 #ffc0cb 1.0 ProfTask <79> 698 -4 5 1307154.918 1307154.918 1307163.906 #ffc0cb 1.0 ProfTask <79> 699 -4 5 1307269.010 1307269.010 1307275.994 #ffc0cb 1.0 ProfTask <79> 700 -4 5 1307284.634 1307300.490 1307478.161 #1f00ff 1.0 Copy Fill Aggregation 79 683 -4 4 1307468.389 1307497.332 1307515.476 #00ff0f 1.0 Copy Fill Deletion 79 684 -4 5 1307531.573 1307531.573 1307536.897 #ffc0cb 1.0 ProfTask <79> 701 -4 5 1307545.301 1307545.301 1307551.859 #ffc0cb 1.0 ProfTask <79> 702 -4 5 1307575.711 1307575.711 1307583.147 #ffc0cb 1.0 ProfTask <79> 703 -4 5 1313026.911 1313044.487 1313088.907 #006600 1.0 Post-Task Execution 36 [[0, 2, 623]] 686 -4 5 1313107.910 1313107.910 1313112.001 #ffc0cb 1.0 ProfTask <36> 704 -4 5 1316552.854 1316552.854 1316569.677 #ffc0cb 1.0 ProfTask <33> 705 -4 5 1316573.910 1316583.573 1316625.438 #006600 1.0 Post-Task Execution 33 [[0, 2, 679]] 687 -4 5 1316644.297 1316644.297 1316648.163 #ffc0cb 1.0 ProfTask <33> 706 -4 5 1320198.948 1320214.501 1320270.219 #006600 1.0 Post-Task Execution 43 [[0, 3, 626]] 688 -4 5 1320297.734 1320297.734 1320303.704 #ffc0cb 1.0 ProfTask <43> 707 -4 5 1333412.634 1333412.634 1333418.933 #ffc0cb 1.0 ProfTask <47> 708 -4 5 1346531.958 1346551.558 1346606.273 #006600 1.0 Post-Task Execution 52 [[0, 2, 628]] 637 -4 5 1353664.429 1353696.939 1353730.416 #009900 1.0 Deferred Commit 54 690 -4 5 1353754.700 1353754.700 1353758.956 #ffc0cb 1.0 ProfTask <54> 709 -4 5 1358449.612 1358473.590 1358523.159 #006600 1.0 Post-Task Execution 65 [[0, 2, 629]] 691 -4 5 1358542.082 1358542.082 1358545.952 #ffc0cb 1.0 ProfTask <65> 710 -4 5 1359051.943 1359051.943 1359070.658 #ffc0cb 1.0 ProfTask <66> 711 -4 5 1373389.096 1373389.096 1373396.919 #ffc0cb 1.0 ProfTask <84> 712 -4 5 1373789.041 1373807.331 1373852.739 #006600 1.0 Post-Task Execution 85 [[0, 3, 630]] 646 -4 5 1373935.631 1373935.631 1373948.425 #ffc0cb 1.0 ProfTask <73> 713 -4 5 1805063.076 1805063.076 1805068.493 #ffc0cb 1.0 ProfTask <79> 714 -4 5 1805280.159 1805312.310 1805350.562 #333399 1.0 Deferred Ready Trigger 86 49 -4 5 1805425.680 1805425.680 1805431.066 #ffc0cb 1.0 ProfTask <86> 715 -4 5 1843719.392 1843737.041 1843768.695 #333399 1.0 Deferred Ready Trigger 89 51 -4 5 1843810.280 1843827.225 1843861.862 #006600 1.0 Post-Task Execution 1 [[0, 4, 12]] 53 -4 5 1843867.763 1843891.732 1843922.152 #333399 1.0 Deferred Ready Trigger 87 283 -4 5 1843972.301 1843992.420 1844012.594 #333399 1.0 Deferred Ready Trigger 88 56 -4 4 1844004.598 1844033.640 1844072.396 #007bff 1.0 Operation Physical Dependence Analysis 88 57 -4 3 1844042.014 1844093.056 1844104.457 #f7ff00 1.0 Trigger Complete 1 [[0, 4, 12]] 58 -4 5 1844020.689 1844126.888 1844192.738 #009900 1.0 Garbage Collection 87 60 -4 2 1844044.059 1844231.819 1844276.782 #009900 1.0 Garbage Collection 87 61 -4 5 1844608.555 1844639.970 1844690.377 #009900 1.0 Garbage Collection 87 284 -4 4 1844673.494 1844718.199 1844750.254 #009900 1.0 Garbage Collection 87 62 -4 3 1844689.761 1844782.026 1844822.422 #009900 1.0 Garbage Collection 87 63 -4 5 1844704.569 1844849.633 1844884.140 #009900 1.0 Garbage Collection 87 285 -4 2 1844722.002 1844910.803 1844947.737 #009900 1.0 Garbage Collection 87 286 -4 4 1844804.386 1844970.793 1845017.478 #009900 1.0 Garbage Collection 87 65 -4 5 1845022.789 1845052.547 1845086.468 #ff8c00 1.0 Top Finish 0 288 -4 3 1844835.242 1845110.994 1845146.179 #009900 1.0 Garbage Collection 87 289 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000002.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000002.tsv deleted file mode 100644 index 0b0a39c8e..000000000 --- a/examples/testbench/good_band/tsv/Proc_0x1d00000000000002.tsv +++ /dev/null @@ -1,67 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -1 3 1164390.880 1164390.880 1164404.064 #ffc0cb 1.0 ProfTask <3> 82 -1 3 1164431.041 1164431.041 1164436.216 #ffc0cb 1.0 ProfTask <3> 83 -1 3 1164746.447 1164746.447 1164753.372 #ffc0cb 1.0 ProfTask <4> 84 -1 3 1164794.721 1164794.721 1164801.321 #ffc0cb 1.0 ProfTask <4> 85 -1 3 1207340.857 1207340.857 1207348.217 #ffc0cb 1.0 ProfTask <5> 86 -1 3 1207357.779 1207357.779 1207362.525 #ffc0cb 1.0 ProfTask <5> 87 -1 3 1257468.208 1257468.208 1257475.225 #ffc0cb 1.0 ProfTask <6> 88 -1 3 1257512.563 1257512.563 1257518.405 #ffc0cb 1.0 ProfTask <6> 89 -1 3 1257612.061 1257612.061 1257621.839 #ffc0cb 1.0 ProfTask <6> 90 -1 3 1257633.588 1257633.588 1257640.573 #ffc0cb 1.0 ProfTask <6> 91 -1 3 1278088.519 1278088.519 1278094.369 #ffc0cb 1.0 ProfTask <8> 92 -1 3 1278227.506 1278227.506 1278250.584 #ffc0cb 1.0 ProfTask <7> 93 -1 3 1278329.460 1278329.460 1278341.946 #ffc0cb 1.0 ProfTask <0> 94 -1 3 1278465.635 1278465.635 1278473.130 #ffc0cb 1.0 ProfTask <9> 95 -1 3 1278531.783 1278531.783 1278539.848 #ffc0cb 1.0 ProfTask <0> 96 -1 3 1278559.197 1278559.197 1278563.854 #ffc0cb 1.0 ProfTask <0> 97 -1 3 1278647.025 1278647.025 1278654.038 #ffc0cb 1.0 ProfTask <12> 98 -1 3 1278732.052 1278732.052 1278737.425 #ffc0cb 1.0 ProfTask <11> 99 -1 3 1278822.472 1278822.472 1278827.664 #ffc0cb 1.0 ProfTask <14> 100 -1 3 1278836.004 1278836.004 1278846.984 #ffc0cb 1.0 ProfTask <13> 101 -1 3 1278863.656 1278863.656 1278867.667 #ffc0cb 1.0 ProfTask <12> 102 -1 3 1278941.853 1278941.853 1278947.582 #ffc0cb 1.0 ProfTask <12> 103 -1 3 1279087.247 1279087.247 1279093.462 #ffc0cb 1.0 ProfTask <15> 104 -1 3 1279119.581 1279119.581 1279132.688 #ffc0cb 1.0 ProfTask <13> 105 -1 3 1279182.513 1279195.488 1290530.227 #00fff6 1.0 legate::numpy::FillTask [CPU] <13> [[0, 1, 570], [0, 3, 624]] [[0, 0, 409], [0, 1, 223], [0, 1, 46]] [[0, 4, 12]] 566 -1 2 1280719.209 1290575.311 1301160.372 #00fff6 1.0 legate::numpy::FillTask [CPU] <23> [[0, 1, 448], [0, 3, 626]] [[0, 1, 328], [0, 0, 321], [0, 0, 407], [0, 0, 324]] [[0, 4, 12]] 568 -1 1 1281679.018 1301205.707 1312999.079 #00fff6 1.0 legate::numpy::FillTask [CPU] <36> [[0, 1, 686]] [[0, 2, 628], [0, 1, 342], [0, 1, 225], [0, 3, 265], [0, 0, 345]] [[0, 4, 12]] 623 -1 3 1290605.372 1313041.542 1316508.577 #00fff6 1.0 legate::numpy::FillTask [CPU] <33> [[0, 1, 687]] [[0, 1, 334], [0, 1, 332]] [[0, 4, 12]] 679 -1 2 1301228.669 1316545.328 1319918.397 #00fff6 1.0 legate::numpy::FillTask [CPU] <42> [[0, 0, 635]] [[0, 0, 163], [0, 0, 216]] [[0, 4, 12]] 3 -1 3 1319957.314 1319957.314 1319964.781 #ffc0cb 1.0 ProfTask <42> 106 -1 3 1319992.164 1320009.542 1333283.719 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <47> [[0, 2, 628], [0, 0, 689]] [[0, 1, 227], [0, 0, 415], [0, 1, 349]] [[0, 4, 12]] 5 -1 3 1333326.173 1333326.173 1333334.715 #ffc0cb 1.0 ProfTask <47> 107 -1 3 1333355.300 1333381.736 1346503.982 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <52> [[0, 2, 7], [0, 2, 623], [0, 1, 637]] [[0, 1, 420], [0, 1, 421], [0, 1, 358], [0, 2, 5]] [[0, 4, 12]] 628 -1 3 1346566.949 1346589.948 1353143.177 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <58> [[0, 3, 269], [0, 0, 639]] [[0, 1, 576], [0, 1, 578], [0, 2, 628]] [[0, 4, 12]] 7 -1 3 1353185.134 1353185.134 1353193.257 #ffc0cb 1.0 ProfTask <58> 108 -1 3 1353219.426 1353240.213 1358415.641 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <65> [[0, 1, 691], [0, 2, 9], [0, 3, 267]] [[0, 1, 463], [0, 1, 464], [0, 3, 265]] [[0, 4, 12]] 629 -1 3 1358489.897 1358516.042 1363745.920 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <71> [[0, 0, 641], [0, 2, 11]] [[0, 0, 479], [0, 2, 629], [0, 0, 476]] [[0, 4, 12]] 9 -1 3 1363795.948 1363795.948 1363805.182 #ffc0cb 1.0 ProfTask <71> 109 -1 3 1363840.145 1363869.877 1368701.245 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <77> [[0, 3, 630], [0, 0, 643]] [[0, 0, 488], [0, 2, 9], [0, 1, 486]] [[0, 4, 12]] 11 -1 3 1368739.249 1368739.249 1368746.421 #ffc0cb 1.0 ProfTask <77> 110 -1 3 1368771.516 1368793.530 1373328.678 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <84> [[0, 0, 645]] [[0, 1, 502], [0, 1, 501], [0, 3, 273]] [[0, 4, 12]] 680 -1 3 1805328.138 1805328.138 1805337.533 #ffc0cb 1.0 ProfTask <86> 111 -1 3 1805375.803 1805375.803 1805382.225 #ffc0cb 1.0 ProfTask <86> 112 -1 3 1843775.371 1843775.371 1843805.275 #ffc0cb 1.0 ProfTask <1> 113 -1 3 1843817.171 1843817.171 1843824.922 #ffc0cb 1.0 ProfTask <89> 114 -1 3 1843844.761 1843844.761 1843861.109 #ffc0cb 1.0 ProfTask <89> 115 -1 3 1843886.263 1843886.263 1843893.154 #ffc0cb 1.0 ProfTask <1> 116 -1 3 1843937.108 1843937.108 1843943.529 #ffc0cb 1.0 ProfTask <89> 117 -1 3 1844034.676 1844034.676 1844041.454 #ffc0cb 1.0 ProfTask <88> 118 -1 3 1844091.466 1844091.466 1844097.428 #ffc0cb 1.0 ProfTask <88> 119 -1 3 1844123.736 1844123.736 1844129.659 #ffc0cb 1.0 ProfTask <1> 120 -1 3 1844167.643 1844167.643 1844182.143 #ffc0cb 1.0 ProfTask <47> 121 -1 3 1844214.123 1844214.123 1844221.266 #ffc0cb 1.0 ProfTask <87> 122 -1 3 1844257.222 1844257.222 1844263.836 #ffc0cb 1.0 ProfTask <48> 123 -1 3 1844301.260 1844301.260 1844305.938 #ffc0cb 1.0 ProfTask <87> 124 -1 3 1844676.874 1844676.874 1844697.739 #ffc0cb 1.0 ProfTask <79> 125 -1 3 1844770.899 1844770.899 1844776.660 #ffc0cb 1.0 ProfTask <87> 126 -1 3 1844809.980 1844809.980 1844816.809 #ffc0cb 1.0 ProfTask <13> 127 -1 3 1844857.582 1844857.582 1844865.890 #ffc0cb 1.0 ProfTask <87> 128 -1 3 1844935.962 1844935.962 1844943.256 #ffc0cb 1.0 ProfTask <23> 129 -1 3 1844963.598 1844963.598 1844971.617 #ffc0cb 1.0 ProfTask <87> 130 -1 3 1845015.224 1845015.224 1845023.543 #ffc0cb 1.0 ProfTask <24> 131 -1 3 1845051.132 1845051.132 1845067.224 #ffc0cb 1.0 ProfTask <87> 132 -1 3 1845129.295 1845129.295 1845137.136 #ffc0cb 1.0 ProfTask <87> 133 -1 3 1845147.332 1845147.332 1845163.365 #ffc0cb 1.0 ProfTask <38> 134 -1 3 1845171.090 1845171.090 1845177.515 #ffc0cb 1.0 ProfTask <87> 135 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000003.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000003.tsv deleted file mode 100644 index 251bedb73..000000000 --- a/examples/testbench/good_band/tsv/Proc_0x1d00000000000003.tsv +++ /dev/null @@ -1,38 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -1 3 1278661.355 1278661.355 1278670.464 #ffc0cb 1.0 ProfTask <10> 292 -1 3 1278677.818 1278677.818 1278682.210 #ffc0cb 1.0 ProfTask <14> 293 -1 3 1279381.573 1279381.573 1279387.931 #ffc0cb 1.0 ProfTask <0> 294 -1 3 1279397.429 1279397.429 1279409.712 #ffc0cb 1.0 ProfTask <15> 295 -1 3 1279450.771 1279450.771 1279457.216 #ffc0cb 1.0 ProfTask <17> 296 -1 3 1279491.926 1279491.926 1279502.598 #ffc0cb 1.0 ProfTask <0> 297 -1 3 1279554.996 1279554.996 1279565.486 #ffc0cb 1.0 ProfTask <17> 298 -1 3 1279612.008 1279612.008 1279618.651 #ffc0cb 1.0 ProfTask <19> 299 -1 3 1279629.022 1279629.022 1279637.142 #ffc0cb 1.0 ProfTask <15> 300 -1 3 1279637.815 1279646.909 1290673.584 #00fff6 1.0 legate::numpy::FillTask [CPU] <15> [[0, 0, 571]] [[0, 0, 406], [0, 0, 277], [0, 0, 282], [0, 1, 199], [0, 3, 569]] [[0, 4, 12]] 567 -1 2 1280268.662 1290724.634 1301522.032 #00fff6 1.0 legate::numpy::FillTask [CPU] <24> [[0, 3, 567], [0, 1, 449]] [[0, 1, 212], [0, 1, 224], [0, 1, 213]] 569 -1 1 1281955.581 1301559.534 1313329.507 #00fff6 1.0 legate::numpy::FillTask [CPU] <38> [[0, 3, 627], [0, 0, 633]] [[0, 2, 566], [0, 1, 344], [0, 0, 157], [0, 0, 411], [0, 1, 226]] [[0, 4, 12]] 624 -1 3 1290746.977 1313364.414 1316831.920 #00fff6 1.0 legate::numpy::FillTask [CPU] <35> [[0, 0, 634]] [[0, 1, 337], [0, 3, 626], [0, 1, 338]] 625 -1 2 1301577.337 1316862.415 1320182.092 #00fff6 1.0 legate::numpy::FillTask [CPU] <43> [[0, 1, 688], [0, 3, 625], [0, 3, 627]] [[0, 1, 165], [0, 0, 218], [0, 2, 568]] [[0, 4, 12]] 626 -1 3 1320203.531 1320208.211 1333389.695 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <48> [[0, 0, 636], [0, 3, 265]] [[0, 0, 348], [0, 1, 351], [0, 3, 626], [0, 3, 624], [0, 0, 360], [0, 1, 350]] [[0, 4, 12]] 627 -1 3 1333436.151 1333450.382 1347048.850 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <53> [[0, 2, 623], [0, 0, 638], [0, 2, 629]] [[0, 0, 359], [0, 0, 357], [0, 0, 356], [0, 3, 627], [0, 0, 166]] [[0, 4, 12]] 265 -1 3 1347087.138 1347087.138 1347098.437 #ffc0cb 1.0 ProfTask <53> 301 -1 3 1347122.092 1347145.449 1353587.731 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <60> [[0, 0, 640]] [[0, 3, 269], [0, 1, 461], [0, 2, 629], [0, 1, 462]] [[0, 4, 12]] 267 -1 3 1353620.664 1353620.664 1353625.527 #ffc0cb 1.0 ProfTask <60> 302 -1 3 1353653.992 1353676.454 1358922.645 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <66> [[0, 0, 692], [0, 3, 271], [0, 3, 267]] [[0, 2, 7], [0, 0, 467], [0, 0, 588]] [[0, 4, 12]] 269 -1 3 1358955.630 1358955.630 1358961.897 #ffc0cb 1.0 ProfTask <66> 303 -1 3 1358980.811 1359020.346 1364298.334 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <72> [[0, 0, 642], [0, 3, 273]] [[0, 1, 480], [0, 3, 269], [0, 1, 483]] [[0, 4, 12]] 271 -1 3 1364340.083 1364340.083 1364346.914 #ffc0cb 1.0 ProfTask <72> 304 -1 3 1364370.248 1364383.652 1369149.144 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <78> [[0, 0, 644], [0, 2, 680]] [[0, 1, 491], [0, 3, 271], [0, 0, 487]] [[0, 4, 12]] 273 -1 3 1369188.043 1369188.043 1369203.231 #ffc0cb 1.0 ProfTask <78> 305 -1 3 1369224.914 1369248.466 1373764.764 #ff0038 1.0 legate::numpy::BinaryOpTask [CPU] <85> [[0, 1, 646]] [[0, 0, 631], [0, 0, 504], [0, 2, 11]] [[0, 4, 12]] 630 -1 3 1843951.637 1843951.637 1843966.439 #ffc0cb 1.0 ProfTask <87> 306 -1 3 1844723.767 1844723.767 1844730.441 #ffc0cb 1.0 ProfTask <87> 307 -1 3 1844738.308 1844738.308 1844743.158 #ffc0cb 1.0 ProfTask <36> 308 -1 3 1844874.628 1844874.628 1844891.521 #ffc0cb 1.0 ProfTask <52> 309 -1 3 1844898.768 1844898.768 1844902.397 #ffc0cb 1.0 ProfTask <87> 310 -1 3 1844966.386 1844966.386 1844973.976 #ffc0cb 1.0 ProfTask <87> 311 -1 3 1845079.615 1845079.615 1845085.862 #ffc0cb 1.0 ProfTask <88> 312 -1 3 1845092.849 1845092.849 1845096.644 #ffc0cb 1.0 ProfTask <15> 313 -1 3 1845103.389 1845103.389 1845108.412 #ffc0cb 1.0 ProfTask <0> 314 -1 3 1845132.386 1845132.386 1845139.801 #ffc0cb 1.0 ProfTask <53> 315 -1 3 1845168.715 1845168.715 1845175.087 #ffc0cb 1.0 ProfTask <87> 316 diff --git a/examples/testbench/good_band/tsv/Proc_0x1d00000000000004.tsv b/examples/testbench/good_band/tsv/Proc_0x1d00000000000004.tsv deleted file mode 100644 index 3b3340a0f..000000000 --- a/examples/testbench/good_band/tsv/Proc_0x1d00000000000004.tsv +++ /dev/null @@ -1,20 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -1 1 494356.555 494356.555 1164322.429 #eb00ff 1.0 legion_python_main <1> [[0, 1, 58], [0, 1, 53]] [[0, 0, 150], [0, 0, 149], [0, 0, 194]] [[0, 2, 566], [0, 2, 679], [0, 3, 624], [0, 3, 630], [0, 2, 3], [0, 3, 627], [0, 3, 267], [0, 3, 273], [0, 2, 9], [0, 2, 680], [0, 2, 5], [0, 3, 265], [0, 2, 628], [0, 3, 567], [0, 2, 7], [0, 3, 271], [0, 2, 623], [0, 3, 626], [0, 2, 629], [0, 2, 568], [0, 3, 269], [0, 2, 11]] 12 -1 1 1164322.429 1164322.429 1164469.122 #eb00ff 0.15 legion_python_main <1> (waiting) 12 -1 1 1164469.122 1164469.122 1164554.852 #eb00ff 0.45 legion_python_main <1> (ready) 12 -1 1 1164554.852 1164554.852 1164686.388 #eb00ff 1.0 legion_python_main <1> 12 -1 1 1164686.388 1164686.388 1164801.809 #eb00ff 0.15 legion_python_main <1> (waiting) 12 -1 1 1164801.809 1164801.809 1164823.261 #eb00ff 0.45 legion_python_main <1> (ready) 12 -1 1 1164823.261 1164823.261 1207258.637 #eb00ff 1.0 legion_python_main <1> 12 -1 1 1207258.637 1207258.637 1207381.756 #eb00ff 0.15 legion_python_main <1> (waiting) 12 -1 1 1207381.756 1207381.756 1207422.856 #eb00ff 0.45 legion_python_main <1> (ready) 12 -1 1 1207422.856 1207422.856 1305677.005 #eb00ff 1.0 legion_python_main <1> 12 -1 1 1305677.005 1305677.005 1307506.675 #eb00ff 0.15 legion_python_main <1> (waiting) 12 -1 1 1307506.675 1307506.675 1307537.619 #eb00ff 0.45 legion_python_main <1> (ready) 12 -1 1 1307537.619 1307537.619 1307553.652 #eb00ff 1.0 legion_python_main <1> 12 -1 1 1307553.652 1307553.652 1387621.722 #eb00ff 0.15 legion_python_main <1> (waiting) 12 -1 1 1387621.722 1387621.722 1387655.987 #eb00ff 0.45 legion_python_main <1> (ready) 12 -1 1 1387655.987 1387655.987 1805303.104 #eb00ff 1.0 legion_python_main <1> 12 -1 1 1805303.104 1805303.104 1805357.525 #eb00ff 0.15 legion_python_main <1> (waiting) 12 -1 1 1805357.525 1805357.525 1805398.321 #eb00ff 0.45 legion_python_main <1> (ready) 12 -1 1 1805398.321 1805398.321 1843718.831 #eb00ff 1.0 legion_python_main <1> 12 diff --git a/examples/testbench/good_band/tsv/all (CPU)_util.tsv b/examples/testbench/good_band/tsv/all (CPU)_util.tsv deleted file mode 100644 index 4fe28da97..000000000 --- a/examples/testbench/good_band/tsv/all (CPU)_util.tsv +++ /dev/null @@ -1,208 +0,0 @@ -time count -0.000 0.00 -1164390.880 0.50 -1164404.064 0.00 -1164431.041 0.50 -1164436.216 0.00 -1164746.447 0.50 -1164753.372 0.00 -1164794.721 0.50 -1164801.321 0.00 -1207340.857 0.50 -1207348.217 0.00 -1207357.779 0.50 -1207362.525 0.00 -1257468.208 0.50 -1257475.225 0.00 -1257512.563 0.50 -1257518.405 0.00 -1257612.061 0.50 -1257621.839 0.00 -1257633.588 0.50 -1257640.573 0.00 -1278088.519 0.50 -1278094.369 0.00 -1278227.506 0.50 -1278250.584 0.00 -1278329.460 0.50 -1278341.946 0.00 -1278465.635 0.50 -1278473.130 0.00 -1278531.783 0.50 -1278539.848 0.00 -1278559.197 0.50 -1278563.854 0.00 -1278647.025 0.50 -1278654.038 0.00 -1278661.355 0.50 -1278670.464 0.00 -1278677.818 0.50 -1278682.210 0.00 -1278732.052 0.50 -1278737.425 0.00 -1278822.472 0.50 -1278827.664 0.00 -1278836.004 0.50 -1278846.984 0.00 -1278863.656 0.50 -1278867.667 0.00 -1278941.853 0.50 -1278947.582 0.00 -1279087.247 0.50 -1279093.462 0.00 -1279119.581 0.50 -1279132.688 0.00 -1279195.488 0.50 -1279381.573 1.00 -1279387.931 0.50 -1279397.429 1.00 -1279409.712 0.50 -1279450.771 1.00 -1279457.216 0.50 -1279491.926 1.00 -1279502.598 0.50 -1279554.996 1.00 -1279565.486 0.50 -1279612.008 1.00 -1279618.651 0.50 -1279629.022 1.00 -1279637.142 0.50 -1279646.909 1.00 -1290530.227 0.50 -1290575.311 1.00 -1290673.584 0.50 -1290724.634 1.00 -1301160.372 0.50 -1301205.707 1.00 -1301522.032 0.50 -1301559.534 1.00 -1312999.079 0.50 -1313041.542 1.00 -1313329.507 0.50 -1313364.414 1.00 -1316508.577 0.50 -1316545.328 1.00 -1316831.920 0.50 -1316862.415 1.00 -1319918.397 0.50 -1319957.314 1.00 -1319964.781 0.50 -1320009.542 1.00 -1320182.092 0.50 -1320208.211 1.00 -1333283.719 0.50 -1333326.173 1.00 -1333334.715 0.50 -1333381.736 1.00 -1333389.695 0.50 -1333450.382 1.00 -1346503.982 0.50 -1346589.948 1.00 -1347048.850 0.50 -1347087.138 1.00 -1347098.437 0.50 -1347145.449 1.00 -1353143.177 0.50 -1353185.134 1.00 -1353193.257 0.50 -1353240.213 1.00 -1353587.731 0.50 -1353620.664 1.00 -1353625.527 0.50 -1353676.454 1.00 -1358415.641 0.50 -1358516.042 1.00 -1358922.645 0.50 -1358955.630 1.00 -1358961.897 0.50 -1359020.346 1.00 -1363745.920 0.50 -1363795.948 1.00 -1363805.182 0.50 -1363869.877 1.00 -1364298.334 0.50 -1364340.083 1.00 -1364346.914 0.50 -1364383.652 1.00 -1368701.245 0.50 -1368739.249 1.00 -1368746.421 0.50 -1368793.530 1.00 -1369149.144 0.50 -1369188.043 1.00 -1369203.231 0.50 -1369248.466 1.00 -1373328.678 0.50 -1373764.764 0.00 -1805328.138 0.50 -1805337.533 0.00 -1805375.803 0.50 -1805382.225 0.00 -1843775.371 0.50 -1843805.275 0.00 -1843817.171 0.50 -1843824.922 0.00 -1843844.761 0.50 -1843861.109 0.00 -1843886.263 0.50 -1843893.154 0.00 -1843937.108 0.50 -1843943.529 0.00 -1843951.637 0.50 -1843966.439 0.00 -1844034.676 0.50 -1844041.454 0.00 -1844091.466 0.50 -1844097.428 0.00 -1844123.736 0.50 -1844129.659 0.00 -1844167.643 0.50 -1844182.143 0.00 -1844214.123 0.50 -1844221.266 0.00 -1844257.222 0.50 -1844263.836 0.00 -1844301.260 0.50 -1844305.938 0.00 -1844676.874 0.50 -1844697.739 0.00 -1844723.767 0.50 -1844730.441 0.00 -1844738.308 0.50 -1844743.158 0.00 -1844770.899 0.50 -1844776.660 0.00 -1844809.980 0.50 -1844816.809 0.00 -1844857.582 0.50 -1844865.890 0.00 -1844874.628 0.50 -1844891.521 0.00 -1844898.768 0.50 -1844902.397 0.00 -1844935.962 0.50 -1844943.256 0.00 -1844963.598 0.50 -1844966.386 1.00 -1844971.617 0.50 -1844973.976 0.00 -1845015.224 0.50 -1845023.543 0.00 -1845051.132 0.50 -1845067.224 0.00 -1845079.615 0.50 -1845085.862 0.00 -1845092.849 0.50 -1845096.644 0.00 -1845103.389 0.50 -1845108.412 0.00 -1845129.295 0.50 -1845132.386 1.00 -1845137.136 0.50 -1845139.801 0.00 -1845147.332 0.50 -1845163.365 0.00 -1845168.715 0.50 -1845171.090 1.00 -1845175.087 0.50 -1845177.515 0.00 diff --git a/examples/testbench/good_band/tsv/all (Channel)_util.tsv b/examples/testbench/good_band/tsv/all (Channel)_util.tsv deleted file mode 100644 index e13bb0242..000000000 --- a/examples/testbench/good_band/tsv/all (Channel)_util.tsv +++ /dev/null @@ -1,4 +0,0 @@ -time count -0.000 0.00 -1373371.458 1.00 -1387561.869 0.00 diff --git a/examples/testbench/good_band/tsv/all (Python)_util.tsv b/examples/testbench/good_band/tsv/all (Python)_util.tsv deleted file mode 100644 index 9d87a3d5a..000000000 --- a/examples/testbench/good_band/tsv/all (Python)_util.tsv +++ /dev/null @@ -1,16 +0,0 @@ -time count -0.000 0.00 -494356.555 1.00 -1164322.429 0.00 -1164554.852 1.00 -1164686.388 0.00 -1164823.261 1.00 -1207258.637 0.00 -1207422.856 1.00 -1305677.005 0.00 -1307537.619 1.00 -1307553.652 0.00 -1387655.987 1.00 -1805303.104 0.00 -1805398.321 1.00 -1843718.831 0.00 diff --git a/examples/testbench/good_band/tsv/all (System Memory)_util.tsv b/examples/testbench/good_band/tsv/all (System Memory)_util.tsv deleted file mode 100644 index c46245cd8..000000000 --- a/examples/testbench/good_band/tsv/all (System Memory)_util.tsv +++ /dev/null @@ -1,24 +0,0 @@ -time count -0.000 0.00 -1278823.735 0.00 -1279061.877 0.01 -1280061.606 0.01 -1280246.078 0.02 -1281367.754 0.02 -1281572.958 0.03 -1282612.241 0.03 -1282784.125 0.04 -1283563.847 0.04 -1283746.860 0.05 -1307133.149 0.06 -1844151.087 0.05 -1844240.657 0.05 -1844651.511 0.04 -1844726.221 0.03 -1844793.065 0.03 -1844857.709 0.02 -1844919.518 0.02 -1844985.437 0.01 -1845081.180 0.01 -1845119.817 0.00 -1845134.718 0.00 diff --git a/examples/testbench/good_band/tsv/all (Utility)_util.tsv b/examples/testbench/good_band/tsv/all (Utility)_util.tsv deleted file mode 100644 index e697ba587..000000000 --- a/examples/testbench/good_band/tsv/all (Utility)_util.tsv +++ /dev/null @@ -1,992 +0,0 @@ -time count -0.000 0.00 -493837.510 0.50 -493896.375 0.00 -493931.102 0.50 -493931.677 1.00 -493944.124 0.50 -494029.929 0.00 -494058.742 0.50 -494058.910 1.00 -494064.325 0.50 -494101.567 0.00 -494125.428 0.50 -494130.615 1.00 -494135.463 0.50 -494193.707 0.00 -494208.875 0.50 -494210.784 1.00 -494214.839 0.50 -494348.350 0.00 -494368.000 0.50 -494371.632 0.00 -1164265.110 0.50 -1164304.048 0.00 -1164313.229 0.50 -1164405.071 1.00 -1164407.217 0.50 -1164511.519 0.00 -1164541.448 0.50 -1164549.085 0.00 -1164682.320 0.50 -1164714.593 0.00 -1164725.526 0.50 -1164772.567 0.00 -1164778.390 0.50 -1164819.329 0.00 -1164842.752 0.50 -1164848.390 0.00 -1207271.028 0.50 -1207305.822 1.00 -1207307.344 0.50 -1207337.594 0.00 -1207339.179 0.50 -1207399.159 0.00 -1207424.454 0.50 -1207430.784 0.00 -1257389.335 0.50 -1257422.422 0.00 -1257444.005 0.50 -1257484.492 0.00 -1257499.072 0.50 -1257585.815 0.00 -1257595.549 0.50 -1257609.470 1.00 -1257615.167 0.50 -1257624.283 0.00 -1257640.055 0.50 -1257646.736 0.00 -1277848.542 0.50 -1278028.704 1.00 -1278028.841 0.50 -1278051.446 1.00 -1278056.549 0.50 -1278061.916 0.00 -1278063.442 0.50 -1278109.764 1.00 -1278119.561 0.50 -1278137.033 1.00 -1278141.642 0.50 -1278162.126 0.00 -1278163.934 0.50 -1278180.326 1.00 -1278186.455 0.50 -1278205.113 0.00 -1278209.774 0.50 -1278308.664 0.00 -1278323.593 0.50 -1278426.961 1.00 -1278440.201 0.50 -1278461.160 1.00 -1278505.618 0.50 -1278538.494 1.00 -1278541.424 0.50 -1278559.476 1.00 -1278619.622 0.50 -1278620.037 0.00 -1278638.486 0.50 -1278641.562 1.00 -1278664.513 0.50 -1278680.314 1.00 -1278712.234 0.50 -1278726.859 1.00 -1278745.693 0.50 -1278783.666 1.00 -1278801.586 0.50 -1278818.753 1.00 -1278849.780 0.50 -1278893.781 1.00 -1278918.912 0.50 -1278940.842 1.00 -1278989.270 0.50 -1279017.443 1.00 -1279099.959 0.50 -1279133.630 1.00 -1279160.544 0.50 -1279231.730 1.00 -1279251.865 0.50 -1279320.699 1.00 -1279351.834 0.50 -1279375.598 0.00 -1279389.655 0.50 -1279418.725 1.00 -1279426.309 0.50 -1279467.951 0.00 -1279479.418 0.50 -1279508.879 1.00 -1279536.461 0.50 -1279561.577 1.00 -1279580.044 0.50 -1279591.038 0.00 -1279611.199 0.50 -1279616.772 1.00 -1279651.982 0.50 -1279674.758 1.00 -1279698.571 0.50 -1279718.086 1.00 -1279761.109 0.50 -1279774.382 0.00 -1279777.897 0.50 -1279792.958 1.00 -1279794.261 0.50 -1279823.597 1.00 -1279866.659 0.50 -1279872.496 0.00 -1279883.399 0.50 -1279895.526 1.00 -1279907.765 0.50 -1279921.310 1.00 -1279925.030 0.50 -1279945.362 0.00 -1279947.145 0.50 -1279958.591 1.00 -1279997.784 0.50 -1280008.249 0.00 -1280011.334 0.50 -1280036.518 1.00 -1280057.763 0.50 -1280076.936 1.00 -1280123.017 0.50 -1280137.759 1.00 -1280175.444 0.50 -1280192.631 1.00 -1280237.601 0.50 -1280252.240 1.00 -1280278.040 0.50 -1280290.082 1.00 -1280302.458 0.50 -1280314.319 1.00 -1280319.182 0.50 -1280324.665 1.00 -1280328.013 0.50 -1280332.985 1.00 -1280336.186 0.50 -1280340.596 1.00 -1280345.027 0.50 -1280349.935 1.00 -1280354.507 0.50 -1280360.608 1.00 -1280368.275 0.50 -1280379.031 0.00 -1280397.006 0.50 -1280404.093 0.00 -1280408.793 0.50 -1280412.723 0.00 -1280415.218 0.50 -1280418.215 1.00 -1280422.494 0.50 -1280427.978 1.00 -1280432.194 0.50 -1280436.774 1.00 -1280440.821 0.50 -1280446.196 1.00 -1280450.961 0.50 -1280456.534 1.00 -1280480.415 0.50 -1280500.201 0.00 -1280517.657 0.50 -1280519.467 1.00 -1280590.069 0.50 -1280618.696 1.00 -1280620.373 0.50 -1280640.616 1.00 -1280675.589 0.50 -1280695.112 1.00 -1280704.966 0.50 -1280724.974 1.00 -1280731.408 0.50 -1280750.931 1.00 -1280799.920 0.50 -1280819.690 1.00 -1280845.001 0.50 -1280864.265 1.00 -1280903.705 0.50 -1280923.262 1.00 -1280948.444 0.50 -1280949.533 0.00 -1280969.101 0.50 -1280975.106 1.00 -1281006.901 0.50 -1281020.886 0.00 -1281026.198 0.50 -1281040.746 1.00 -1281082.549 0.50 -1281102.897 1.00 -1281117.395 0.50 -1281128.249 0.00 -1281133.593 0.50 -1281156.030 0.00 -1281168.256 0.50 -1281168.977 1.00 -1281202.632 0.50 -1281216.424 1.00 -1281221.133 0.50 -1281244.468 1.00 -1281263.117 0.50 -1281278.236 1.00 -1281304.887 0.50 -1281307.180 0.00 -1281323.992 0.50 -1281331.290 1.00 -1281352.380 0.50 -1281369.623 1.00 -1281426.948 0.50 -1281441.165 1.00 -1281453.949 0.50 -1281469.680 1.00 -1281491.546 0.50 -1281511.464 1.00 -1281524.905 0.50 -1281540.900 1.00 -1281542.779 0.50 -1281578.718 1.00 -1281646.649 0.50 -1281662.778 1.00 -1281672.107 0.50 -1281687.437 0.00 -1281702.413 0.50 -1281711.894 1.00 -1281728.933 0.50 -1281747.438 1.00 -1281795.038 0.50 -1281819.066 1.00 -1281833.954 0.50 -1281854.322 1.00 -1281914.727 0.50 -1281935.560 1.00 -1281962.837 0.50 -1281968.754 0.00 -1281982.725 0.50 -1281987.215 1.00 -1281997.474 0.50 -1282022.385 1.00 -1282052.736 0.50 -1282073.815 1.00 -1282075.305 0.50 -1282094.433 1.00 -1282135.609 0.50 -1282156.222 0.00 -1282156.494 0.50 -1282176.348 1.00 -1282184.635 0.50 -1282204.439 1.00 -1282213.490 0.50 -1282231.574 0.00 -1282232.852 0.50 -1282247.509 1.00 -1282254.507 0.50 -1282263.334 1.00 -1282265.809 0.50 -1282284.700 1.00 -1282290.552 0.50 -1282298.502 1.00 -1282305.272 0.50 -1282312.818 1.00 -1282321.895 0.50 -1282329.352 1.00 -1282334.523 0.50 -1282342.111 1.00 -1282347.445 0.50 -1282350.095 0.00 -1282355.476 0.50 -1282370.051 1.00 -1282376.626 0.50 -1282383.996 1.00 -1282390.851 0.50 -1282398.511 1.00 -1282404.761 0.50 -1282412.358 1.00 -1282431.565 0.50 -1282451.010 1.00 -1282495.982 0.50 -1282517.522 1.00 -1282537.356 0.50 -1282560.296 1.00 -1282570.883 0.50 -1282589.505 1.00 -1282637.613 0.50 -1282666.567 1.00 -1282670.256 0.50 -1282676.118 1.00 -1282682.844 0.50 -1282687.683 1.00 -1282691.027 0.50 -1282695.682 1.00 -1282699.349 0.50 -1282704.941 1.00 -1282708.191 0.50 -1282712.962 1.00 -1282717.209 0.50 -1282721.947 1.00 -1282725.259 0.50 -1282729.621 1.00 -1282732.909 0.50 -1282738.061 1.00 -1282742.186 0.50 -1282747.803 1.00 -1282880.412 0.50 -1282895.492 1.00 -1282898.743 0.50 -1282903.269 1.00 -1282906.398 0.50 -1282911.963 1.00 -1282915.130 0.50 -1282919.738 1.00 -1282922.982 0.50 -1282928.128 1.00 -1282935.817 0.50 -1282942.383 1.00 -1282942.785 0.50 -1282966.964 0.00 -1282980.146 0.50 -1282986.367 1.00 -1282991.345 0.50 -1282998.561 1.00 -1283003.565 0.50 -1283010.418 1.00 -1283015.397 0.50 -1283022.770 1.00 -1283027.895 0.50 -1283034.875 1.00 -1283040.014 0.50 -1283046.978 1.00 -1283052.050 0.50 -1283059.186 1.00 -1283065.631 0.50 -1283073.383 1.00 -1283076.987 0.50 -1283098.801 1.00 -1283110.127 0.50 -1283130.304 1.00 -1283130.494 0.50 -1283150.656 1.00 -1283156.284 0.50 -1283163.621 0.00 -1283164.014 0.50 -1283182.622 1.00 -1283188.104 0.50 -1283195.694 1.00 -1283204.944 0.50 -1283211.677 1.00 -1283220.390 0.50 -1283227.561 1.00 -1283232.886 0.50 -1283239.761 1.00 -1283244.909 0.50 -1283251.950 0.00 -1283252.211 0.50 -1283272.054 1.00 -1283278.592 0.50 -1283285.846 1.00 -1283291.196 0.50 -1283298.174 1.00 -1283303.562 0.50 -1283311.221 1.00 -1283324.969 0.50 -1283344.437 1.00 -1283395.670 0.50 -1283414.744 1.00 -1283430.716 0.50 -1283450.278 1.00 -1283480.049 0.50 -1283500.017 1.00 -1283500.409 0.50 -1283519.252 1.00 -1283537.974 0.50 -1283621.832 1.00 -1283626.988 0.50 -1283634.116 1.00 -1283639.765 0.50 -1283647.210 1.00 -1283652.142 0.50 -1283658.525 1.00 -1283663.327 0.50 -1283669.788 1.00 -1283674.776 0.50 -1283681.015 1.00 -1283687.272 0.50 -1283695.521 1.00 -1283891.905 0.50 -1283930.408 1.00 -1283931.392 0.50 -1283956.807 1.00 -1283991.577 0.50 -1283996.266 0.00 -1284006.864 0.50 -1284019.731 1.00 -1284026.542 0.50 -1284031.957 0.00 -1284037.065 0.50 -1284043.643 0.00 -1284046.066 0.50 -1284050.070 0.00 -1284052.387 0.50 -1284055.707 1.00 -1284059.289 0.50 -1284060.505 0.00 -1284067.513 0.50 -1284070.087 1.00 -1284074.595 0.50 -1284076.801 0.00 -1284080.228 0.50 -1284085.420 1.00 -1284086.541 0.50 -1284091.929 0.00 -1284092.440 0.50 -1284096.296 0.00 -1284100.863 0.50 -1284101.982 1.00 -1284106.383 0.50 -1284107.585 0.00 -1284111.488 0.50 -1284115.765 0.00 -1284116.830 0.50 -1284121.233 1.00 -1284123.552 0.50 -1284125.707 0.00 -1284131.344 0.50 -1284132.489 1.00 -1284135.349 0.50 -1284139.516 0.00 -1284140.596 0.50 -1284144.671 0.00 -1284148.163 0.50 -1284149.723 1.00 -1284154.638 0.50 -1284156.310 0.00 -1284161.552 0.50 -1284163.452 1.00 -1284167.611 0.50 -1284172.102 1.00 -1284175.585 0.50 -1284177.046 0.00 -1284182.497 0.50 -1284189.542 0.00 -1290561.994 0.50 -1290575.892 1.00 -1290581.206 0.50 -1290645.947 0.00 -1290672.470 0.50 -1290682.613 0.00 -1290706.341 0.50 -1290712.299 0.00 -1290721.686 0.50 -1290776.945 1.00 -1290793.748 0.50 -1290814.031 1.00 -1290821.356 0.50 -1290821.681 0.00 -1290851.820 0.50 -1290857.268 0.00 -1301189.824 0.50 -1301196.603 0.00 -1301211.605 0.50 -1301251.876 0.00 -1301276.326 0.50 -1301282.541 0.00 -1301544.868 0.50 -1301552.926 0.00 -1301559.661 0.50 -1301606.151 1.00 -1301629.806 0.50 -1301641.799 0.00 -1301646.722 0.50 -1301651.116 0.00 -1301693.731 0.50 -1301697.364 0.00 -1303168.646 0.50 -1303281.263 1.00 -1303283.977 0.50 -1303305.777 1.00 -1303312.883 0.50 -1303320.693 0.00 -1303321.376 0.50 -1303344.045 1.00 -1303349.993 0.50 -1303396.088 0.00 -1303396.962 0.50 -1303414.273 1.00 -1303418.400 0.50 -1303482.714 0.00 -1303483.722 0.50 -1303497.656 1.00 -1303502.117 0.50 -1303545.046 1.00 -1303558.517 0.50 -1303573.877 1.00 -1303624.181 0.50 -1303642.161 0.00 -1303670.965 0.50 -1303671.094 1.00 -1303704.125 0.50 -1303718.836 0.00 -1303732.487 0.50 -1303745.784 1.00 -1303770.128 0.50 -1303786.168 1.00 -1303805.810 0.50 -1303811.406 0.00 -1303820.840 0.50 -1303844.177 0.00 -1303845.931 0.50 -1303856.281 1.00 -1303879.903 0.50 -1303908.169 0.00 -1303909.035 0.50 -1303922.034 1.00 -1303925.681 0.50 -1303931.496 1.00 -1303935.527 0.50 -1303940.923 1.00 -1303944.758 0.50 -1303950.746 1.00 -1303965.082 0.50 -1303983.695 1.00 -1303988.852 0.50 -1303996.469 1.00 -1304002.083 0.50 -1304010.979 1.00 -1304016.012 0.50 -1304034.134 1.00 -1304053.638 0.50 -1304057.203 0.00 -1304070.131 0.50 -1304076.332 1.00 -1304082.034 0.50 -1304089.969 1.00 -1304095.865 0.50 -1304099.441 0.00 -1304104.636 0.50 -1304120.480 1.00 -1304128.900 0.50 -1304137.321 1.00 -1304143.536 0.50 -1304151.481 1.00 -1304158.130 0.50 -1304166.492 1.00 -1304172.116 0.50 -1304179.541 1.00 -1304185.478 0.50 -1304194.596 1.00 -1304201.779 0.50 -1304225.353 1.00 -1304268.486 0.50 -1304287.341 1.00 -1304297.327 0.50 -1304317.260 1.00 -1304378.464 0.50 -1304388.941 0.00 -1304398.660 0.50 -1304402.496 1.00 -1304436.193 0.50 -1304450.099 1.00 -1304450.999 0.50 -1304470.099 1.00 -1304504.123 0.50 -1304516.057 1.00 -1304538.039 0.50 -1304551.018 1.00 -1304564.826 0.50 -1304575.121 0.00 -1304586.431 0.50 -1304587.656 1.00 -1304609.345 0.50 -1304619.350 0.00 -1304622.305 0.50 -1304637.141 1.00 -1304643.365 0.50 -1304651.780 1.00 -1304658.683 0.50 -1304666.550 1.00 -1304672.388 0.50 -1304680.459 1.00 -1304688.024 0.50 -1304690.689 0.00 -1304698.019 0.50 -1304706.331 1.00 -1304723.689 0.50 -1304762.829 1.00 -1304772.128 0.50 -1304783.673 0.00 -1304792.515 0.50 -1304816.987 1.00 -1304856.819 0.50 -1304888.752 0.00 -1304897.074 0.50 -1304903.629 1.00 -1304949.175 0.50 -1304964.588 1.00 -1305012.316 0.50 -1305034.947 1.00 -1305056.498 0.50 -1305071.433 0.00 -1305078.479 0.50 -1305086.886 1.00 -1305111.303 0.50 -1305123.950 1.00 -1305127.879 0.50 -1305132.242 1.00 -1305135.716 0.50 -1305140.603 1.00 -1305144.069 0.50 -1305148.825 1.00 -1305152.880 0.50 -1305158.699 1.00 -1305162.057 0.50 -1305168.106 1.00 -1305176.877 0.50 -1305192.136 0.00 -1305199.516 0.50 -1305206.007 1.00 -1305232.334 0.50 -1305234.115 0.00 -1305245.411 0.50 -1305252.611 1.00 -1305308.677 0.50 -1305319.714 0.00 -1305327.160 0.50 -1305339.765 1.00 -1305345.502 0.50 -1305353.891 1.00 -1305360.727 0.50 -1305370.367 1.00 -1305382.614 0.50 -1305404.041 1.00 -1305480.738 0.50 -1305504.378 1.00 -1305514.951 0.50 -1305536.821 1.00 -1305567.074 0.50 -1305594.413 1.00 -1305610.959 0.50 -1305631.496 1.00 -1305686.197 0.50 -1305712.259 1.00 -1305727.618 0.50 -1305742.024 1.00 -1305770.369 0.50 -1305783.995 1.00 -1305807.428 0.50 -1305813.329 0.00 -1305832.088 0.50 -1305888.240 1.00 -1305893.515 0.50 -1305920.984 1.00 -1305922.460 0.50 -1305952.530 1.00 -1305961.048 0.50 -1305972.370 1.00 -1305975.704 0.50 -1305994.539 1.00 -1306000.231 0.50 -1306007.662 1.00 -1306012.745 0.50 -1306018.660 1.00 -1306024.251 0.50 -1306031.062 1.00 -1306036.169 0.50 -1306042.053 1.00 -1306046.201 0.50 -1306051.923 1.00 -1306055.204 0.50 -1306061.397 1.00 -1306068.757 0.50 -1306077.209 1.00 -1306082.911 0.50 -1306089.960 1.00 -1306095.305 0.50 -1306102.116 1.00 -1306106.899 0.50 -1306113.792 1.00 -1306118.325 0.50 -1306125.177 1.00 -1306129.472 0.50 -1306135.484 1.00 -1306139.885 0.50 -1306146.163 1.00 -1306151.014 0.50 -1306157.922 1.00 -1306162.843 0.50 -1306169.196 1.00 -1306173.805 0.50 -1306180.863 1.00 -1306186.221 0.50 -1306192.428 1.00 -1306198.940 0.50 -1306207.747 1.00 -1306213.896 0.50 -1306224.076 1.00 -1306224.570 0.50 -1306244.535 1.00 -1306251.719 0.50 -1306258.625 1.00 -1306262.340 0.50 -1306266.639 1.00 -1306269.915 0.50 -1306274.647 1.00 -1306278.288 0.50 -1306284.148 1.00 -1306288.891 0.50 -1306295.085 1.00 -1306316.875 0.50 -1306337.294 1.00 -1306373.980 0.50 -1306390.469 1.00 -1306410.407 0.50 -1306431.241 0.00 -1306438.072 0.50 -1306444.023 1.00 -1306475.533 0.50 -1306487.743 1.00 -1306501.791 0.50 -1306520.623 1.00 -1306546.595 0.50 -1306556.205 0.00 -1306561.231 0.50 -1306570.551 1.00 -1306596.581 0.50 -1306597.755 0.00 -1306609.046 0.50 -1306616.486 1.00 -1306620.257 0.50 -1306625.100 1.00 -1306628.442 0.50 -1306633.053 1.00 -1306638.535 0.50 -1306643.545 1.00 -1306647.468 0.50 -1306651.973 1.00 -1306655.289 0.50 -1306659.951 1.00 -1306663.338 0.50 -1306667.811 1.00 -1306671.169 0.50 -1306676.051 1.00 -1306680.523 0.50 -1306685.372 1.00 -1306688.634 0.50 -1306692.987 1.00 -1306696.272 0.50 -1306701.710 1.00 -1306706.054 0.50 -1306710.872 1.00 -1306714.195 0.50 -1306719.516 1.00 -1306723.164 0.50 -1306727.419 1.00 -1306730.709 0.50 -1306739.454 1.00 -1306745.991 0.50 -1306751.542 1.00 -1306756.065 0.50 -1306756.354 0.00 -1306761.979 0.50 -1306766.736 0.00 -1306773.560 0.50 -1306776.655 1.00 -1306781.569 0.50 -1306790.612 0.00 -1306792.355 0.50 -1306802.720 1.00 -1306806.557 0.50 -1306811.402 0.00 -1306869.300 0.50 -1306875.443 0.00 -1306886.823 0.50 -1306898.727 0.00 -1306924.051 0.50 -1306929.726 0.00 -1306948.288 0.50 -1306999.684 1.00 -1307020.185 0.50 -1307038.067 0.00 -1307056.365 0.50 -1307059.257 1.00 -1307084.938 0.50 -1307095.699 1.00 -1307099.265 0.50 -1307154.918 1.00 -1307163.906 0.50 -1307269.010 1.00 -1307275.994 0.50 -1307300.490 1.00 -1307307.680 0.50 -1307478.161 0.00 -1307484.883 0.50 -1307497.332 1.00 -1307515.476 0.50 -1307531.573 1.00 -1307536.897 0.50 -1307545.301 1.00 -1307547.707 0.50 -1307551.859 0.00 -1307575.711 0.50 -1307583.147 0.00 -1313028.908 0.50 -1313043.492 0.00 -1313044.487 0.50 -1313088.907 0.00 -1313107.910 0.50 -1313112.001 0.00 -1313377.313 0.50 -1313383.481 0.00 -1313415.699 0.50 -1313465.770 0.00 -1313482.463 0.50 -1313486.229 0.00 -1316552.854 0.50 -1316569.677 0.00 -1316583.573 0.50 -1316625.438 0.00 -1316644.297 0.50 -1316648.163 0.00 -1316874.269 0.50 -1316881.752 0.00 -1316912.943 0.50 -1316958.130 0.00 -1316974.511 0.50 -1316978.142 0.00 -1319995.186 0.50 -1320025.818 0.00 -1320040.609 0.50 -1320044.432 0.00 -1320214.501 0.50 -1320214.870 1.00 -1320221.281 0.50 -1320270.219 0.00 -1320297.734 0.50 -1320303.704 0.00 -1333333.783 0.50 -1333386.811 0.00 -1333412.514 0.50 -1333412.634 1.00 -1333418.805 0.50 -1333418.933 0.00 -1333430.989 0.50 -1333469.596 0.00 -1333486.409 0.50 -1333490.897 0.00 -1346545.220 0.50 -1346551.558 1.00 -1346557.434 0.50 -1346606.273 0.00 -1346633.938 0.50 -1346640.148 0.00 -1347130.799 0.50 -1347181.604 0.00 -1347201.196 0.50 -1347205.096 0.00 -1353197.202 0.50 -1353243.345 0.00 -1353265.362 0.50 -1353269.535 0.00 -1353631.730 0.50 -1353696.535 0.00 -1353696.939 0.50 -1353712.876 1.00 -1353716.802 0.50 -1353730.416 0.00 -1353754.700 0.50 -1353758.956 0.00 -1358452.236 0.50 -1358458.994 0.00 -1358473.590 0.50 -1358523.159 0.00 -1358542.082 0.50 -1358545.952 0.00 -1358967.387 0.50 -1359027.712 0.00 -1359051.943 0.50 -1359070.658 0.00 -1363809.927 0.50 -1363860.938 0.00 -1363885.600 0.50 -1363890.292 0.00 -1364374.287 0.50 -1364433.513 0.00 -1364452.289 0.50 -1364456.250 0.00 -1368751.598 0.50 -1368796.172 0.00 -1368816.259 0.50 -1368820.470 0.00 -1369233.364 0.50 -1369285.700 0.00 -1369303.293 0.50 -1369306.996 0.00 -1373388.953 0.50 -1373389.096 1.00 -1373396.919 0.50 -1373442.745 0.00 -1373498.990 0.50 -1373505.271 0.00 -1373792.113 0.50 -1373798.465 0.00 -1373807.331 0.50 -1373852.739 0.00 -1373877.596 0.50 -1373884.279 0.00 -1373892.118 0.50 -1373914.139 0.00 -1373935.631 0.50 -1373948.425 0.00 -1387284.123 0.50 -1387301.770 0.00 -1387620.271 0.50 -1387635.470 0.00 -1804975.977 0.50 -1805012.283 0.00 -1805063.076 0.50 -1805068.493 0.00 -1805259.310 0.50 -1805292.870 0.00 -1805312.310 0.50 -1805350.358 1.00 -1805350.562 0.50 -1805386.009 0.00 -1805425.680 0.50 -1805431.066 0.00 -1843677.054 0.50 -1843737.041 1.00 -1843768.695 0.50 -1843815.161 0.00 -1843827.225 0.50 -1843860.017 1.00 -1843861.862 0.50 -1843891.732 1.00 -1843907.874 0.50 -1843922.152 0.00 -1843936.415 0.50 -1843992.420 1.00 -1844012.594 0.50 -1844033.640 1.00 -1844072.396 0.50 -1844093.056 1.00 -1844104.457 0.50 -1844126.888 1.00 -1844192.738 0.50 -1844231.819 1.00 -1844276.782 0.50 -1844639.970 1.00 -1844690.377 0.50 -1844718.199 1.00 -1844750.254 0.50 -1844782.026 1.00 -1844822.422 0.50 -1844849.633 1.00 -1844884.140 0.50 -1844910.803 1.00 -1844942.276 0.50 -1844947.737 0.00 -1844965.071 0.50 -1844970.793 1.00 -1845017.478 0.50 -1845051.566 0.00 -1845052.547 0.50 -1845069.252 1.00 -1845086.468 0.50 -1845104.383 0.00 -1845110.994 0.50 -1845126.065 1.00 -1845146.179 0.50 -1845155.068 0.00 diff --git a/examples/testbench/legion_prof/dataflow_legion_python_main_1.pdf b/examples/testbench/legion_prof/dataflow_legion_python_main_1.pdf deleted file mode 100644 index 49ba1be92373ebda1448adea7f5931c32ec07b29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33085 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 WjUAoOEdm1N<>w=0Vv<&oA^bnr2%($+ diff --git a/examples/testbench/legion_prof/index.html b/examples/testbench/legion_prof/index.html deleted file mode 100644 index 2f9a68d06..000000000 --- a/examples/testbench/legion_prof/index.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - -
-
Node Range: :
-
- - -
-
-
-
-
-
- - diff --git a/examples/testbench/legion_prof/js/timeline.js b/examples/testbench/legion_prof/js/timeline.js deleted file mode 100644 index ba3db5e30..000000000 --- a/examples/testbench/legion_prof/js/timeline.js +++ /dev/null @@ -1,2734 +0,0 @@ -// Some of the constants are read in from load_scale_json -var constants = { - margin_left: 350, - margin_right: 75, - margin_bottom: 50, - margin_top: 50, - min_feature_width: 3, - min_gap_width: 1, - util_height: 100, - util_levels: 4, - elem_separation: 2, -} - -var op_dependencies = {}; -var base_map = {}; -var prof_uid_map = {}; - -// Contains the children for each util file -var util_files = {}; - -var state = {}; -var mouseX = 0; -var utilline = d3.svg.line() - .interpolate("step-after") - .x(function(d) { return state.x(+d.time); }) - .y(function(d) { return state.y(+d.count); }); -var timeBisector = d3.bisector(function(d) { return d.time; }).left; -// const num_colors = 20; -// var color = d3.scale.linear() -// .domain([0, num_colors]) -// .range(["green", "blue", "red", "yellow"]); - -String.prototype.hashCode = function() { - var hash = 0; - if (this.length == 0) return hash; - for (i = 0; i < this.length; i++) { - var c = this.charCodeAt(i); - var b = this.charCodeAt(c % this.length); - hash = ((hash<<5)-hash)^c^b; - hash = hash & hash; - } - return Math.abs(hash); -} - -function parseURLParameters() { - var match, - pl = /\+/g, // Regex for replacing addition symbol with a space - search = /([^&=]+)=?([^&]*)/g, - decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, - query = window.location.search.substring(1); - - var urlParams = {}; - while (match = search.exec(query)) - urlParams[decode(match[1])] = decode(match[2]); - - if ("collapseAll" in urlParams) - state.collapseAll = (urlParams["collapseAll"].toLowerCase() === "true"); - - if ("resolution" in urlParams) - state.resolution = Math.max(1, parseFloat(urlParams["resolution"])); - // adjust zoom - var zstart = constants.start; - if ("start" in urlParams) - zstart = Math.max(constants.start, parseFloat(urlParams["start"])); - - var zend = constants.end; - if ("end" in urlParams) - zend = Math.min(constants.end, parseFloat(urlParams["end"])); - - if(zstart < zend) { - // set zoom to get: (zend - start) * zoom * scale = $("#timeline").width() - var newZoom = $("#timeline").width() / state.scale / (zend - zstart); - adjustZoom(newZoom, false); - - // set scrollLeft to get: zstart * zoom * state.scale = scrollLeft() - $("#timeline").scrollLeft(convertToPos(state, zstart)); - } - - if ("search" in urlParams) { - state.searchEnabled = true; - searchRegex = new Array(sizeHistory); - currentPos = 0; - nextPos = 1; - searchRegex[currentPos] = new RegExp(urlParams["search"]); - } -} - -function makeTimelineTransparent() { - state.timelineSvg.select("g#timeline").style("opacity", "0.1"); - $("#timeline").css("overflow-x", "hidden"); - state.timelineSvg.select("g#lines").style("opacity", "0.1"); - state.timelineSvg.select("g.locator").style("opacity", "0.1"); - state.timelineSvg.selectAll("path.util").style("opacity", "0.1"); -} - -function makeTimelineOpaque() { - state.timelineSvg.select("g#timeline").style("opacity", "1.0"); - $("#timeline").css("overflow-x", "scroll"); - state.timelineSvg.select("g#lines").style("opacity", "1.0"); - state.timelineSvg.select("g.locator").style("opacity", "1.0"); - state.timelineSvg.selectAll("path.util").style("opacity", "1.0"); -} - -function mouseMoveHandlerWhenDown() { - var p = d3.mouse(this); - var select_block = state.timelineSvg.select("rect.select-block"); - var select_text = state.timelineSvg.select("text.select-block"); - var newWidth = Math.abs(p[0] - mouseX); - select_block.attr("width", newWidth); - if (p[0] >= mouseX) { - select_block.attr("x", mouseX); - select_text.attr("x", mouseX + (p[0] - mouseX) / 2); - } else { - select_block.attr("x", p[0]); - select_text.attr("x", p[0] + (mouseX - p[0]) / 2); - } - var time = convertToTime(state, newWidth); - select_text.text(getTimeString(time, time)); -} - -function mouseMoveHandlerWhenUp() { - var p = d3.mouse(this); - var x = parseFloat(p[0]); - var scrollLeft = $("#timeline").scrollLeft(); - var paneWidth = $("#timeline").width(); - var currentTime = convertToTime(state, x); - - state.timelineSvg.select("g.locator").remove(); - var locator = state.timelineSvg.append("g").attr("class", "locator"); - locator.insert("line") - .attr({ - x1: p[0], - y1: 0, - x2: p[0], - y2: p[1] - state.thickness / 2, - class: "locator", - }); - locator.append("line") - .attr({ - x1: p[0], - y1: p[1] + state.thickness / 2, - x2: p[0], - y2: state.height, - class: "locator", - }); - var locatorText = locator.append("text"); - var text = getTimeString(currentTime, convertToTime(state, paneWidth)); - locatorText.attr("class", "locator").text(text) - if ((x - scrollLeft) < paneWidth - 100) { - locatorText.attr({x: x + 2, y: $(window).scrollTop() + 10}); - locatorText.attr("anchor", "start"); - } - else { - locatorText.attr({x: x - 2 - text.length * 7, y: $(window).scrollTop() + 10}); - locatorText.attr("anchor", "end"); - } -} - -function mouseDownHandler() { - state.timelineSvg.select("g.locator").remove(); - var p = d3.mouse(this); - state.timelineSvg.append("rect") - .attr({ - x : p[0], - y : 0, - class : "select-block", - width : 0, - height : state.height - }); - state.timelineSvg.append("text") - .attr({ - x : p[0], - y : p[1], - class : "select-block", - anchor : "middle", - "text-anchor" : "middle", - }).text("0 us"); - mouseX = p[0]; - state.timelineSvg.on("mousemove", null); - state.timelineSvg.on("mousemove", mouseMoveHandlerWhenDown); - $(document).off("keydown"); -} - -function get_kind(name) { - var util_regex = /\((.*?)\)/; - var kind_match = util_regex.exec(name); - if (kind_match) { - return kind_match[1]; - } -} - -function getLineColor(elem) { - var kind = get_kind(elem.text); - const colorMap = { - "CPU": "steelblue", - "GPU": "olivedrab", - "Utility": "crimson", - "IO": "orangered", - "Proc Group": "orangered", - "Proc Set": "orangered", - "OpenMP": "orangered", - "Python": "olivedrab", - "System Memory": "olivedrab", - "GASNet Global Memory": "crimson", - "Registered Memory": "darkmagenta", - "Socket Memory": "orangered", - "Zero-Copy Memory": "crimson", - "Framebuffer Memory": "blue", - "Disk Memory": "darkgoldenrod", - "HDF5 Memory": "olivedrab", - "File Memory": "orangered", - "L3 Cache Memory": "crimson", - "L2 Cache Memory": "darkmagenta", - "L1 Cache Memory": "olivedrab", - "Channel": "orangered" - }; - return colorMap[kind]; -} - -function drawUtil() { - // TODO: Add to state - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - var start_time = convertToTime(state, windowStart); - var end_time = convertToTime(state, windowEnd); - var filteredUtilData = []; - for (var i = 0; i < state.flattenedLayoutData.length; i++) { - var elem = state.flattenedLayoutData[i]; - if (elem.type == "util" && elem.enabled && elem.loaded && elem.visible) { - filteredUtilData.push(filterUtilData(elem)); - } - } - - state.x = d3.scale.linear().range([0, convertToPos(state, end_time)]); - state.x.domain([0, end_time]); - state.timelineSvg.selectAll("rect.util").remove(); - state.timelineSvg.selectAll("path.util").remove(); - var paths = state.timelineSvg.selectAll("path") - .data(filteredUtilData); - var totalWidth = windowStart + $("#timeline").width(); - paths.enter().append("rect") - .attr("class", "util") - .attr("base_y", lineLevelCalculator) - .attr("y", lineLevelCalculator) - .attr("x", 0) - .attr("fill", "transparent") - .attr("width", totalWidth) - .attr("height", constants.util_levels * state.thickness) - .on("mouseover", mouseover) - .on("mousemove", mousemove) - .on("mouseout", function() { - state.timelineSvg.select("g.focus").remove(); - state.timelineSvg.select("g.utilDesc").remove(); - }); - paths.enter().append("path") - .attr("base_y", lineLevelCalculator) - .attr("class", "util") - .attr("id", function(d, i) { return "util" + i}) - .attr("d", function (d) { return utilline(d.data); }) - .attr("stroke", getLineColor) - .on("mouseover", mouseover) - .on("mousemove", mousemove) - .on("mouseout", function() { - state.timelineSvg.select("g.focus").remove(); - state.timelineSvg.select("g.utilDesc").remove(); - }) - .attr("transform", - function(d) { - var y = lineLevelCalculator(d); - return "translate(0," + y + ")" - }); -} - - -function mouseUpHandler() { - var p = d3.mouse(this); - var select_block = state.timelineSvg.select("rect.select-block"); - var prevZoom = state.zoom; - var selectWidth = parseInt(select_block.attr("width")); - var svgWidth = state.timelineSvg.attr("width"); - if (state.rangeZoom && selectWidth > 10) { - var x = select_block.attr("x"); - state.zoomHistory.push({zoom: prevZoom, start: $("#timeline").scrollLeft()}); - adjustZoom(svgWidth / selectWidth, false); - $("#timeline").scrollLeft(x / prevZoom * state.zoom); - } - - state.timelineSvg.selectAll("rect.select-block").remove(); - state.timelineSvg.selectAll("text.select-block").remove(); - mouseX = 0; - state.timelineSvg.on("mousemove", null); - state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); - $(document).on("keydown", defaultKeydown); -} - -function turnOffMouseHandlers() { - state.timelineSvg.on("mousedown", null); - state.timelineSvg.on("mouseup", null); - state.timelineSvg.on("mousemove", null); - state.timelineSvg.on("mousemove", null); - // prevent right-click menu - state.timelineSvg.on("contextmenu", function () { - d3.event.preventDefault(); - }); -} - -function turnOnMouseHandlers() { - state.timelineSvg.on("mousedown", mouseDownHandler); - state.timelineSvg.on("mouseup", mouseUpHandler); - state.timelineSvg.on("mousemove", mouseMoveHandlerWhenUp); - // prevent right-click menu - state.timelineSvg.on("contextmenu", function () { - d3.event.preventDefault(); - }); -} - -function drawLoaderIcon() { - var loaderGroup = state.loaderSvg.append("g") - .attr({ - id: "loader-icon", - }); - loaderGroup.append("path") - .attr({ - opacity: 0.2, - stroke: "steelblue", - fill: "#000", - d: "M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z" - }); - var path = loaderGroup.append("path") - .attr({ - stroke: "steelblue", - fill: "#000", - d: "M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0C22.32,8.481,24.301,9.057,26.013,10.047z" - }); - path.append("animateTransform") - .attr({ - attributeType: "xml", - attributeName: "transform", - type: "rotate", - from: "0 20 20", - to: "360 20 20", - dur: "0.5s", - repeatCount: "indefinite" - }); - state.loaderSvg.select("g").attr("visibility", "hidden"); - state.loaderSvg.attr("width", "0px") - .attr("height", "0px"); -} - -function showLoaderIcon() { - state.numLoading++; - state.loaderSvg.select("g").attr("visibility", "visible"); - state.loaderSvg.attr("width", "40px") - .attr("height", "40px"); -} - -function hideLoaderIcon() { - state.numLoading--; - if (state.numLoading == 0) { - state.loaderSvg.select("g").attr("visibility", "hidden"); - state.loaderSvg.attr("width", "0px") - .attr("height", "0px"); -; - } -} - -function get_time_str(time_val, convert) -{ - if (convert) { - if (time_val >= 1000000) { - var val = time_val/1000000; - val = parseFloat(val.toFixed(3)) - return val.toString() + " sec"; - } - if (time_val >= 1000) { - var val = time_val/1000; - val = parseFloat(val.toFixed(3)) - return val.toString() + " ms"; - } - } - return time_val.toString() + " us"; -} - -function getMouseOver() { - var paneWidth = $("#timeline").width(); - var left = paneWidth / 3; - var right = paneWidth * 2 / 3; - return function(d, i) { - var p = d3.mouse(this); - var x = parseFloat(p[0]); - var y = timelineLevelCalculator(d) - 5; - var descView = state.timelineSvg.append("g") - .attr("id", "desc"); - var text = descView.append("text") - .attr("x", x) - .attr("y", y) - .attr("class", "desc"); - var depElem = prof_uid_map[d.prof_uid][0]; - if ((depElem.in.length != 0) || (depElem.out.length != 0) || - (depElem.children.length !== 0) || (depElem.parents.length !==0 )) { - d3.select(this).style("cursor", "pointer"); - } - // descTexts is an array of Texts we will store in the desc view - var descTexts = []; - var total = d.end - d.start; - var delay = d.start - d.ready; - total = parseFloat(total.toFixed(3)) - delay = parseFloat(delay.toFixed(3)) - var initiation = ""; - // Insert texts in reverse order - if ((d.ready != undefined) && (d.ready != "") && (delay != 0)) { - descTexts.push("Ready State: " + get_time_str(delay,false)); - } - descTexts.push("End: " + get_time_str(d.end, false)); - descTexts.push("Start: " + get_time_str(d.start, false)); - descTexts.push("Total: " + get_time_str(total, true)); - if ((d.initiation != undefined) && d.initiation != "") { - descTexts.push("Initiator: " + state.operations[d.initiation].desc); - } - - // split d.title - var titles = d.title.split("$"); - if (titles.length > 0) { - for (var i = titles.length-1; i >= 0; --i) { - descTexts.push(titles[i]); - } - } - var title = text.append("tspan") - .attr("x", x) - .attr("dy", -12) - .attr("class", "desc") - .text(descTexts[0].replace(/ /g, "\u00A0")); // preserve spacing - - for (var i = 1; i < descTexts.length; ++i) { - var elem = text.append("tspan") - .attr("x", x) - .attr("dy", -12) - .attr("class", "desc") - .text(descTexts[i].replace(/ /g, "\u00A0")); // preserve spacing - } - - var bbox = descView.node().getBBox(); - var padding = 2; - var rect = descView.insert("rect", "text") - .attr("x", bbox.x - 2*padding) - .attr("y", bbox.y - padding) - .attr("width", bbox.width + (padding*4)) - .attr("height", bbox.height + (padding*2)) - .style("fill", "#222") - .style("opacity", "0.7"); - - var bboxRight = bbox.x + bbox.width; - var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); - - // If the box moves off the screen, nudge it back - if (bboxRight > timelineRight) { - var translation = -(bboxRight - timelineRight + 20); - descView.attr("transform", "translate(" + translation + ",0)"); - } - }; -} - -var sizeHistory = 10; -var currentPos; -var nextPos; -var searchRegex = null; - -function showSlider() { - $('#lowerLimit').text($('#node_slider').slider("values", 0)); - $('#upperLimit').text($('#node_slider').slider("values", 1)); -} - -function createMenuList1() { - var memory_kinds = []; - var num_nodes = state.num_nodes; - var num_mems = 0; - var dropdown_options = [ - { value: "ready", - id: "ready_all", - text: "View", - count: 1, - low_range: 0, - high_range: 1 - }, - { value: "memories", - id: "memories_all", - text: "Memories", - count: num_mems, - low_range: 0, - high_range: num_mems -1 - } - ]; - - // memories list - dropdown_options_memories = []; - - // misc items list - var pkind = { - id: "rr", - value: "rdy", - count: 1, - low_range: 0, - high_range: 1, - text: "Ready State" - }; - - dropdown_options_misc = []; - dropdown_options_misc.push(pkind); - - // create the remaining entries - function appendKind(elem) { - var value = state.processor_kinds[elem]; - if (elem.includes("Memory") && (value.count >= 0)) - { - num_mems = num_mems+1; - dropdown_options_memories.push(value); - } - if ((value.count >= 0) && (value.low_range != -1)) { - dropdown_options.push(value); - } - } - Object.keys(state.processor_kinds).forEach(appendKind); - - // main menu - d3.select("#dropdown").selectAll("optgroup") - .data(dropdown_options) - .enter() - .append("optgroup") - .attr('label', function(d) { return d.text;}) - .attr("id", function(d) { return d.id;}) - .attr("value", function(d) { return d.value;}); - - for (var j=0; j val)) - kind_proc.low_range = val; - if (kind_proc.high_range < val) - kind_proc.high_range = val; - } - } - } - - // Util graphs will have processors as their children as well. - if (type == "util") { - // get the children for the util view - var proc_children = getProcessors(text); - var count = 1; - var node_id = get_node_id(text); - var kind = get_kind(text); - // add to processor kinds: union of all processor kinds - if (!(kind in state.processor_kinds)) { - var pkind = { - id: kind, - value: kind, - count: proc_children.length, - low_range: -1, - high_range: -1, - text: kind - }; - state.processor_kinds[kind] = pkind; - } - if (state.processor_kinds[kind].count < proc_children.length) - state.processor_kinds[kind].count = proc_children.length; - - proc_children.forEach(function(proc_child) { - var child_element = getElement(depth + 1, proc_child.text, - proc_child.full_text, "proc", - proc_child.height, load_proc_timeline, - proc_child.tsv, element, undefined, - true, false); - element.children.push(child_element); - }); - } - - return element; -} - - -function calculateLayout() { - - // First element in the layout will be the all_util. All first-level - // elements will start off not enabled, and will be uncollapsed later - // programmatically - var num_nodes = Object.keys(util_files).length; - if (num_nodes > 1) { - var proc_kinds = util_files["all"]; - proc_kinds.forEach(function(name) { - var kind = "(" + get_kind(name) + ")"; - var util_name = "all nodes " + kind; - var kind_element = getElement(0, util_name, undefined, "util", - constants.util_levels, load_util, - "tsv/" + name + "_util.tsv", - undefined, util_files[kind], false, true); - state.layoutData.push(kind_element); - }); - } - - var seen_nodes = []; - state.processors.forEach(function(proc) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - var proc_regex = /(Processor|Memory) 0x1(e|d)([a-fA-f0-9]{4})[a-fA-f0-9]{10}$/; - // Memory Channel - var proc_channel_regex = /(Memory) 0x1(e)([a-fA-f0-9]{4})[a-fA-f0-9]{10}.*Channel/; - var proc_channel_match = proc_channel_regex.exec(proc.full_text); - var proc_match = proc_regex.exec(proc.full_text); - proc_match = proc_match || proc_channel_match; - if (proc_match) { - var node_id = parseInt(proc_match[3], 16); - if (!(node_id in seen_nodes)) { - seen_nodes[node_id] = 1; - if (node_id in util_files) { - var proc_kinds = util_files[node_id]; - proc_kinds.forEach(function(kind) { - var util_name = "node " + kind; - var kind_element = getElement(0, util_name, undefined, "util", - constants.util_levels, load_util, - "tsv/" + kind + "_util.tsv", - undefined, util_files[kind], - false, true); - state.layoutData.push(kind_element); - }); - } - } - } - else { - state.layoutData.push(getElement(0, proc.text, proc.full_text, "proc", - proc.height, load_proc_timeline, - proc.tsv, undefined, undefined, - false, true)); - } - }); - state.num_nodes = seen_nodes.length; -} - -function getElemCoords(elems) { - var proc = elems[0].proc; - var level = elems[0].level; - var startX = convertToPos(state, elems[0].start); - var endX = convertToPos(state, elems[elems.length-1].end); - var endBase = +proc.base; - var endLevel = endBase + level; - var y = dependencyLineLevelCalculator(endLevel); - return {startX: startX, endX: endX, y: y}; -} - - -function addLine(group, x1, x2, y1, y2, color, dashed) { - var line; - if (dashed) { - line = group.append("line") - .attr("x1", x1) - .attr("y1", y1) - .attr("x2", x2) - .attr("y2", y2) - .style("stroke", color) - .style("stroke-dasharray", "3,3") - .style("stroke-width", "1px"); - } else { - line = group.append("line") - .attr("x1", x1) - .attr("y1", y1) - .attr("x2", x2) - .attr("y2", y2) - .style("stroke", color) - .style("stroke-width", "1px"); - } - - var slope = (y2 - y1) / (x2 - x1); - var intercept = y1 - (slope * x1); - var triangleRotation = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI - 90; - - group.append("line") - .attr("x1", x1) - .attr("y1", y1) - .attr("x2", x2) - .attr("y2", y2) - .style("stroke", "transparent") - .style("stroke-width", "20px") - .on("mouseover", function() { - group.append("g") - .attr("class", "marker") - .append("path") - .attr("d", d3.svg.symbol().type("triangle-down").size(20)) - .style("stroke", color) - .style("fill", color); - }) - .on("mousemove", function() { - var marker = group.select("g.marker"); - var px = d3.mouse(this)[0] - 10; - var py = d3.mouse(this)[1] - ((slope > 0 ? 1 : -1) * 20); - if (px < Math.min(x1, x2)) { - px += 20; - } - if (py < Math.min(y1, y2)) { - py += 40; - } - - // some linear algebra here - var cx = (slope * py + px - slope * intercept) / (slope * slope + 1); - var cy = (slope * slope * py + slope * px + intercept) / (slope * slope + 1); - - marker.attr("transform", "translate(" + cx + "," + cy + ") rotate(" + triangleRotation + ")"); - }) - .on("mouseout", function() { - group.select("g.marker").remove(); - }); - - group.append("circle") - .attr("cx", x1) - .attr("cy", y1) - .attr("fill", "white") - .attr("stroke", "black") - .attr("r", 2.5) - .style("stroke-width", "1px"); - - group.append("circle") - .attr("cx", x2) - .attr("cy", y2) - .attr("fill", "white") - .attr("stroke", "black") - .attr("r", 2.5) - .style("stroke-width", "1px"); -} - - -function drawCriticalPath() { - state.timelineSvg.selectAll("g.critical_path_lines").remove(); - if (state.critical_path == undefined || !state.display_critical_path) { - return; - } - var depGroup = state.timelineSvg.append("g") - .attr("class", "critical_path_lines"); - state.critical_path.forEach(function(op) { - var proc = base_map[op[0] + "," + op[1]]; // set in calculateBases - if (proc != undefined && proc.visible && proc.enabled && proc.loaded && proc.selected) { - var elems = prof_uid_map[op[2]]; - if (elems != undefined) { - var coords = getElemCoords(elems) - var startX = coords.startX; - var endX = coords.endX; - var y = coords.y; - elems[0].out.forEach(function(dep) { - if (dep[2] in state.critical_path_prof_uids) { - var depElems = prof_uid_map[dep[2]]; - if (depElems != undefined) { - var depProc = depElems[0].proc; - // is the proc visible? - if (depProc.visible && depProc.enabled && depProc.loaded) { - var depCoords = getElemCoords(depElems); - var depX = depCoords.endX; - var depY = depCoords.y; - addLine(depGroup, depX, startX, depY, y, "grey", false); - } - } - } - }); - // Draw parent-child lines - var lastChildCoords = undefined; - var firstChildCoords = undefined; - elems[0].children.forEach(function(child) { - if (child[2] in state.critical_path_prof_uids) { - var childElems = prof_uid_map[child[2]]; - var childCoords = getElemCoords(childElems); - if (childElems !== undefined) { - if (lastChildCoords === undefined || - childCoords.startX > lastChildCoords.startX) { - lastChildCoords = childCoords; - } - if (firstChildCoords === undefined || - childCoords.endX < firstChildCoords.endX) { - firstChildCoords = childCoords; - } - } - } - }); - if (firstChildCoords !== undefined) { - addLine(depGroup, startX, firstChildCoords.startX, - y, firstChildCoords.y, "grey", true); - } - if (lastChildCoords !== undefined) { - addLine(depGroup, lastChildCoords.endX, endX, - lastChildCoords.y, y, "grey", true); - } - } - } - }); -} - -function drawDependencies() { - state.timelineSvg.select("g.dependencies").remove(); - var timelineEvent = state.dependencyEvent; - if (timelineEvent == undefined || - !timelineEvent.proc.visible || !timelineEvent.proc.enabled) { - return; // don't draw in this case, the src isn't present - } - var srcElems = prof_uid_map[timelineEvent.prof_uid]; - timelineEvent = srcElems[0]; // only the first elem will have deps and children - var srcCoords = getElemCoords(srcElems); - var srcStartX = srcCoords.startX; - var srcEndX = srcCoords.endX; - var srcY = srcCoords.y; - var depGroup = state.timelineSvg.append("g") - .attr("class", "dependencies"); - - var addDependency = function(dep, dir, dashed) { - var depProc = base_map[dep[0] + "," + dep[1]]; // set in calculateBases - if (depProc.visible && depProc.enabled && depProc.selected) { - var depElems = prof_uid_map[dep[2]]; - if (depElems != undefined) { - console.log(dir); - var depCoords = getElemCoords(depElems); - var dstY = depCoords.y; - if (dir === "in") { - addLine(depGroup, srcEndX, depCoords.startX, srcY, dstY, "black", dashed); - } else if (dir === "out") { - addLine(depGroup, depCoords.endX, srcStartX, dstY, srcY, "black", dashed); - } else if (dir === "parent") { - addLine(depGroup, depCoords.startX, srcStartX, dstY, srcY, "black", dashed); - addLine(depGroup, srcEndX, depCoords.endX, srcY, dstY, "black", dashed); - } else if (dir === "child") { - addLine(depGroup, srcStartX, depCoords.startX, srcY, dstY, "black", dashed); - addLine(depGroup, depCoords.endX, srcEndX, dstY, srcY, "black", dashed); - } - - } - } - } - - if (state.drawDeps) { - timelineEvent.in.forEach(function(dep) {addDependency(dep, "in", false)}); - timelineEvent.out.forEach(function(dep) {addDependency(dep, "out", false)}); - } - if (state.drawChildren) { - timelineEvent.parents.forEach(function(dep) {addDependency(dep, "parent", true)}); - timelineEvent.children.forEach(function(dep) {addDependency(dep, "child", true)}); - } -} - -function timelineEventsExistAndEqual(a, b) { - if (a == undefined || b == undefined) { - return false; - } - return (a.proc.base == b.proc.base) && (a.prof_uid == b.prof_uid); -} - -function timelineElementStrokeCalculator(elem) { - if (timelineEventsExistAndEqual(elem, state.dependencyEvent)) { - return true; - } else if (state.display_critical_path && - elem.prof_uid in state.critical_path_prof_uids) { - return true; - } - return false; -} - -function timelineEventMouseDown(_timelineEvent) { - // only the first event of this uid will have information - var timelineEvent = prof_uid_map[_timelineEvent.prof_uid][0]; - var hasDependencies = ((timelineEvent.in.length != 0) || - (timelineEvent.out.length != 0)); - - if (hasDependencies) { - if (timelineEventsExistAndEqual(timelineEvent, state.dependencyEvent)) { - if (d3.event.button === 0) { - state.drawDeps = !state.drawDeps; - } else if (d3.event.button === 2) { - state.drawChildren = !state.drawChildren; - } - if (state.drawDeps === false && state.drawChildren === false) { - state.dependencyEvent = undefined; - } - } else { - timelineEvent.in.concat(timelineEvent.out).forEach(function(dep) { - expandByNodeProc(dep[0], dep[1]) - }); - state.dependencyEvent = timelineEvent; - if (d3.event.button === 0) { - state.drawDeps = true; - } else if (d3.event.button === 2) { - state.drawChildren = true; - } - } - redraw(); - } -} - -function drawTimeline() { - showLoaderIcon() - - updateURL(state.zoom, state.scale); - var timelineGroup = state.timelineSvg.select("g#timeline"); - timelineGroup.selectAll("rect").remove(); - timelineGroup.selectAll("text").remove(); - var timeline = timelineGroup.selectAll("rect") - .data(state.dataToDraw, function(d) { return d.proc.base + "-" + d.id; }); - var timelineText = timelineGroup.selectAll("text") - .data(state.memoryTexts); - var mouseOver = getMouseOver(); - - timeline.enter().append("rect"); - - timeline - .attr("id", function(d) { return "block-" + d.proc.base + "-" + d.id; }) - .attr("x", function(d) { return convertToPos(state, d.start); }) - .attr("y", timelineLevelCalculator) - .style("fill", function(d) { - if (!state.searchEnabled || - searchRegex[currentPos].exec(d.title) == null) - return d.color; - else return "#ff0000"; - }) - .attr("width", function(d) { - return Math.max(constants.min_feature_width, convertToPos(state, d.end - d.start)); - }) - .attr("stroke", function(d) { - if (timelineElementStrokeCalculator(d)) { - return "red"; - } else { - return "black"; - } - }) - .attr("stroke-width", function(d) { - if (timelineElementStrokeCalculator(d)) { - return "1.5"; - } else { - return "0.5"; - } - }) - .attr("height", state.thickness) - .style("opacity", function(d) { - if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) != null || searchRegex[currentPos].exec(d.initiation) != null) { - return d.opacity; - } - else return 0.05; - }) - .on("mouseout", function(d, i) { - if ((d.in.length != 0) || (d.out.length != 0)) { - d3.select(this).style("cursor", "default"); - } - state.timelineSvg.selectAll("#desc").remove(); - }) - .on("mousedown", timelineEventMouseDown) - - - timelineText.enter().append("text"); - - timelineText - .attr("class", "timeline") - .attr("y", timelineTextLevelCalculator) - .attr("text-anchor", "start") - .text(function(d) { - var sizeRegex = /Size=(.*)/; - var match = sizeRegex.exec(d.title); - return match[1]; - }) - .attr("visibility", function(d) { - var textWidth = this.getComputedTextLength(); - var startX = convertToPos(state, d.start); - var endX = convertToPos(state, d.end); - var boxWidth = endX - startX; - return boxWidth > textWidth ? "visible" : "hidden"; - }) - .attr("x", function(d) { - var textWidth = this.getComputedTextLength(); - var midPoint = convertToPos(state, d.start + (d.end - d.start) / 2); - midPoint -= textWidth / 2; - return midPoint - }); - - drawUtil(); - timeline.on("mouseover", mouseOver); - timeline.exit().remove(); - hideLoaderIcon(); -} - -function redraw() { - if (state.numLoading == 0) { - calculateBases(); - filterAndMergeBlocks(state); - constants.max_level = calculateVisibileLevels(); - recalculateHeight(); - drawTimeline(); - drawDependencies(); - drawCriticalPath(); - drawLayout(); - } -} - -function calculateVisibileLevels() { - var levels = 0; - state.flattenedLayoutData.forEach(function(elem) { - if (elem.visible) { - if (elem.enabled) { - if (state.ready_selected && elem.num_levels_ready != undefined) - levels += elem.num_levels_ready; - else - levels += elem.num_levels; - } - levels += constants.elem_separation; - } - }); - return levels; -} - -function is_proc(proc) { - // the full text of this proc should start with 0x1d to be a processor - return /0x1d/.exec(proc.full_text) !== undefined; -} - -function is_proc_string(text) -{ - return /0x1d/.exec(text) != undefined; -} - -function is_mem_string(text) { - return /0x1e/.exec(text) != undefined; -} - -function get_node_val(text) { - var match = /\d+/.exec(text); - if (match) { - var val = parseInt(text.match(/\d+/)); - return val; - } - return match; -} - -function get_node_id(text) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - var proc_regex = /(Memory|Processor) 0x1(e|d)([a-fA-f0-9]{4})/; - var proc_match = proc_regex.exec(text); - // if there's only one node, then per-node graphs are redundant - if (proc_match) { - var node_id = parseInt(proc_match[3], 16); - return node_id - } -} - -function get_proc_in_node(text) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - var proc_regex = /Processor 0x1d[a-fA-f0-9]{11}([a-fA-f0-9]{3})/; - var proc_match = proc_regex.exec(text); - // if there's only one node, then per-node graphs are redundant - if (proc_match) { - var proc_in_node = parseInt(proc_match[1], 16); - return proc_in_node; - } -} - -function calculateBases() { - var base = 0; - state.flattenedLayoutData.forEach(function(elem) { - elem.base = base; - var node_id = get_node_id(elem.full_text); - var proc_in_node = get_proc_in_node(elem.full_text); - if (node_id != undefined && proc_in_node != undefined) { - base_map[(+node_id) + "," + (+proc_in_node)] = elem; - } - if (elem.visible) { - if (elem.enabled) { - if (state.ready_selected && elem.num_levels_ready != undefined) - base += elem.num_levels_ready; - else - base += elem.num_levels; - } - base += constants.elem_separation; - } - }); -} - -function expandHandler(elem, index) { - elem.expanded = !elem.expanded; - - if (elem.expanded) { - function expandChild(child) { - child.visible = true; - //child.enabled = true; - if(!child.loaded) { - showLoaderIcon(); - child.loader(child); // will redraw the timeline once loaded - } else if (child.expanded) { - child.children.forEach(expandChild); - } - } - elem.children.forEach(expandChild); - } else { - function collapseChildren(child) { - child.visible = false; - child.children.forEach(collapseChildren); - } - elem.children.forEach(collapseChildren); - } - redraw(); -} - -// This handler is called when you collapse/uncollapse a row in the -// timeline -function collapseHandler(d, index) { - d.enabled = !d.enabled; - - if (!d.loaded) { - // should always be expanding here - showLoaderIcon(); - //var elem = state.flattenedLayoutData[index]; - d.loader(d); // will redraw the timeline once loaded - } else { - redraw(); - } -} - -// This expands a particular element and its parents if necessary -function expandElementAndParents(elem) { - if (elem !== undefined) { - var elemPath = []; // path up to parent - var curElem = elem; - while (curElem != undefined) { - elemPath.push(curElem); - curElem = curElem.parent; - } - - for (var i = elemPath.length - 1; i >= 0; --i) { - var elem = elemPath[i]; - if (!elem.expanded) { - expandHandler(elem); - } - // uncollapse if necessary - if ((i == 0) && !elem.enabled) { - collapseHandler(elem); - } - } - } -} - - -function expandByNodeProc(node, proc) { - // PROCESSOR: tag:8 = 0x1d, owner_node:16, (unused):28, proc_idx: 12 - // ugh why isn't there string formatting - var nodeHex = ("0000" + node.toString(16)).slice(-4); - var procHex = ("000" + proc.toString(16)).slice(-3); - var expectedTitle = "0x1d" + nodeHex + "0000000" + procHex; - var matchedElement = undefined; - for (var i = 0; i < state.flattenedLayoutData.length; i++) { - var timelineElement = state.flattenedLayoutData[i]; - if ((timelineElement.full_text != undefined) && - (timelineElement.full_text.indexOf(expectedTitle) !=-1)) { - matchedElement = timelineElement; - break; - } - } - expandElementAndParents(matchedElement) -} - - -function lineLevelCalculator(timelineElement) { - var level = timelineElement.base + 1; - if (timelineElement.enabled) { - if (state.ready_selected && timelineElement.num_levels_ready != undefined) - level += timelineElement.num_levels_ready; - else - level += timelineElement.num_levels; - } - return constants.margin_top + level * state.thickness; -}; - -function utilLevelCalculator(timelineElement) { - var level = timelineElement.base; - if (timelineElement.enabled) { - if (state.ready_selected && timelineElement.num_levels_ready != undefined) - level += timeLineElement.num_levels_ready; - else - level += timeLineElement.num_levels; - } - return constants.margin_top + level * state.thickness; -}; - - -function timelineLevelCalculator(timelineEvent) { - return constants.margin_top + - (timelineEvent.proc.base + timelineEvent.level) * state.thickness; -}; - -function timelineTextLevelCalculator(timelineEvent) { - return constants.margin_top + - (timelineEvent.proc.base + timelineEvent.level + 0.75) * state.thickness; -}; - -function dependencyLineLevelCalculator(level) { - return constants.margin_top + ((level+0.5) * state.thickness); -} - -function drawLayout() { - d3.select("#processors").select("svg").remove(); - state.timelineSvg.select("g#lines").remove(); - - var data = state.flattenedLayoutData; - var svg = d3.select("#processors").append("svg") - .attr("width", constants.margin_left) - .attr("height", state.height); - - var namesGroup = svg.selectAll(".processors") - .data(data) - .enter().append("g"); - - var names = namesGroup.append("text"); - - var thickness = state.thickness; - var xCalculator = function(d) { return (d.depth + 1) * 15; }; - names.attr("text-anchor", "start") - .attr("class", "processor") - .text(function(d) { return d.text; }) - .attr("x", xCalculator) - .attr("y", lineLevelCalculator) - .attr("visibility", function(elem) { - return (elem.visible) ? "visible" : "hidden" - }) - .style("fill", "#000000") - .style("opacity", function(proc) { - return (proc.enabled) ? 1 : 0.5; - }); - - - // names.each(function(d) { - // var elem = d3.select(this); - // var text = d.text; - // var tokens = d.text.split(" to "); - // if (tokens.length == 1) - // elem.append("tspan").text(d.text); - // else { - // var source = tokens[0]; - // var target = tokens[1].replace(" Channel", ""); - // elem.append("tspan").text(source) - // .attr("x", xCalculator) - // .attr("dy", -10); - // elem.append("tspan").text("==> " + target) - // .attr("x", xCalculator) - // .attr("dy", 10); - // } - // }); - names.on({ - "mouseover": function(d) { - d3.select(this).style("cursor", "pointer") - if (d.full_text != undefined) { - var x = xCalculator(d); - var y = lineLevelCalculator(d) - state.thickness; - - var overlaySvg = d3.select("#overlay").append("svg"); - var descView = overlaySvg.append("g").attr("id", "desc"); - - var text = descView.append("text") - .attr("x", x) - .attr("y", y) - .attr("text-anchor", "start") - .attr("class", "desc") - .text(unescape(escape(d.full_text))); - - var bbox = text.node().getBBox(); - var padding = 2; - var rect = descView.insert("rect", "text") - .attr("x", bbox.x - padding) - .attr("y", bbox.y - padding) - .attr("width", bbox.width + (padding*2)) - .attr("height", bbox.height + (padding*2)) - .style("fill", "#222") - .style("opacity", "0.7"); - - overlaySvg.attr("width", bbox.x + bbox.width + (padding*2)) - .attr("height", bbox.y + bbox.height + (padding*2)); - } - }, - "mouseout": function(d) { - d3.select(this).style("cursor", "default") - if (d.full_text != undefined) { - d3.select("#overlay").selectAll("svg").remove(); - } - }, - "click": collapseHandler - }); - - var expandableNodes = namesGroup.filter(function(elem) { - return elem.children.length > 0; - }); - - var expand_group = expandableNodes.append("g"); - - var expand_clickable = expand_group.append("circle") - .attr("fill", "transparent") - .attr("stroke", "transparent") - .attr("r", 8); - var expand_icons = expand_group.append("path"); - var arc = d3.svg.symbol().type('triangle-down') - .size(12); - - - //.attr("transform", function(elem) { - // var x = constants.margin_left - 10; - // var y = lineLevelCalculator(elem); - // return "translate(" + x + "," + y + ")"; - //}) - expand_icons.attr("class", "processor") - .attr("d", arc) - .attr("visibility", function(elem) { - return (elem.visible) ? "visible" : "hidden" - }) - .style("fill", "#000000") - .style("stroke", "#000000") - .style("opacity", function(proc) { - return (proc.enabled) ? 1 : 0.5; - }); - - expand_group.each(function(elem) { - var path = d3.select(this); - var x = elem.depth * 15 + 5; - var y = lineLevelCalculator(elem) - 3; - - if (elem.expanded) { - path.attr("transform", "translate(" + x + ", " + y + ") rotate(0)"); - } else { - path.attr("transform", "translate(" + x + ", " + y + ") rotate(30)"); - } - - }); - - - expand_group.on({ - "mouseover": function(d) { - d3.select(this).style("cursor", "pointer") - }, - "mouseout": function(d) { - d3.select(this).style("cursor", "default") - }, - "click": expandHandler - }); - - - var lines = state.timelineSvg - .append("g") - .attr("id", "lines"); - - var thickness = state.thickness; - lines.selectAll(".lines") - .data(data) - .enter().append("line") - .attr("x1", 0) - .attr("y1", lineLevelCalculator) - .attr("x2", state.zoom * state.width) - .attr("y2", lineLevelCalculator) - .attr("visibility", function(elem) { - return (elem.visible) ? "visible" : "hidden" - }) - .style("stroke", "#000000") - .style("stroke-width", "2px") - .style("opacity", function(proc) { - return (proc.enabled) ? 1 : 0.5; - }); -} - -function drawHelpBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - - var helpBoxGroup = popUpSvg.append("g"); - var helpBoxWidth = Math.min(450, width - 100); - var helpTextOffset = 20; - var helpBoxHeight = Math.min(helpMessage.length * helpTextOffset + 100, - height - 100); - - var boxStartX = (width - helpBoxWidth) / 2; - var boxStartY = (height - helpBoxHeight) / 2; - - helpBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: helpBoxWidth, - height: helpBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var helpText = helpBoxGroup.append("text") - .attr("class", "help-box") - .style("width", helpBoxWidth); - var helpTitle = "Keyboard Shortcuts"; - helpText.append("tspan") - .attr({ x: boxStartX + helpBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text(helpTitle); - var off = 15; - for (var i = 0; i < helpMessage.length; ++i) { - helpText.append("tspan") - .style("font-size", "12pt") - .attr("text-anchor", "start") - .attr({ x: boxStartX + 30, dy: off + helpTextOffset}) - .text(helpMessage[i]); - off = 0; - } -} - -function evalExpandRequest(re) { - var re = new RegExp(re); - state.flattenedLayoutData.forEach(function(elem) { - if (re.exec(elem.text)) { - expandElementAndParents(elem); - } - }); - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); -} - -function drawExpandBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - var expandBoxGroup = popUpSvg.append("g"); - var expandBoxWidth = Math.min(450, width - 100); - var expandBoxHeight = Math.min(220, height - 100); - - var thicknessRatio = state.thickness / state.baseThickness; - var boxStartX = (width - expandBoxWidth) / 2; - var boxStartY = (height - expandBoxHeight) / 2; - - expandBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: expandBoxWidth, - height: expandBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var expandText = expandBoxGroup.append("text") - .attr("class", "expand-box") - .style("width", expandBoxWidth); - expandText.append("tspan") - .attr({ x: boxStartX + expandBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text("expand"); - var expandInputWidth = expandBoxWidth - 40; - var expandInputHeight = 50; - var expandInputStartY = 65; - - - expandBoxGroup.append("foreignObject") - .attr({ x: boxStartX + 20, y: boxStartY + expandInputStartY, - width: expandInputWidth, height: expandBoxHeight - expandInputStartY}) - .attr("text-anchor", "middle") - .html( - "" - + "
" - + "" - + "Presets" - + "" - + "
" - + "
" - + "" - + "" - + "" - + "" - + "" - + "" - + "
" - ); - $("input.expand-box").focus(); -} - -function drawSearchBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - var searchBoxGroup = popUpSvg.append("g"); - var searchBoxWidth = Math.min(450, width - 100); - var searchBoxHeight = Math.min(250, height - 100); - - var thicknessRatio = state.thickness / state.baseThickness; - var boxStartX = (width - searchBoxWidth) / 2; - var boxStartY = (height - searchBoxHeight) / 2; - - searchBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: searchBoxWidth, - height: searchBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var searchText = searchBoxGroup.append("text") - .attr("class", "search-box") - .style("width", searchBoxWidth); - searchText.append("tspan") - .attr({ x: boxStartX + searchBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text("Search"); - var searchInputWidth = searchBoxWidth - 40; - var searchInputHeight = 50; - searchBoxGroup.append("foreignObject") - .attr({ x: boxStartX + 20, y: boxStartY + 150, - width: searchInputWidth, height: searchInputHeight}) - .attr("text-anchor", "middle") - .html(""); - $("input.search-box").focus(); -} - -function drawSearchHistoryBox() { - var width = $(window).width(); - var height = $(window).height(); - var popUpSvg = d3.select("#pop-up").select("svg"); - - var historyBoxGroup = popUpSvg.append("g"); - var historyBoxWidth = Math.min(450, width - 100); - var historyBoxHeight = Math.min(350, height - 100); - - var boxStartX = (width - historyBoxWidth) / 2; - var boxStartY = (height - historyBoxHeight) / 2; - - historyBoxGroup.append("rect") - .attr({ - rx: 30, - ry: 30, - x: boxStartX, - y: boxStartY, - width: historyBoxWidth, - height: historyBoxHeight, - style: "fill: #222; opacity: 0.8;" - }); - var historyText = historyBoxGroup.append("text") - .attr("class", "history-box") - .style("width", historyBoxWidth); - var historyTitle = "Search History"; - historyText.append("tspan") - .attr({ x: boxStartX + historyBoxWidth / 2, y: boxStartY + 50}) - .attr("text-anchor", "middle") - .style("font-size", "20pt") - .text(historyTitle); - if (searchRegex != null) { - var off = 15; - var id = 1; - for (var i = 0; i < sizeHistory; ++i) { - var pos = (nextPos + i) % sizeHistory; - var regex = searchRegex[pos]; - if (regex != null) { - if (pos == currentPos) prefix = ">>> "; - else prefix = id + " : "; - historyText.append("tspan") - .attr("text-anchor", "start") - .attr({ x: boxStartX + 30, dy: off + 25}) - .text(prefix + regex.source); - off = 0; - id++; - } - } - } -} - -function updateURL() { - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - var start_time = convertToTime(state, windowStart); - var end_time = convertToTime(state, windowEnd); - var url = window.location.href.split('?')[0]; - url += "?start=" + start_time; - url += "&end=" + end_time; - url += "&collapseAll=" + state.collapseAll; - url += "&resolution=" + state.resolution; - if (state.searchEnabled) - url += "&search=" + searchRegex[currentPos].source; - window.history.replaceState("", "", url); -} - -function adjustZoom(newZoom, scroll) { - var prevZoom = state.zoom; - state.zoom = Math.round(newZoom * 10) / 10; - - var svg = d3.select("#timeline").select("svg"); - - svg.attr("width", state.zoom * state.width) - .attr("height", state.height); - - var timelineGroup = svg.select("g#timeline"); - //timelineGroup.selectAll("rect").remove(); - - svg.select("g#lines").selectAll("line") - .attr("x2", state.zoom * state.width); - svg.selectAll("#desc").remove(); - svg.selectAll("g.locator").remove(); - d3.select("#overlay").selectAll("svg").remove(); - - if (scroll) { - var paneWidth = $("#timeline").width(); - var pos = ($("#timeline").scrollLeft() + paneWidth / 2) / prevZoom; - // this will trigger a scroll event which in turn redraws the timeline - $("#timeline").scrollLeft(pos * state.zoom - state.width / 2); - } else { - filterAndMergeBlocks(state); - drawTimeline(); - } - drawDependencies(); - drawCriticalPath(); -} - -function recalculateHeight() { - // adjust the height based on the new thickness and max level - state.height = constants.margin_top + constants.margin_bottom + - (state.thickness * constants.max_level); - var util_height = constants.util_levels * state.thickness; - state.y = d3.scale.linear().range([util_height, 0]); - state.y.domain([0, 1]); - - d3.select("#processors").select("svg").remove(); - var svg = d3.select("#timeline").select("svg"); - svg.attr("width", state.zoom * state.width) - .attr("height", state.height); - var lines = state.timelineSvg.select("g#lines"); - lines.remove(); - - svg.selectAll("#desc").remove(); - svg.selectAll("g.locator").remove(); - d3.select("#overlay").selectAll("svg").remove(); - -} - -function adjustThickness(newThickness) { - state.thickness = newThickness; - recalculateHeight(); - drawTimeline(); - drawLayout(); -} - -function suppressdefault(e) { - if (e.preventDefault) e.preventDefault(); - if (e.stopPropagation) e.stopPropagation(); -} - -function setKeyHandler(handler) { - $(document).off("keydown"); - $(document).on("keydown", handler); -} - -function makeModalKeyHandler(validKeys, callback) { - return function(e) { - if (!e) e = event; - var code = e.keyCode || e.charCode; - if (!(e.ctrlKey || e.metaKey || e.altKey)) { - for (var i = 0; i < validKeys.length; ++i) { - if (keys[code] == validKeys[i]) { - callback(keys[code]); - return false; - } - } - } - return true; - } -} - -function displayPopUp() { - d3.select("#pop-up").append("svg") - .attr("width", $(window).width()) - .attr("height", $(window).height()); -} - -function removePopUp() { - var popUpSvg = d3.select("#pop-up").selectAll("svg").remove(); -} - - -function defaultKeydown(e) { - if (!e) e = event; - - var code = e.keyCode || e.charCode; - var commandType = Command.none; - var modifier = e.ctrlKey || e.metaKey || e.altKey; - var multiFnKeys = e.metaKey && e.ctrlKey || e.altKey && e.ctrlKey; - - var translatedCode = keys[code]; - - if (!modifier) { - commandType = noModifierCommands[translatedCode]; - } else if (!multiFnKeys) { - commandType = modifierCommands[translatedCode]; - } else { - commandType = multipleModifierCommands[translatedCode]; - } - - if (commandType == undefined) { - if (e.metaKey || e.altKey) - state.rangeZoom = false; - return true; - } - - suppressdefault(e); - if (commandType == Command.help) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - // make help box visible - displayPopUp(); - drawHelpBox(); - setKeyHandler(makeModalKeyHandler(['/', 'esc'], function(key) { - // make help box invisible - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - else if (commandType == Command.search) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - displayPopUp(); - drawSearchBox(); - setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { - if (key == 'enter') { - var re = $("input.search-box").val(); - if (re.trim() != "") { - if (searchRegex == null) { - searchRegex = new Array(sizeHistory); - currentPos = -1; - nextPos = 0; - } - currentPos = nextPos; - nextPos = (nextPos + 1) % sizeHistory; - searchRegex[currentPos] = new RegExp(re); - state.searchEnabled = true; - } - } - removePopUp(); - if (state.searchEnabled) { - filterAndMergeBlocks(state); - drawTimeline(); - } - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - else if (commandType == Command.expand) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - displayPopUp(); - drawExpandBox(); - setKeyHandler(makeModalKeyHandler(['enter', 'esc'], function(key) { - if (key == 'enter') { - var re = $("input.expand-box").val(); - if (re.trim() != "") { - re = new RegExp(re); - state.flattenedLayoutData.forEach(function(elem) { - if (re.exec(elem.text)) { - expandElementAndParents(elem); - } - }); - } - } - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - else if (commandType == Command.search_history) { - turnOffMouseHandlers(); - makeTimelineTransparent(); - displayPopUp(); - drawSearchHistoryBox(); - setKeyHandler(makeModalKeyHandler(['h', 'esc'], function(key) { - removePopUp(); - makeTimelineOpaque(); - setKeyHandler(defaultKeydown); - turnOnMouseHandlers(); - })); - return false; - } - - if (commandType == Command.zix) { - var inc = 4.0; - adjustZoom(state.zoom + inc, true); - } else if (commandType == Command.zox) { - var dec = 4.0; - if (state.zoom - dec > 0) - adjustZoom(state.zoom - dec, true); - } else if (commandType == Command.zrx) { - state.zoomHistory = Array(); - adjustZoom(1.0, false); - $("#timeline").scrollLeft(0); - } else if (commandType == Command.zux) { - if (state.zoomHistory.length > 0) { - var previousZoomHistory = state.zoomHistory.pop(); - adjustZoom(previousZoomHistory.zoom, false); - $("#timeline").scrollLeft(previousZoomHistory.start); - } - } else if (commandType == Command.ziy) - adjustThickness(state.thickness * 2); - else if (commandType == Command.zoy) - adjustThickness(state.thickness / 2); - else if (commandType == Command.zry) { - state.height = $(window).height() - constants.margin_bottom - constants.margin_top; - state.thickness = state.height / constants.max_level; - adjustThickness(state.thickness); - } - else if (commandType == Command.clear_search) { - state.searchEnabled = false; - searchRegex = null; - filterAndMergeBlocks(state); - drawTimeline(); - } - else if (commandType == Command.toggle_search) { - if (searchRegex != null) { - state.searchEnabled = !state.searchEnabled; - filterAndMergeBlocks(state); - drawTimeline(); - } - } - else if (commandType == Command.previous_search || - commandType == Command.next_search) { - if (state.searchEnabled) { - var pos = commandType == Command.previous_search ? - (currentPos - 1 + sizeHistory) % sizeHistory : - (currentPos + 1) % sizeHistory; - var sentinel = commandType == Command.previous_search ? - (nextPos - 1 + sizeHistory) % sizeHistory : nextPos; - if (pos != sentinel && searchRegex[pos] != null) { - currentPos = pos; - filterAndMergeBlocks(state); - drawTimeline(); - } - } - } - else if (commandType == Command.toggle_critical_path) { - state.display_critical_path = !state.display_critical_path; - if (state.display_critical_path) { - state.critical_path.forEach(function(op) { - expandByNodeProc(op[0], op[1]); - }); - } - redraw(); - } - return false; -} - -function defaultKeyUp(e) { - if (!e) e = event; - if (!(e.metaKey || e.altKey)) { - state.rangeZoom = true; - } - return true; -} - -function load_proc_timeline(proc) { - var proc_name = proc.full_text; - state.processorData[proc_name] = {}; - var num_levels_ready = proc.num_levels; - if (state.ready_selected) { - proc.num_levels_ready = proc.num_levels; - } - d3.tsv(proc.tsv, - function(d, i) { - var level = +d.level; - var ready = +d.ready; - var start = +d.start; - var end = +d.end; - var level_ready = +d.level_ready; - var total = end - start; - var _in = d.in === "" ? [] : JSON.parse(d.in) - var out = d.out === "" ? [] : JSON.parse(d.out) - var children = d.children === "" ? [] : JSON.parse(d.children) - var parents = d.parents === "" ? [] : JSON.parse(d.parents) - if (total > state.resolution) { - return { - id: i, - level: level, - level_ready: level_ready, - ready: ready, - start: start, - end: end, - color: d.color, - opacity: d.opacity, - initiation: d.initiation, - title: d.title, - in: _in, - out: out, - children: children, - parents: parents, - prof_uid: d.prof_uid, - proc: proc - }; - } - }, - function(data) { - var num_levels_ready=0 - // split profiling items by which level they're on - for(var i = 0; i < data.length; i++) { - var d = data[i]; - var level_sel=d.level; - if (level_sel in state.processorData[proc_name]) { - state.processorData[proc_name][level_sel].push(d); - } else { - state.processorData[proc_name][level_sel] = [d]; - } - if ((d.level_ready != undefined) && (d.level_ready != 0) && - num_levels_ready < d.level_ready) - num_levels_ready = d.level_ready; - - if (d.prof_uid != undefined && d.prof_uid !== "") { - if (d.prof_uid in prof_uid_map) { - prof_uid_map[d.prof_uid].push(d); - } else { - prof_uid_map[d.prof_uid] = [d]; - } - } - } - if (num_levels_ready > proc.num_levels) - proc.num_levels_ready = num_levels_ready; - else - proc.num_levels_ready = proc.num_levels; - proc.loaded = true; - hideLoaderIcon(); - redraw(); - } - ); -} - -function initTimelineElements() { - var timelineGroup = state.timelineSvg.append("g") - .attr("id", "timeline"); - - $("#timeline").scrollLeft(0); - parseURLParameters(); - - var windowCenterY = $(window).height() / 2; - $(window).scroll(function() { - $("#loader-icon").css("top", $(window).scrollTop() + windowCenterY); - $("#pop-up").css("top", $(window).scrollTop()); - }); - - // set scroll callback - var timer = null; - $("#timeline").scroll(function() { - if (timer !== null) { - clearTimeout(timer); - } - timer = setTimeout(function() { - filterAndMergeBlocks(state); - drawTimeline(); - }, 100); - }); - if (!state.collapseAll) { - // initially load in all the cpu processors and the "all util" - var util_regex = /node/; - for (var i = 0; i < state.flattenedLayoutData.length; i++) { - var timelineElement = state.flattenedLayoutData[i]; - if (timelineElement.type == "util" && - util_regex.exec(timelineElement.text) && - timelineElement.depth == 0) { - collapseHandler(timelineElement, i); - } - } - } - turnOnMouseHandlers(); -} - - -function load_ops_and_timeline() { - d3.tsv("legion_prof_ops.tsv", // TODO: move to tsv folder - function(d) { - return d; - }, - function(data) { - data.forEach(function(d) { - state.operations[parseInt(d.op_id)] = d; - }); - // initTimelineElements depends on the ops to be loaded - initTimelineElements(); - } - ); -} - -function load_procs(callback) { - d3.tsv('legion_prof_processor.tsv', - function(d) { - return { - full_text: d.full_text, - text: d.text, - height: +d.levels, - tsv: d.tsv - }; - }, - function(data) { - var prevEnd = 0; - var base = 0; - data.forEach(function(proc) { - proc.enabled = false; - proc.loaded = false; - proc.base = base; - - base += 2; - }); - state.processors = data; - calculateLayout(); - - // flatten the layout and get the new calculated max num levels - flattenLayout(); - calculateBases(); - drawLayout(); - createMenuList1(); - callback(); - - // TODO: fix - load_critical_path(); - } - ); -} - -function getMinElement(arr, mapF) { - if (arr.length === undefined || arr.length == 0) { - throw "invalid array: " + arr; - } - var minElement = arr[0]; - if (mapF === undefined) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] < minElement) { - minElement = arr[i]; - } - } - } else { - minValue = mapF(minElement); - for (var i = 1; i < arr.length; i++) { - var elem = arr[i]; - var value = mapF(elem); - if (value < minValue) { - minElement = elem; - minValue = value; - } - } - } - return minElement; -} - -function filterUtilData(timelineElem) { - var data = state.utilData[timelineElem.tsv]; // TODO: attach to object - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - var start_time = convertToTime(state, windowStart - 100); - var end_time = convertToTime(state, windowEnd + 100); - - var startIndex = timeBisector(data, start_time); - var endIndex = timeBisector(data, end_time); - - startIndex = Math.max(0, startIndex - 1); - endIndex = Math.min(data.length, endIndex + 2); - var length = endIndex - startIndex; - var newData = Array(); - // we will average points together if they are too close together - var resolution = 1; // 3 pixel resolution - var elem = {time: 0, count: 0}; - var startTime = data[startIndex].time; - var startX = convertToPos(state, startTime); - var endTime = 0; - - for (var i = startIndex; i < endIndex - 1; i++) { - endTime = data[i+1].time; - elem.count += data[i].count * (endTime - data[i].time); - //elem.time += data[i].time; - var endX = convertToPos(state, endTime); - if ((endX - startX) >= resolution || i == (endIndex - 2)) { - var totalTime = endTime - startTime; - elem.count /= totalTime; - //avgElem.time /= windowSize; - elem.time = startTime; - newData.push(elem); - elem = {time: 0, count: 0}; - startX = endX; - startTime = endTime; - } - } - - newData.push({time: endTime, count:0}); - - return { - text: timelineElem.text, - base: timelineElem.base, - num_levels: timelineElem.num_levels, - num_levels_ready: timelineElem.num_levels_ready, - data: newData - }; -} - -function mouseover() { - var focus = state.timelineSvg.append("g") - .attr("class", "focus"); - - focus.append("circle") - .attr("fill", "none") - .attr("stroke", "black") - .attr("r", 4.5); - - var utilDescView = state.timelineSvg.append("g") - .attr("class", "utilDesc"); - utilDescView.append("text") - .attr("x", 7) - .attr("y", -4.5) - .attr("class", "desc") - .attr("dy", ".35em"); - utilDescView.insert("rect", "text") - .style("fill", "#222") - .style("opacity", "0.7"); -} - -function mousemove(d, i) { - var line = document.getElementById("util" + i); - - // offset for this particular line grapgh - var base_y = +line.getAttribute("base_y"); - var px = d3.mouse(line)[0]; - var py = d3.mouse(line)[1] + base_y; - - var start = 0; - var end = line.getTotalLength(); - var target = undefined; - var pos = undefined; - - // https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91 - while (true){ - target = Math.floor((start + end) / 2); - pos = line.getPointAtLength(target); - if ((target === end || target === start) && pos.x !== px) { - break; - } - if (pos.x > px) end = target; - else if (pos.x < px) start = target; - else break; //position found - } - - - var cx = pos.x; - var cy = pos.y + base_y; - - var focus = state.timelineSvg.select("g.focus"); - focus.attr("transform", "translate(" + cx + "," + cy + ")"); - - var utilDescView = state.timelineSvg.select("g.utilDesc"); - utilDescView.attr("transform", "translate(" + (px + 10) + "," + (py - 10) + ")"); - var text = utilDescView.select("text") - - text.text(Math.round(state.y.invert(pos.y) * 100) + "% utilization"); - - var bbox = text.node().getBBox(); - var padding = 2; - var rect = utilDescView.select("rect", "text"); - rect.attr("x", bbox.x - padding) - .attr("y", bbox.y - padding) - .attr("width", bbox.width + (padding*2)) - .attr("height", bbox.height + (padding*2)); - - var timelineRight = $("#timeline").scrollLeft() + $("#timeline").width(); - var bboxRight = px + bbox.x + bbox.width; - // If the box moves off the screen, nudge it back - if (bboxRight > timelineRight) { - var translation = -(bboxRight - timelineRight + 20); - text.attr("transform", "translate(" + translation + ",0)"); - rect.attr("transform", "translate(" + translation + ",0)"); - } -} - -// Get the data -function load_util(elem) { - var util_file = elem.tsv; - - // exit early if we already loaded it - if(state.utilData[util_file]) { - elem.loaded = true; - hideLoaderIcon(); - redraw(); - return; - } - - d3.tsv(util_file, - function(d) { - return { - time: +d.time, - count: +d.count - }; - }, - function(error, data) { - state.utilData[util_file] = data; - elem.loaded = true; - hideLoaderIcon(); - redraw(); - } - ); -} - -function load_critical_path() { - $.getJSON("json/critical_path.json", function(json) { - state.critical_path = json.map(function(p) {return p.tuple}); - state.critical_path_prof_uids = {}; - state.critical_path.forEach(function(p) { - state.critical_path_prof_uids[p[2]] = 1; - }); - }); -} - -function load_data() { - load_procs(load_ops_and_timeline); -} - -function initializeState() { - var margin = constants.margin_left + constants.margin_right; - state.width = $(window).width() - margin; - state.height = $(window).height() - constants.margin_bottom; - state.scale = state.width / (constants.end - constants.start); - state.zoom = 1.0; - state.zoomHistory = Array(); - state.numLoading = 0; - state.dependencyEvent = undefined; - state.drawDeps = false; - state.drawChildren = false; - - state.layoutData = []; - state.flattenedLayoutData = []; - - state.profilingData = {}; - state.processorData = {}; - state.utilData = []; - - state.operations = {}; - state.thickness = 20; //Math.max(state.height / constants.max_level, 20); - state.baseThickness = state.height / constants.max_level; - state.height = constants.max_level * state.thickness; - state.resolution = 10; // time (in us) of the smallest feature we want to load - state.searchEnabled = false; - state.rangeZoom = true; - state.collapseAll = false; - state.display_critical_path = false; - state.processor_kinds = {}; - - // display task ready state? - state.ready_selected = false; - // TODO: change this - state.x = d3.scale.linear().range([0, state.width]); - state.y = d3.scale.linear().range([constants.util_levels * state.thickness, 0]); - state.y.domain([0, 1]); - - setKeyHandler(defaultKeydown); - $(document).on("keyup", defaultKeyUp); - state.timelineSvg = d3.select("#timeline").select("svg").remove(); - state.timelineSvg = d3.select("#timeline").append("svg") - .attr("width", state.zoom * state.width) - .attr("height", state.height); - - state.loaderSvg = d3.select("#loader-icon").select("svg").remove(); - state.loaderSvg = d3.select("#loader-icon").append("svg") - .attr("width", "40px") - .attr("height", "40px"); - - d3.select("#processors").select("svg").remove(); - - drawLoaderIcon(); - drawHelpBox(); - load_data(); -} - -function load_util_json(callback) { - $.getJSON("json/utils.json", function(json) { - util_files = json; - callback(); - }); -} - -// Loads constants such as max_level, start/end time, and number of levels -// of a util view -function load_scale_json(callback) { - $.getJSON("json/scale.json", function(json) { - // add the read-in constants - $.each(json, function(key, val) { - constants[key] = val; - }); - load_util_json(callback); - }); -} - -function load_op_deps_json(callback) { - $.getJSON("json/op_dependencies.json", function(json) { - op_dependencies = json; - load_scale_json(callback); - }); -} - -function load_jsons(callback) { - load_scale_json(callback); -} - -function main() { - load_jsons(initializeState); -} - -main(); diff --git a/examples/testbench/legion_prof/js/util.js b/examples/testbench/legion_prof/js/util.js deleted file mode 100644 index 16ea770f2..000000000 --- a/examples/testbench/legion_prof/js/util.js +++ /dev/null @@ -1,378 +0,0 @@ -//----------------------------------------------------------------------------- -// UTILS -//----------------------------------------------------------------------------- - -var helpMessage = [ - "Zoom-in (x-axis) : Ctrl + / 4", - "Zoom-out (x-axis) : Ctrl - / 3", - "Reset zoom (x-axis): Ctrl 0 / 0", - "Undo zoom (x-axis) : u / U", - "Zoom-in (y-axis) : Ctrl-Alt + / 2", - "Zoom-out (y-axis) : Ctrl-Alt - / 1", - "Reset zoom (y-axis): Ctrl-Alt 0 / `", - "Range Zoom-in : drag-select", - "Measure duration : Alt + drag-select", - "Expand : e / E", - "Draw Critical Path : a / A", - "Search : s / S", - "Search History : h / H", - "Previous Search : p / P", - "Next Search : n / N", - "Clear Search : c / C", - "Toggle Search : t / T", -]; - -var Command = { - none : 0, - help : 1, - zox : 2, - zix : 3, - zrx : 4, - zux : 5, - zoy : 6, - ziy : 7, - zry : 8, - search : 9, - clear_search : 10, - toggle_search : 11, - expand: 12, - toggle_critical_path: 13, - search_history : 14, - previous_search : 15, - next_search : 16 -}; - -// commands without a modifier key pressed -var noModifierCommands = { - '0': Command.zrx, - '1': Command.zoy, - '2': Command.ziy, - '3': Command.zox, - '4': Command.zix, - 'c': Command.clear_search, - 'e': Command.expand, - 'h': Command.search_history, - 'n': Command.next_search, - 'p': Command.previous_search, - 's': Command.search, - 'a': Command.toggle_critical_path, - 't': Command.toggle_search, - 'u': Command.zux, - '/': Command.help -}; - -var modifierCommands = { - '+': Command.zix, - '-': Command.zox, - '0': Command.zrx -} - -var multipleModifierCommands = { - '+': Command.ziy, - '-': Command.zoy, - '0': Command.zry -} - -var keys = { - 13 : 'enter', - 27 : 'esc', - 48 : '0', - 49 : '1', - 50 : '2', - 51 : '3', - 52 : '4', - 61 : '+', // Firefox - 65 : 'a', - 67 : 'c', - 69 : 'e', - 72 : 'h', - 78 : 'n', - 80 : 'p', - 83 : 's', - 84 : 't', - 85 : 'u', - 173 : '-', // Firefox - 187 : '+', - 189 : '-', - 191 : '/', - 192 : '`' -}; - -/** - * Function: convertToTime - * - * Description: - * Takes a value and converts it to time. The input 'x' can either be - * a single position on the timeline, or it can be a width. - */ -function convertToTime(state, x) { - return x / state.zoom / state.scale; -} - -/** - * Function: convertToPos - * - * Description: - * Takes a time and converts it to a position in the window. - * The 'time' parameter MUST BE IN us - */ -function convertToPos(state, time) { - return time * state.zoom * state.scale; -} - -/** - * Function: getTimeString - * - * Description: - * This function takes a time (in us) as well as a 'width' - * field. The 'width' field determines over what interval - * the time is being considered. - * - * If the width is too large, the time will be converted - * to either ms or sec. - * - * The function will return a string representation of the - * (possibly) scaled time at the end of the method - */ -function getTimeString(time, timeWidth) { - var unit = "us"; - var scaledTime = Math.floor(time); - if (timeWidth >= 100000) { - var scaledTime = Math.floor(time / 1000); - unit = "ms"; - } else if (timeWidth >= 100000000) { - var scaledTime = Math.floor(time / 1000000); - unit = "s"; - } - return scaledTime + " " + unit; -} - -// timeField should be 'end' for the left hand side and -// 'start' for the right hand side -function binarySearch(data, level, time, useStart) { - var low = 0; - var high = data[level].length; - while (true) { - // ugh is there a way to do integer division in javascrtipt? - var mid = Math.floor((high - low) / 2) + low; - - // In this case, we haven't found it. This is as close - // as we were able to get. - if (low == high || low == mid) { - return low; - } else if (high == mid) { - return high; - } - var midTime; - if (useStart) { - midTime = data[level][mid].start; - } else { - midTime = data[level][mid].end; - } - - if (midTime > time) { - // need to look below - high = mid; - } else if (midTime < time) { - // need to look above - low = mid; - } else { - // Exact Match - return mid; - } - } -} - -dataReady = {}; -function redoData(proc) { - dataReady = {}; - var items = state.processorData[proc.full_text]; - for (var level in items) { - for (var j = 0; j< items[level].length; j++) { - d = items[level][j]; - // ready state items - if (d.level_ready != undefined && d.level_ready != "" && - d.ready != undefined && d.ready != "") { - // if the level has already been switched, then don't do anything - var level_to_set = d.level_ready; - if (d.level_ready_set != undefined && d.level_ready_set == true) - level_to_set = d.level; - var d_ready = { - id: d.id+items[level].length+1, // unique id - level: level_to_set, - level_ready: d.level, - ready: d.ready, - start: d.ready, - end: d.start, - color: d.color, - opacity: "0.45", - initiation: d.initiation, - title: d.title + " (ready)", - in: d.in, - out: d.out, - children: d.children, - parents: d.parents, - prof_uid: d.prof_uid, - proc: d.proc - }; - // switch levels if we need to - if (d.level_ready_set == undefined || d.level_ready_set == false) - { - var level_tmp = d.level; - d.level = d.level_ready; - d.level_ready = level_tmp; - d.level_ready_set = true; - } - if (d.level_ready in dataReady){ - dataReady[d.level_ready].push(d_ready); - dataReady[d.level_ready].push(d); - } - else { - dataReady[d.level_ready] = [d_ready]; - dataReady[d.level_ready].push(d); - } - } - // add items to the level - else { - if (d.level in dataReady) - dataReady[d.level].push(d); - else - dataReady[d.level] = [d]; - } - } - } -} - -function readyData(proc) { - redoData(proc); -} - -function filterAndMergeBlocks(state) { - var windowStart = $("#timeline").scrollLeft(); - var windowEnd = windowStart + $("#timeline").width(); - state.dataToDraw = Array(); - state.memoryTexts = Array(); - var startTime = convertToTime(state, windowStart); - var endTime = convertToTime(state, windowEnd); - var min_feature_time = convertToTime(state, constants.min_feature_width); - var min_gap_time = convertToTime(state, constants.min_gap_width); - for (var index in state.flattenedLayoutData) { - var timelineElement = state.flattenedLayoutData[index]; - if (timelineElement.type == "proc" && timelineElement.enabled && timelineElement.visible) { - var items = state.processorData[timelineElement.full_text]; - var memoryRegex = /Memory/; - var isMemory = memoryRegex.exec(timelineElement.text); - if (state.ready_selected) { - readyData(timelineElement); - items = dataReady; - } - - for (var level in items) { - // gap merging below assumes intervals are sorted - do that first - //items[level].sort(function(a,b) { return a.start - b.start; }); - - // We will use binary search to limit the following section - var startIndex = binarySearch(items, level, startTime, false); - var endIndex = binarySearch(items, level, endTime, true); - for (var i = startIndex; i <= endIndex; ++i) { - var d = items[level][i]; - var start = d.start; - var end = d.end; - // fix the level here - if (state.ready_selected == false && d.level_ready_set != undefined - && d.level_ready_set == true) - { - // switch levels - var level_tmp = d.level; - d.level = d.level_ready; - d.level_ready = level_tmp; - d.level_ready_set = false; - } - // is this block too narrow? - if ((end - start) < min_feature_time) { - // see how many more after this are also too narrow and too close to us - var count = 1; - // don't do this if we're the subject of the current search and don't merge with - // something that is - if (!state.searchEnabled || searchRegex[currentPos].exec(d.title) == null) { - while (((i + count) < items[level].length) && - ((items[level][i + count].start - end) < min_gap_time) && - ((items[level][i + count].end - items[level][i + count].start) < min_feature_time) && - (!state.searchEnabled || searchRegex[currentPos].exec(items[level][i + count].title) == null)) { - end = items[level][i + count].end; - count++; - } - } - // are we still too narrow? if so, bloat, but make sure we don't overlap something later - if ((end - start) < min_feature_time) { - end = start + min_feature_time; - if (((i + count) < items[level].length) && (items[level][i + count].start < end)) - end = items[level][i + count].start; - } - if (count > 1) { - state.dataToDraw.push({ - id: d.id, - prof_uid: d.prof_uid, - proc: timelineElement, - level: d.level, - ready: d.ready, - start: d.start, - end: Math.round(end), - color: "#808080", - title: count + " merged tasks", - in: [], - out: [], - children: [], - parents: [] - }); - i += (count - 1); - } else { - var elem = { - id: d.id, - prof_uid: d.prof_uid, - proc: timelineElement, - level: d.level, - ready: d.ready, - start: d.start, - end: d.end, - color: d.color, - initiation: d.initiation, - title: d.title + " (expanded for visibility)", - in: d.in, - out: d.out, - children: d.children, - parents: d.parents - } - state.dataToDraw.push(elem); - if (isMemory) { - state.memoryTexts.push(elem); - } - } - } else { - var elem = { - id: d.id, - prof_uid: d.prof_uid, - proc: timelineElement, - level: d.level, - ready: d.ready, - start: d.start, - end: d.end, - opacity: d.opacity, - color: d.color, - initiation: d.initiation, - title: d.title, - in: d.in, - out: d.out, - children: d.children, - parents: d.parents - } - state.dataToDraw.push(elem); - if (isMemory) { - state.memoryTexts.push(elem); - } - } - } - } - } - } -} diff --git a/examples/testbench/legion_prof/legion_prof_ops.tsv b/examples/testbench/legion_prof/legion_prof_ops.tsv deleted file mode 100644 index fc406664e..000000000 --- a/examples/testbench/legion_prof/legion_prof_ops.tsv +++ /dev/null @@ -1,59 +0,0 @@ -op_id desc proc level -1 legion_python_main <1> Python Processor 0x1d00000000000003 2 -28 Task Operation <28> -34 Task Operation <34> -39 Task Operation <39> -40 Task Operation <40> -8 legate::numpy::FillTask [CPU] <8> CPU Processor 0x1d00000000000002 2 -12 legate::numpy::FillTask [CPU] <12> CPU Processor 0x1d00000000000002 2 -13 legate::numpy::FillTask [CPU] <13> CPU Processor 0x1d00000000000002 2 -23 legate::numpy::FusedOpTask [CPU] <23> CPU Processor 0x1d00000000000002 2 -35 legate::numpy::FusedOpTask [CPU] <35> CPU Processor 0x1d00000000000002 2 -0 Operation <0> -3 Tunable Operation <3> -5 Tunable Operation <5> -6 legate::numpy::FillTask [CPU] <6> CPU Processor 0x1d00000000000002 2 -7 Merge Close Operation <7> -11 Merge Close Operation <11> -10 legate::numpy::FillTask [CPU] <10> CPU Processor 0x1d00000000000002 2 -14 legate::numpy::FillTask [CPU] <14> CPU Processor 0x1d00000000000002 2 -15 Attach Operation <15> -16 Merge Close Operation <16> -17 Attach Operation <17> -18 Merge Close Operation <18> -19 Attach Operation <19> -20 Merge Close Operation <20> -21 Attach Operation <21> -22 Merge Close Operation <22> -24 Merge Close Operation <24> -36 Merge Close Operation <36> -37 Merge Close Operation <37> -38 Mapping Operation <38> -50 Deletion Operation <50> -51 Deletion Operation <51> -52 Deletion Operation <52> -53 Deletion Operation <53> -54 Deletion Operation <54> -55 Deletion Operation <55> -56 Deletion Operation <56> -57 Deletion Operation <57> -58 Deletion Operation <58> -9 Merge Close Operation <9> -4 Tunable Operation <4> -25 Attach Operation <25> -27 Attach Operation <27> -30 Attach Operation <30> -32 Attach Operation <32> -41 Fence Operation <41> -42 Detach Operation <42> -43 Detach Operation <43> -44 Detach Operation <44> -45 Detach Operation <45> -46 Detach Operation <46> -47 Detach Operation <47> -48 Detach Operation <48> -49 Detach Operation <49> -29 Merge Close Operation <29> -33 Merge Close Operation <33> -26 Merge Close Operation <26> -31 Merge Close Operation <31> diff --git a/examples/testbench/legion_prof/legion_prof_processor.tsv b/examples/testbench/legion_prof/legion_prof_processor.tsv deleted file mode 100644 index 80cc631bf..000000000 --- a/examples/testbench/legion_prof/legion_prof_processor.tsv +++ /dev/null @@ -1,6 +0,0 @@ -full_text text tsv levels -Utility Processor 0x1d00000000000000 Utility Proc 0 tsv/Proc_0x1d00000000000000.tsv 3 -Utility Processor 0x1d00000000000001 Utility Proc 1 tsv/Proc_0x1d00000000000001.tsv 2 -CPU Processor 0x1d00000000000002 CPU Proc 2 tsv/Proc_0x1d00000000000002.tsv 1 -Python Processor 0x1d00000000000003 Python Proc 3 tsv/Proc_0x1d00000000000003.tsv 1 -System Memory 0x1e00000000000000 [n0] sys tsv/Mem_0x1e00000000000000.tsv 7 diff --git a/examples/testbench/legion_prof/tsv/0 (CPU)_util.tsv b/examples/testbench/legion_prof/tsv/0 (CPU)_util.tsv deleted file mode 100644 index b5a809961..000000000 --- a/examples/testbench/legion_prof/tsv/0 (CPU)_util.tsv +++ /dev/null @@ -1,206 +0,0 @@ -time count -0.000 0.00 -1131871.414 1.00 -1131877.823 0.00 -1131902.582 1.00 -1131907.442 0.00 -1131967.180 1.00 -1131973.556 0.00 -1887540.878 1.00 -1887549.090 0.00 -2004081.928 1.00 -2004089.422 0.00 -2064305.095 1.00 -2064310.462 0.00 -2064366.713 1.00 -2064373.269 0.00 -2064467.966 1.00 -2064474.773 0.00 -2064854.771 1.00 -2064860.185 0.00 -2064917.697 1.00 -2065292.716 0.00 -2065321.206 1.00 -2065629.402 0.00 -2065651.028 1.00 -2065655.364 0.00 -2065660.845 1.00 -2065664.930 0.00 -2065670.191 1.00 -2065674.528 0.00 -2065678.796 1.00 -2065682.654 0.00 -2065686.872 1.00 -2065690.098 0.00 -2065694.309 1.00 -2065697.477 0.00 -2065703.630 1.00 -2065708.390 0.00 -2065714.725 1.00 -2065719.262 0.00 -2065723.840 1.00 -2065727.832 0.00 -2065780.941 1.00 -2066111.116 0.00 -2066144.783 1.00 -2066215.987 0.00 -2066245.594 1.00 -2066251.163 0.00 -2066259.095 1.00 -2066264.225 0.00 -2066301.621 1.00 -2066377.311 0.00 -2066405.630 1.00 -2066412.893 0.00 -2066421.100 1.00 -2066427.548 0.00 -2066471.431 1.00 -2066479.071 0.00 -2066535.583 1.00 -2066593.473 0.00 -2067346.675 1.00 -2067354.303 0.00 -2067387.727 1.00 -2067394.617 0.00 -2067442.872 1.00 -2067451.090 0.00 -2067474.731 1.00 -2067480.297 0.00 -2067488.729 1.00 -2067495.305 0.00 -2067532.311 1.00 -2067539.293 0.00 -2067571.934 1.00 -2067579.663 0.00 -2067606.592 1.00 -2067612.221 0.00 -2067621.464 1.00 -2067627.153 0.00 -2067662.795 1.00 -2067670.163 0.00 -2067679.315 1.00 -2067686.512 0.00 -2067705.097 1.00 -2067711.610 0.00 -2067719.563 1.00 -2067726.024 0.00 -2067760.488 1.00 -2067767.837 0.00 -2067834.393 1.00 -2067841.326 0.00 -2067867.718 1.00 -2067875.021 0.00 -2067900.658 1.00 -2067906.286 0.00 -2067951.131 1.00 -2067956.251 0.00 -2067963.814 1.00 -2067967.314 0.00 -2068872.288 1.00 -2068882.867 0.00 -2069260.928 1.00 -2070348.048 0.00 -2070377.866 1.00 -2070383.587 0.00 -2070819.172 1.00 -2070828.288 0.00 -2070840.483 1.00 -2070848.019 0.00 -2070858.887 1.00 -2070866.815 0.00 -2071135.872 1.00 -2071143.400 0.00 -2071175.560 1.00 -2071188.129 0.00 -2071441.366 1.00 -2072373.142 0.00 -2072407.594 1.00 -2072415.756 0.00 -2223654.660 1.00 -2223670.393 0.00 -2223681.067 1.00 -2223688.333 0.00 -2223729.950 1.00 -2223735.924 0.00 -2223828.994 1.00 -2223833.763 0.00 -2223878.262 1.00 -2223882.918 0.00 -2223928.589 1.00 -2223933.189 0.00 -2223979.621 1.00 -2223984.034 0.00 -2224047.331 1.00 -2224051.623 0.00 -2224101.138 1.00 -2224106.757 0.00 -2224148.335 1.00 -2224161.362 0.00 -2224186.534 1.00 -2224191.200 0.00 -2224220.301 1.00 -2224223.906 0.00 -2224253.499 1.00 -2224257.289 0.00 -2224316.993 1.00 -2224321.896 0.00 -2224371.021 1.00 -2224376.481 0.00 -2224382.616 1.00 -2224387.519 0.00 -2224404.275 1.00 -2224409.090 0.00 -2224422.632 1.00 -2224427.511 0.00 -2224432.534 1.00 -2224435.672 0.00 -2224462.197 1.00 -2224466.176 0.00 -2224561.477 1.00 -2224567.447 0.00 -2224577.316 1.00 -2224583.749 0.00 -2224592.176 1.00 -2224597.422 0.00 -2224605.256 1.00 -2224611.578 0.00 -2224625.618 1.00 -2224631.298 0.00 -2224640.500 1.00 -2224647.306 0.00 -2224655.645 1.00 -2224662.140 0.00 -2224723.627 1.00 -2224727.850 0.00 -2224771.060 1.00 -2224775.847 0.00 -2224811.759 1.00 -2224816.039 0.00 -2224822.127 1.00 -2224825.941 0.00 -2224867.885 1.00 -2224872.650 0.00 -2224902.872 1.00 -2224908.376 0.00 -2224914.147 1.00 -2224917.592 0.00 -2224963.214 1.00 -2224967.510 0.00 -2225013.096 1.00 -2225017.772 0.00 -2225061.833 1.00 -2225067.872 0.00 -2225110.405 1.00 -2225115.363 0.00 -2225145.405 1.00 -2225149.977 0.00 -2225157.536 1.00 -2225162.322 0.00 -2225219.074 1.00 -2225225.623 0.00 -2225247.956 1.00 -2225252.965 0.00 -2225278.124 1.00 -2225284.676 0.00 -2225330.082 1.00 -2225334.333 0.00 diff --git a/examples/testbench/legion_prof/tsv/0 (Python)_util.tsv b/examples/testbench/legion_prof/tsv/0 (Python)_util.tsv deleted file mode 100644 index 2aea9b2e8..000000000 --- a/examples/testbench/legion_prof/tsv/0 (Python)_util.tsv +++ /dev/null @@ -1,16 +0,0 @@ -time count -0.000 0.00 -1134192.460 1.00 -1887460.195 0.00 -1887666.489 1.00 -1887795.983 0.00 -1888027.844 1.00 -2004013.143 0.00 -2004155.450 1.00 -2071175.689 0.00 -2071636.356 1.00 -2071651.215 0.00 -2072465.988 1.00 -2125746.910 0.00 -2125906.215 1.00 -2223592.200 0.00 diff --git a/examples/testbench/legion_prof/tsv/0 (System Memory)_util.tsv b/examples/testbench/legion_prof/tsv/0 (System Memory)_util.tsv deleted file mode 100644 index f6914d7c8..000000000 --- a/examples/testbench/legion_prof/tsv/0 (System Memory)_util.tsv +++ /dev/null @@ -1,16 +0,0 @@ -time count -0.000 0.00 -2064650.117 0.00 -2065147.467 0.00 -2065598.615 0.00 -2069053.346 0.00 -2069121.527 0.00 -2071048.359 0.00 -2071113.099 0.00 -2224133.183 0.00 -2224204.270 0.00 -2224388.739 0.00 -2224448.793 0.00 -2224510.529 0.00 -2224556.754 0.00 -2224609.631 0.00 diff --git a/examples/testbench/legion_prof/tsv/0 (Utility)_util.tsv b/examples/testbench/legion_prof/tsv/0 (Utility)_util.tsv deleted file mode 100644 index 67767ff36..000000000 --- a/examples/testbench/legion_prof/tsv/0 (Utility)_util.tsv +++ /dev/null @@ -1,648 +0,0 @@ -time count -0.000 0.00 -1131662.511 0.50 -1131743.730 0.00 -1131750.448 0.50 -1131777.645 1.00 -1131796.014 0.50 -1131842.077 1.00 -1131847.857 0.50 -1131875.771 1.00 -1131881.475 0.50 -1131943.421 1.00 -1131945.331 0.50 -1132089.267 0.00 -1132112.899 0.50 -1132119.532 0.00 -1887393.247 0.50 -1887455.149 0.00 -1887469.337 0.50 -1887480.054 1.00 -1887485.915 0.50 -1887516.954 0.00 -1887535.605 0.50 -1887638.705 0.00 -1887666.368 0.50 -1887676.134 0.00 -1887805.820 0.50 -1887841.593 0.00 -1887867.399 0.50 -1887872.806 0.00 -1887873.868 0.50 -1887911.228 0.00 -1887939.316 0.50 -1887942.877 1.00 -1887943.976 0.50 -1887986.727 0.00 -1888015.869 0.50 -1888019.680 0.00 -2004015.227 0.50 -2004050.023 1.00 -2004051.755 0.50 -2004073.805 0.00 -2004078.517 0.50 -2004100.736 1.00 -2004106.103 0.50 -2004121.149 0.00 -2004142.069 0.50 -2004145.762 0.00 -2064129.215 0.50 -2064271.214 1.00 -2064275.023 0.50 -2064295.923 1.00 -2064297.548 0.50 -2064314.243 1.00 -2064318.757 0.50 -2064336.527 1.00 -2064342.601 0.50 -2064358.130 0.00 -2064363.504 0.50 -2064372.340 1.00 -2064378.142 0.50 -2064439.767 1.00 -2064440.663 0.50 -2064491.009 1.00 -2064519.103 0.50 -2064684.275 1.00 -2064696.490 0.50 -2064796.569 1.00 -2064815.504 0.50 -2064851.735 1.00 -2064912.591 0.50 -2064920.144 0.00 -2064938.430 0.50 -2064939.541 1.00 -2064943.295 0.50 -2064949.158 1.00 -2064959.621 0.50 -2064960.112 0.00 -2064966.408 0.50 -2064974.539 1.00 -2064979.176 0.50 -2064985.140 1.00 -2064987.569 0.50 -2065001.319 1.00 -2065005.803 0.50 -2065008.315 0.00 -2065011.887 0.50 -2065021.505 1.00 -2065026.318 0.50 -2065074.606 0.00 -2065080.934 0.50 -2065087.801 1.00 -2065093.099 0.50 -2065175.981 1.00 -2065183.321 0.50 -2065193.676 1.00 -2065222.977 0.50 -2065259.007 0.00 -2065260.230 0.50 -2065279.744 0.00 -2065285.153 0.50 -2065290.919 0.00 -2065298.864 0.50 -2065304.046 0.00 -2065311.838 0.50 -2065314.647 1.00 -2065323.070 0.50 -2065330.219 1.00 -2065357.418 0.50 -2065374.476 0.00 -2065376.792 0.50 -2065395.290 1.00 -2065404.409 0.50 -2065406.576 0.00 -2065413.072 0.50 -2065431.175 1.00 -2065437.527 0.50 -2065462.884 1.00 -2065463.379 0.50 -2065478.480 1.00 -2065518.172 0.50 -2065531.848 1.00 -2065541.822 0.50 -2065555.739 1.00 -2065572.335 0.50 -2065594.419 1.00 -2065660.636 0.50 -2065705.960 1.00 -2065742.165 0.50 -2065761.473 1.00 -2065773.170 0.50 -2065786.367 0.00 -2065798.928 0.50 -2065820.023 1.00 -2065822.530 0.50 -2065831.153 1.00 -2065836.685 0.50 -2065841.234 1.00 -2065844.525 0.50 -2065873.896 1.00 -2065876.598 0.50 -2065899.023 1.00 -2065909.599 0.50 -2065965.066 0.00 -2065981.765 0.50 -2065991.392 1.00 -2066001.818 0.50 -2066047.656 1.00 -2066048.507 0.50 -2066070.084 1.00 -2066079.325 0.50 -2066081.533 0.00 -2066094.843 0.50 -2066102.388 1.00 -2066108.878 0.50 -2066135.812 1.00 -2066147.756 0.50 -2066156.610 1.00 -2066197.991 0.50 -2066210.980 0.00 -2066220.415 0.50 -2066235.493 1.00 -2066242.836 0.50 -2066253.371 1.00 -2066284.954 0.50 -2066303.311 0.00 -2066319.571 0.50 -2066330.336 1.00 -2066339.047 0.50 -2066349.384 1.00 -2066355.745 0.50 -2066365.568 1.00 -2066367.395 0.50 -2066384.163 1.00 -2066388.487 0.50 -2066394.872 1.00 -2066398.119 0.50 -2066420.978 1.00 -2066445.626 0.50 -2066461.318 1.00 -2066463.174 0.50 -2066479.174 1.00 -2066483.256 0.50 -2066515.270 0.00 -2066529.232 0.50 -2066533.681 0.00 -2066627.150 0.50 -2066634.424 0.00 -2066642.926 0.50 -2066670.867 0.00 -2066698.558 0.50 -2066703.281 0.00 -2067301.801 0.50 -2067308.792 1.00 -2067319.124 0.50 -2067341.192 1.00 -2067367.273 0.50 -2067368.328 0.00 -2067388.990 0.50 -2067395.492 1.00 -2067401.134 0.50 -2067420.603 0.00 -2067421.580 0.50 -2067439.875 1.00 -2067454.232 0.50 -2067455.291 0.00 -2067472.127 0.50 -2067474.609 1.00 -2067512.496 0.50 -2067527.751 1.00 -2067549.614 0.50 -2067566.785 1.00 -2067579.536 0.50 -2067590.043 0.00 -2067602.973 0.50 -2067607.985 1.00 -2067641.326 0.50 -2067641.791 0.00 -2067656.500 0.50 -2067663.628 1.00 -2067679.151 0.50 -2067681.707 0.00 -2067705.309 0.50 -2067706.016 1.00 -2067735.601 0.50 -2067752.698 0.00 -2067762.961 0.50 -2067774.098 1.00 -2067780.707 0.50 -2067810.448 0.00 -2067816.908 0.50 -2067830.114 1.00 -2067845.249 0.50 -2067868.331 1.00 -2067873.646 0.50 -2067911.279 1.00 -2067928.423 0.50 -2067944.485 0.00 -2067945.510 0.50 -2067997.003 0.00 -2068005.933 0.50 -2068011.781 1.00 -2068016.154 0.50 -2068034.238 0.00 -2068034.716 0.50 -2068050.192 1.00 -2068053.972 0.50 -2068081.412 0.00 -2068099.841 0.50 -2068103.496 0.00 -2068718.776 0.50 -2068819.324 0.00 -2068819.800 0.50 -2068838.765 1.00 -2068843.921 0.50 -2068845.196 0.00 -2068851.002 0.50 -2068869.449 1.00 -2068873.194 0.50 -2068888.720 1.00 -2068893.183 0.50 -2068895.729 0.00 -2068899.579 0.50 -2068920.805 1.00 -2068925.382 0.50 -2068967.735 0.00 -2068981.108 0.50 -2068987.640 1.00 -2068992.969 0.50 -2069083.012 1.00 -2069106.618 0.50 -2069147.523 1.00 -2069165.785 0.50 -2069234.110 1.00 -2069255.619 0.50 -2069272.218 1.00 -2069279.820 0.50 -2069292.337 0.00 -2069296.143 0.50 -2069304.388 0.00 -2069306.933 0.50 -2069322.918 1.00 -2069326.187 0.50 -2069340.380 1.00 -2069345.572 0.50 -2069352.748 1.00 -2069356.475 0.50 -2069374.511 1.00 -2069390.333 0.50 -2069390.747 0.00 -2069407.691 0.50 -2069418.366 1.00 -2069425.098 0.50 -2069432.480 1.00 -2069437.167 0.50 -2069444.029 1.00 -2069449.166 0.50 -2069456.488 1.00 -2069488.484 0.50 -2069500.754 0.00 -2069509.402 0.50 -2069521.646 1.00 -2069528.013 0.50 -2069535.567 0.00 -2069535.964 0.50 -2069555.271 1.00 -2069565.176 0.50 -2069568.751 0.00 -2069581.553 0.50 -2069631.187 1.00 -2069638.355 0.50 -2069659.704 1.00 -2069663.194 0.50 -2069689.634 1.00 -2069729.027 0.50 -2069736.823 0.00 -2069756.624 0.50 -2069762.525 1.00 -2069769.736 0.50 -2069778.737 1.00 -2069783.086 0.50 -2069790.728 1.00 -2069792.334 0.50 -2069810.149 1.00 -2069831.359 0.50 -2069849.405 1.00 -2069870.888 0.50 -2069877.565 0.00 -2069886.021 0.50 -2069894.631 0.00 -2069907.512 0.50 -2069911.435 1.00 -2069922.920 0.50 -2069941.733 0.00 -2069947.237 0.50 -2069960.854 1.00 -2069966.367 0.50 -2069974.700 0.00 -2069978.389 0.50 -2069998.435 1.00 -2070005.542 0.50 -2070010.923 0.00 -2070014.959 0.50 -2070032.572 1.00 -2070036.122 0.50 -2070040.870 1.00 -2070044.094 0.50 -2070048.472 1.00 -2070051.774 0.50 -2070056.245 1.00 -2070060.009 0.50 -2070067.424 1.00 -2070073.169 0.50 -2070075.913 0.00 -2070081.771 0.50 -2070087.538 0.00 -2070094.373 0.50 -2070099.524 0.00 -2070101.685 0.50 -2070107.471 1.00 -2070108.096 0.50 -2070113.258 0.00 -2070116.927 0.50 -2070120.860 1.00 -2070123.965 0.50 -2070125.106 0.00 -2070131.877 0.50 -2070133.033 1.00 -2070136.189 0.50 -2070139.695 0.00 -2070141.398 0.50 -2070145.072 0.00 -2070148.618 0.50 -2070150.171 1.00 -2070154.829 0.50 -2070155.876 0.00 -2070159.785 0.50 -2070164.050 0.00 -2070164.942 0.50 -2070170.490 0.00 -2070311.079 0.50 -2070326.801 0.00 -2070329.126 0.50 -2070369.981 0.00 -2070370.602 0.50 -2070377.373 0.00 -2070385.334 0.50 -2070388.785 1.00 -2070392.574 0.50 -2070426.871 0.00 -2070469.051 0.50 -2070475.390 0.00 -2070698.337 0.50 -2070781.152 1.00 -2070791.932 0.50 -2070806.013 0.00 -2070812.162 0.50 -2070823.632 1.00 -2070835.663 0.50 -2070843.027 0.00 -2070851.863 0.50 -2070860.505 1.00 -2070865.751 0.50 -2070872.848 1.00 -2070873.378 0.50 -2070889.815 1.00 -2070895.005 0.50 -2070895.393 0.00 -2070901.054 0.50 -2070912.589 1.00 -2070917.128 0.50 -2070962.074 0.00 -2070975.805 0.50 -2070982.478 1.00 -2070987.821 0.50 -2071077.383 1.00 -2071100.087 0.50 -2071113.591 1.00 -2071152.023 0.50 -2071213.450 1.00 -2071219.974 0.50 -2071426.355 1.00 -2071432.285 0.50 -2071450.221 1.00 -2071458.232 0.50 -2071475.719 0.00 -2071485.324 0.50 -2071501.085 1.00 -2071507.744 0.50 -2071649.220 0.00 -2071675.248 0.50 -2071681.510 0.00 -2071933.817 0.50 -2071943.818 1.00 -2071946.793 0.50 -2071971.528 1.00 -2071975.936 0.50 -2072004.306 0.00 -2072030.588 0.50 -2072036.622 0.00 -2072345.424 0.50 -2072358.717 0.00 -2072364.643 0.50 -2072392.367 0.00 -2072393.575 0.50 -2072400.046 0.00 -2072409.183 0.50 -2072416.299 1.00 -2072424.207 0.50 -2072446.614 0.00 -2072472.619 0.50 -2072478.026 0.00 -2125594.978 0.50 -2125632.752 0.00 -2125703.515 0.50 -2125736.612 0.00 -2125756.869 0.50 -2125782.049 0.00 -2125799.828 0.50 -2125832.850 0.00 -2125852.771 0.50 -2125854.803 1.00 -2125859.590 0.50 -2125862.182 0.00 -2125867.246 0.50 -2125872.861 1.00 -2125873.486 0.50 -2125881.155 0.00 -2142117.664 0.50 -2142134.517 1.00 -2142169.070 0.50 -2142358.907 0.00 -2142379.766 0.50 -2142408.752 0.00 -2142421.085 0.50 -2142427.615 1.00 -2142458.056 0.50 -2142459.315 0.00 -2142479.998 0.50 -2142484.084 1.00 -2142508.841 0.50 -2142515.953 0.00 -2142532.780 0.50 -2142536.863 1.00 -2142562.055 0.50 -2142567.397 0.00 -2142583.695 0.50 -2142588.483 1.00 -2142608.823 0.50 -2142626.280 1.00 -2142703.362 0.50 -2142703.838 0.00 -2142733.551 0.50 -2142734.195 1.00 -2142782.824 0.50 -2142785.276 0.00 -2142814.771 0.50 -2142815.494 1.00 -2142861.600 0.50 -2142864.105 0.00 -2142883.833 0.50 -2142886.938 1.00 -2142927.830 0.50 -2142935.202 0.00 -2142956.698 0.50 -2142960.779 1.00 -2142996.567 0.50 -2143001.829 0.00 -2143017.553 0.50 -2143022.880 1.00 -2143036.927 0.50 -2143044.755 0.00 -2143061.789 0.50 -2143069.506 1.00 -2143079.681 0.50 -2143090.109 0.00 -2143099.040 0.50 -2143115.876 1.00 -2143122.640 0.50 -2143135.627 0.00 -2143142.620 0.50 -2143148.702 0.00 -2143155.140 0.50 -2143156.407 1.00 -2143161.598 0.50 -2143162.254 0.00 -2143171.528 0.50 -2143172.191 1.00 -2143177.719 0.50 -2143178.522 0.00 -2143185.422 0.50 -2143187.525 1.00 -2143191.048 0.50 -2143193.553 0.00 -2143198.224 0.50 -2143201.377 1.00 -2143203.776 0.50 -2143207.104 0.00 -2143211.338 0.50 -2143214.741 1.00 -2143217.153 0.50 -2143220.451 0.00 -2143224.599 0.50 -2143228.060 1.00 -2143230.439 0.50 -2143233.807 0.00 -2143237.897 0.50 -2143242.015 1.00 -2143243.990 0.50 -2143248.158 0.00 -2143251.772 0.50 -2143255.895 1.00 -2143257.547 0.50 -2143261.633 0.00 -2143265.286 0.50 -2143269.666 1.00 -2143270.949 0.50 -2143275.896 0.00 -2143278.912 0.50 -2143284.717 1.00 -2143285.057 0.50 -2143290.933 0.00 -2143293.352 0.50 -2143298.720 0.00 -2143299.577 0.50 -2143305.733 0.00 -2143306.574 0.50 -2143312.669 0.00 -2143314.699 0.50 -2143320.490 1.00 -2143321.041 0.50 -2143326.021 0.00 -2223542.740 0.50 -2223616.705 1.00 -2223642.437 0.50 -2223677.391 1.00 -2223704.338 0.50 -2223734.963 1.00 -2223802.748 0.50 -2223832.624 1.00 -2223858.909 0.50 -2223882.005 1.00 -2223910.536 0.50 -2223931.926 1.00 -2223959.271 0.50 -2223980.553 1.00 -2224025.655 0.50 -2224049.819 1.00 -2224080.825 0.50 -2224105.842 1.00 -2224166.333 0.50 -2224191.035 1.00 -2224232.413 0.50 -2224263.865 1.00 -2224296.398 0.50 -2224318.069 1.00 -2224347.889 0.50 -2224355.751 0.00 -2224375.532 0.50 -2224376.294 1.00 -2224402.223 0.50 -2224417.523 0.00 -2224426.629 0.50 -2224439.970 1.00 -2224479.424 0.50 -2224502.241 1.00 -2224530.123 0.50 -2224548.176 1.00 -2224579.936 0.50 -2224600.946 1.00 -2224638.734 0.50 -2224661.822 1.00 -2224698.721 0.50 -2224723.490 1.00 -2224750.426 0.50 -2224773.650 1.00 -2224786.089 0.50 -2224803.090 0.00 -2224815.571 0.50 -2224820.990 1.00 -2224845.602 0.50 -2224869.634 1.00 -2224881.576 0.50 -2224899.178 0.00 -2224907.668 0.50 -2224920.916 1.00 -2224944.521 0.50 -2224966.963 1.00 -2224994.594 0.50 -2225014.514 1.00 -2225039.487 0.50 -2225062.158 1.00 -2225090.887 0.50 -2225112.927 1.00 -2225125.099 0.50 -2225132.778 0.00 -2225153.557 0.50 -2225195.458 1.00 -2225195.976 0.50 -2225219.705 1.00 -2225224.165 0.50 -2225253.992 1.00 -2225258.537 0.50 -2225281.446 1.00 -2225309.583 0.50 -2225312.131 0.00 -2225335.279 0.50 -2225341.226 0.00 diff --git a/examples/testbench/legion_prof/tsv/Mem_0x1e00000000000000.tsv b/examples/testbench/legion_prof/tsv/Mem_0x1e00000000000000.tsv deleted file mode 100644 index 75255cee7..000000000 --- a/examples/testbench/legion_prof/tsv/Mem_0x1e00000000000000.tsv +++ /dev/null @@ -1,8 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -7 2064650.117 2224204.270 #00fff6 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048577]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000001 $Size: 468.750 KiB 6 128 -6 2065147.467 2224388.739 #00fff6 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048578]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000002 $Size: 468.750 KiB 8 129 -5 2065598.615 2224609.631 #00fff6 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048579]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000003 $Size: 468.750 KiB 10 125 -4 2069053.346 2224448.793 #ff7a00 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048584]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000008 $Size: 468.750 KiB 23 130 -3 2069121.527 2224510.529 #ff7a00 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048585]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x4000000000000009 $Size: 468.750 KiB 23 131 -2 2071048.359 2224133.183 #ff7a00 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048590]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000e $Size: 468.750 KiB 35 127 -1 2071113.099 2224556.754 #ff7a00 1.0 Region: ispace:1[0:59999] x fspace:1$Fields: [fid:1048591]$Layout Order: [Struct-of-arrays (SOA)] $Inst: 0x400000000000000f $Size: 468.750 KiB 35 126 diff --git a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000000.tsv b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000000.tsv deleted file mode 100644 index 78775a78e..000000000 --- a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000000.tsv +++ /dev/null @@ -1,174 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -3 6 1131636.472 1131662.511 1131743.730 #c4ff00 1.0 Deferred Enqueue Task 1 [[0, 3, 16]] 227 -3 6 1131777.645 1131777.645 1131796.014 #ffc0cb 1.0 ProfTask <1> 236 -3 6 1131825.852 1131842.077 1131881.475 #ee00ff 1.0 Task Physical Dependence Analysis 1 [[0, 3, 16]] 19 -3 6 1131929.728 1131943.421 1132089.267 #ee00ff 1.0 Task Physical Dependence Analysis 1 [[0, 3, 16]] 245 -3 6 1887337.668 1887393.247 1887455.149 #007bff 1.0 Logical Dependence Analysis 3 228 -3 6 1887480.054 1887480.054 1887485.915 #ffc0cb 1.0 ProfTask <3> 237 -3 6 1887504.651 1887535.605 1887638.705 #001eff 1.0 Operation Physical Dependence Analysis 3 246 -3 6 1887763.546 1887805.820 1887841.593 #007bff 1.0 Logical Dependence Analysis 4 230 -3 6 1887867.399 1887867.399 1887872.806 #ffc0cb 1.0 ProfTask <4> 238 -3 6 1887890.796 1887942.877 1887986.727 #001eff 1.0 Operation Physical Dependence Analysis 4 231 -3 6 1888015.869 1888015.869 1888019.680 #ffc0cb 1.0 ProfTask <4> 239 -3 6 2003971.035 2004015.227 2004051.755 #007bff 1.0 Logical Dependence Analysis 5 24 -3 6 2004063.491 2004078.517 2004121.149 #001eff 1.0 Operation Physical Dependence Analysis 5 249 -3 6 2064084.727 2064129.215 2064275.023 #007bff 1.0 Logical Dependence Analysis 6 [[0, 2, 244]] 26 -3 6 2064287.989 2064295.923 2064342.601 #001eff 1.0 Operation Physical Dependence Analysis 7 28 -3 6 2064350.761 2064363.504 2064440.663 #9d00ff 1.0 Scheduler 0 29 -3 6 2064491.009 2064491.009 2064519.103 #007bff 1.0 Logical Dependence Analysis 8 [[0, 2, 7]] 233 -3 6 2064519.103 2064519.103 2064832.086 #007bff 0.15 Logical Dependence Analysis (waiting) 8 233 -3 6 2064832.086 2064832.086 2064851.735 #007bff 0.45 Logical Dependence Analysis (ready) 8 233 -3 6 2064851.735 2064851.735 2064920.144 #007bff 1.0 Logical Dependence Analysis 8 233 -2 5 2064684.275 2064684.275 2064696.490 #ffc0cb 1.0 ProfTask <6> 291 -2 5 2064765.377 2064796.569 2064815.504 #ff00ad 1.0 Mapper Continuation 8 [[0, 2, 7]] 30 -3 6 2064939.541 2064939.541 2064943.295 #ffc0cb 1.0 ProfTask <6> 240 -3 6 2064949.158 2064949.158 2064960.112 #ffc0cb 1.0 ProfTask <8> 241 -3 5 2064951.272 2064966.408 2064987.569 #001eff 1.0 Operation Physical Dependence Analysis 9 234 -3 5 2065001.319 2065001.319 2065005.803 #ffc0cb 1.0 ProfTask <9> 242 -3 6 2064998.019 2065011.887 2065074.606 #9d00ff 1.0 Scheduler 0 235 -3 6 2065087.801 2065087.801 2065093.099 #ffc0cb 1.0 ProfTask <0> 243 -3 5 2065175.981 2065175.981 2065183.321 #ffc0cb 1.0 ProfTask <8> 292 -3 6 2065193.676 2065193.676 2065222.977 #007bff 1.0 Logical Dependence Analysis 10 [[0, 2, 298]] 256 -3 6 2065222.977 2065222.977 2065295.140 #007bff 0.15 Logical Dependence Analysis (waiting) 10 256 -3 6 2065295.140 2065295.140 2065314.647 #007bff 0.45 Logical Dependence Analysis (ready) 10 256 -3 6 2065314.647 2065314.647 2065357.418 #007bff 1.0 Logical Dependence Analysis 10 256 -2 5 2065218.157 2065260.230 2065279.744 #ff00ad 1.0 Mapper Continuation 10 [[0, 2, 298]] 255 -3 5 2065338.495 2065376.792 2065406.576 #333399 1.0 Deferred Ready Trigger 11 33 -3 6 2065422.853 2065431.175 2065463.379 #333399 1.0 Deferred Ready Trigger 10 [[0, 2, 298]] 36 -3 5 2065439.589 2065478.480 2065518.172 #007bff 1.0 Logical Dependence Analysis 12 [[0, 2, 9]] 37 -3 6 2065507.551 2065531.848 2065541.822 #333399 1.0 Deferred Ready Trigger 12 [[0, 2, 9]] 38 -3 6 2065555.739 2065555.739 2065620.847 #ee00ff 1.0 Task Physical Dependence Analysis 10 [[0, 2, 298]] 288 -3 6 2065620.847 2065620.847 2065644.003 #ee00ff 0.15 Task Physical Dependence Analysis (waiting) 10 288 -3 6 2065644.003 2065644.003 2065671.369 #ee00ff 0.45 Task Physical Dependence Analysis (ready) 10 288 -3 6 2065671.369 2065671.369 2065773.170 #ee00ff 1.0 Task Physical Dependence Analysis 10 288 -2 5 2065562.363 2065562.363 2065707.741 #ff0b00 1.0 Mapper Call map_task for 10 10 [[0, 2, 298]] 290 -3 6 2065798.928 2065798.928 2065822.530 #ffc0cb 1.0 ProfTask <8> 293 -3 6 2065831.153 2065831.153 2065836.685 #ffc0cb 1.0 ProfTask <10> 294 -3 6 2065841.234 2065841.234 2065844.525 #ffc0cb 1.0 ProfTask <0> 295 -3 6 2065854.207 2065873.896 2065965.066 #ee00ff 1.0 Task Physical Dependence Analysis 12 [[0, 2, 9]] 300 -3 6 2065991.392 2065991.392 2066001.818 #ffc0cb 1.0 ProfTask <12> 323 -3 6 2066028.814 2066047.656 2066079.325 #333399 1.0 Deferred Ready Trigger 13 [[0, 2, 11]] 301 -3 6 2066102.388 2066102.388 2066108.878 #ffc0cb 1.0 ProfTask <13> 324 -3 6 2066135.812 2066135.812 2066147.756 #ffc0cb 1.0 ProfTask <10> 325 -3 5 2066135.907 2066156.610 2066197.991 #006600 1.0 Post-Task Execution 10 [[0, 2, 298]] 349 -3 6 2066194.275 2066220.415 2066303.311 #ee00ff 1.0 Task Physical Dependence Analysis 13 [[0, 2, 11]] 303 -3 6 2066330.336 2066330.336 2066339.047 #ffc0cb 1.0 ProfTask <12> 326 -3 6 2066349.384 2066349.384 2066355.745 #ffc0cb 1.0 ProfTask <13> 327 -3 6 2066356.299 2066365.568 2066398.119 #333399 1.0 Deferred Ready Trigger 14 [[0, 2, 299]] 42 -3 6 2066398.294 2066420.978 2066445.626 #006600 1.0 Post-Task Execution 13 [[0, 2, 11]] 43 -3 6 2066454.530 2066461.318 2066515.270 #ee00ff 1.0 Task Physical Dependence Analysis 14 [[0, 2, 299]] 304 -3 6 2066529.232 2066529.232 2066533.681 #ffc0cb 1.0 ProfTask <14> 328 -3 6 2066627.150 2066627.150 2066634.424 #ffc0cb 1.0 ProfTask <14> 329 -3 6 2066698.558 2066698.558 2066703.281 #ffc0cb 1.0 ProfTask <14> 330 -3 6 2067285.724 2067301.801 2067368.328 #007bff 1.0 Logical Dependence Analysis 15 306 -3 6 2067395.492 2067395.492 2067401.134 #ffc0cb 1.0 ProfTask <15> 331 -3 6 2067406.666 2067421.580 2067455.291 #333399 1.0 Deferred Ready Trigger 15 51 -3 5 2067438.999 2067474.609 2067579.536 #001eff 1.0 Operation Physical Dependence Analysis 15 55 -3 4 2067578.560 2067607.985 2067641.326 #333399 1.0 Deferred Ready Trigger 17 57 -3 6 2067552.580 2067663.628 2067679.151 #f7ff00 1.0 Prepipeline Stage 19 60 -3 5 2067626.890 2067705.309 2067752.698 #001eff 1.0 Operation Physical Dependence Analysis 17 307 -3 6 2067774.098 2067774.098 2067780.707 #ffc0cb 1.0 ProfTask <17> 332 -3 6 2067784.883 2067816.908 2067873.646 #001eff 1.0 Operation Physical Dependence Analysis 19 67 -3 6 2067893.332 2067911.279 2067944.485 #333399 1.0 Deferred Ready Trigger 22 70 -3 6 2067977.348 2068005.933 2068034.238 #333399 1.0 Deferred Ready Trigger 21 308 -3 6 2068050.192 2068050.192 2068053.972 #ffc0cb 1.0 ProfTask <21> 333 -3 6 2068701.125 2068718.776 2068819.324 #007bff 1.0 Logical Dependence Analysis 23 [[0, 2, 13]] 309 -3 5 2068838.765 2068838.765 2068843.921 #ffc0cb 1.0 ProfTask <23> 334 -3 6 2068834.478 2068851.002 2068873.194 #001eff 1.0 Operation Physical Dependence Analysis 24 310 -3 5 2068888.720 2068888.720 2068893.183 #ffc0cb 1.0 ProfTask <24> 335 -3 6 2068884.784 2068899.579 2068967.735 #9d00ff 1.0 Scheduler 0 355 -3 5 2068958.116 2068981.108 2069255.619 #ee00ff 1.0 Task Physical Dependence Analysis 23 [[0, 2, 13]] 311 -2 6 2068988.209 2068988.209 2069159.228 #ff0b00 1.0 Mapper Call map_task for 23 23 [[0, 2, 13]] 321 -3 6 2069257.831 2069272.218 2069292.337 #333399 1.0 Deferred Ready Trigger 26 357 -3 5 2069284.832 2069306.933 2069326.187 #001eff 1.0 Operation Physical Dependence Analysis 26 359 -3 6 2069340.380 2069340.380 2069345.572 #ffc0cb 1.0 ProfTask <23> 336 -3 5 2069340.950 2069352.748 2069390.333 #001eff 1.0 Operation Physical Dependence Analysis 25 361 -3 6 2069375.203 2069407.691 2069488.484 #007bff 1.0 Logical Dependence Analysis 27 312 -3 6 2069488.981 2069509.402 2069535.567 #001eff 1.0 Operation Physical Dependence Analysis 29 364 -3 5 2069531.900 2069555.271 2069568.751 #f7ff00 1.0 Prepipeline Stage 30 366 -3 6 2069608.648 2069631.187 2069663.194 #333399 1.0 Deferred Ready Trigger 31 368 -3 5 2069650.683 2069689.634 2069729.027 #001eff 1.0 Operation Physical Dependence Analysis 31 369 -3 6 2069703.806 2069756.624 2069792.334 #333399 1.0 Deferred Ready Trigger 30 370 -3 6 2069797.392 2069810.149 2069877.565 #007bff 1.0 Logical Dependence Analysis 32 315 -3 6 2069881.531 2069907.512 2069922.920 #006600 1.0 Post-Task Execution 28 373 -3 5 2069861.000 2069947.237 2069974.700 #001eff 1.0 Operation Physical Dependence Analysis 33 374 -3 5 2069998.435 2069998.435 2070005.542 #ffc0cb 1.0 ProfTask <27> 337 -3 6 2069996.220 2070014.959 2070075.913 #001eff 1.0 Operation Physical Dependence Analysis 32 317 -3 6 2070101.685 2070101.685 2070108.096 #ffc0cb 1.0 ProfTask <27> 338 -3 6 2070116.927 2070116.927 2070123.965 #ffc0cb 1.0 ProfTask <30> 339 -3 6 2070133.033 2070133.033 2070139.695 #ffc0cb 1.0 ProfTask <32> 340 -3 6 2070148.618 2070148.618 2070155.876 #ffc0cb 1.0 ProfTask <28> 341 -3 6 2070164.942 2070164.942 2070170.490 #ffc0cb 1.0 ProfTask <32> 342 -3 6 2070293.609 2070311.079 2070326.801 #006600 1.0 Post-Task Execution 34 318 -3 5 2070370.602 2070370.602 2070377.373 #ffc0cb 1.0 ProfTask <34> 343 -3 6 2070369.776 2070385.334 2070426.871 #006600 1.0 Post-Task Execution 23 [[0, 2, 13]] 377 -3 6 2070667.976 2070698.337 2070791.932 #007bff 1.0 Logical Dependence Analysis 35 [[0, 2, 15]] 73 -3 5 2070768.213 2070812.162 2070835.663 #333399 1.0 Deferred Ready Trigger 37 77 -3 6 2070826.521 2070851.863 2070873.378 #001eff 1.0 Operation Physical Dependence Analysis 37 319 -3 5 2070889.815 2070889.815 2070895.005 #ffc0cb 1.0 ProfTask <37> 344 -3 6 2070884.998 2070901.054 2070962.074 #9d00ff 1.0 Scheduler 0 380 -3 5 2070975.805 2070975.805 2071133.560 #ee00ff 1.0 Task Physical Dependence Analysis 35 [[0, 2, 15]] 320 -3 5 2071133.560 2071133.560 2071172.787 #ee00ff 0.15 Task Physical Dependence Analysis (waiting) 35 320 -3 5 2071172.787 2071172.787 2071230.794 #ee00ff 0.45 Task Physical Dependence Analysis (ready) 35 320 -3 5 2071230.794 2071230.794 2071432.285 #ee00ff 1.0 Task Physical Dependence Analysis 35 320 -2 6 2070983.664 2070983.664 2071255.461 #ff0b00 1.0 Mapper Call map_task for 35 35 [[0, 2, 15]] 322 -1 4 2071094.504 2071179.516 2071190.430 #f7ff00 1.0 Prepipeline Stage 38 381 -3 6 2071450.221 2071450.221 2071458.232 #ffc0cb 1.0 ProfTask <35> 345 -3 6 2071462.205 2071485.324 2071649.220 #001eff 1.0 Operation Physical Dependence Analysis 38 383 -3 6 2071898.389 2071933.817 2071946.793 #006600 1.0 Post-Task Execution 39 455 -3 6 2071971.528 2071971.528 2071975.936 #ffc0cb 1.0 ProfTask <39> 475 -3 6 2072030.588 2072030.588 2072036.622 #ffc0cb 1.0 ProfTask <39> 476 -3 6 2072328.841 2072345.424 2072358.717 #006600 1.0 Post-Task Execution 40 457 -3 6 2072393.575 2072393.575 2072400.046 #ffc0cb 1.0 ProfTask <40> 477 -3 5 2072394.979 2072409.183 2072446.614 #006600 1.0 Post-Task Execution 35 [[0, 2, 15]] 458 -3 6 2072472.619 2072472.619 2072478.026 #ffc0cb 1.0 ProfTask <35> 478 -3 6 2125438.432 2125594.978 2125632.752 #009900 1.0 Deferred Commit 38 385 -3 6 2125645.320 2125703.515 2125736.612 #007bff 1.0 Logical Dependence Analysis 41 459 -3 5 2125724.982 2125756.869 2125782.049 #333399 1.0 Deferred Ready Trigger 41 460 -3 6 2125771.586 2125799.828 2125832.850 #001eff 1.0 Operation Physical Dependence Analysis 41 386 -3 6 2125852.771 2125852.771 2125859.590 #ffc0cb 1.0 ProfTask <41> 479 -3 6 2125867.246 2125867.246 2125873.486 #ffc0cb 1.0 ProfTask <41> 480 -3 6 2140637.501 2142117.664 2142358.907 #007bff 1.0 Logical Dependence Analysis 42 387 -3 5 2142231.268 2142379.766 2142408.752 #333399 1.0 Deferred Ready Trigger 42 462 -3 4 2142266.330 2142427.615 2142458.056 #333399 1.0 Deferred Ready Trigger 44 463 -3 3 2142283.931 2142479.998 2142508.841 #333399 1.0 Deferred Ready Trigger 45 464 -3 2 2142315.059 2142532.780 2142562.055 #333399 1.0 Deferred Ready Trigger 47 465 -3 1 2142347.612 2142583.695 2142608.823 #333399 1.0 Deferred Ready Trigger 49 466 -3 6 2142444.331 2142626.280 2142703.362 #001eff 1.0 Operation Physical Dependence Analysis 44 391 -3 5 2142444.978 2142733.551 2142785.276 #001eff 1.0 Operation Physical Dependence Analysis 43 468 -3 4 2142549.062 2142815.494 2142864.105 #001eff 1.0 Operation Physical Dependence Analysis 47 393 -3 3 2142553.937 2142883.833 2142927.830 #001eff 1.0 Operation Physical Dependence Analysis 48 394 -3 2 2142674.619 2142956.698 2142996.567 #009900 1.0 Garbage Collection 44 395 -3 6 2142766.968 2143017.553 2143036.927 #009900 1.0 Garbage Collection 45 396 -3 5 2142845.594 2143061.789 2143079.681 #009900 1.0 Garbage Collection 46 397 -3 4 2142913.343 2143099.040 2143122.640 #009900 1.0 Garbage Collection 48 398 -3 6 2143142.620 2143142.620 2143148.702 #ffc0cb 1.0 ProfTask <42> 481 -3 6 2143156.407 2143156.407 2143162.254 #ffc0cb 1.0 ProfTask <42> 482 -3 6 2143171.528 2143171.528 2143177.719 #ffc0cb 1.0 ProfTask <44> 483 -3 6 2143185.422 2143185.422 2143191.048 #ffc0cb 1.0 ProfTask <45> 484 -3 6 2143198.224 2143198.224 2143203.776 #ffc0cb 1.0 ProfTask <47> 485 -3 6 2143211.338 2143211.338 2143217.153 #ffc0cb 1.0 ProfTask <49> 486 -3 6 2143224.599 2143224.599 2143230.439 #ffc0cb 1.0 ProfTask <42> 487 -3 6 2143237.897 2143237.897 2143243.990 #ffc0cb 1.0 ProfTask <43> 488 -3 6 2143251.772 2143251.772 2143257.547 #ffc0cb 1.0 ProfTask <46> 489 -3 6 2143265.286 2143265.286 2143270.949 #ffc0cb 1.0 ProfTask <49> 490 -3 6 2143278.912 2143278.912 2143285.057 #ffc0cb 1.0 ProfTask <42> 491 -3 6 2143293.352 2143293.352 2143298.720 #ffc0cb 1.0 ProfTask <43> 492 -3 6 2143306.574 2143306.574 2143312.669 #ffc0cb 1.0 ProfTask <47> 493 -3 6 2143320.490 2143320.490 2143326.021 #ffc0cb 1.0 ProfTask <49> 494 -3 6 2223513.340 2223542.740 2223802.748 #007bff 1.0 Logical Dependence Analysis 50 83 -3 5 2223773.308 2223832.624 2223858.909 #333399 1.0 Deferred Ready Trigger 51 85 -3 6 2223848.090 2223882.005 2223910.536 #001eff 1.0 Operation Physical Dependence Analysis 51 86 -3 5 2223889.580 2223931.926 2223959.271 #333399 1.0 Deferred Ready Trigger 52 88 -3 6 2223948.000 2223980.553 2224025.655 #001eff 1.0 Operation Physical Dependence Analysis 52 89 -3 5 2224003.975 2224049.819 2224080.825 #333399 1.0 Deferred Ready Trigger 53 91 -3 6 2224030.127 2224105.842 2224166.333 #009900 1.0 Garbage Collection 50 92 -3 4 2224062.367 2224191.035 2224232.413 #009900 1.0 Garbage Collection 50 93 -3 3 2224068.115 2224263.865 2224296.398 #001eff 1.0 Operation Physical Dependence Analysis 53 94 -3 6 2224274.059 2224318.069 2224355.751 #333399 1.0 Deferred Ready Trigger 54 97 -3 5 2224317.587 2224375.532 2224402.223 #990000 1.0 Deferred Execute 51 98 -3 6 2224388.205 2224426.629 2224786.089 #990000 1.0 Deferred Execute 52 107 -3 5 2224767.393 2224815.571 2224881.576 #990000 1.0 Deferred Execute 53 111 -3 6 2224865.471 2224907.668 2225132.778 #990000 1.0 Deferred Execute 54 120 -3 6 2225177.967 2225195.458 2225224.165 #990000 1.0 Deferred Execute 56 122 -3 6 2225241.887 2225253.992 2225312.131 #990000 1.0 Deferred Execute 58 399 diff --git a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000001.tsv b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000001.tsv deleted file mode 100644 index c974b81fa..000000000 --- a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000001.tsv +++ /dev/null @@ -1,169 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -2 7 1131726.584 1131750.448 1131847.857 #9d00ff 1.0 Scheduler 0 18 -2 7 1131865.246 1131875.771 1131945.331 #9d00ff 1.0 Scheduler 0 20 -2 7 1132112.899 1132112.899 1132119.532 #ffc0cb 1.0 ProfTask <1> 260 -2 7 1887430.900 1887469.337 1887516.954 #333399 1.0 Deferred Ready Trigger 3 22 -2 7 1887666.368 1887666.368 1887676.134 #ffc0cb 1.0 ProfTask <3> 261 -2 7 1887820.758 1887873.868 1887911.228 #333399 1.0 Deferred Ready Trigger 4 247 -2 7 1887939.316 1887939.316 1887943.976 #ffc0cb 1.0 ProfTask <4> 262 -2 7 2004033.501 2004050.023 2004073.805 #333399 1.0 Deferred Ready Trigger 5 248 -2 7 2004100.736 2004100.736 2004106.103 #ffc0cb 1.0 ProfTask <5> 263 -2 7 2004142.069 2004142.069 2004145.762 #ffc0cb 1.0 ProfTask <5> 264 -2 7 2064237.437 2064271.214 2064297.548 #333399 1.0 Deferred Ready Trigger 7 250 -2 7 2064314.243 2064314.243 2064318.757 #ffc0cb 1.0 ProfTask <7> 265 -2 7 2064325.150 2064336.527 2064358.130 #333399 1.0 Deferred Ready Trigger 6 [[0, 2, 244]] 251 -2 7 2064372.340 2064372.340 2064378.142 #ffc0cb 1.0 ProfTask <6> 266 -2 7 2064425.658 2064439.767 2064912.591 #ee00ff 1.0 Task Physical Dependence Analysis 6 [[0, 2, 244]] 232 -1 6 2064460.470 2064460.470 2064757.963 #ff0b00 1.0 Mapper Call map_task for 6 6 [[0, 2, 244]] 258 -2 6 2064895.840 2064938.430 2064959.621 #333399 1.0 Deferred Ready Trigger 9 252 -2 7 2064974.539 2064974.539 2064979.176 #ffc0cb 1.0 ProfTask <9> 267 -2 6 2064977.098 2064985.140 2065008.315 #333399 1.0 Deferred Ready Trigger 8 [[0, 2, 7]] 253 -2 7 2065021.505 2065021.505 2065026.318 #ffc0cb 1.0 ProfTask <8> 268 -2 7 2065063.470 2065080.934 2065259.007 #ee00ff 1.0 Task Physical Dependence Analysis 8 [[0, 2, 7]] 254 -1 6 2065092.988 2065092.988 2065205.897 #ff0b00 1.0 Mapper Call map_task for 8 8 [[0, 2, 7]] 259 -2 7 2065285.153 2065285.153 2065290.919 #ffc0cb 1.0 ProfTask <8> 269 -2 7 2065298.864 2065298.864 2065304.046 #ffc0cb 1.0 ProfTask <10> 270 -2 7 2065311.838 2065311.838 2065323.070 #ffc0cb 1.0 ProfTask <6> 271 -2 6 2065314.045 2065330.219 2065374.476 #006600 1.0 Post-Task Execution 6 [[0, 2, 244]] 31 -2 6 2065395.290 2065395.290 2065404.409 #ffc0cb 1.0 ProfTask <10> 272 -2 7 2065392.769 2065413.072 2065437.527 #001eff 1.0 Operation Physical Dependence Analysis 11 34 -2 7 2065449.415 2065462.884 2065572.335 #9d00ff 1.0 Scheduler 0 39 -2 6 2065594.419 2065594.419 2065660.636 #9d00ff 1.0 Scheduler 0 257 -2 6 2065660.636 2065660.636 2065797.939 #9d00ff 0.15 Scheduler (waiting) 0 257 -2 6 2065797.939 2065797.939 2065820.023 #9d00ff 0.45 Scheduler (ready) 0 257 -2 6 2065820.023 2065820.023 2065876.598 #9d00ff 1.0 Scheduler 0 257 -1 7 2065645.624 2065705.960 2065742.165 #006600 1.0 Post-Task Execution 8 [[0, 2, 7]] 287 -1 5 2065714.422 2065761.473 2065786.367 #ff00ad 1.0 Mapper Continuation 0 289 -2 7 2065899.023 2065899.023 2065909.599 #ffc0cb 1.0 ProfTask <0> 273 -2 7 2065942.215 2065981.765 2066048.507 #007bff 1.0 Logical Dependence Analysis 13 [[0, 2, 11]] 348 -2 6 2066070.084 2066070.084 2066081.533 #ffc0cb 1.0 ProfTask <13> 400 -2 7 2066066.582 2066094.843 2066210.980 #9d00ff 1.0 Scheduler 0 40 -2 7 2066235.493 2066235.493 2066242.836 #ffc0cb 1.0 ProfTask <10> 401 -2 6 2066236.561 2066253.371 2066284.954 #006600 1.0 Post-Task Execution 12 [[0, 2, 9]] 302 -2 5 2066240.578 2066319.571 2066367.395 #007bff 1.0 Logical Dependence Analysis 14 [[0, 2, 299]] 350 -2 6 2066384.163 2066384.163 2066388.487 #ffc0cb 1.0 ProfTask <14> 402 -2 7 2066383.816 2066394.872 2066463.174 #9d00ff 1.0 Scheduler 0 351 -2 7 2066479.174 2066479.174 2066483.256 #ffc0cb 1.0 ProfTask <0> 403 -2 7 2066612.567 2066642.926 2066670.867 #006600 1.0 Post-Task Execution 14 [[0, 2, 299]] 305 -2 7 2067269.088 2067308.792 2067319.124 #f7ff00 1.0 Prepipeline Stage 15 45 -2 7 2067333.123 2067341.192 2067367.273 #333399 1.0 Deferred Ready Trigger 16 47 -2 6 2067355.636 2067388.990 2067420.603 #001eff 1.0 Operation Physical Dependence Analysis 16 48 -2 7 2067426.791 2067439.875 2067454.232 #f7ff00 1.0 Prepipeline Stage 17 50 -2 6 2067441.364 2067472.127 2067512.496 #007bff 1.0 Logical Dependence Analysis 17 52 -2 7 2067491.307 2067527.751 2067549.614 #333399 1.0 Deferred Ready Trigger 18 54 -2 6 2067539.805 2067566.785 2067590.043 #001eff 1.0 Operation Physical Dependence Analysis 18 56 -2 7 2067572.388 2067602.973 2067641.791 #007bff 1.0 Logical Dependence Analysis 19 59 -2 6 2067619.191 2067656.500 2067681.707 #333399 1.0 Deferred Ready Trigger 20 62 -2 7 2067670.435 2067706.016 2067735.601 #001eff 1.0 Operation Physical Dependence Analysis 20 63 -2 6 2067721.619 2067762.961 2067810.448 #333399 1.0 Deferred Ready Trigger 19 64 -2 7 2067816.229 2067830.114 2067845.249 #f7ff00 1.0 Prepipeline Stage 21 66 -2 6 2067836.417 2067868.331 2067928.423 #007bff 1.0 Logical Dependence Analysis 21 68 -2 7 2067930.983 2067945.510 2067997.003 #001eff 1.0 Operation Physical Dependence Analysis 22 352 -2 7 2068011.781 2068011.781 2068016.154 #ffc0cb 1.0 ProfTask <22> 404 -2 7 2068021.691 2068034.716 2068081.412 #001eff 1.0 Operation Physical Dependence Analysis 21 353 -2 7 2068099.841 2068099.841 2068103.496 #ffc0cb 1.0 ProfTask <21> 405 -2 7 2068787.182 2068819.800 2068845.196 #333399 1.0 Deferred Ready Trigger 24 72 -2 7 2068859.786 2068869.449 2068895.729 #333399 1.0 Deferred Ready Trigger 23 [[0, 2, 13]] 354 -2 7 2068920.805 2068920.805 2068925.382 #ffc0cb 1.0 ProfTask <23> 406 -2 7 2068987.640 2068987.640 2068992.969 #ffc0cb 1.0 ProfTask <0> 407 -2 7 2069083.012 2069083.012 2069106.618 #ffc0cb 1.0 ProfTask <23> 408 -2 7 2069147.523 2069147.523 2069165.785 #ffc0cb 1.0 ProfTask <23> 409 -2 7 2069217.627 2069234.110 2069279.820 #007bff 1.0 Logical Dependence Analysis 25 356 -2 7 2069203.330 2069296.143 2069304.388 #f7ff00 1.0 Prepipeline Stage 25 358 -2 7 2069316.441 2069322.918 2069356.475 #333399 1.0 Deferred Ready Trigger 25 360 -2 7 2069358.027 2069374.511 2069390.747 #f7ff00 1.0 Prepipeline Stage 27 362 -2 7 2069418.366 2069418.366 2069425.098 #ffc0cb 1.0 ProfTask <25> 410 -2 7 2069432.480 2069432.480 2069437.167 #ffc0cb 1.0 ProfTask <26> 411 -2 7 2069444.029 2069444.029 2069449.166 #ffc0cb 1.0 ProfTask <25> 412 -2 6 2069444.938 2069456.488 2069500.754 #333399 1.0 Deferred Ready Trigger 29 363 -2 6 2069521.646 2069521.646 2069528.013 #ffc0cb 1.0 ProfTask <26> 413 -2 7 2069521.212 2069535.964 2069565.176 #333399 1.0 Deferred Ready Trigger 27 365 -2 7 2069567.777 2069581.553 2069638.355 #007bff 1.0 Logical Dependence Analysis 30 367 -2 6 2069553.670 2069659.704 2069736.823 #001eff 1.0 Operation Physical Dependence Analysis 27 313 -2 7 2069762.525 2069762.525 2069769.736 #ffc0cb 1.0 ProfTask <25> 414 -2 6 2069778.737 2069778.737 2069783.086 #ffc0cb 1.0 ProfTask <25> 415 -2 7 2069777.307 2069790.728 2069831.359 #001eff 1.0 Operation Physical Dependence Analysis 30 314 -2 7 2069837.412 2069849.405 2069870.888 #333399 1.0 Deferred Ready Trigger 33 371 -2 7 2069778.190 2069886.021 2069894.631 #f7ff00 1.0 Prepipeline Stage 32 372 -2 6 2069889.106 2069911.435 2069941.733 #3dff00 1.0 Trigger Complete 28 316 -2 6 2069960.854 2069960.854 2069966.367 #ffc0cb 1.0 ProfTask <27> 416 -2 7 2069960.237 2069978.389 2070010.923 #333399 1.0 Deferred Ready Trigger 32 375 -2 7 2070032.572 2070032.572 2070036.122 #ffc0cb 1.0 ProfTask <29> 417 -2 7 2070040.870 2070040.870 2070044.094 #ffc0cb 1.0 ProfTask <29> 418 -2 7 2070048.472 2070048.472 2070051.774 #ffc0cb 1.0 ProfTask <27> 419 -2 7 2070056.245 2070056.245 2070060.009 #ffc0cb 1.0 ProfTask <30> 420 -2 7 2070067.424 2070067.424 2070073.169 #ffc0cb 1.0 ProfTask <30> 421 -2 7 2070081.771 2070081.771 2070087.538 #ffc0cb 1.0 ProfTask <31> 422 -2 7 2070094.373 2070094.373 2070099.524 #ffc0cb 1.0 ProfTask <31> 423 -2 7 2070107.471 2070107.471 2070113.258 #ffc0cb 1.0 ProfTask <30> 424 -2 7 2070120.860 2070120.860 2070125.106 #ffc0cb 1.0 ProfTask <33> 425 -2 7 2070131.877 2070131.877 2070136.189 #ffc0cb 1.0 ProfTask <32> 426 -2 7 2070141.398 2070141.398 2070145.072 #ffc0cb 1.0 ProfTask <28> 427 -2 7 2070150.171 2070150.171 2070154.829 #ffc0cb 1.0 ProfTask <33> 428 -2 7 2070159.785 2070159.785 2070164.050 #ffc0cb 1.0 ProfTask <32> 429 -2 7 2070310.674 2070329.126 2070369.981 #3dff00 1.0 Trigger Complete 34 376 -2 7 2070388.785 2070388.785 2070392.574 #ffc0cb 1.0 ProfTask <34> 430 -2 7 2070469.051 2070469.051 2070475.390 #ffc0cb 1.0 ProfTask <23> 431 -2 7 2070749.142 2070781.152 2070806.013 #333399 1.0 Deferred Ready Trigger 36 75 -2 6 2070797.695 2070823.632 2070843.027 #001eff 1.0 Operation Physical Dependence Analysis 36 378 -2 7 2070860.505 2070860.505 2070865.751 #ffc0cb 1.0 ProfTask <36> 432 -2 6 2070861.048 2070872.848 2070895.393 #333399 1.0 Deferred Ready Trigger 35 [[0, 2, 15]] 379 -2 7 2070912.589 2070912.589 2070917.128 #ffc0cb 1.0 ProfTask <35> 433 -2 7 2070982.478 2070982.478 2070987.821 #ffc0cb 1.0 ProfTask <0> 434 -2 7 2071077.383 2071077.383 2071100.087 #ffc0cb 1.0 ProfTask <35> 435 -2 7 2071106.819 2071113.591 2071152.023 #007bff 1.0 Logical Dependence Analysis 38 79 -2 7 2071213.450 2071213.450 2071219.974 #ffc0cb 1.0 ProfTask <38> 436 -2 7 2071391.508 2071426.355 2071475.719 #333399 1.0 Deferred Ready Trigger 38 382 -2 7 2071501.085 2071501.085 2071507.744 #ffc0cb 1.0 ProfTask <38> 437 -2 7 2071675.248 2071675.248 2071681.510 #ffc0cb 1.0 ProfTask <38> 438 -2 7 2071919.090 2071943.818 2072004.306 #3dff00 1.0 Trigger Complete 39 456 -2 7 2072340.685 2072364.643 2072392.367 #3dff00 1.0 Trigger Complete 40 384 -2 7 2072416.299 2072416.299 2072424.207 #ffc0cb 1.0 ProfTask <40> 439 -2 7 2125854.803 2125854.803 2125862.182 #ffc0cb 1.0 ProfTask <38> 440 -2 7 2125872.861 2125872.861 2125881.155 #ffc0cb 1.0 ProfTask <41> 441 -2 7 2140598.711 2142134.517 2142169.070 #f7ff00 1.0 Prepipeline Stage 42 461 -2 7 2142250.991 2142421.085 2142459.315 #333399 1.0 Deferred Ready Trigger 43 388 -2 6 2142299.250 2142484.084 2142515.953 #333399 1.0 Deferred Ready Trigger 46 389 -2 5 2142332.758 2142536.863 2142567.397 #333399 1.0 Deferred Ready Trigger 48 390 -2 4 2142398.468 2142588.483 2142703.838 #001eff 1.0 Operation Physical Dependence Analysis 42 467 -2 7 2142496.269 2142734.195 2142782.824 #001eff 1.0 Operation Physical Dependence Analysis 45 392 -2 3 2142502.585 2142814.771 2142861.600 #001eff 1.0 Operation Physical Dependence Analysis 46 469 -2 6 2142598.817 2142886.938 2142935.202 #001eff 1.0 Operation Physical Dependence Analysis 49 470 -2 5 2142677.812 2142960.779 2143001.829 #009900 1.0 Garbage Collection 42 471 -2 4 2142769.448 2143022.880 2143044.755 #009900 1.0 Garbage Collection 43 472 -2 7 2142848.058 2143069.506 2143090.109 #009900 1.0 Garbage Collection 47 473 -2 3 2142918.009 2143115.876 2143135.627 #009900 1.0 Garbage Collection 49 474 -2 7 2143155.140 2143155.140 2143161.598 #ffc0cb 1.0 ProfTask <42> 442 -2 7 2143172.191 2143172.191 2143178.522 #ffc0cb 1.0 ProfTask <43> 443 -2 7 2143187.525 2143187.525 2143193.553 #ffc0cb 1.0 ProfTask <46> 444 -2 7 2143201.377 2143201.377 2143207.104 #ffc0cb 1.0 ProfTask <48> 445 -2 7 2143214.741 2143214.741 2143220.451 #ffc0cb 1.0 ProfTask <44> 446 -2 7 2143228.060 2143228.060 2143233.807 #ffc0cb 1.0 ProfTask <45> 447 -2 7 2143242.015 2143242.015 2143248.158 #ffc0cb 1.0 ProfTask <47> 448 -2 7 2143255.895 2143255.895 2143261.633 #ffc0cb 1.0 ProfTask <48> 449 -2 7 2143269.666 2143269.666 2143275.896 #ffc0cb 1.0 ProfTask <44> 450 -2 7 2143284.717 2143284.717 2143290.933 #ffc0cb 1.0 ProfTask <45> 451 -2 7 2143299.577 2143299.577 2143305.733 #ffc0cb 1.0 ProfTask <46> 452 -2 7 2143314.699 2143314.699 2143321.041 #ffc0cb 1.0 ProfTask <48> 453 -2 7 2223597.529 2223616.705 2223642.437 #333399 1.0 Deferred Ready Trigger 50 81 -2 7 2223649.894 2223677.391 2223704.338 #006600 1.0 Post-Task Execution 1 [[0, 3, 16]] 82 -2 6 2223632.052 2223734.963 2224347.889 #001eff 1.0 Operation Physical Dependence Analysis 50 95 -2 7 2224083.656 2224376.294 2224417.523 #009900 1.0 Garbage Collection 50 99 -2 5 2224105.062 2224439.970 2224479.424 #009900 1.0 Garbage Collection 50 100 -2 4 2224122.255 2224502.241 2224530.123 #009900 1.0 Garbage Collection 50 101 -2 3 2224174.081 2224548.176 2224579.936 #009900 1.0 Garbage Collection 50 102 -2 2 2224202.446 2224600.946 2224638.734 #009900 1.0 Garbage Collection 50 103 -2 1 2224342.247 2224661.822 2224698.721 #001eff 1.0 Operation Physical Dependence Analysis 54 104 -2 7 2224676.790 2224723.490 2224750.426 #333399 1.0 Deferred Ready Trigger 55 106 -2 6 2224739.059 2224773.650 2224803.090 #001eff 1.0 Operation Physical Dependence Analysis 55 108 -2 7 2224780.989 2224820.990 2224845.602 #333399 1.0 Deferred Ready Trigger 56 110 -2 6 2224835.122 2224869.634 2224899.178 #001eff 1.0 Operation Physical Dependence Analysis 56 112 -2 7 2224877.537 2224920.916 2224944.521 #333399 1.0 Deferred Ready Trigger 57 114 -2 6 2224934.343 2224966.963 2224994.594 #001eff 1.0 Operation Physical Dependence Analysis 57 115 -2 7 2224974.658 2225014.514 2225039.487 #333399 1.0 Deferred Ready Trigger 58 117 -2 6 2225028.841 2225062.158 2225090.887 #001eff 1.0 Operation Physical Dependence Analysis 58 118 -2 7 2225070.170 2225112.927 2225125.099 #3dff00 1.0 Trigger Complete 1 [[0, 3, 16]] 119 -2 6 2225114.068 2225153.557 2225195.976 #990000 1.0 Deferred Execute 55 121 -2 7 2225208.142 2225219.705 2225258.537 #990000 1.0 Deferred Execute 57 123 -2 7 2225273.472 2225281.446 2225309.583 #5eff00 1.0 Top Finish 0 124 -2 7 2225335.279 2225335.279 2225341.226 #ffc0cb 1.0 ProfTask <58> 454 diff --git a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000002.tsv b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000002.tsv deleted file mode 100644 index 6b101db3e..000000000 --- a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000002.tsv +++ /dev/null @@ -1,103 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -1 2 1131871.414 1131871.414 1131877.823 #ffc0cb 1.0 ProfTask <0> 132 -1 2 1131902.582 1131902.582 1131907.442 #ffc0cb 1.0 ProfTask <1> 133 -1 2 1131967.180 1131967.180 1131973.556 #ffc0cb 1.0 ProfTask <0> 134 -1 2 1887540.878 1887540.878 1887549.090 #ffc0cb 1.0 ProfTask <3> 135 -1 2 2004081.928 2004081.928 2004089.422 #ffc0cb 1.0 ProfTask <5> 136 -1 2 2064305.095 2064305.095 2064310.462 #ffc0cb 1.0 ProfTask <6> 137 -1 2 2064366.713 2064366.713 2064373.269 #ffc0cb 1.0 ProfTask <7> 138 -1 2 2064467.966 2064467.966 2064474.773 #ffc0cb 1.0 ProfTask <0> 139 -1 2 2064854.771 2064854.771 2064860.185 #ffc0cb 1.0 ProfTask <8> 140 -1 2 2064900.104 2064917.697 2065292.716 #00fff6 1.0 legate::numpy::FillTask [CPU] <6> [[0, 1, 31], [0, 2, 13]] [[0, 0, 26], [0, 1, 251], [0, 1, 258], [0, 1, 232]] [[0, 3, 16]] 244 -1 1 2065246.858 2065321.206 2065629.402 #00fff6 1.0 legate::numpy::FillTask [CPU] <8> [[0, 1, 287], [0, 2, 11]] [[0, 1, 253], [0, 0, 233], [0, 1, 254], [0, 1, 259], [0, 0, 30]] [[0, 3, 16]] 7 -1 2 2065651.028 2065651.028 2065655.364 #ffc0cb 1.0 ProfTask <6> 141 -1 2 2065660.845 2065660.845 2065664.930 #ffc0cb 1.0 ProfTask <11> 142 -1 2 2065670.191 2065670.191 2065674.528 #ffc0cb 1.0 ProfTask <11> 143 -1 2 2065678.796 2065678.796 2065682.654 #ffc0cb 1.0 ProfTask <10> 144 -1 2 2065686.872 2065686.872 2065690.098 #ffc0cb 1.0 ProfTask <12> 145 -1 2 2065694.309 2065694.309 2065697.477 #ffc0cb 1.0 ProfTask <12> 146 -1 2 2065703.630 2065703.630 2065708.390 #ffc0cb 1.0 ProfTask <0> 147 -1 2 2065714.725 2065714.725 2065719.262 #ffc0cb 1.0 ProfTask <10> 148 -1 2 2065723.840 2065723.840 2065727.832 #ffc0cb 1.0 ProfTask <8> 149 -1 2 2065758.538 2065780.941 2066111.116 #00fff6 1.0 legate::numpy::FillTask [CPU] <10> [[0, 2, 299], [0, 0, 349]] [[0, 0, 288], [0, 0, 290], [0, 0, 255], [0, 0, 36], [0, 0, 256]] [[0, 3, 16]] 298 -1 1 2065952.164 2066144.783 2066215.987 #00fff6 1.0 legate::numpy::FillTask [CPU] <12> [[0, 1, 302]] [[0, 0, 38], [0, 0, 300], [0, 0, 37]] [[0, 3, 16]] 9 -1 2 2066245.594 2066245.594 2066251.163 #ffc0cb 1.0 ProfTask <0> 150 -1 2 2066259.095 2066259.095 2066264.225 #ffc0cb 1.0 ProfTask <12> 151 -1 2 2066286.943 2066301.621 2066377.311 #00fff6 1.0 legate::numpy::FillTask [CPU] <13> [[0, 0, 43], [0, 2, 13]] [[0, 0, 303], [0, 2, 7], [0, 1, 348], [0, 0, 301]] [[0, 3, 16]] 11 -1 2 2066405.630 2066405.630 2066412.893 #ffc0cb 1.0 ProfTask <13> 152 -1 2 2066421.100 2066421.100 2066427.548 #ffc0cb 1.0 ProfTask <14> 153 -1 2 2066471.431 2066471.431 2066479.071 #ffc0cb 1.0 ProfTask <13> 154 -1 2 2066505.171 2066535.583 2066593.473 #00fff6 1.0 legate::numpy::FillTask [CPU] <14> [[0, 2, 13], [0, 1, 305]] [[0, 2, 298], [0, 0, 304], [0, 0, 42], [0, 1, 350]] [[0, 3, 16]] 299 -1 2 2067346.675 2067346.675 2067354.303 #ffc0cb 1.0 ProfTask <15> 155 -1 2 2067387.727 2067387.727 2067394.617 #ffc0cb 1.0 ProfTask <16> 156 -1 2 2067442.872 2067442.872 2067451.090 #ffc0cb 1.0 ProfTask <16> 157 -1 2 2067474.731 2067474.731 2067480.297 #ffc0cb 1.0 ProfTask <17> 158 -1 2 2067488.729 2067488.729 2067495.305 #ffc0cb 1.0 ProfTask <15> 159 -1 2 2067532.311 2067532.311 2067539.293 #ffc0cb 1.0 ProfTask <17> 160 -1 2 2067571.934 2067571.934 2067579.663 #ffc0cb 1.0 ProfTask <18> 161 -1 2 2067606.592 2067606.592 2067612.221 #ffc0cb 1.0 ProfTask <15> 162 -1 2 2067621.464 2067621.464 2067627.153 #ffc0cb 1.0 ProfTask <18> 163 -1 2 2067662.795 2067662.795 2067670.163 #ffc0cb 1.0 ProfTask <17> 164 -1 2 2067679.315 2067679.315 2067686.512 #ffc0cb 1.0 ProfTask <19> 165 -1 2 2067705.097 2067705.097 2067711.610 #ffc0cb 1.0 ProfTask <19> 166 -1 2 2067719.563 2067719.563 2067726.024 #ffc0cb 1.0 ProfTask <20> 167 -1 2 2067760.488 2067760.488 2067767.837 #ffc0cb 1.0 ProfTask <20> 168 -1 2 2067834.393 2067834.393 2067841.326 #ffc0cb 1.0 ProfTask <19> 169 -1 2 2067867.718 2067867.718 2067875.021 #ffc0cb 1.0 ProfTask <21> 170 -1 2 2067900.658 2067900.658 2067906.286 #ffc0cb 1.0 ProfTask <19> 171 -1 2 2067951.131 2067951.131 2067956.251 #ffc0cb 1.0 ProfTask <21> 172 -1 2 2067963.814 2067963.814 2067967.314 #ffc0cb 1.0 ProfTask <22> 173 -1 2 2068872.288 2068872.288 2068882.867 #ffc0cb 1.0 ProfTask <24> 174 -1 2 2069241.423 2069260.928 2070348.048 #ff7a00 1.0 legate::numpy::FusedOpTask [CPU] <23> [[0, 0, 377]] [[0, 0, 309], [0, 1, 354], [0, 2, 244], [0, 2, 299], [0, 0, 321], [0, 0, 311], [0, 2, 11]] [[0, 3, 16]] 13 -1 2 2070377.866 2070377.866 2070383.587 #ffc0cb 1.0 ProfTask <23> 175 -1 2 2070819.172 2070819.172 2070828.288 #ffc0cb 1.0 ProfTask <35> 176 -1 2 2070840.483 2070840.483 2070848.019 #ffc0cb 1.0 ProfTask <36> 177 -1 2 2070858.887 2070858.887 2070866.815 #ffc0cb 1.0 ProfTask <37> 178 -1 2 2071135.872 2071135.872 2071143.400 #ffc0cb 1.0 ProfTask <35> 179 -1 2 2071175.560 2071175.560 2071188.129 #ffc0cb 1.0 ProfTask <38> 180 -1 2 2071419.524 2071441.366 2072373.142 #ff7a00 1.0 legate::numpy::FusedOpTask [CPU] <35> [[0, 0, 458]] [[0, 1, 379], [0, 0, 320], [0, 0, 322], [0, 0, 73]] [[0, 3, 16]] 15 -1 2 2072407.594 2072407.594 2072415.756 #ffc0cb 1.0 ProfTask <35> 181 -1 2 2223654.660 2223654.660 2223670.393 #ffc0cb 1.0 ProfTask <1> 182 -1 2 2223681.067 2223681.067 2223688.333 #ffc0cb 1.0 ProfTask <50> 183 -1 2 2223729.950 2223729.950 2223735.924 #ffc0cb 1.0 ProfTask <1> 184 -1 2 2223828.994 2223828.994 2223833.763 #ffc0cb 1.0 ProfTask <50> 185 -1 2 2223878.262 2223878.262 2223882.918 #ffc0cb 1.0 ProfTask <51> 186 -1 2 2223928.589 2223928.589 2223933.189 #ffc0cb 1.0 ProfTask <51> 187 -1 2 2223979.621 2223979.621 2223984.034 #ffc0cb 1.0 ProfTask <52> 188 -1 2 2224047.331 2224047.331 2224051.623 #ffc0cb 1.0 ProfTask <52> 189 -1 2 2224101.138 2224101.138 2224106.757 #ffc0cb 1.0 ProfTask <53> 190 -1 2 2224148.335 2224148.335 2224161.362 #ffc0cb 1.0 ProfTask <35> 191 -1 2 2224186.534 2224186.534 2224191.200 #ffc0cb 1.0 ProfTask <50> 192 -1 2 2224220.301 2224220.301 2224223.906 #ffc0cb 1.0 ProfTask <6> 193 -1 2 2224253.499 2224253.499 2224257.289 #ffc0cb 1.0 ProfTask <50> 194 -1 2 2224316.993 2224316.993 2224321.896 #ffc0cb 1.0 ProfTask <53> 195 -1 2 2224371.021 2224371.021 2224376.481 #ffc0cb 1.0 ProfTask <50> 196 -1 2 2224382.616 2224382.616 2224387.519 #ffc0cb 1.0 ProfTask <54> 197 -1 2 2224404.275 2224404.275 2224409.090 #ffc0cb 1.0 ProfTask <8> 198 -1 2 2224422.632 2224422.632 2224427.511 #ffc0cb 1.0 ProfTask <51> 199 -1 2 2224432.534 2224432.534 2224435.672 #ffc0cb 1.0 ProfTask <50> 200 -1 2 2224462.197 2224462.197 2224466.176 #ffc0cb 1.0 ProfTask <23> 201 -1 2 2224561.477 2224561.477 2224567.447 #ffc0cb 1.0 ProfTask <50> 202 -1 2 2224577.316 2224577.316 2224583.749 #ffc0cb 1.0 ProfTask <23> 203 -1 2 2224592.176 2224592.176 2224597.422 #ffc0cb 1.0 ProfTask <50> 204 -1 2 2224605.256 2224605.256 2224611.578 #ffc0cb 1.0 ProfTask <35> 205 -1 2 2224625.618 2224625.618 2224631.298 #ffc0cb 1.0 ProfTask <50> 206 -1 2 2224640.500 2224640.500 2224647.306 #ffc0cb 1.0 ProfTask <10> 207 -1 2 2224655.645 2224655.645 2224662.140 #ffc0cb 1.0 ProfTask <50> 208 -1 2 2224723.627 2224723.627 2224727.850 #ffc0cb 1.0 ProfTask <54> 209 -1 2 2224771.060 2224771.060 2224775.847 #ffc0cb 1.0 ProfTask <55> 210 -1 2 2224811.759 2224811.759 2224816.039 #ffc0cb 1.0 ProfTask <52> 211 -1 2 2224822.127 2224822.127 2224825.941 #ffc0cb 1.0 ProfTask <55> 212 -1 2 2224867.885 2224867.885 2224872.650 #ffc0cb 1.0 ProfTask <56> 213 -1 2 2224902.872 2224902.872 2224908.376 #ffc0cb 1.0 ProfTask <53> 214 -1 2 2224914.147 2224914.147 2224917.592 #ffc0cb 1.0 ProfTask <56> 215 -1 2 2224963.214 2224963.214 2224967.510 #ffc0cb 1.0 ProfTask <57> 216 -1 2 2225013.096 2225013.096 2225017.772 #ffc0cb 1.0 ProfTask <57> 217 -1 2 2225061.833 2225061.833 2225067.872 #ffc0cb 1.0 ProfTask <58> 218 -1 2 2225110.405 2225110.405 2225115.363 #ffc0cb 1.0 ProfTask <58> 219 -1 2 2225145.405 2225145.405 2225149.977 #ffc0cb 1.0 ProfTask <1> 220 -1 2 2225157.536 2225157.536 2225162.322 #ffc0cb 1.0 ProfTask <54> 221 -1 2 2225219.074 2225219.074 2225225.623 #ffc0cb 1.0 ProfTask <55> 222 -1 2 2225247.956 2225247.956 2225252.965 #ffc0cb 1.0 ProfTask <56> 223 -1 2 2225278.124 2225278.124 2225284.676 #ffc0cb 1.0 ProfTask <57> 224 -1 2 2225330.082 2225330.082 2225334.333 #ffc0cb 1.0 ProfTask <0> 225 diff --git a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000003.tsv b/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000003.tsv deleted file mode 100644 index 1e74f88b1..000000000 --- a/examples/testbench/legion_prof/tsv/Proc_0x1d00000000000003.tsv +++ /dev/null @@ -1,20 +0,0 @@ -level level_ready ready start end color opacity title initiation in out children parents prof_uid -1 1 1134192.460 1134192.460 1887460.195 #eb00ff 1.0 legion_python_main <1> [[0, 1, 82], [0, 1, 119]] [[0, 0, 227], [0, 0, 19], [0, 0, 245]] [[0, 2, 7], [0, 2, 299], [0, 2, 13], [0, 2, 244], [0, 2, 9], [0, 2, 15], [0, 2, 298], [0, 2, 11]] 16 -1 1 1887460.195 1887460.195 1887589.038 #eb00ff 0.15 legion_python_main <1> (waiting) 16 -1 1 1887589.038 1887589.038 1887666.489 #eb00ff 0.45 legion_python_main <1> (ready) 16 -1 1 1887666.489 1887666.489 1887795.983 #eb00ff 1.0 legion_python_main <1> 16 -1 1 1887795.983 1887795.983 1887960.477 #eb00ff 0.15 legion_python_main <1> (waiting) 16 -1 1 1887960.477 1887960.477 1888027.844 #eb00ff 0.45 legion_python_main <1> (ready) 16 -1 1 1888027.844 1888027.844 2004013.143 #eb00ff 1.0 legion_python_main <1> 16 -1 1 2004013.143 2004013.143 2004103.065 #eb00ff 0.15 legion_python_main <1> (waiting) 16 -1 1 2004103.065 2004103.065 2004155.450 #eb00ff 0.45 legion_python_main <1> (ready) 16 -1 1 2004155.450 2004155.450 2071175.689 #eb00ff 1.0 legion_python_main <1> 16 -1 1 2071175.689 2071175.689 2071586.179 #eb00ff 0.15 legion_python_main <1> (waiting) 16 -1 1 2071586.179 2071586.179 2071636.356 #eb00ff 0.45 legion_python_main <1> (ready) 16 -1 1 2071636.356 2071636.356 2071651.215 #eb00ff 1.0 legion_python_main <1> 16 -1 1 2071651.215 2071651.215 2072431.368 #eb00ff 0.15 legion_python_main <1> (waiting) 16 -1 1 2072431.368 2072431.368 2072465.988 #eb00ff 0.45 legion_python_main <1> (ready) 16 -1 1 2072465.988 2072465.988 2125746.910 #eb00ff 1.0 legion_python_main <1> 16 -1 1 2125746.910 2125746.910 2125806.643 #eb00ff 0.15 legion_python_main <1> (waiting) 16 -1 1 2125806.643 2125806.643 2125906.215 #eb00ff 0.45 legion_python_main <1> (ready) 16 -1 1 2125906.215 2125906.215 2223592.200 #eb00ff 1.0 legion_python_main <1> 16 diff --git a/examples/testbench/legion_prof/tsv/all (CPU)_util.tsv b/examples/testbench/legion_prof/tsv/all (CPU)_util.tsv deleted file mode 100644 index b5a809961..000000000 --- a/examples/testbench/legion_prof/tsv/all (CPU)_util.tsv +++ /dev/null @@ -1,206 +0,0 @@ -time count -0.000 0.00 -1131871.414 1.00 -1131877.823 0.00 -1131902.582 1.00 -1131907.442 0.00 -1131967.180 1.00 -1131973.556 0.00 -1887540.878 1.00 -1887549.090 0.00 -2004081.928 1.00 -2004089.422 0.00 -2064305.095 1.00 -2064310.462 0.00 -2064366.713 1.00 -2064373.269 0.00 -2064467.966 1.00 -2064474.773 0.00 -2064854.771 1.00 -2064860.185 0.00 -2064917.697 1.00 -2065292.716 0.00 -2065321.206 1.00 -2065629.402 0.00 -2065651.028 1.00 -2065655.364 0.00 -2065660.845 1.00 -2065664.930 0.00 -2065670.191 1.00 -2065674.528 0.00 -2065678.796 1.00 -2065682.654 0.00 -2065686.872 1.00 -2065690.098 0.00 -2065694.309 1.00 -2065697.477 0.00 -2065703.630 1.00 -2065708.390 0.00 -2065714.725 1.00 -2065719.262 0.00 -2065723.840 1.00 -2065727.832 0.00 -2065780.941 1.00 -2066111.116 0.00 -2066144.783 1.00 -2066215.987 0.00 -2066245.594 1.00 -2066251.163 0.00 -2066259.095 1.00 -2066264.225 0.00 -2066301.621 1.00 -2066377.311 0.00 -2066405.630 1.00 -2066412.893 0.00 -2066421.100 1.00 -2066427.548 0.00 -2066471.431 1.00 -2066479.071 0.00 -2066535.583 1.00 -2066593.473 0.00 -2067346.675 1.00 -2067354.303 0.00 -2067387.727 1.00 -2067394.617 0.00 -2067442.872 1.00 -2067451.090 0.00 -2067474.731 1.00 -2067480.297 0.00 -2067488.729 1.00 -2067495.305 0.00 -2067532.311 1.00 -2067539.293 0.00 -2067571.934 1.00 -2067579.663 0.00 -2067606.592 1.00 -2067612.221 0.00 -2067621.464 1.00 -2067627.153 0.00 -2067662.795 1.00 -2067670.163 0.00 -2067679.315 1.00 -2067686.512 0.00 -2067705.097 1.00 -2067711.610 0.00 -2067719.563 1.00 -2067726.024 0.00 -2067760.488 1.00 -2067767.837 0.00 -2067834.393 1.00 -2067841.326 0.00 -2067867.718 1.00 -2067875.021 0.00 -2067900.658 1.00 -2067906.286 0.00 -2067951.131 1.00 -2067956.251 0.00 -2067963.814 1.00 -2067967.314 0.00 -2068872.288 1.00 -2068882.867 0.00 -2069260.928 1.00 -2070348.048 0.00 -2070377.866 1.00 -2070383.587 0.00 -2070819.172 1.00 -2070828.288 0.00 -2070840.483 1.00 -2070848.019 0.00 -2070858.887 1.00 -2070866.815 0.00 -2071135.872 1.00 -2071143.400 0.00 -2071175.560 1.00 -2071188.129 0.00 -2071441.366 1.00 -2072373.142 0.00 -2072407.594 1.00 -2072415.756 0.00 -2223654.660 1.00 -2223670.393 0.00 -2223681.067 1.00 -2223688.333 0.00 -2223729.950 1.00 -2223735.924 0.00 -2223828.994 1.00 -2223833.763 0.00 -2223878.262 1.00 -2223882.918 0.00 -2223928.589 1.00 -2223933.189 0.00 -2223979.621 1.00 -2223984.034 0.00 -2224047.331 1.00 -2224051.623 0.00 -2224101.138 1.00 -2224106.757 0.00 -2224148.335 1.00 -2224161.362 0.00 -2224186.534 1.00 -2224191.200 0.00 -2224220.301 1.00 -2224223.906 0.00 -2224253.499 1.00 -2224257.289 0.00 -2224316.993 1.00 -2224321.896 0.00 -2224371.021 1.00 -2224376.481 0.00 -2224382.616 1.00 -2224387.519 0.00 -2224404.275 1.00 -2224409.090 0.00 -2224422.632 1.00 -2224427.511 0.00 -2224432.534 1.00 -2224435.672 0.00 -2224462.197 1.00 -2224466.176 0.00 -2224561.477 1.00 -2224567.447 0.00 -2224577.316 1.00 -2224583.749 0.00 -2224592.176 1.00 -2224597.422 0.00 -2224605.256 1.00 -2224611.578 0.00 -2224625.618 1.00 -2224631.298 0.00 -2224640.500 1.00 -2224647.306 0.00 -2224655.645 1.00 -2224662.140 0.00 -2224723.627 1.00 -2224727.850 0.00 -2224771.060 1.00 -2224775.847 0.00 -2224811.759 1.00 -2224816.039 0.00 -2224822.127 1.00 -2224825.941 0.00 -2224867.885 1.00 -2224872.650 0.00 -2224902.872 1.00 -2224908.376 0.00 -2224914.147 1.00 -2224917.592 0.00 -2224963.214 1.00 -2224967.510 0.00 -2225013.096 1.00 -2225017.772 0.00 -2225061.833 1.00 -2225067.872 0.00 -2225110.405 1.00 -2225115.363 0.00 -2225145.405 1.00 -2225149.977 0.00 -2225157.536 1.00 -2225162.322 0.00 -2225219.074 1.00 -2225225.623 0.00 -2225247.956 1.00 -2225252.965 0.00 -2225278.124 1.00 -2225284.676 0.00 -2225330.082 1.00 -2225334.333 0.00 diff --git a/examples/testbench/legion_prof/tsv/all (Python)_util.tsv b/examples/testbench/legion_prof/tsv/all (Python)_util.tsv deleted file mode 100644 index 2aea9b2e8..000000000 --- a/examples/testbench/legion_prof/tsv/all (Python)_util.tsv +++ /dev/null @@ -1,16 +0,0 @@ -time count -0.000 0.00 -1134192.460 1.00 -1887460.195 0.00 -1887666.489 1.00 -1887795.983 0.00 -1888027.844 1.00 -2004013.143 0.00 -2004155.450 1.00 -2071175.689 0.00 -2071636.356 1.00 -2071651.215 0.00 -2072465.988 1.00 -2125746.910 0.00 -2125906.215 1.00 -2223592.200 0.00 diff --git a/examples/testbench/legion_prof/tsv/all (System Memory)_util.tsv b/examples/testbench/legion_prof/tsv/all (System Memory)_util.tsv deleted file mode 100644 index f6914d7c8..000000000 --- a/examples/testbench/legion_prof/tsv/all (System Memory)_util.tsv +++ /dev/null @@ -1,16 +0,0 @@ -time count -0.000 0.00 -2064650.117 0.00 -2065147.467 0.00 -2065598.615 0.00 -2069053.346 0.00 -2069121.527 0.00 -2071048.359 0.00 -2071113.099 0.00 -2224133.183 0.00 -2224204.270 0.00 -2224388.739 0.00 -2224448.793 0.00 -2224510.529 0.00 -2224556.754 0.00 -2224609.631 0.00 diff --git a/examples/testbench/legion_prof/tsv/all (Utility)_util.tsv b/examples/testbench/legion_prof/tsv/all (Utility)_util.tsv deleted file mode 100644 index 67767ff36..000000000 --- a/examples/testbench/legion_prof/tsv/all (Utility)_util.tsv +++ /dev/null @@ -1,648 +0,0 @@ -time count -0.000 0.00 -1131662.511 0.50 -1131743.730 0.00 -1131750.448 0.50 -1131777.645 1.00 -1131796.014 0.50 -1131842.077 1.00 -1131847.857 0.50 -1131875.771 1.00 -1131881.475 0.50 -1131943.421 1.00 -1131945.331 0.50 -1132089.267 0.00 -1132112.899 0.50 -1132119.532 0.00 -1887393.247 0.50 -1887455.149 0.00 -1887469.337 0.50 -1887480.054 1.00 -1887485.915 0.50 -1887516.954 0.00 -1887535.605 0.50 -1887638.705 0.00 -1887666.368 0.50 -1887676.134 0.00 -1887805.820 0.50 -1887841.593 0.00 -1887867.399 0.50 -1887872.806 0.00 -1887873.868 0.50 -1887911.228 0.00 -1887939.316 0.50 -1887942.877 1.00 -1887943.976 0.50 -1887986.727 0.00 -1888015.869 0.50 -1888019.680 0.00 -2004015.227 0.50 -2004050.023 1.00 -2004051.755 0.50 -2004073.805 0.00 -2004078.517 0.50 -2004100.736 1.00 -2004106.103 0.50 -2004121.149 0.00 -2004142.069 0.50 -2004145.762 0.00 -2064129.215 0.50 -2064271.214 1.00 -2064275.023 0.50 -2064295.923 1.00 -2064297.548 0.50 -2064314.243 1.00 -2064318.757 0.50 -2064336.527 1.00 -2064342.601 0.50 -2064358.130 0.00 -2064363.504 0.50 -2064372.340 1.00 -2064378.142 0.50 -2064439.767 1.00 -2064440.663 0.50 -2064491.009 1.00 -2064519.103 0.50 -2064684.275 1.00 -2064696.490 0.50 -2064796.569 1.00 -2064815.504 0.50 -2064851.735 1.00 -2064912.591 0.50 -2064920.144 0.00 -2064938.430 0.50 -2064939.541 1.00 -2064943.295 0.50 -2064949.158 1.00 -2064959.621 0.50 -2064960.112 0.00 -2064966.408 0.50 -2064974.539 1.00 -2064979.176 0.50 -2064985.140 1.00 -2064987.569 0.50 -2065001.319 1.00 -2065005.803 0.50 -2065008.315 0.00 -2065011.887 0.50 -2065021.505 1.00 -2065026.318 0.50 -2065074.606 0.00 -2065080.934 0.50 -2065087.801 1.00 -2065093.099 0.50 -2065175.981 1.00 -2065183.321 0.50 -2065193.676 1.00 -2065222.977 0.50 -2065259.007 0.00 -2065260.230 0.50 -2065279.744 0.00 -2065285.153 0.50 -2065290.919 0.00 -2065298.864 0.50 -2065304.046 0.00 -2065311.838 0.50 -2065314.647 1.00 -2065323.070 0.50 -2065330.219 1.00 -2065357.418 0.50 -2065374.476 0.00 -2065376.792 0.50 -2065395.290 1.00 -2065404.409 0.50 -2065406.576 0.00 -2065413.072 0.50 -2065431.175 1.00 -2065437.527 0.50 -2065462.884 1.00 -2065463.379 0.50 -2065478.480 1.00 -2065518.172 0.50 -2065531.848 1.00 -2065541.822 0.50 -2065555.739 1.00 -2065572.335 0.50 -2065594.419 1.00 -2065660.636 0.50 -2065705.960 1.00 -2065742.165 0.50 -2065761.473 1.00 -2065773.170 0.50 -2065786.367 0.00 -2065798.928 0.50 -2065820.023 1.00 -2065822.530 0.50 -2065831.153 1.00 -2065836.685 0.50 -2065841.234 1.00 -2065844.525 0.50 -2065873.896 1.00 -2065876.598 0.50 -2065899.023 1.00 -2065909.599 0.50 -2065965.066 0.00 -2065981.765 0.50 -2065991.392 1.00 -2066001.818 0.50 -2066047.656 1.00 -2066048.507 0.50 -2066070.084 1.00 -2066079.325 0.50 -2066081.533 0.00 -2066094.843 0.50 -2066102.388 1.00 -2066108.878 0.50 -2066135.812 1.00 -2066147.756 0.50 -2066156.610 1.00 -2066197.991 0.50 -2066210.980 0.00 -2066220.415 0.50 -2066235.493 1.00 -2066242.836 0.50 -2066253.371 1.00 -2066284.954 0.50 -2066303.311 0.00 -2066319.571 0.50 -2066330.336 1.00 -2066339.047 0.50 -2066349.384 1.00 -2066355.745 0.50 -2066365.568 1.00 -2066367.395 0.50 -2066384.163 1.00 -2066388.487 0.50 -2066394.872 1.00 -2066398.119 0.50 -2066420.978 1.00 -2066445.626 0.50 -2066461.318 1.00 -2066463.174 0.50 -2066479.174 1.00 -2066483.256 0.50 -2066515.270 0.00 -2066529.232 0.50 -2066533.681 0.00 -2066627.150 0.50 -2066634.424 0.00 -2066642.926 0.50 -2066670.867 0.00 -2066698.558 0.50 -2066703.281 0.00 -2067301.801 0.50 -2067308.792 1.00 -2067319.124 0.50 -2067341.192 1.00 -2067367.273 0.50 -2067368.328 0.00 -2067388.990 0.50 -2067395.492 1.00 -2067401.134 0.50 -2067420.603 0.00 -2067421.580 0.50 -2067439.875 1.00 -2067454.232 0.50 -2067455.291 0.00 -2067472.127 0.50 -2067474.609 1.00 -2067512.496 0.50 -2067527.751 1.00 -2067549.614 0.50 -2067566.785 1.00 -2067579.536 0.50 -2067590.043 0.00 -2067602.973 0.50 -2067607.985 1.00 -2067641.326 0.50 -2067641.791 0.00 -2067656.500 0.50 -2067663.628 1.00 -2067679.151 0.50 -2067681.707 0.00 -2067705.309 0.50 -2067706.016 1.00 -2067735.601 0.50 -2067752.698 0.00 -2067762.961 0.50 -2067774.098 1.00 -2067780.707 0.50 -2067810.448 0.00 -2067816.908 0.50 -2067830.114 1.00 -2067845.249 0.50 -2067868.331 1.00 -2067873.646 0.50 -2067911.279 1.00 -2067928.423 0.50 -2067944.485 0.00 -2067945.510 0.50 -2067997.003 0.00 -2068005.933 0.50 -2068011.781 1.00 -2068016.154 0.50 -2068034.238 0.00 -2068034.716 0.50 -2068050.192 1.00 -2068053.972 0.50 -2068081.412 0.00 -2068099.841 0.50 -2068103.496 0.00 -2068718.776 0.50 -2068819.324 0.00 -2068819.800 0.50 -2068838.765 1.00 -2068843.921 0.50 -2068845.196 0.00 -2068851.002 0.50 -2068869.449 1.00 -2068873.194 0.50 -2068888.720 1.00 -2068893.183 0.50 -2068895.729 0.00 -2068899.579 0.50 -2068920.805 1.00 -2068925.382 0.50 -2068967.735 0.00 -2068981.108 0.50 -2068987.640 1.00 -2068992.969 0.50 -2069083.012 1.00 -2069106.618 0.50 -2069147.523 1.00 -2069165.785 0.50 -2069234.110 1.00 -2069255.619 0.50 -2069272.218 1.00 -2069279.820 0.50 -2069292.337 0.00 -2069296.143 0.50 -2069304.388 0.00 -2069306.933 0.50 -2069322.918 1.00 -2069326.187 0.50 -2069340.380 1.00 -2069345.572 0.50 -2069352.748 1.00 -2069356.475 0.50 -2069374.511 1.00 -2069390.333 0.50 -2069390.747 0.00 -2069407.691 0.50 -2069418.366 1.00 -2069425.098 0.50 -2069432.480 1.00 -2069437.167 0.50 -2069444.029 1.00 -2069449.166 0.50 -2069456.488 1.00 -2069488.484 0.50 -2069500.754 0.00 -2069509.402 0.50 -2069521.646 1.00 -2069528.013 0.50 -2069535.567 0.00 -2069535.964 0.50 -2069555.271 1.00 -2069565.176 0.50 -2069568.751 0.00 -2069581.553 0.50 -2069631.187 1.00 -2069638.355 0.50 -2069659.704 1.00 -2069663.194 0.50 -2069689.634 1.00 -2069729.027 0.50 -2069736.823 0.00 -2069756.624 0.50 -2069762.525 1.00 -2069769.736 0.50 -2069778.737 1.00 -2069783.086 0.50 -2069790.728 1.00 -2069792.334 0.50 -2069810.149 1.00 -2069831.359 0.50 -2069849.405 1.00 -2069870.888 0.50 -2069877.565 0.00 -2069886.021 0.50 -2069894.631 0.00 -2069907.512 0.50 -2069911.435 1.00 -2069922.920 0.50 -2069941.733 0.00 -2069947.237 0.50 -2069960.854 1.00 -2069966.367 0.50 -2069974.700 0.00 -2069978.389 0.50 -2069998.435 1.00 -2070005.542 0.50 -2070010.923 0.00 -2070014.959 0.50 -2070032.572 1.00 -2070036.122 0.50 -2070040.870 1.00 -2070044.094 0.50 -2070048.472 1.00 -2070051.774 0.50 -2070056.245 1.00 -2070060.009 0.50 -2070067.424 1.00 -2070073.169 0.50 -2070075.913 0.00 -2070081.771 0.50 -2070087.538 0.00 -2070094.373 0.50 -2070099.524 0.00 -2070101.685 0.50 -2070107.471 1.00 -2070108.096 0.50 -2070113.258 0.00 -2070116.927 0.50 -2070120.860 1.00 -2070123.965 0.50 -2070125.106 0.00 -2070131.877 0.50 -2070133.033 1.00 -2070136.189 0.50 -2070139.695 0.00 -2070141.398 0.50 -2070145.072 0.00 -2070148.618 0.50 -2070150.171 1.00 -2070154.829 0.50 -2070155.876 0.00 -2070159.785 0.50 -2070164.050 0.00 -2070164.942 0.50 -2070170.490 0.00 -2070311.079 0.50 -2070326.801 0.00 -2070329.126 0.50 -2070369.981 0.00 -2070370.602 0.50 -2070377.373 0.00 -2070385.334 0.50 -2070388.785 1.00 -2070392.574 0.50 -2070426.871 0.00 -2070469.051 0.50 -2070475.390 0.00 -2070698.337 0.50 -2070781.152 1.00 -2070791.932 0.50 -2070806.013 0.00 -2070812.162 0.50 -2070823.632 1.00 -2070835.663 0.50 -2070843.027 0.00 -2070851.863 0.50 -2070860.505 1.00 -2070865.751 0.50 -2070872.848 1.00 -2070873.378 0.50 -2070889.815 1.00 -2070895.005 0.50 -2070895.393 0.00 -2070901.054 0.50 -2070912.589 1.00 -2070917.128 0.50 -2070962.074 0.00 -2070975.805 0.50 -2070982.478 1.00 -2070987.821 0.50 -2071077.383 1.00 -2071100.087 0.50 -2071113.591 1.00 -2071152.023 0.50 -2071213.450 1.00 -2071219.974 0.50 -2071426.355 1.00 -2071432.285 0.50 -2071450.221 1.00 -2071458.232 0.50 -2071475.719 0.00 -2071485.324 0.50 -2071501.085 1.00 -2071507.744 0.50 -2071649.220 0.00 -2071675.248 0.50 -2071681.510 0.00 -2071933.817 0.50 -2071943.818 1.00 -2071946.793 0.50 -2071971.528 1.00 -2071975.936 0.50 -2072004.306 0.00 -2072030.588 0.50 -2072036.622 0.00 -2072345.424 0.50 -2072358.717 0.00 -2072364.643 0.50 -2072392.367 0.00 -2072393.575 0.50 -2072400.046 0.00 -2072409.183 0.50 -2072416.299 1.00 -2072424.207 0.50 -2072446.614 0.00 -2072472.619 0.50 -2072478.026 0.00 -2125594.978 0.50 -2125632.752 0.00 -2125703.515 0.50 -2125736.612 0.00 -2125756.869 0.50 -2125782.049 0.00 -2125799.828 0.50 -2125832.850 0.00 -2125852.771 0.50 -2125854.803 1.00 -2125859.590 0.50 -2125862.182 0.00 -2125867.246 0.50 -2125872.861 1.00 -2125873.486 0.50 -2125881.155 0.00 -2142117.664 0.50 -2142134.517 1.00 -2142169.070 0.50 -2142358.907 0.00 -2142379.766 0.50 -2142408.752 0.00 -2142421.085 0.50 -2142427.615 1.00 -2142458.056 0.50 -2142459.315 0.00 -2142479.998 0.50 -2142484.084 1.00 -2142508.841 0.50 -2142515.953 0.00 -2142532.780 0.50 -2142536.863 1.00 -2142562.055 0.50 -2142567.397 0.00 -2142583.695 0.50 -2142588.483 1.00 -2142608.823 0.50 -2142626.280 1.00 -2142703.362 0.50 -2142703.838 0.00 -2142733.551 0.50 -2142734.195 1.00 -2142782.824 0.50 -2142785.276 0.00 -2142814.771 0.50 -2142815.494 1.00 -2142861.600 0.50 -2142864.105 0.00 -2142883.833 0.50 -2142886.938 1.00 -2142927.830 0.50 -2142935.202 0.00 -2142956.698 0.50 -2142960.779 1.00 -2142996.567 0.50 -2143001.829 0.00 -2143017.553 0.50 -2143022.880 1.00 -2143036.927 0.50 -2143044.755 0.00 -2143061.789 0.50 -2143069.506 1.00 -2143079.681 0.50 -2143090.109 0.00 -2143099.040 0.50 -2143115.876 1.00 -2143122.640 0.50 -2143135.627 0.00 -2143142.620 0.50 -2143148.702 0.00 -2143155.140 0.50 -2143156.407 1.00 -2143161.598 0.50 -2143162.254 0.00 -2143171.528 0.50 -2143172.191 1.00 -2143177.719 0.50 -2143178.522 0.00 -2143185.422 0.50 -2143187.525 1.00 -2143191.048 0.50 -2143193.553 0.00 -2143198.224 0.50 -2143201.377 1.00 -2143203.776 0.50 -2143207.104 0.00 -2143211.338 0.50 -2143214.741 1.00 -2143217.153 0.50 -2143220.451 0.00 -2143224.599 0.50 -2143228.060 1.00 -2143230.439 0.50 -2143233.807 0.00 -2143237.897 0.50 -2143242.015 1.00 -2143243.990 0.50 -2143248.158 0.00 -2143251.772 0.50 -2143255.895 1.00 -2143257.547 0.50 -2143261.633 0.00 -2143265.286 0.50 -2143269.666 1.00 -2143270.949 0.50 -2143275.896 0.00 -2143278.912 0.50 -2143284.717 1.00 -2143285.057 0.50 -2143290.933 0.00 -2143293.352 0.50 -2143298.720 0.00 -2143299.577 0.50 -2143305.733 0.00 -2143306.574 0.50 -2143312.669 0.00 -2143314.699 0.50 -2143320.490 1.00 -2143321.041 0.50 -2143326.021 0.00 -2223542.740 0.50 -2223616.705 1.00 -2223642.437 0.50 -2223677.391 1.00 -2223704.338 0.50 -2223734.963 1.00 -2223802.748 0.50 -2223832.624 1.00 -2223858.909 0.50 -2223882.005 1.00 -2223910.536 0.50 -2223931.926 1.00 -2223959.271 0.50 -2223980.553 1.00 -2224025.655 0.50 -2224049.819 1.00 -2224080.825 0.50 -2224105.842 1.00 -2224166.333 0.50 -2224191.035 1.00 -2224232.413 0.50 -2224263.865 1.00 -2224296.398 0.50 -2224318.069 1.00 -2224347.889 0.50 -2224355.751 0.00 -2224375.532 0.50 -2224376.294 1.00 -2224402.223 0.50 -2224417.523 0.00 -2224426.629 0.50 -2224439.970 1.00 -2224479.424 0.50 -2224502.241 1.00 -2224530.123 0.50 -2224548.176 1.00 -2224579.936 0.50 -2224600.946 1.00 -2224638.734 0.50 -2224661.822 1.00 -2224698.721 0.50 -2224723.490 1.00 -2224750.426 0.50 -2224773.650 1.00 -2224786.089 0.50 -2224803.090 0.00 -2224815.571 0.50 -2224820.990 1.00 -2224845.602 0.50 -2224869.634 1.00 -2224881.576 0.50 -2224899.178 0.00 -2224907.668 0.50 -2224920.916 1.00 -2224944.521 0.50 -2224966.963 1.00 -2224994.594 0.50 -2225014.514 1.00 -2225039.487 0.50 -2225062.158 1.00 -2225090.887 0.50 -2225112.927 1.00 -2225125.099 0.50 -2225132.778 0.00 -2225153.557 0.50 -2225195.458 1.00 -2225195.976 0.50 -2225219.705 1.00 -2225224.165 0.50 -2225253.992 1.00 -2225258.537 0.50 -2225281.446 1.00 -2225309.583 0.50 -2225312.131 0.00 -2225335.279 0.50 -2225341.226 0.00 diff --git a/examples/testbench/test.py b/examples/testbench/test.py deleted file mode 100644 index 951d73a04..000000000 --- a/examples/testbench/test.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime - -#import pdb -#pdb.set_trace() -import legate.numpy as np - -#import numpy as np -#import numpy as np -N=500000 -M=2 -b1 = np.zeros(N) -b2 = np.zeros(N) -b3 = np.zeros(N) -b4 = np.zeros(N) -b5 = np.zeros(N) - -b1.fill(2) -b2.fill(3) -b3.fill(4) - -#dummy ops -# dumb hack so the loop starts at nOps=10 -# so the window/pipe is empty -b3.fill(4) -b3.fill(4) -#gg=b1+b2+b3 -#print(gg) -#for i in range(10000): -for i in range(1000): - b1=b1+b2+b3+b4+b5+b1+b2+b3+b4+b5+b1 - #b3+=b3 - #b3=b1+b2 - -#print(b3) -""" -def shor_form(a): - a+=a - return a -def long_form(a): - a=a+a - return a -import ast,inspect -func_src = inspect.getsource(long_form) -entry_node = ast.parse(func_src) -print(ast.dump(entry_node)) - -func_src = inspect.getsource(shor_form) -entry_node = ast.parse(func_src) -print(ast.dump(entry_node)) - - - - -#a=a+a -#a=a+a -#b=mul_add(b, b1,b2) -#print(sum(g)) - - -long_form(b,b1,b2) -#c = np.sum(a, axis=0) -c = np.dot(a,b) -#c = np.dot(a,b) -#c = np.dot(a,b) - -#sink? -print(sum(c)) - - - -n1 = 300 -n2= 20 -a = npo.zeros((n1,n2)) -b = npo.zeros((N)) -c= npo.zeros((N)) -print("s",sum(long_form(a,b,c))) -a+=a -M=800000 -d0 = np.zeros(M) -d0.fill(1) -d1 = np.zeros(M) -d2 = np.zeros(M) -print(sum(e)) -""" diff --git a/examples/wgrad.py b/examples/wgrad.py deleted file mode 100644 index 9140a3222..000000000 --- a/examples/wgrad.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -from __future__ import print_function - -import argparse -import datetime -import math - -import legate.numpy as np - - -def initialize(C, K, B, H, W): - x = np.random.randn(C, B, H, W) - y = np.random.randn(K, B, H, W) - return x, y - - -def cross_correlate(x, y, C, K, R, S, B, H, W): - dw = np.zeros(shape=(R, S, C, K)) - # cross-correlate images to compute weight gradients - y_pad = np.zeros(shape=(K, B, H + R - 1, W + S - 1)) - y_pad[:, :, R / 2 : -(R / 2), S / 2 : -(S / 2)] = y - for r in range(R): - for s in range(S): - y_shift = y_pad[:, :, r : r + H, s : s + W] - for c in range(C): - for k in range(K): - dw[r, s, c, k] = np.sum( - x[c, :, :, :] * y_shift[k, :, :, :] - ) - return dw - - -def run_wgrad(H=256, W=256, B=32, C=256, K=32, R=5, S=5, timing=False): - if timing: - start = datetime.datetime.now() - x, y = initialize(C, K, B, H, W) - dw = cross_correlate(x, y, C, K, R, S, B, H, W) - # Do a little sum over dw to sync the results - total = np.sum(dw) - assert not math.isnan(total) - if timing: - stop = datetime.datetime.now() - delta = stop - start - print("Elapsed Time: " + str(delta.total_seconds() * 1000.0) + " ms") - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-b", "--batch", type=int, default=32, dest="B", help="batch size" - ) - parser.add_argument( - "--height", - type=int, - default=256, - dest="H", - help="height of images in pixels", - ) - parser.add_argument( - "-i", "--input", type=int, default=256, dest="C", help="input channels" - ) - parser.add_argument( - "-o", - "--output", - type=int, - default=32, - dest="K", - help="output channels", - ) - parser.add_argument( - "-r", - "--radix", - type=int, - default=5, - dest="R", - help="convolution radix", - ) - parser.add_argument( - "-t", - "--time", - dest="timing", - action="store_true", - help="perform timing", - ) - parser.add_argument( - "-w", - "--width", - type=int, - default=256, - dest="W", - help="width of images in pixels", - ) - args = parser.parse_args() - run_wgrad( - args.H, args.W, args.B, args.C, args.K, args.R, args.R, args.timing - ) From 5c6708157223d8bbc56887a6a5d09ba754d4d198 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 3 Oct 2021 20:33:57 -0700 Subject: [PATCH 09/46] re add in examples --- examples/benchmark.py | 52 +++++ examples/black_scholes.py | 144 +++++++++++++ examples/cg.py | 281 +++++++++++++++++++++++++ examples/gemm.py | 128 ++++++++++++ examples/jacobi.py | 130 ++++++++++++ examples/kmeans.py | 246 ++++++++++++++++++++++ examples/kmeans_slow.py | 247 ++++++++++++++++++++++ examples/kmeans_sort.py | 248 ++++++++++++++++++++++ examples/linreg.py | 160 ++++++++++++++ examples/logreg.py | 172 +++++++++++++++ examples/lstm_backward.py | 134 ++++++++++++ examples/lstm_forward.py | 124 +++++++++++ examples/lstm_full.py | 429 ++++++++++++++++++++++++++++++++++++++ examples/stencil.py | 107 ++++++++++ examples/wgrad.py | 112 ++++++++++ 15 files changed, 2714 insertions(+) create mode 100644 examples/benchmark.py create mode 100644 examples/black_scholes.py create mode 100644 examples/cg.py create mode 100644 examples/gemm.py create mode 100644 examples/jacobi.py create mode 100644 examples/kmeans.py create mode 100644 examples/kmeans_slow.py create mode 100644 examples/kmeans_sort.py create mode 100644 examples/linreg.py create mode 100644 examples/logreg.py create mode 100644 examples/lstm_backward.py create mode 100644 examples/lstm_forward.py create mode 100644 examples/lstm_full.py create mode 100644 examples/stencil.py create mode 100644 examples/wgrad.py diff --git a/examples/benchmark.py b/examples/benchmark.py new file mode 100644 index 000000000..429480a94 --- /dev/null +++ b/examples/benchmark.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import math +import sys + +if sys.version_info > (3, 0): + from functools import reduce + + +# A helper method for benchmarking applications +def run_benchmark(f, samples, name, args): + if samples > 1: + results = [f(*args) for s in range(samples)] + # Remove the largest and the smallest ones + if samples >= 3: + results.remove(max(results)) + if samples >= 2: + results.remove(min(results)) + mean = sum(results) / len(results) + variance = sum(map(lambda x: (x - mean) ** 2, results)) / len(results) + stddev = math.sqrt(variance) + print("-----------------------------------------------") + print("BENCHMARK RESULTS: " + name) + print("Total Samples: " + str(samples)) + print("Average Time: " + str(mean) + " ms") + print("Variance: " + str(variance) + " ms") + print("Stddev: " + str(stddev) + " ms") + print( + "All Results: " + + reduce(lambda x, y: x + y, map(lambda x: str(x) + ", ", results)) + ) + print("-----------------------------------------------") + else: + # Just run the application like normal + f(*args) diff --git a/examples/black_scholes.py b/examples/black_scholes.py new file mode 100644 index 000000000..7dafe85af --- /dev/null +++ b/examples/black_scholes.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +from benchmark import run_benchmark + +import legate.numpy as np + + +def generate_random(N, min, max, D): + diff = D(max) - D(min) + rands = np.random.random(N).astype(D) + rands = rands * diff + rands = rands + D(min) + return rands + + +def initialize(N, D): + S = generate_random(N, 5, 30, D) + X = generate_random(N, 1, 100, D) + T = generate_random(N, 0.25, 10, D) + R = 0.02 + V = 0.3 + return S, X, T, R, V + + +def cnd(d): + A1 = 0.31938153 + A2 = -0.356563782 + A3 = 1.781477937 + A4 = -1.821255978 + A5 = 1.330274429 + RSQRT2PI = 0.39894228040143267793994605993438 + + K = 1.0 / (1.0 + 0.2316419 * np.absolute(d)) + + cnd = ( + RSQRT2PI + * np.exp(-0.5 * d * d) + * (K * (A1 + K * (A2 + K * (A3 + K * (A4 + K * A5))))) + ) + + return np.where(d > 0, 1.0 - cnd, cnd) + + +def black_scholes(S, X, T, R, V): + sqrt_t = np.sqrt(T) + d1 = np.log(S / X) + (R + 0.5 * V * V) * T / (V * sqrt_t) + d2 = d1 - V * sqrt_t + cnd_d1 = cnd(d1) + cnd_d2 = cnd(d2) + exp_rt = np.exp(-R * T) + call_result = S * cnd_d1 - X * exp_rt * cnd_d2 + put_result = X * exp_rt * (1.0 - cnd_d2) - S * (1.0 - cnd_d1) + return call_result, put_result + + +def run_black_scholes(N, D): + print("Running black scholes on %dK options..." % N) + N *= 1000 + start = datetime.datetime.now() + S, X, T, R, V = initialize(N, D) + call, put = black_scholes(S, X, T, R, V) + # Check the result for NaNs to synchronize before stopping timing + call_sum = np.sum(call) + put_sum = np.sum(put) + assert not math.isnan(call_sum) and not math.isnan(put_sum) + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-n", + "--num", + type=int, + default=10, + dest="N", + help="number of options to price in thousands", + ) + parser.add_argument( + "-p", + "--precision", + type=int, + default=32, + dest="P", + help="precision of the computation in bits", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + args = parser.parse_args() + if args.P == 16: + run_benchmark( + run_black_scholes, + args.benchmark, + "Black Scholes", + (args.N, np.float16), + ) + elif args.P == 32: + run_benchmark( + run_black_scholes, + args.benchmark, + "Black Scholes", + (args.N, np.float32), + ) + elif args.P == 64: + run_benchmark( + run_black_scholes, + args.benchmark, + "Black Scholes", + (args.N, np.float64), + ) + else: + raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/cg.py b/examples/cg.py new file mode 100644 index 000000000..f6f9b688c --- /dev/null +++ b/examples/cg.py @@ -0,0 +1,281 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime + +from benchmark import run_benchmark + +import legate.numpy as np + + +# This is technically dead code right now, but we'll keep it around in +# case we want to generate a symmetrix positive definite matrix later +def generate_random(N): + print("Generating %dx%d symmetric positive definite system..." % (N, N)) + # Generate a random matrix + A = np.random.rand(N, N) + # Make sure the matrix is symmetric + A = 0.5 * (A + A.T) + # Now make sure that it is positive definite + A = A + N * np.eye(N) + b = np.random.rand(N) + return A, b + + +def generate_2D(N, corners): + if corners: + print( + "Generating %dx%d 2-D adjacency system with corners..." + % (N ** 2, N ** 2) + ) + A = np.zeros((N ** 2, N ** 2)) + 8 * np.eye(N ** 2) + else: + print( + "Generating %dx%d 2-D adjacency system without corners..." + % (N ** 2, N ** 2) + ) + A = np.zeros((N ** 2, N ** 2)) + 4 * np.eye(N ** 2) + # These are the same for both cases + off_one = np.full(N ** 2 - 1, -1, dtype=np.float64) + A += np.diag(off_one, k=1) + A += np.diag(off_one, k=-1) + off_N = np.full(N * (N - 1), -1, dtype=np.float64) + A += np.diag(off_N, k=N) + A += np.diag(off_N, k=-N) + # If we have corners then we have four more cases + if corners: + off_N_plus = np.full(N * (N - 1) - 1, -1, dtype=np.float64) + A += np.diag(off_N_plus, k=N + 1) + A += np.diag(off_N_plus, k=-(N + 1)) + off_N_minus = np.full(N * (N - 1) + 1, -1, dtype=np.float64) + A += np.diag(off_N_minus, k=N - 1) + A += np.diag(off_N_minus, k=-(N - 1)) + # Then we can generate a random b matrix + b = np.random.rand(N ** 2) + return A, b + + +def solve(A, b, conv_iters, max_iters, verbose): + print("Solving system...") + x = np.zeros(A.shape[1]) + r = b - A.dot(x) + p = r + rsold = r.dot(r) + converged = -1 + # Should always converge in fewer iterations than this + max_iters = ( + min(max_iters, b.shape[0]) if max_iters is not None else b.shape[0] + ) + for i in range(max_iters): + Ap = A.dot(p) + alpha = rsold / (p.dot(Ap)) + x = x + alpha * p + r = r - alpha * Ap + rsnew = r.dot(r) + # We only do the convergence test every conv_iters or on the last + # iteration + if (i % conv_iters == 0 or i == (max_iters - 1)) and np.sqrt( + rsnew + ) < 1e-10: + converged = i + break + if verbose: + print("Residual: " + str(rsnew)) + beta = rsnew / rsold + p = r + beta * p + rsold = rsnew + if converged < 0: + print("Convergence FAILURE!") + else: + print("Converged in %d iterations" % (converged)) + return x + + +def precondition(A, N, corners): + if corners: + d = 8 * (N ** 2) + else: + d = 4 * (N ** 2) + M = np.diag(np.full(N ** 2, 1.0 / d)) + return M + + +def preconditioned_solve(A, M, b, conv_iters, max_iters, verbose): + print("Solving system with preconditioner...") + x = np.zeros(A.shape[1]) + r = b - A.dot(x) + z = M.dot(r) + p = z + rzold = r.dot(z) + converged = -1 + # Should always converge in fewer iterations than this + max_iters = ( + min(max_iters, b.shape[0]) if max_iters is not None else b.shape[0] + ) + for i in range(max_iters): + Ap = A.dot(p) + alpha = rzold / (p.dot(Ap)) + x = x + alpha * p + r = r - alpha * Ap + rznew = r.dot(r) + # We only do the convergence test every conv_iters or on the + # last iteration + if (i % conv_iters == 0 or i == (max_iters - 1)) and np.sqrt( + rznew + ) < 1e-10: + converged = i + break + if verbose: + print("Residual: " + str(rznew)) + z = M.dot(r) + rznew = r.dot(z) + beta = rznew / rzold + p = z + beta * p + rzold = rznew + if converged < 0: + print("Convergence FAILURE!") + else: + print("Converged in %d iterations" % (converged)) + return x + + +def check(A, x, b): + print("Checking result...") + if np.allclose(A.dot(x), b): + print("PASS!") + else: + print("FAIL!") + + +def run_cg( + N, + corners, + preconditioner, + conv_iters, + max_iters, + perform_check, + timing, + verbose, +): + start = datetime.datetime.now() + # A, b = generate_random(N) + A, b = generate_2D(N, corners) + if preconditioner: + M = precondition(A, N, corners) + x = preconditioned_solve(A, M, b, conv_iters, max_iters, verbose) + else: + x = solve(A, b, conv_iters, max_iters, verbose) + if perform_check: + check(A, x, b) + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + if timing: + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-c", + "--check", + dest="check", + action="store_true", + help="check the result of the solve", + ) + parser.add_argument( + "-k", + "--corners", + dest="corners", + action="store_true", + help="include corners when generating the adjacency matrix", + ) + parser.add_argument( + "-i", + "--iters", + type=int, + default=25, + dest="conv_iters", + help="iterations between convergence tests", + ) + parser.add_argument( + "-p", + "--pre", + dest="precondition", + action="store_true", + help="use a Jacobi preconditioner", + ) + parser.add_argument( + "-m", + "--max", + type=int, + default=None, + dest="max_iters", + help="bound the maximum number of iterations", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=10, + dest="N", + help="number of elements in one dimension", + ) + parser.add_argument( + "-t", + "--time", + dest="timing", + action="store_true", + help="perform timing", + ) + parser.add_argument( + "-v", + "--verbose", + dest="verbose", + action="store_true", + help="print verbose output", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + + args = parser.parse_args() + run_benchmark( + run_cg, + args.benchmark, + "PreCG" if args.precondition else "CG", + ( + args.N, + args.corners, + args.precondition, + args.conv_iters, + args.max_iters, + args.check, + args.timing, + args.verbose, + ), + ) diff --git a/examples/gemm.py b/examples/gemm.py new file mode 100644 index 000000000..b3bd0d523 --- /dev/null +++ b/examples/gemm.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +from benchmark import run_benchmark + +import legate.numpy as np + + +def initialize(M, N, K, ft): + A = np.random.rand(N, N).astype(ft) + B = np.random.rand(N, N).astype(ft) + C = np.zeros((N, N), dtype=ft) + return A, B, C + + +def total_flops(M, N, K): + return M * N * (2 * K - 1) + + +def total_space(M, N, K, ft): + return (M * N + M * K + K * N) * np.dtype(ft).itemsize + + +def run_gemm(N, I, ft): # noqa: E741 + print("Problem Size: M=" + str(N) + " N=" + str(N) + " K=" + str(N)) + print("Total Iterations: " + str(I)) + flops = total_flops(N, N, N) + print("Total Flops: " + str(flops / 1e9) + " GFLOPS/iter") + space = total_space(N, N, N, ft) + print("Total Size: " + str(space / 1e6) + " MB") + A, B, C = initialize(N, N, N, ft) + # Compute some sums and check for NaNs to force synchronization + # before we start the timing + assert not math.isnan(np.sum(A)) + assert not math.isnan(np.sum(B)) + assert not math.isnan(np.sum(C)) + start = datetime.datetime.now() + # Run for as many iterations as was requested + for idx in range(I): + np.dot(A, B, out=C) + # We need to rotate the matrices to keep Legate honest + # about moving data so it can't just duplicate A and B + # on the first iteration and reuse them, this means + # that A, B, C all need to be square + A, B, C = B, C, A + # Do another sum to synchronize for timings, B is last output + assert not math.isnan(np.sum(B)) + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + print("Elapsed Time: " + str(total) + " ms") + average = total / I + print("Average GEMM: " + str(average) + " ms") + print("FLOPS/s: " + str(flops / (average * 1e6)) + " GFLOPS/s") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-i", + "--iter", + type=int, + default=100, + dest="I", + help="number of iterations to run", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=100, + dest="N", + help="number of elements in one dimension", + ) + parser.add_argument( + "-p", + "--precision", + type=int, + default=32, + dest="P", + help="number of bits of precision to use for the gemm computation " + "(16,32,64)", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + args = parser.parse_args() + if args.P == 16: + run_benchmark( + run_gemm, args.benchmark, "HGEMM", (args.N, args.I, np.float16) + ) + elif args.P == 32: + run_benchmark( + run_gemm, args.benchmark, "SGEMM", (args.N, args.I, np.float32) + ) + elif args.P == 64: + run_benchmark( + run_gemm, args.benchmark, "DGEMM", (args.N, args.I, np.float64) + ) + else: + raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/jacobi.py b/examples/jacobi.py new file mode 100644 index 000000000..7bc2bed5f --- /dev/null +++ b/examples/jacobi.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +from benchmark import run_benchmark + +import legate.numpy as np + + +def generate_random(N): + print("Generating %dx%d system..." % (N, N)) + # Generate a random matrix + A = np.random.rand(N, N) + # Make sure that it is diagonally dominate + A = A + N * np.eye(N) + # Generate a random vector + b = np.random.rand(N) + return A, b + + +def solve(A, b, iters, verbose): + print("Solving system...") + x = np.zeros(A.shape[1]) + d = np.diag(A) + R = A - np.diag(d) + for i in range(iters): + x = (b - np.dot(R, x)) / d + return x + + +def check(A, x, b): + print("Checking result...") + if np.allclose(A.dot(x), b): + print("PASS!") + else: + print("FAIL!") + + +def run_jacobi(N, iters, perform_check, timing, verbose): + start = datetime.datetime.now() + A, b = generate_random(N) + x = solve(A, b, iters, verbose) + if perform_check: + check(A, x, b) + else: + # Need a synchronization here for timing + assert not math.isnan(np.sum(x)) + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + if timing: + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-c", + "--check", + dest="check", + action="store_true", + help="check the result of the solve", + ) + parser.add_argument( + "-i", + "--iters", + type=int, + default=1000, + dest="iters", + help="number of iterations to run", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=100, + dest="N", + help="number of elements in one dimension", + ) + parser.add_argument( + "-t", + "--time", + dest="timing", + action="store_true", + help="perform timing", + ) + parser.add_argument( + "-v", + "--verbose", + dest="verbose", + action="store_true", + help="print verbose output", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + + args = parser.parse_args() + run_benchmark( + run_jacobi, + args.benchmark, + "Jacobi", + (args.N, args.iters, args.check, args.timing, args.verbose), + ) diff --git a/examples/kmeans.py b/examples/kmeans.py new file mode 100644 index 000000000..c7636e51d --- /dev/null +++ b/examples/kmeans.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +# Derived from https://github.com/bryancatanzaro/kmeans + +from __future__ import print_function + +import argparse +import datetime + +from benchmark import run_benchmark + +import legate.numpy as np + + +def initialize(N, D, C, T): + # Uncomment this if we want execution to be deterministic with + # original numpy np.random.seed(0) + data = np.random.random((N, D)).astype(T) + # Since points are random, we'll just generate some random centers + centroids = np.random.random((C, D)).astype(T) + return data, centroids + + +def calculate_distances(data, centroids, data_dots): + centroid_dots = np.square(np.linalg.norm(centroids, ord=2, axis=1)) + pairwise_distances = ( + data_dots[:, np.newaxis] + centroid_dots[np.newaxis, :] + ) + # ||x-y||^2 = ||x||^2 + ||y||^2 - 2 x . y + # pairwise_distances has ||x||^2 + ||y||^2, so beta = 1 + # The gemm calculates x.y for all x and y, so alpha = -2.0 + pairwise_distances -= 2.0 * np.dot(data, centroids.T) + return pairwise_distances + + +def relabel(pairwise_distances): + return np.argmin(pairwise_distances, axis=1) + + +def find_centroids(centroids, data, labels, pairwise_distances, zero_point, C): + # Get the number of points associated with each centroid + counts = np.bincount(labels, minlength=C) + + # more bincounts using the positions as weights produce the unnormalized + # updated centroid locations (have to do each dimension separately since + # a weight cannot be a vector) + for idx in range(data.shape[1]): + centroids[:, idx] = np.bincount( + labels, weights=data[:, idx], minlength=C + ) + + # would have been nice if numpy offered a combined amin/argmin to avoid + # iterating over pairwise_distances twice + distance_sum = np.sum(np.amin(pairwise_distances, axis=1)) + + # To avoid introducing divide by zero errors + # If a centroid has no weight, we'll do no normalization + # This will keep its coordinates defined. + counts = np.maximum(counts, np.ones((1,), dtype=np.uint64)) + centroids /= counts[:, np.newaxis] + return distance_sum + + +def run_kmeans(C, D, T, I, N, S, benchmarking): # noqa: E741 + print("Running kmeans...") + print("Number of data points: " + str(N)) + print("Number of dimensions: " + str(D)) + print("Number of centroids: " + str(C)) + print("Max iterations: " + str(I)) + start = datetime.datetime.now() + data, centroids = initialize(N, D, C, T) + + data_dots = np.square(np.linalg.norm(data, ord=2, axis=1)) + zero_point = np.zeros((1, data.shape[1]), dtype=data.dtype) + + labels = None + iteration = 0 + prior_distance_sum = None + # We run for max iterations or until we converge + # We only test convergence every S iterations + while iteration < I: + pairwise_distances = calculate_distances(data, centroids, data_dots) + + new_labels = relabel(pairwise_distances) + + distance_sum = find_centroids( + centroids, data, new_labels, pairwise_distances, zero_point, C + ) + + if iteration > 0 and iteration % S == 0: + changes = np.not_equal(labels, new_labels) + total_changes = np.sum(changes) + delta = distance_sum / prior_distance_sum + print( + "Iteration " + + str(iteration) + + " produced " + + str(total_changes) + + " changes, and total distance is " + + str(distance_sum) + ) + # We ignore the result of the threshold test in the case + # that we are running performance benchmarks to measure + # performance for a certain number of iterations + if delta > 1 - 0.000001 and not benchmarking: + print("Threshold triggered, terminating iterations early") + break + prior_distance_sum = distance_sum + labels = new_labels + iteration += 1 + # This final distance sum also synchronizes the results + print( + "Final distance sum at iteration " + + str(iteration) + + ": " + + str(prior_distance_sum) + ) + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-c", + "--centers", + type=int, + default=10, + dest="C", + help="number of centroids", + ) + parser.add_argument( + "-d", + "--dims", + type=int, + default=2, + dest="D", + help="number of dimensions for each input data point", + ) + parser.add_argument( + "-m", + "--max-iters", + type=int, + default=1000, + dest="I", + help="maximum number of iterations to run the algorithm for", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=10, + dest="N", + help="number of elements in the data set in thousands", + ) + parser.add_argument( + "-p", + "--precision", + type=int, + default=32, + dest="P", + help="precision of the computation in bits", + ) + parser.add_argument( + "-s", + "--sample", + type=int, + default=25, + dest="S", + help="number of iterations between sampling the log likelihood", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application" + " (default 1 - normal execution)", + ) + args = parser.parse_args() + if args.P == 16: + run_benchmark( + run_kmeans, + args.benchmark, + "KMEANS(H)", + ( + args.C, + args.D, + np.float16, + args.I, + args.N * 1000, + args.S, + args.benchmark > 1, + ), + ) + elif args.P == 32: + run_benchmark( + run_kmeans, + args.benchmark, + "KMEANS(S)", + ( + args.C, + args.D, + np.float32, + args.I, + args.N * 1000, + args.S, + args.benchmark > 1, + ), + ) + elif args.P == 64: + run_benchmark( + run_kmeans, + args.benchmark, + "KMEANS(D)", + ( + args.C, + args.D, + np.float64, + args.I, + args.N * 1000, + args.S, + args.benchmark > 1, + ), + ) + else: + raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/kmeans_slow.py b/examples/kmeans_slow.py new file mode 100644 index 000000000..070122891 --- /dev/null +++ b/examples/kmeans_slow.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +# Derived from https://github.com/bryancatanzaro/kmeans + +from __future__ import print_function + +import argparse +import datetime + +from benchmark import run_benchmark + +import legate.numpy as np + + +def initialize(N, D, C, T): + # Uncomment this if we want execution to be deterministic + # np.random.seed(0) + data = np.random.random((N, D)).astype(T) + # Since points are random, we'll just generate some random centers + centroids = np.random.random((C, D)).astype(T) + return data, centroids + + +def calculate_distances(data, centroids, data_dots): + centroid_dots = np.square(np.linalg.norm(centroids, ord=2, axis=1)) + pairwise_distances = ( + data_dots[:, np.newaxis] + centroid_dots[np.newaxis, :] + ) + # ||x-y||^2 = ||x||^2 + ||y||^2 - 2 x . y + # pairwise_distances has ||x||^2 + ||y||^2, so beta = 1 + # The gemm calculates x.y for all x and y, so alpha = -2.0 + pairwise_distances -= 2.0 * np.dot(data, centroids.T) + return pairwise_distances + + +def relabel(pairwise_distances): + return np.argmin(pairwise_distances, axis=1) + + +def find_centroids( + centroids, data, labels, pairwise_distances, zero_point, C, D +): + # Get the number of points associated with each centroid + counts = np.bincount(labels, minlength=C) + # Build label masks for each centroid and sum across all the + # points assocated with each new centroid + distance_sum = 0.0 + for idx in range(C): + # Boolean mask indicating where the points are for this center + centroid_mask = labels == idx + centroids[idx, :] = np.sum( + np.where(centroid_mask[..., np.newaxis], data, zero_point), axis=0 + ) + distance_sum += np.sum( + np.where(centroid_mask, pairwise_distances[:, idx], 0.0) + ) + # To avoid introducing divide by zero errors + # If a centroid has no weight, we'll do no normalization + # This will keep its coordinates defined. + counts = np.maximum(counts, np.ones((1,), dtype=np.uint64)) + centroids /= counts[:, np.newaxis] + return distance_sum + + +def run_kmeans(C, D, T, I, N, S, benchmarking): # noqa: E741 + print("Running kmeans...") + print("Number of data points: " + str(N)) + print("Number of dimensions: " + str(D)) + print("Number of centroids: " + str(C)) + print("Max iterations: " + str(I)) + start = datetime.datetime.now() + data, centroids = initialize(N, D, C, T) + + data_dots = np.square(np.linalg.norm(data, ord=2, axis=1)) + zero_point = np.zeros((1, data.shape[1]), dtype=data.dtype) + + labels = None + iteration = 0 + prior_distance_sum = None + # We run for max iterations or until we converge + # We only test convergence every S iterations + while iteration < I: + pairwise_distances = calculate_distances(data, centroids, data_dots) + + new_labels = relabel(pairwise_distances) + + distance_sum = find_centroids( + centroids, data, new_labels, pairwise_distances, zero_point, C, D + ) + + if iteration > 0 and iteration % S == 0: + changes = np.not_equal(labels, new_labels) + total_changes = np.sum(changes) + delta = distance_sum / prior_distance_sum + print( + "Iteration " + + str(iteration) + + " produced " + + str(total_changes) + + " changes, and total distance is " + + str(distance_sum) + ) + # We ignore the result of the threshold test in the case + # that we are running performance benchmarks to measure + # performance for a certain number of iterations + if delta > 1 - 0.000001 and not benchmarking: + print("Threshold triggered, terminating iterations early") + break + prior_distance_sum = distance_sum + labels = new_labels + iteration += 1 + # This final distance sum also synchronizes the results + print( + "Final distance sum at iteration " + + str(iteration) + + ": " + + str(prior_distance_sum) + ) + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-c", + "--centers", + type=int, + default=10, + dest="C", + help="number of centroids", + ) + parser.add_argument( + "-d", + "--dims", + type=int, + default=2, + dest="D", + help="number of dimensions for each input data point", + ) + parser.add_argument( + "-m", + "--max-iters", + type=int, + default=1000, + dest="I", + help="maximum number of iterations to run the algorithm for", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=10, + dest="N", + help="number of elements in the data set in thousands", + ) + parser.add_argument( + "-p", + "--precision", + type=int, + default=32, + dest="P", + help="precision of the computation in bits", + ) + parser.add_argument( + "-s", + "--sample", + type=int, + default=25, + dest="S", + help="number of iterations between sampling the log likelihood", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + args = parser.parse_args() + if args.P == 16: + run_benchmark( + run_kmeans, + args.benchmark, + "KMEANS(H)", + ( + args.C, + args.D, + np.float16, + args.I, + args.N * 1000, + args.S, + args.benchmark > 1, + ), + ) + elif args.P == 32: + run_benchmark( + run_kmeans, + args.benchmark, + "KMEANS(S)", + ( + args.C, + args.D, + np.float32, + args.I, + args.N * 1000, + args.S, + args.benchmark > 1, + ), + ) + elif args.P == 64: + run_benchmark( + run_kmeans, + args.benchmark, + "KMEANS(D)", + ( + args.C, + args.D, + np.float64, + args.I, + args.N * 1000, + args.S, + args.benchmark > 1, + ), + ) + else: + raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/kmeans_sort.py b/examples/kmeans_sort.py new file mode 100644 index 000000000..10cf8d355 --- /dev/null +++ b/examples/kmeans_sort.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +# Derived from https://github.com/bryancatanzaro/kmeans + +from __future__ import print_function + +import argparse +import datetime + +from benchmark import run_benchmark + +import legate.numpy as np + +try: + xrange +except NameError: + xrange = range + + +def initialize(N, D, C, T): + # Uncomment this if we want execution to be deterministic + # np.random.seed(0) + data = np.random.random((N, D)).astype(T) + # Since points are random, we'll just generate some random centers + centroids = np.random.random((C, D)).astype(T) + return data, centroids + + +def calculate_distances(data, centroids, data_dots): + centroid_dots = np.square(np.linalg.norm(centroids, ord=2, axis=1)) + pairwise_distances = ( + data_dots[:, np.newaxis] + centroid_dots[np.newaxis, :] + ) + # ||x-y||^2 = ||x||^2 + ||y||^2 - 2 x . y + # pairwise_distances has ||x||^2 + ||y||^2, so beta = 1 + # The gemm calculates x.y for all x and y, so alpha = -2.0 + pairwise_distances -= 2.0 * np.dot(data, centroids.T) + return pairwise_distances + + +def relabel(pairwise_distances, data_index): + new_labels = np.argmin(pairwise_distances, axis=1) + distances = pairwise_distances[data_index, new_labels] + return new_labels, distances + + +def find_centroids(data, labels, C, D): + # Sort the points by their labels + indices = np.argsort(labels) + sorted_points = data[indices] + # Compute counts and indexes for ending of sets of points for each centroid + counts = np.bincount(labels, minlength=C) + indexes = np.cumsum(counts) + # Now we can use the indexes to split the array into sub-arrays and then + # sum across them to create the centroids + centroids = np.empty((C, D), dtype=data.dtype) + ragged_arrays = np.split(sorted_points, indexes) + for idx in xrange(C): + centroids[idx, :] = np.sum(ragged_arrays[idx], axis=0) + # To avoid introducing divide by zero errors + # If a centroid has no weight, we'll do no normalization + # This will keep its coordinates defined. + counts = np.maximum(counts, 1) + return centroids / counts[:, np.newaxis] + + +def run_kmeans(C, D, T, I, N, S, benchmarking): # noqa: E741 + print("Running kmeans...") + print("Number of data points: " + str(N)) + print("Number of dimensions: " + str(D)) + print("Number of centroids: " + str(C)) + print("Max iterations: " + str(I)) + start = datetime.datetime.now() + data, centroids = initialize(N, D, C, T) + + data_dots = np.square(np.linalg.norm(data, ord=2, axis=1)) + data_index = np.linspace(0, N - 1, N, dtype=np.int) + + labels = None + iteration = 0 + prior_distance_sum = None + # We run for max iterations or until we converge + # We only test convergence every S iterations + while iteration < I: + pairwise_distances = calculate_distances(data, centroids, data_dots) + + new_labels, distances = relabel(pairwise_distances, data_index) + distance_sum = np.sum(distances) + + centroids = find_centroids(data, new_labels, C, D) + + if iteration > 0 and iteration % S == 0: + changes = np.not_equal(labels, new_labels) + total_changes = np.sum(changes) + delta = distance_sum / prior_distance_sum + print( + "Iteration " + + str(iteration) + + " produced " + + str(total_changes) + + " changes, and total distance is " + + str(distance_sum) + ) + # We ignore the result of the threshold test in the case that we + # are running performance benchmarks to measure performance for a + # certain number of iterations + if delta > 1 - 0.000001 and not benchmarking: + print("Threshold triggered, terminating iterations early") + break + prior_distance_sum = distance_sum + labels = new_labels + iteration += 1 + # This final distance sum also synchronizes the results + print( + "Final distance sum at iteration " + + str(iteration) + + ": " + + str(prior_distance_sum) + ) + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-c", + "--centers", + type=int, + default=10, + dest="C", + help="number of centroids", + ) + parser.add_argument( + "-d", + "--dims", + type=int, + default=2, + dest="D", + help="number of dimensions for each input data point", + ) + parser.add_argument( + "-m", + "--max-iters", + type=int, + default=1000, + dest="I", + help="maximum number of iterations to run the algorithm for", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=10, + dest="N", + help="number of elements in the data set in thousands", + ) + parser.add_argument( + "-p", + "--precision", + type=int, + default=32, + dest="P", + help="precision of the computation in bits", + ) + parser.add_argument( + "-s", + "--sample", + type=int, + default=25, + dest="S", + help="number of iterations between sampling the log likelihood", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + args = parser.parse_args() + if args.P == 16: + run_benchmark( + run_kmeans, + args.benchmark, + "KMEANS(H)", + ( + args.C, + args.D, + np.float16, + args.I, + args.N * 1000, + args.S, + args.benchmark > 1, + ), + ) + elif args.P == 32: + run_benchmark( + run_kmeans, + args.benchmark, + "KMEANS(S)", + ( + args.C, + args.D, + np.float32, + args.I, + args.N * 1000, + args.S, + args.benchmark > 1, + ), + ) + elif args.P == 64: + run_benchmark( + run_kmeans, + args.benchmark, + "KMEANS(D)", + ( + args.C, + args.D, + np.float64, + args.I, + args.N * 1000, + args.S, + args.benchmark > 1, + ), + ) + else: + raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/linreg.py b/examples/linreg.py new file mode 100644 index 000000000..ed5f43015 --- /dev/null +++ b/examples/linreg.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +from benchmark import run_benchmark + +import legate.numpy as np + + +def initialize(N, F, T): + # We'll generate some random inputs here + # since we don't need it to converge + x = np.random.randn(N, F).astype(T) + y = np.random.random(N).astype(T) + return x, y + + +def linear_regression( + T, features, target, steps, learning_rate, sample, add_intercept=False +): + if add_intercept: + intercept = np.ones((features.shape[0], 1), dtype=T) + features = np.hstack((intercept, features)) + + weights = np.zeros(features.shape[1], dtype=T) + + for step in range(steps): + scores = np.dot(features, weights) + error = scores - target + gradient = -(1.0 / len(features)) * error.dot(features) + weights += learning_rate * gradient + + if step % sample == 0: + print( + "Error of step " + + str(step) + + ": " + + str(np.sum(np.power(error, 2))) + ) + + return weights + + +def run_linear_regression(N, F, T, I, S, B): # noqa: E741 + print("Running linear regression...") + print("Number of data points: " + str(N) + "K") + print("Number of features: " + str(F)) + print("Number of iterations: " + str(I)) + start = datetime.datetime.now() + features, target = initialize(N * 1000, F, T) + weights = linear_regression(T, features, target, I, 1e-5, S, B) + # Check the weights for NaNs to synchronize before stopping timing + assert not math.isnan(np.sum(weights)) + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-b", + "--intercept", + dest="B", + action="store_true", + help="include an intercept in the calculation", + ) + parser.add_argument( + "-f", + "--features", + type=int, + default=32, + dest="F", + help="number of features for each input data point", + ) + parser.add_argument( + "-i", + "--iterations", + type=int, + default=1000, + dest="I", + help="number of iterations to run the algorithm for", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=10, + dest="N", + help="number of elements in the data set in thousands", + ) + parser.add_argument( + "-p", + "--precision", + type=int, + default=32, + dest="P", + help="precision of the computation in bits", + ) + parser.add_argument( + "-s", + "--sample", + type=int, + default=100, + dest="S", + help="number of iterations between sampling the log likelihood", + ) + parser.add_argument( + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + args = parser.parse_args() + if args.P == 16: + run_benchmark( + run_linear_regression, + args.benchmark, + "LINREG(H)", + (args.N, args.F, np.float16, args.I, args.S, args.B), + ) + elif args.P == 32: + run_benchmark( + run_linear_regression, + args.benchmark, + "LINREG(S)", + (args.N, args.F, np.float32, args.I, args.S, args.B), + ) + elif args.P == 64: + run_benchmark( + run_linear_regression, + args.benchmark, + "LINREG(D)", + (args.N, args.F, np.float64, args.I, args.S, args.B), + ) + else: + raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/logreg.py b/examples/logreg.py new file mode 100644 index 000000000..46a013fa3 --- /dev/null +++ b/examples/logreg.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +from benchmark import run_benchmark + +import legate.numpy as np + + +def initialize(N, F, T): + # We'll generate some random inputs here + # since we don't need it to converge + x = np.random.randn(N, F).astype(T) + # Give the results either a 0 or 1 value + y = np.floor(2.0 * np.random.random(N).astype(T)) + return x, y + + +def sigmoid(x): + return 1.0 / (1.0 + np.exp(-x)) + + +def log_likelihood(features, target, weights): + scores = np.dot(features, weights) + return np.sum(target * scores - np.log(1.0 + np.exp(scores))) + + +def logistic_regression( + T, features, target, steps, learning_rate, sample, add_intercept=False +): + if add_intercept: + intercept = np.ones((features.shape[0], 1), dtype=T) + features = np.hstack((intercept, features)) + + weights = np.zeros(features.shape[1], dtype=T) + + for step in range(steps): + scores = np.dot(features, weights) + predictions = sigmoid(scores) + + error = target - predictions + gradient = np.dot(error, features) + weights += learning_rate * gradient + + if step % sample == 0: + print( + "Log Likelihood of step " + + str(step) + + ": " + + str(log_likelihood(features, target, weights)) + ) + + return weights + + +def run_logistic_regression(N, F, T, I, S, B): # noqa: E741 + print("Running logistic regression...") + print("Number of data points: " + str(N) + "K") + print("Number of features: " + str(F)) + print("Number of iterations: " + str(I)) + start = datetime.datetime.now() + features, target = initialize(N * 1000, F, T) + weights = logistic_regression(T, features, target, I, 1e-5, S, B) + # Check the weights for NaNs to synchronize before stopping timing + assert not math.isnan(np.sum(weights)) + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-b", + "--intercept", + dest="B", + action="store_true", + help="include an intercept in the calculation", + ) + parser.add_argument( + "-f", + "--features", + type=int, + default=32, + dest="F", + help="number of features for each input data point", + ) + parser.add_argument( + "-i", + "--iterations", + type=int, + default=1000, + dest="I", + help="number of iterations to run the algorithm for", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=10, + dest="N", + help="number of elements in the data set in thousands", + ) + parser.add_argument( + "-p", + "--precision", + type=int, + default=32, + dest="P", + help="precision of the computation in bits", + ) + parser.add_argument( + "-s", + "--sample", + type=int, + default=100, + dest="S", + help="number of iterations between sampling the log likelihood", + ) + parser.add_argument( + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + args = parser.parse_args() + if args.P == 16: + run_benchmark( + run_logistic_regression, + args.benchmark, + "LOGREG(H)", + (args.N, args.F, np.float16, args.I, args.S, args.B), + ) + elif args.P == 32: + run_benchmark( + run_logistic_regression, + args.benchmark, + "LOGREG(S)", + (args.N, args.F, np.float32, args.I, args.S, args.B), + ) + elif args.P == 64: + run_benchmark( + run_logistic_regression, + args.benchmark, + "LOGREG(D)", + (args.N, args.F, np.float64, args.I, args.S, args.B), + ) + else: + raise TypeError("Precision must be one of 16, 32, or 64") diff --git a/examples/lstm_backward.py b/examples/lstm_backward.py new file mode 100644 index 000000000..45e9b2d29 --- /dev/null +++ b/examples/lstm_backward.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +from benchmark import run_benchmark + +import legate.numpy as np + + +def run_lstm(batch_size, hidden_size, sentence_length, word_size, timing): + start = datetime.datetime.now() + + WLSTM = np.random.randn( + word_size + hidden_size, 4 * hidden_size + ) / np.sqrt(word_size + hidden_size) + + xphpb = WLSTM.shape[0] + d = hidden_size + n = sentence_length + b = batch_size + + dHout = np.random.randn(n, b, d) + IFOGf = np.random.randn(n, b, d * 4) + C = np.random.randn(n, b, d) + Ct = np.random.randn(n, b, d) + Hin = np.random.randn(n, b, xphpb) + + dIFOG = np.zeros((n, b, d * 4)) + dIFOGf = np.zeros(IFOGf.shape) + dHin = np.zeros(Hin.shape) + dC = np.zeros(C.shape) + dh0 = np.zeros((1, d)) + + for t in reversed(range(n)): + tanhCt = Ct[t] + dIFOGf[t, :, 2 * d : 3 * d] = tanhCt * dHout[t] + # backprop tanh non-linearity first then continue backprop + dC[t] += (1 - tanhCt ** 2) * (IFOGf[t, :, 2 * d : 3 * d] * dHout[t]) + + if t > 0: + dIFOGf[t, :, d : 2 * d] = C[t - 1] * dC[t] + dC[t - 1] += IFOGf[t, :, d : 2 * d] * dC[t] + + dIFOGf[t, :, :d] = IFOGf[t, :, 3 * d :] * dC[t] + dIFOGf[t, :, 3 * d :] = IFOGf[t, :, :d] * dC[t] + + # backprop activation functions + dIFOG[t, :, 3 * d :] = (1 - IFOGf[t, :, 3 * d :] ** 2) * dIFOGf[ + t, :, 3 * d : + ] + y = IFOGf[t, :, : 3 * d] + dIFOG[t, :, : 3 * d] = (y * (1.0 - y)) * dIFOGf[t, :, : 3 * d] + + # backprop matrix multiply + dHin[t] = dIFOG[t].dot(WLSTM.transpose()) + + # backprop the identity transforms into Hin + if t > 0: + dHout[t - 1, :] += dHin[t, :, word_size:] + else: + dh0[0] += np.sum(dHin[t, :, word_size:], 0) + + # Do a little sum to synchronize and check for NaNs + total = np.sum(dh0) + assert not math.isnan(total) + + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + if timing: + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-b", "--batch", type=int, default=32, dest="batch", help="batch size" + ) + parser.add_argument( + "--hidden", type=int, default=10, dest="hidden", help="hidden size" + ) + parser.add_argument( + "-s", + "--sentence", + type=int, + default=4, + dest="sentence", + help="sentence length", + ) + parser.add_argument( + "-w", "--word", type=int, default=10, dest="word", help="word size" + ) + parser.add_argument( + "-t", + "--time", + dest="timing", + action="store_true", + help="perform timing", + ) + parser.add_argument( + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + args = parser.parse_args() + run_benchmark( + run_lstm, + args.benchmark, + "LSTM Backward", + (args.batch, args.hidden, args.sentence, args.word, args.timing), + ) diff --git a/examples/lstm_forward.py b/examples/lstm_forward.py new file mode 100644 index 000000000..c3ac6b779 --- /dev/null +++ b/examples/lstm_forward.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +from benchmark import run_benchmark + +import legate.numpy as np + + +def run_lstm(batch_size, hidden_size, sentence_length, word_size, timing): + start = datetime.datetime.now() + + X = np.random.randn(sentence_length, batch_size, hidden_size) + h0 = np.random.randn(1, hidden_size) + WLSTM = np.random.randn( + word_size + hidden_size, 4 * hidden_size + ) / np.sqrt(word_size + hidden_size) + + xphpb = WLSTM.shape[0] + d = hidden_size + n = sentence_length + b = batch_size + + Hin = np.zeros((n, b, xphpb)) + Hout = np.zeros((n, b, d)) + IFOG = np.zeros((n, b, d * 4)) + IFOGf = np.zeros((n, b, d * 4)) + C = np.zeros((n, b, d)) + Ct = np.zeros((n, b, d)) + + for t in range(0, n): + if t == 0: + prev = np.tile(h0, (b, 1)) + else: + prev = Hout[t - 1] + + Hin[t, :, :word_size] = X[t] + Hin[t, :, word_size:] = prev + # compute all gate activations. dots: + IFOG[t] = Hin[t].dot(WLSTM) + # non-linearities + IFOGf[t, :, : 3 * d] = 1.0 / ( + 1.0 + np.exp(-IFOG[t, :, : 3 * d]) + ) # sigmoids these are the gates + IFOGf[t, :, 3 * d :] = np.tanh(IFOG[t, :, 3 * d :]) # tanh + # compute the cell activation + C[t] = IFOGf[t, :, :d] * IFOGf[t, :, 3 * d :] + if t > 0: + C[t] += IFOGf[t, :, d : 2 * d] * C[t - 1] + Ct[t] = np.tanh(C[t]) + Hout[t] = IFOGf[t, :, 2 * d : 3 * d] * Ct[t] + + # Do a little sum of the outputs to synchronize and check for NaNs + total = np.sum(Hout) + assert not math.isnan(total) + + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + if timing: + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-b", "--batch", type=int, default=32, dest="batch", help="batch size" + ) + parser.add_argument( + "--hidden", type=int, default=10, dest="hidden", help="hidden size" + ) + parser.add_argument( + "-s", + "--sentence", + type=int, + default=4, + dest="sentence", + help="sentence length", + ) + parser.add_argument( + "-w", "--word", type=int, default=10, dest="word", help="word size" + ) + parser.add_argument( + "-t", + "--time", + dest="timing", + action="store_true", + help="perform timing", + ) + parser.add_argument( + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + args = parser.parse_args() + run_benchmark( + run_lstm, + args.benchmark, + "LSTM Forward", + (args.batch, args.hidden, args.sentence, args.word, args.timing), + ) diff --git a/examples/lstm_full.py b/examples/lstm_full.py new file mode 100644 index 000000000..071482229 --- /dev/null +++ b/examples/lstm_full.py @@ -0,0 +1,429 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime + +from benchmark import run_benchmark + +import legate.numpy as np + + +class Param: + def __init__(self, name, value): + self.name = name + self.v = value # parameter value + self.d = np.zeros_like(value) # derivative + self.m = np.zeros_like(value) # momentum for AdaGrad + + +class Parameters: + def __init__(self, H_size, X_size, z_size, weight_sd): + self.W_f = Param( + "W_f", np.random.randn(H_size, z_size) * weight_sd + 0.5 + ) + self.b_f = Param("b_f", np.zeros((H_size, 1))) + + self.W_i = Param( + "W_i", np.random.randn(H_size, z_size) * weight_sd + 0.5 + ) + self.b_i = Param("b_i", np.zeros((H_size, 1))) + + self.W_C = Param("W_C", np.random.randn(H_size, z_size) * weight_sd) + self.b_C = Param("b_C", np.zeros((H_size, 1))) + + self.W_o = Param( + "W_o", np.random.randn(H_size, z_size) * weight_sd + 0.5 + ) + self.b_o = Param("b_o", np.zeros((H_size, 1))) + + # For final layer to predict the next character + self.W_v = Param("W_v", np.random.randn(X_size, H_size) * weight_sd) + self.b_v = Param("b_v", np.zeros((X_size, 1))) + + def all(self): + return [ + self.W_f, + self.W_i, + self.W_C, + self.W_o, + self.W_v, + self.b_f, + self.b_i, + self.b_C, + self.b_o, + self.b_v, + ] + + +def sigmoid(x): + return 1 / (1 + np.exp(-x)) + + +def dsigmoid(y): + return y * (1 - y) + + +def tanh(x): + return np.tanh(x) + + +def dtanh(y): + return 1 - y * y + + +def forward(x, h_prev, C_prev, H_size, X_size, p): + assert x.shape == (X_size, 1) + assert h_prev.shape == (H_size, 1) + assert C_prev.shape == (H_size, 1) + + z = np.row_stack((h_prev, x)) + f = sigmoid(np.dot(p.W_f.v, z) + p.b_f.v) + i = sigmoid(np.dot(p.W_i.v, z) + p.b_i.v) + C_bar = tanh(np.dot(p.W_C.v, z) + p.b_C.v) + + C = f * C_prev + i * C_bar + o = sigmoid(np.dot(p.W_o.v, z) + p.b_o.v) + h = o * tanh(C) + + v = np.dot(p.W_v.v, h) + p.b_v.v + y = np.exp(v) / np.sum(np.exp(v)) # softmax + + return z, f, i, C_bar, C, o, h, v, y + + +def backward( + target, + dh_next, + dC_next, + C_prev, + H_size, + X_size, + z, + f, + i, + C_bar, + C, + o, + h, + v, + y, + p, +): + + assert z.shape == (X_size + H_size, 1) + assert v.shape == (X_size, 1) + assert y.shape == (X_size, 1) + + for param in [dh_next, dC_next, C_prev, f, i, C_bar, C, o, h]: + assert param.shape == (H_size, 1) + + dv = np.copy(y) + dv[target] -= 1 + + p.W_v.d += np.dot(dv, h.T) + p.b_v.d += dv + + dh = np.dot(p.W_v.v.T, dv) + dh += dh_next + do = dh * tanh(C) + do = dsigmoid(o) * do + p.W_o.d += np.dot(do, z.T) + p.b_o.d += do + + dC = np.copy(dC_next) + dC += dh * o * dtanh(tanh(C)) + dC_bar = dC * i + dC_bar = dtanh(C_bar) * dC_bar + p.W_C.d += np.dot(dC_bar, z.T) + p.b_C.d += dC_bar + + di = dC * C_bar + di = dsigmoid(i) * di + p.W_i.d += np.dot(di, z.T) + p.b_i.d += di + + df = dC * C_prev + df = dsigmoid(f) * df + p.W_f.d += np.dot(df, z.T) + p.b_f.d += df + + dz = ( + np.dot(p.W_f.v.T, df) + + np.dot(p.W_i.v.T, di) + + np.dot(p.W_C.v.T, dC_bar) + + np.dot(p.W_o.v.T, do) + ) + dh_prev = dz[:H_size, :] + dC_prev = f * dC + + return dh_prev, dC_prev + + +def clear_gradients(params): + for p in params.all(): + p.d.fill(0) + + +def clip_gradients(params): + for p in params.all(): + np.clip(p.d, -1, 1, out=p.d) + + +def forward_backward( + inputs, targets, h_prev, C_prev, T_steps, H_size, X_size, parameters +): + # To store the values for each time step + x_s, z_s, f_s, i_s, = ( + {}, + {}, + {}, + {}, + ) + C_bar_s, C_s, o_s, h_s = {}, {}, {}, {} + v_s, y_s = {}, {} + + # Values at t - 1 + h_s[-1] = np.copy(h_prev) + C_s[-1] = np.copy(C_prev) + + loss = 0 + # Loop through time steps + assert len(inputs) == T_steps + for t in range(len(inputs)): + x_s[t] = np.zeros((X_size, 1)) + x_s[t][inputs[t]] = 1 # Input character + + ( + z_s[t], + f_s[t], + i_s[t], + C_bar_s[t], + C_s[t], + o_s[t], + h_s[t], + v_s[t], + y_s[t], + ) = forward( + x_s[t], h_s[t - 1], C_s[t - 1], H_size, X_size, parameters + ) # Forward pass + + loss += -np.log(y_s[t][targets[t], 0]) # Loss for at t + + clear_gradients(parameters) + + dh_next = np.zeros_like(h_s[0]) # dh from the next character + dC_next = np.zeros_like(C_s[0]) # dh from the next character + + for t in reversed(range(len(inputs))): + # Backward pass + dh_next, dC_next = backward( + target=targets[t], + dh_next=dh_next, + dC_next=dC_next, + C_prev=C_s[t - 1], + H_size=H_size, + X_size=X_size, + z=z_s[t], + f=f_s[t], + i=i_s[t], + C_bar=C_bar_s[t], + C=C_s[t], + o=o_s[t], + h=h_s[t], + v=v_s[t], + y=y_s[t], + p=parameters, + ) + + clip_gradients(parameters) + + return loss, h_s[len(inputs) - 1], C_s[len(inputs) - 1] + + +def update_parameters(learning_rate, params): + for p in params.all(): + p.m += p.d * p.d # Calculate sum of gradients + # print(learning_rate * dparam) + p.v += -(learning_rate * p.d / np.sqrt(p.m + 1e-8)) + + +def update_status(iteration, smooth_loss): + print("iter %d, loss %f" % (iteration, smooth_loss)) + + +def run_lstm( + file_name, + H_size, + T_steps, + max_iters, + learning_rate, + weight_sd, + dump, + timing, +): + with open(file_name, "r") as f: + data = f.read() + chars = list(set(data)) + data_size, X_size = len(data), len(chars) + print("data has %d characters, %d unique" % (data_size, X_size)) + char_to_idx = {ch: i for i, ch in enumerate(chars)} + + z_size = H_size + X_size # Size of concatenate(H, X) vector + + parameters = Parameters(H_size, X_size, z_size, weight_sd) + + # Exponential average of loss + # Initialize to a error of a random model + smooth_loss = -np.log(1.0 / X_size) * T_steps + + pointer = 0 + + start = datetime.datetime.now() + + for iteration in range(max_iters): + # Reset + if pointer + T_steps >= len(data) or iteration == 0: + g_h_prev = np.zeros((H_size, 1)) + g_C_prev = np.zeros((H_size, 1)) + pointer = 0 + + inputs = [char_to_idx[ch] for ch in data[pointer : pointer + T_steps]] + targets = [ + char_to_idx[ch] for ch in data[pointer + 1 : pointer + T_steps + 1] + ] + + loss, g_h_prev, g_C_prev = forward_backward( + inputs, + targets, + g_h_prev, + g_C_prev, + T_steps, + H_size, + X_size, + parameters, + ) + smooth_loss = smooth_loss * 0.999 + loss * 0.001 + + # Print every hundred steps + if iteration % dump == 0: + update_status(iteration, smooth_loss) + + update_parameters(learning_rate, parameters) + + pointer += T_steps + update_status(max_iters, smooth_loss) + + stop = datetime.datetime.now() + delta = stop - start + total = delta.total_seconds() * 1000.0 + if timing: + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-d", + "--dump", + type=int, + default=100, + dest="dump", + help="how many iterations of training between dumping output", + ) + parser.add_argument( + "-f", + "--file", + type=str, + default="input.txt", + dest="file_name", + help="input file name", + ) + parser.add_argument( + "--hidden", + type=int, + default=100, + dest="hidden", + help="size of hidden layer", + ) + parser.add_argument( + "-l", + "--loops", + type=int, + default=10000, + dest="loops", + help="maximum number of training loops to run", + ) + parser.add_argument( + "-r", + "--rate", + type=float, + default=1e-1, + dest="rate", + help="learning rate", + ) + parser.add_argument( + "-s", + "--steps", + type=int, + default=25, + dest="steps", + help="number of time steps (length of the sequence) used for training", + ) + parser.add_argument( + "-t", + "--time", + dest="timing", + action="store_true", + help="perform timing", + ) + parser.add_argument( + "-w", + "--weight", + type=float, + default=0.1, + dest="weight", + help="standard deviation of weights for initialization", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 - " + "normal execution)", + ) + args = parser.parse_args() + run_benchmark( + run_lstm, + args.benchmark, + "LSTM Full", + ( + args.file_name, + args.hidden, + args.steps, + args.loops, + args.rate, + args.weight, + args.dump, + args.timing, + ), + ) diff --git a/examples/stencil.py b/examples/stencil.py new file mode 100644 index 000000000..7794255e4 --- /dev/null +++ b/examples/stencil.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +from benchmark import run_benchmark + +import legate.numpy as np + + +def initialize(N): + print("Initializing stencil grid...") + grid = np.zeros((N + 2, N + 2)) + grid[:, 0] = -273.15 + grid[:, -1] = -273.15 + grid[-1, :] = -273.15 + grid[0, :] = 40.0 + return grid + + +def run(grid, I, N): # noqa: E741 + print("Running Jacobi stencil...") + center = grid[1:-1, 1:-1] + north = grid[0:-2, 1:-1] + east = grid[1:-1, 2:] + west = grid[1:-1, 0:-2] + south = grid[2:, 1:-1] + for i in range(I): + average = center + north + east + west + south + work = 0.2 * average + # delta = np.sum(np.absolute(work - center)) + center[:] = work + total = np.sum(center) + return total / (N ** 2) + + +def run_stencil(N, I, timing): # noqa: E741 + start = datetime.datetime.now() + grid = initialize(N) + average = run(grid, I, N) + # This will sync the timing because we will need to wait for the result + assert not math.isnan(average) + stop = datetime.datetime.now() + print("Average energy is %.8g" % average) + delta = stop - start + total = delta.total_seconds() * 1000.0 + if timing: + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-i", + "--iter", + type=int, + default=100, + dest="I", + help="number of iterations to run", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=100, + dest="N", + help="number of elements in one dimension", + ) + parser.add_argument( + "-t", + "--time", + dest="timing", + action="store_true", + help="perform timing", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 " + "- normal execution)", + ) + args = parser.parse_args() + run_benchmark( + run_stencil, args.benchmark, "Stencil", (args.N, args.I, args.timing) + ) diff --git a/examples/wgrad.py b/examples/wgrad.py new file mode 100644 index 000000000..9140a3222 --- /dev/null +++ b/examples/wgrad.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +import legate.numpy as np + + +def initialize(C, K, B, H, W): + x = np.random.randn(C, B, H, W) + y = np.random.randn(K, B, H, W) + return x, y + + +def cross_correlate(x, y, C, K, R, S, B, H, W): + dw = np.zeros(shape=(R, S, C, K)) + # cross-correlate images to compute weight gradients + y_pad = np.zeros(shape=(K, B, H + R - 1, W + S - 1)) + y_pad[:, :, R / 2 : -(R / 2), S / 2 : -(S / 2)] = y + for r in range(R): + for s in range(S): + y_shift = y_pad[:, :, r : r + H, s : s + W] + for c in range(C): + for k in range(K): + dw[r, s, c, k] = np.sum( + x[c, :, :, :] * y_shift[k, :, :, :] + ) + return dw + + +def run_wgrad(H=256, W=256, B=32, C=256, K=32, R=5, S=5, timing=False): + if timing: + start = datetime.datetime.now() + x, y = initialize(C, K, B, H, W) + dw = cross_correlate(x, y, C, K, R, S, B, H, W) + # Do a little sum over dw to sync the results + total = np.sum(dw) + assert not math.isnan(total) + if timing: + stop = datetime.datetime.now() + delta = stop - start + print("Elapsed Time: " + str(delta.total_seconds() * 1000.0) + " ms") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-b", "--batch", type=int, default=32, dest="B", help="batch size" + ) + parser.add_argument( + "--height", + type=int, + default=256, + dest="H", + help="height of images in pixels", + ) + parser.add_argument( + "-i", "--input", type=int, default=256, dest="C", help="input channels" + ) + parser.add_argument( + "-o", + "--output", + type=int, + default=32, + dest="K", + help="output channels", + ) + parser.add_argument( + "-r", + "--radix", + type=int, + default=5, + dest="R", + help="convolution radix", + ) + parser.add_argument( + "-t", + "--time", + dest="timing", + action="store_true", + help="perform timing", + ) + parser.add_argument( + "-w", + "--width", + type=int, + default=256, + dest="W", + help="width of images in pixels", + ) + args = parser.parse_args() + run_wgrad( + args.H, args.W, args.B, args.C, args.K, args.R, args.R, args.timing + ) From 983985a13a5b93f022868e29c9de7a2984d809fc Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Thu, 14 Oct 2021 15:05:55 -0700 Subject: [PATCH 10/46] partial fusion --- build.sh | 4 ++-- legate/numpy/deferred.py | 5 +++++ src/fused/binary_op_template.inl | 4 ++-- src/fused/fused_op.cc | 25 +++++++++++++++++++------ 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/build.sh b/build.sh index 1c3802966..6024105a4 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ #touch src/matrix/matvecmul.cc #touch src/fused/fused_op.cc cd ../legate.core/ -python setup.py --no-cuda +python setup.py --no-cuda cd ../legate.numpy/ -python setup.py --with-core /Users/shivsundram/Desktop/coding/legate/legate.core/install/ --with-openblas /usr/local/opt/openblas/ -j 4 --verbose +python setup.py --with-core ~/legate/legate.core/install/ --verbose #../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/legate/numpy/deferred.py b/legate/numpy/deferred.py index 2bf2ef98d..4144da473 100644 --- a/legate/numpy/deferred.py +++ b/legate/numpy/deferred.py @@ -1460,6 +1460,11 @@ def binary_op( # Populate the Legate launcher all_scalar_rhs = rhs1.scalar and rhs2.scalar + + if (src1.scalar): + print("is scalar") + print("is_ready", src1.base.storage.is_ready()) + if all_scalar_rhs: task_id = NumPyOpCode.SCALAR_BINARY_OP else: diff --git a/src/fused/binary_op_template.inl b/src/fused/binary_op_template.inl index 10e538033..9e72d2d7b 100644 --- a/src/fused/binary_op_template.inl +++ b/src/fused/binary_op_template.inl @@ -116,8 +116,8 @@ static void binary_op_template(TaskContext& context) int inputStart=0; int outputStart=0; - - for (int i=0; i(), std::move(extra_args)}; diff --git a/src/fused/fused_op.cc b/src/fused/fused_op.cc index 0142f85f2..49124b74c 100644 --- a/src/fused/fused_op.cc +++ b/src/fused/fused_op.cc @@ -21,6 +21,7 @@ #include #include #include +#include namespace legate { namespace numpy { @@ -131,13 +132,15 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) int nOps = context.fusionMetadata.nOps; //struct timeval start, end; MakeshiftSerializer ms; - //gettimeofday(&start, NULL); - + //VariantID chosen_variant = 0; + //Legion::Internal::VariantImpl* variant_impl = context.runtime_->find_variant(1074141829, 0); + //bool isLeaf = variant_impl->is_leaf(); + auto opIDs = context.fusionMetadata.opIDs; for (int i=0; iindex_point; @@ -148,13 +151,23 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) auto& req = context.task_->regions[reqIdx]; leaf_launcher.add_region_requirement(req); } + //add appropriate futures + auto futureStarts = context.fusionMetadata.futureStarts; + for (int32_t fuid = futureStarts[i]; fuidfutures[fuid]; + leaf_launcher.add_future(f); + } + context.runtime_->execute_task(context.context_, leaf_launcher); + //gettimeofday(&start, NULL); + //binary_op_template(context); + //gettimeofday(&end, NULL); + // printf("%ld\n", ((end.tv_sec * 1000000 + end.tv_usec) +// - (start.tv_sec * 1000000 + start.tv_usec))); } - //gettimeofday(&end, NULL); //gettimeofday(&end, NULL); - //printf("%ld\n", ((end.tv_sec * 1000000 + end.tv_usec) -// - (start.tv_sec * 1000000 + start.tv_usec))); } From caac1ee5534c1d44646d199e2bd99104b6d33b8b Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Thu, 14 Oct 2021 18:47:16 -0700 Subject: [PATCH 11/46] finishing merge --- legate/numpy/config.py | 1 - src/fused/binary_op.h | 4 +- src/legate_numpy_c.h | 96 -------------------------------------- src/numpy.mk | 8 ++-- src/numpy/legate_numpy_c.h | 2 + 5 files changed, 7 insertions(+), 104 deletions(-) delete mode 100644 src/legate_numpy_c.h diff --git a/legate/numpy/config.py b/legate/numpy/config.py index 1bbcfaaed..ac7eb8431 100644 --- a/legate/numpy/config.py +++ b/legate/numpy/config.py @@ -113,7 +113,6 @@ class NumPyOpCode(IntEnum): UNARY_RED = legate_numpy.NUMPY_UNARY_RED WHERE = legate_numpy.NUMPY_WHERE WRITE = legate_numpy.NUMPY_WRITE - NONZERO = legate_numpy.NUMPY_NONZERO DOUBLE_BINARY_OP = legate_numpy.NUMPY_DOUBLE_BINARY_OP FUSED_OP = legate_numpy.NUMPY_FUSED_OP diff --git a/src/fused/binary_op.h b/src/fused/binary_op.h index 2e6cadb24..778ad3a84 100644 --- a/src/fused/binary_op.h +++ b/src/fused/binary_op.h @@ -21,7 +21,7 @@ namespace legate { namespace numpy { - +/* struct BinaryOpArgs { const Array& in1; const Array& in2; @@ -29,7 +29,7 @@ struct BinaryOpArgs { BinaryOpCode op_code; std::vector args; }; - +*/ class FusedOpTask : public NumPyTask { public: static const int TASK_ID = NUMPY_FUSED_OP; diff --git a/src/legate_numpy_c.h b/src/legate_numpy_c.h deleted file mode 100644 index 6fcdb2aaa..000000000 --- a/src/legate_numpy_c.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#ifndef __LEGATE_NUMPY_C_H__ -#define __LEGATE_NUMPY_C_H__ - -#include "legate_preamble.h" - -// Match these to NumPyOpCode in legate/numpy/config.py -enum NumPyOpCode { - NUMPY_BINARY_OP = 400000, - NUMPY_SCALAR_BINARY_OP = 400002, - NUMPY_FILL = 400003, - NUMPY_SCALAR_UNARY_RED = 400004, - NUMPY_UNARY_RED = 400005, - NUMPY_UNARY_OP = 400006, - NUMPY_SCALAR_UNARY_OP = 400007, - NUMPY_BINARY_RED = 400008, - NUMPY_CONVERT = 400010, - NUMPY_SCALAR_CONVERT = 400011, - NUMPY_WHERE = 400012, - NUMPY_SCALAR_WHERE = 400013, - NUMPY_READ = 400014, - NUMPY_WRITE = 400015, - NUMPY_DIAG = 400016, - NUMPY_MATMUL = 400017, - NUMPY_MATVECMUL = 400018, - NUMPY_DOT = 400019, - NUMPY_BINCOUNT = 400020, - NUMPY_EYE = 400021, - NUMPY_RAND = 400022, - NUMPY_ARANGE = 400023, - NUMPY_TRANSPOSE = 400024, - NUMPY_TILE = 400025, - NUMPY_NONZERO = 400026, - NUMPY_DOUBLE_BINARY_OP = 400027, - NUMPY_FUSED_OP = 400028, -}; - -// Match these to NumPyRedopCode in legate/numpy/config.py -enum NumPyRedopID { - NUMPY_ARGMIN_REDOP = LEGION_REDOP_KIND_TOTAL + 1, - NUMPY_ARGMAX_REDOP, - NUMPY_SCALAR_MAX_REDOP = 500, - NUMPY_SCALAR_MIN_REDOP = 501, - NUMPY_SCALAR_PROD_REDOP = 502, - NUMPY_SCALAR_SUM_REDOP = 503, - NUMPY_SCALAR_ARGMAX_REDOP = 504, - NUMPY_SCALAR_ARGMIN_REDOP = 505, -}; - -// Match these to NumPyMappingTag in legate/numpy/config.py -enum NumPyTag { - NUMPY_SUBRANKABLE_TAG = 0x1, - NUMPY_CPU_ONLY_TAG = 0x2, - NUMPY_GPU_ONLY_TAG = 0x4, - NUMPY_NO_MEMOIZE_TAG = 0x8, - NUMPY_KEY_REGION_TAG = 0x10, -}; - -// Match these to NumPyTunable in legate/numpy/config.py -enum NumPyTunable { - NUMPY_TUNABLE_NUM_GPUS = 1, - NUMPY_TUNABLE_MAX_EAGER_VOLUME = 2, -}; - -enum NumPyBounds { - NUMPY_MAX_MAPPERS = 1, - NUMPY_MAX_REDOPS = 1024, - NUMPY_MAX_TASKS = 1048576, -}; - -#ifdef __cplusplus -extern "C" { -#endif - -void legate_numpy_perform_registration(); - -#ifdef __cplusplus -} -#endif - -#endif // __LEGATE_NUMPY_C_H__ diff --git a/src/numpy.mk b/src/numpy.mk index a846e57b2..d4c3de924 100644 --- a/src/numpy.mk +++ b/src/numpy.mk @@ -11,15 +11,13 @@ # 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. -# double_binary/double_binary_op.cc -#double_binary/double_binary_op_omp.cc -#double_binary/double_binary_op.cu # + # List all the application source files that need OpenMP separately # since we have to add the -fopenmp flag to CC_FLAGS for them GEN_CPU_SRC += numpy/ternary/where.cc \ - fused/fused_op.cc \ numpy/binary/binary_op.cc \ + numpy/fused/fused_op.cc \ numpy/binary/binary_red.cc \ numpy/unary/scalar_unary_red.cc \ numpy/unary/unary_op.cc \ @@ -48,8 +46,8 @@ GEN_CPU_SRC += numpy/ternary/where.cc \ ifeq ($(strip $(USE_OPENMP)),1) GEN_CPU_SRC += numpy/ternary/where_omp.cc \ - fused/fused_op_omp.cc \ numpy/binary/binary_op_omp.cc \ + numpy/fused/fused_op_omp.cc \ numpy/binary/binary_red_omp.cc \ numpy/unary/unary_op_omp.cc \ numpy/unary/scalar_unary_red_omp.cc \ diff --git a/src/numpy/legate_numpy_c.h b/src/numpy/legate_numpy_c.h index 7ac7894ec..bccde6ba3 100644 --- a/src/numpy/legate_numpy_c.h +++ b/src/numpy/legate_numpy_c.h @@ -42,6 +42,8 @@ enum NumPyOpCode { NUMPY_UNARY_RED = 19, NUMPY_WHERE = 20, NUMPY_WRITE = 21, + NUMPY_DOUBLE_BINARY_OP = 23, + NUMPY_FUSED_OP = 24, }; // Match these to NumPyRedopCode in legate/numpy/config.py From ba128b139e24230055fbcbce29e18848a98ab0d2 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Mon, 25 Oct 2021 14:34:18 -0700 Subject: [PATCH 12/46] op registry working --- build.sh | 4 +-- examples/black_scholes.py | 19 +++++++------- examples/stencil.py | 3 ++- legate/numpy/array.py | 54 ++++++++++++++++++++++++++------------- legate/numpy/deferred.py | 4 ++- legate/numpy/runtime.py | 4 +++ src/fused/fused_op.cc | 2 ++ 7 files changed, 59 insertions(+), 31 deletions(-) diff --git a/build.sh b/build.sh index 6024105a4..03eb5e764 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ #touch src/matrix/matvecmul.cc #touch src/fused/fused_op.cc cd ../legate.core/ -python setup.py --no-cuda +python setup.py --no-cuda cd ../legate.numpy/ -python setup.py --with-core ~/legate/legate.core/install/ --verbose +python setup.py --with-core ~/legate/legate.core/install/ --verbose #../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/examples/black_scholes.py b/examples/black_scholes.py index d38cf5b4b..1fbb19478 100644 --- a/examples/black_scholes.py +++ b/examples/black_scholes.py @@ -64,13 +64,10 @@ def cnd(d): def black_scholes(S, X, T, R, V): sqrt_t = np.sqrt(T) - #d1 = np.log(S / X) + (R + 0.5 * V * V) * T / (V * sqrt_t) - d1a = np.log(S / X) - d1b = (R + 0.5 * V * V) - d1c = d1b*T - d1d = d1c/(V * sqrt_t) - d1 = d1a+d1d - + sqrt_t = np.sqrt(T) + sqrt_t = np.sqrt(T) + sqrt_t = np.sqrt(T) + d1 = np.log(S / X) + (R + 0.5 * V * V) * T / (V * sqrt_t) d2 = d1 - V * sqrt_t cnd_d1 = cnd(d1) cnd_d2 = cnd(d2) @@ -81,19 +78,23 @@ def black_scholes(S, X, T, R, V): def run_black_scholes(N, D): - print("Running black scholes on %dK options..." % N) + #print("Running black scholes on %dK options..." % N) N *= 1000 start = datetime.datetime.now() S, X, T, R, V = initialize(N, D) call, put = black_scholes(S, X, T, R, V) # Check the result for NaNs to synchronize before stopping timing call_sum = np.sum(call) + call_sum2 = np.sum(call) put_sum = np.sum(put) + put_sum2 = np.sum(put) + #print(call_sum, put_sum) + #print(call_sum2, put_sum2) assert not math.isnan(call_sum) and not math.isnan(put_sum) stop = datetime.datetime.now() delta = stop - start total = delta.total_seconds() * 1000.0 - print("Elapsed Time: " + str(total) + " ms") + #print("Elapsed Time: " + str(total) + " ms") return total diff --git a/examples/stencil.py b/examples/stencil.py index 7794255e4..1826baac4 100644 --- a/examples/stencil.py +++ b/examples/stencil.py @@ -44,11 +44,12 @@ def run(grid, I, N): # noqa: E741 west = grid[1:-1, 0:-2] south = grid[2:, 1:-1] for i in range(I): - average = center + north + east + west + south + average = center + north + south + east + west work = 0.2 * average # delta = np.sum(np.absolute(work - center)) center[:] = work total = np.sum(center) + #return total return total / (N ** 2) diff --git a/legate/numpy/array.py b/legate/numpy/array.py index 6f4e51344..12fd2f3a2 100644 --- a/legate/numpy/array.py +++ b/legate/numpy/array.py @@ -2132,26 +2132,44 @@ def perform_binary_op( if one.dtype != two.dtype: common_type = cls.find_common_type(one, two) if one.dtype != common_type: - temp = ndarray( - shape=one.shape, - dtype=common_type, - stacklevel=(stacklevel + 1), - inputs=(one, two, where), - ) - temp._thunk.convert( - one._thunk, stacklevel=(stacklevel + 1) - ) + if one.shape==(): + temp = ndarray( + shape=one.shape, + dtype=common_type, + buffer = one._thunk.array.astype(common_type), + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + else: + temp = ndarray( + shape=one.shape, + dtype=common_type, + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + temp._thunk.convert( + one._thunk, stacklevel=(stacklevel + 1) + ) one = temp if two.dtype != common_type: - temp = ndarray( - shape=two.shape, - dtype=common_type, - stacklevel=(stacklevel + 1), - inputs=(one, two, where), - ) - temp._thunk.convert( - two._thunk, stacklevel=(stacklevel + 1) - ) + if two.shape==(): + temp = ndarray( + shape=two.shape, + dtype=common_type, + buffer = two._thunk.array.astype(common_type), + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + else: + temp = ndarray( + shape=two.shape, + dtype=common_type, + stacklevel=(stacklevel + 1), + inputs=(one, two, where), + ) + temp._thunk.convert( + two._thunk, stacklevel=(stacklevel + 1) + ) two = temp if out.dtype != out_dtype: temp = ndarray( diff --git a/legate/numpy/deferred.py b/legate/numpy/deferred.py index 1316c5bf0..77d78bdfe 100644 --- a/legate/numpy/deferred.py +++ b/legate/numpy/deferred.py @@ -248,6 +248,9 @@ def __numpy_array__(self, stacklevel=0): return np.empty(shape=self.shape, dtype=self.dtype) if self.scalar: + if not self.base._storage: + self.runtime.legate_runtime._launch_outstanding() + result = np.full( self.shape, self.get_scalar_array(stacklevel=(stacklevel + 1)), @@ -1529,7 +1532,6 @@ def binary_op( task.add_alignment(lhs, rhs1) task.add_alignment(lhs, rhs2) - task.execute() @profile diff --git a/legate/numpy/runtime.py b/legate/numpy/runtime.py index d552c577c..0fca71766 100644 --- a/legate/numpy/runtime.py +++ b/legate/numpy/runtime.py @@ -394,6 +394,8 @@ def compute_parent_child_mapping(array): assert child_ptr >= parent_ptr ptr_diff = child_ptr - parent_ptr parent_shape = array.base.shape + if parent_shape==(): + parent_shape = [1] div = ( reduce(lambda x, y: x * y, parent_shape) if len(parent_shape) > 1 @@ -500,6 +502,7 @@ def find_or_create_array_thunk( ): if array.size == 1 and not share: # This is a single value array + import pdb; pdb.set_trace() result = self.create_scalar( array.data, array.dtype, @@ -545,6 +548,7 @@ def create_empty_thunk(self, shape, dtype, inputs=None): store = self.legate_context.create_store( dtype, shape=shape, optimize_scalar=True ) + result = DeferredArray(self, store, dtype=dtype) # If we're doing shadow debug make an EagerArray shadow if self.shadow_debug: diff --git a/src/fused/fused_op.cc b/src/fused/fused_op.cc index 49124b74c..fa3a4c7b5 100644 --- a/src/fused/fused_op.cc +++ b/src/fused/fused_op.cc @@ -138,6 +138,7 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) auto opIDs = context.fusionMetadata.opIDs; for (int i=0; i reqIds = ms.getReqIds(); for (int32_t reqIdx : reqIds) { + std::cout<<"req "<regions[reqIdx]; leaf_launcher.add_region_requirement(req); } From 5bc9d7bc8ee7998066f4e2e491edad0a04c22520 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Mon, 25 Oct 2021 15:27:03 -0700 Subject: [PATCH 13/46] add new fused dir --- src/numpy/fused/binary_op.cu | 79 ++++++ src/numpy/fused/binary_op.h | 48 ++++ src/numpy/fused/binary_op_template.inl | 151 ++++++++++++ src/numpy/fused/binary_op_util.h | 322 +++++++++++++++++++++++++ src/numpy/fused/fused_op.cc | 246 +++++++++++++++++++ src/numpy/fused/fused_op_omp.cc | 62 +++++ 6 files changed, 908 insertions(+) create mode 100644 src/numpy/fused/binary_op.cu create mode 100644 src/numpy/fused/binary_op.h create mode 100644 src/numpy/fused/binary_op_template.inl create mode 100644 src/numpy/fused/binary_op_util.h create mode 100644 src/numpy/fused/fused_op.cc create mode 100644 src/numpy/fused/fused_op_omp.cc diff --git a/src/numpy/fused/binary_op.cu b/src/numpy/fused/binary_op.cu new file mode 100644 index 000000000..a83792b69 --- /dev/null +++ b/src/numpy/fused/binary_op.cu @@ -0,0 +1,79 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "binary/binary_op.h" +#include "binary_op_template.inl" + +#include "cuda_help.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) + dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + out[idx] = func(in1[idx], in2[idx]); +} + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( + size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + auto point = pitches.unflatten(idx, rect.lo); + out[point] = func(in1[point], in2[point]); +} + +template +struct BinaryOpImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + size_t volume = rect.volume(); + const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); + } else { + generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); + } + } +}; + +/*static*/ void BinaryOpTask::gpu_variant(TaskContext& context) +{ + binary_op_template(context); +} + +} // namespace numpy +} // namespace legate diff --git a/src/numpy/fused/binary_op.h b/src/numpy/fused/binary_op.h new file mode 100644 index 000000000..61947551b --- /dev/null +++ b/src/numpy/fused/binary_op.h @@ -0,0 +1,48 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy/numpy.h" +#include "numpy/binary/binary_op_util.h" + +namespace legate { +namespace numpy { + +struct BinaryOpArgs { + const Array& in1; + const Array& in2; + const Array& out; + BinaryOpCode op_code; + std::vector args; +}; + +class FusedOpTask : public NumPyTask { + public: + static const int TASK_ID = NUMPY_FUSED_OP; + + public: + static void cpu_variant(TaskContext& context); +#ifdef LEGATE_USE_OPENMP + static void omp_variant(TaskContext& context); +#endif +#ifdef LEGATE_USE_CUDA + static void gpu_variant(TaskContext& context); +#endif +}; + +} // namespace numpy +} // namespace legate diff --git a/src/numpy/fused/binary_op_template.inl b/src/numpy/fused/binary_op_template.inl new file mode 100644 index 000000000..8db132212 --- /dev/null +++ b/src/numpy/fused/binary_op_template.inl @@ -0,0 +1,151 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "numpy/binary/binary_op_util.h" +#include "numpy/pitches.h" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryOpImplBody; + +template +struct BinaryOpImpl { + template ::valid>* = nullptr> + void operator()(BinaryOpArgs& args) const + { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + auto rect = args.out.shape(); + + Pitches pitches; + size_t volume = pitches.flatten(rect); + + if (volume == 0) return; + std::cout<<"rect1 "<()<()<(rect); + auto in1 = args.in1.read_accessor(rect); + auto in2 = args.in2.read_accessor(rect); + +#ifndef LEGION_BOUNDS_CHECKS + // Check to see if this is dense or not + bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && + in2.accessor.is_dense_row_major(rect); +#else + // No dense execution if we're doing bounds checks + bool dense = false; +#endif + + OP func{args.args}; + BinaryOpImplBody()(func, out, in1, in2, pitches, rect, dense); + } + + template ::valid>* = nullptr> + void operator()(BinaryOpArgs& args) const + { + assert(false); + } +}; + +template +struct BinaryOpDispatch { + template + void operator()(BinaryOpArgs& args) const + { + auto dim = std::max(1, args.out.dim()); + double_dispatch(dim, args.in1.code(), BinaryOpImpl{}, args); + } +}; + +template +static void binary_op_template(TaskContext& context) +{ + /* + auto& inputs = context.inputs(); + auto& outputs = context.outputs(); + auto& scalars = context.scalars(); + + std::vector extra_args; + for (size_t idx = 2; idx < inputs.size(); ++idx) extra_args.push_back(std::move(inputs[idx])); + + BinaryOpArgs args{ + inputs[0], inputs[1], outputs[0], scalars[0].value(), std::move(extra_args)}; + op_dispatch(args.op_code, BinaryOpDispatch{}, args); + */ + auto& inputs = context.inputs(); + auto& outputs = context.outputs(); + auto& scalars = context.scalars(); +/* + std::vector extra_args; + for (size_t idx = 2; idx < inputs.size(); ++idx) + extra_args.push_back(inputs[idx].scalar()); + std::cout<<"extra args size"<(), std::move(extra_args)}; + op_dispatch(args.op_code, BinaryOpDispatch{}, args); +*/ + //std::cout<<"fused inputs"<().hi.x; + //std::cout<<"nops "<(); + auto opcode_i = static_cast::type>(opcode); + //std::cout<<"opcode "<().lo.x<<" "<().hi.x< extra_args; + //for (size_t idx = 3; idx < inputs.size(); ++idx) + // extra_args.push_back(inputs[idx].scalar()); + + int inputStart=0; + int outputStart=0; + + for (int i=0; i(), std::move(extra_args)}; + std::cout<<"dispatching "<{}, args); + inputStart+=2; + outputStart+=1; + } + + +} + +} // namespace numpy +} // namespace legate diff --git a/src/numpy/fused/binary_op_util.h b/src/numpy/fused/binary_op_util.h new file mode 100644 index 000000000..c109bbb78 --- /dev/null +++ b/src/numpy/fused/binary_op_util.h @@ -0,0 +1,322 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "numpy/numpy.h" + +namespace legate { +namespace numpy { + +enum class BinaryOpCode : int { + ADD = 1, + DIVIDE, + EQUAL, + FLOOR_DIVIDE, + GREATER, + GREATER_EQUAL, + LESS, + LESS_EQUAL, + MAXIMUM, + MINIMUM, + MOD, + MULTIPLY, + NOT_EQUAL, + POWER, + SUBTRACT, + ALLCLOSE, +}; + +template +constexpr decltype(auto) op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) +{ + switch (op_code) { + case BinaryOpCode::ADD: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::DIVIDE: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::FLOOR_DIVIDE: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::GREATER: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::GREATER_EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::LESS: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::LESS_EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MAXIMUM: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MINIMUM: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MOD: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::MULTIPLY: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::NOT_EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::POWER: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::SUBTRACT: + return f.template operator()(std::forward(args)...); + default: break; + } + assert(false); + return f.template operator()(std::forward(args)...); +} + +template +constexpr decltype(auto) reduce_op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) +{ + switch (op_code) { + case BinaryOpCode::EQUAL: + return f.template operator()(std::forward(args)...); + case BinaryOpCode::ALLCLOSE: + return f.template operator()(std::forward(args)...); + default: break; + } + assert(false); + return f.template operator()(std::forward(args)...); +} + +template +struct BinaryOp { + static constexpr bool valid = false; +}; + +template +struct BinaryOp : std::plus> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::divides> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::equal_to> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +using std::floor; +template +struct BinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return floor(a / b); } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = false; + BinaryOp(const std::vector& args) {} +}; + +template <> +struct BinaryOp { + static constexpr bool valid = false; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::greater> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::greater_equal> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::less> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::less_equal> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return std::max(a, b); } +}; + +template +struct BinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} + constexpr T operator()(const T& a, const T& b) const { return std::min(a, b); } +}; + +template +constexpr T real_mod(const T& a, const T& b) +{ + T res = std::fmod(a, b); + if (res) { + if ((b < static_cast(0)) != (res < static_cast(0))) res += b; + } else { + res = std::copysign(static_cast(0), b); + } + return res; +} + +template +struct BinaryOp { + using T = legate_type_of; + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} + template ::value>* = nullptr> + constexpr _T operator()(const _T& a, const _T& b) const + { + return a % b; + } + + template ::value>* = nullptr> + constexpr _T operator()(const _T& a, const _T& b) const + { + return real_mod(a, b); + } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const + { + return static_cast<__half>(real_mod(static_cast(a), static_cast(b))); + } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = false; + BinaryOp(const std::vector& args) {} +}; + +template <> +struct BinaryOp { + static constexpr bool valid = false; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::multiplies> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp : std::not_equal_to> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp { + using VAL = legate_type_of; + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} + constexpr VAL operator()(const VAL& a, const VAL& b) const { return std::pow(a, b); } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const + { + return pow(a, b); + } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX complex operator()(const complex& a, + const complex& b) const + { + return pow(a, b); + } +}; + +template <> +struct BinaryOp { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} + LEGATE_DEVICE_PREFIX complex operator()(const complex& a, + const complex& b) const + { + return pow(a, b); + } +}; + +template +struct BinaryOp : std::minus> { + static constexpr bool valid = true; + BinaryOp(const std::vector& args) {} +}; + +template +struct BinaryOp { + using VAL = legate_type_of; + static constexpr bool valid = true; + + BinaryOp(const std::vector& args) + { + assert(args.size() == 2); + rtol_ = args[0].scalar(); + atol_ = args[1].scalar(); + } + + template ::value>* = nullptr> + constexpr bool operator()(const T& a, const T& b) const + { + using std::fabs; + return fabs(static_cast(a) - static_cast(b)) <= + atol_ + rtol_ * static_cast(fabs(b)); + } + + template ::value>* = nullptr> + constexpr bool operator()(const T& a, const T& b) const + { + return static_cast(abs(a - b)) <= atol_ + rtol_ * static_cast(abs(b)); + } + + double rtol_{0}; + double atol_{0}; +}; + +} // namespace numpy +} // namespace legate diff --git a/src/numpy/fused/fused_op.cc b/src/numpy/fused/fused_op.cc new file mode 100644 index 000000000..4aaec0ced --- /dev/null +++ b/src/numpy/fused/fused_op.cc @@ -0,0 +1,246 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "core/utilities/makeshift_serializer.h" +#include "core/runtime/runtime.h" +#include "core/runtime/context.h" +#include "numpy/fused/binary_op.h" +#include "numpy/fused/binary_op_template.inl" +#include "legion.h" +#include +#include +#include +#include + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryOpImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + const size_t volume = rect.volume(); + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); + } else { + for (size_t idx = 0; idx < volume; ++idx) { + auto p = pitches.unflatten(idx, rect.lo); + out[p] = func(in1[p], in2[p]); + } + } + } +}; + + + +//op id refers not to the op's type, but the index in the list of fused ops +void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) +{ + auto inputStarts = context.fusionMetadata.inputStarts; + auto outputStarts = context.fusionMetadata.outputStarts; + auto offsetStarts = context.fusionMetadata.offsetStarts; + auto offsets = context.fusionMetadata.offsets; + auto reductionStarts = context.fusionMetadata.reductionStarts; + auto scalarStarts = context.fusionMetadata.scalarStarts; + + //the leaf task cannot be fused ops currently + ms.pack((bool) false); + + //pack inputs + unsigned nInputs = (inputStarts[opID+1]-inputStarts[opID]); //want to pack this as a 32 bit uint + ms.pack((uint32_t) nInputs); + //std::cout<<"inputs "<0) + { + bufferID--; + //std::cout<<"packing input "<index_point; + //add appropriate region requirements for this op + std::vector reqIds = ms.getReqIds(); + for (int32_t reqIdx : reqIds) + { + auto& req = context.task_->regions[reqIdx]; + leaf_launcher.add_region_requirement(req); + } + //add appropriate futures + auto futureStarts = context.fusionMetadata.futureStarts; + for (int32_t fuid = futureStarts[i]; fuidfutures[fuid]; + leaf_launcher.add_future(f); + } + + */ + std::vector regions; + //for (int k : reqIds) + { + //regions.push_back(context.regions_[k]); + } + + //context.runtime_->execute_task(context.context_, leaf_launcher); + + //create new context + const Legion::Task* task = (Legion::Task*) context.task_; + + //pack inputs + std::vector inputs; + auto inputStarts = context.fusionMetadata.inputStarts; + auto outputStarts = context.fusionMetadata.outputStarts; + auto offsetStarts = context.fusionMetadata.offsetStarts; + unsigned nInputs = (inputStarts[i+1]-inputStarts[i]); //want to pack this as a 32 bit uint + for (unsigned j = 0; j outputs; + unsigned nOutputs = (outputStarts[i+1]-outputStarts[i]); //want to pack this as a 32 bit uint + for (unsigned j = 0; j scalars; + auto scalarStarts = context.fusionMetadata.scalarStarts; + int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); + for (unsigned j = 0; j outputs; + outputs.push_back(std::move(context.outputs()[i+0])); + */ + std::vector scalars; + scalars.push_back(std::move(context.scalars()[i+0])); + + TaskContext context3(task, (const std::vector) regions);// inputs, outputs, scalars); + context3.inputs_ = std::move(inputs); + context3.outputs_ = std::move(outputs); + context3.scalars_ = std::move(scalars); + + //launch + auto descp = Core::cpuDescriptors.find(opIDs[i]); + auto desc = descp->second; + desc(context3); + + //move it back?? + //context.outputs_[i] = std::move(context3.outputs_[i]); + + //binary_op_template(context); + //gettimeofday(&start, NULL); + //gettimeofday(&end, NULL); + // printf("%ld\n", ((end.tv_sec * 1000000 + end.tv_usec) +// - (start.tv_sec * 1000000 + start.tv_usec))); + } + + +} + +namespace // unnamed +{ +static void __attribute__((constructor)) register_tasks(void) { FusedOpTask::register_variants(); } +} // namespace + +} // namespace numpy +} // namespace legate diff --git a/src/numpy/fused/fused_op_omp.cc b/src/numpy/fused/fused_op_omp.cc new file mode 100644 index 000000000..0d4151442 --- /dev/null +++ b/src/numpy/fused/fused_op_omp.cc @@ -0,0 +1,62 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "fused/binary_op.h" +#include "fused/binary_op_template.inl" + +namespace legate { +namespace numpy { + +using namespace Legion; + +template +struct BinaryOpImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + const size_t volume = rect.volume(); + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); + } else { +#pragma omp parallel for schedule(static) + for (size_t idx = 0; idx < volume; ++idx) { + auto p = pitches.unflatten(idx, rect.lo); + out[p] = func(in1[p], in2[p]); + } + } + } +}; + +/*static*/ void FusedOpTask::omp_variant(TaskContext& context) +{ + binary_op_template(context); +} + +} // namespace numpy +} // namespace legate From 3c9698b52e53a6332f296caf53ca204c5a9c0503 Mon Sep 17 00:00:00 2001 From: Marcin Zalewski Date: Wed, 27 Oct 2021 14:19:33 -0700 Subject: [PATCH 14/46] Update the package version for the release --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 85cee9bce..6bdcd4b8d 100755 --- a/setup.py +++ b/setup.py @@ -74,7 +74,7 @@ def run(self): sys.argv.remove("--recurse") setup( name="cunumeric", - version="0.1", + version="21.10.00", packages=[ "cunumeric", "cunumeric.linalg", From 02d8ce6a249260a07d261e331f2dcabc2bfc3d82 Mon Sep 17 00:00:00 2001 From: Wonchan Lee Date: Wed, 27 Oct 2021 15:16:41 -0700 Subject: [PATCH 15/46] Fix #111 --- cunumeric/module.py | 2 +- tests/array_creation.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/cunumeric/module.py b/cunumeric/module.py index 9fa29f1c9..81cb02564 100644 --- a/cunumeric/module.py +++ b/cunumeric/module.py @@ -182,7 +182,7 @@ def array(obj, dtype=None, copy=True, order="K", subok=False, ndmin=0): ) array = ndarray(shape=None, stacklevel=2, thunk=thunk) else: - array = array + array = obj if dtype is not None and array.dtype != dtype: array = array.astype(dtype) elif copy and obj is array: diff --git a/tests/array_creation.py b/tests/array_creation.py index 6d0f310d1..cefd7c192 100644 --- a/tests/array_creation.py +++ b/tests/array_creation.py @@ -25,6 +25,11 @@ def test(): assert np.array_equal(x, z) assert x.dtype == z.dtype + x = num.array([1, 2, 3]) + y = num.array(x) + assert num.array_equal(x, y) + assert x.dtype == y.dtype + xe = num.empty((2, 3)) ye = np.empty((2, 3)) assert xe.shape == ye.shape From b698b3387a095d235b94226b6a1fcd58f06ed6fa Mon Sep 17 00:00:00 2001 From: Marcin Zalewski Date: Thu, 28 Oct 2021 18:56:22 -0700 Subject: [PATCH 16/46] Decrease relative tolerance in allclose for float16 values --- cunumeric/module.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cunumeric/module.py b/cunumeric/module.py index 81cb02564..d2c750065 100644 --- a/cunumeric/module.py +++ b/cunumeric/module.py @@ -627,7 +627,11 @@ def logical_not(a, out=None, where=True, dtype=None, **kwargs): @copy_docstring(np.allclose) -def allclose(a, b, rtol=1e-5, atol=1e-8, equal_nan=False): +def allclose(a, b, rtol=None, atol=1e-8, equal_nan=False): + if rtol is None and a.dtype == np.float16: + rtol = 1e-3 + elif rtol is None: + rtol = 1e-5 a_array = ndarray.convert_to_cunumeric_ndarray(a) b_array = ndarray.convert_to_cunumeric_ndarray(b) if equal_nan: @@ -644,6 +648,7 @@ def allclose(a, b, rtol=1e-5, atol=1e-8, equal_nan=False): ) + @copy_docstring(np.array_equal) def array_equal(a, b): a_array = ndarray.convert_to_cunumeric_ndarray(a) From ac314deeed09981c6c8d9860d65d84afb5249e75 Mon Sep 17 00:00:00 2001 From: Marcin Zalewski Date: Thu, 28 Oct 2021 21:00:23 -0700 Subject: [PATCH 17/46] Revert "Decrease relative tolerance in allclose for float16 values" This reverts commit b698b3387a095d235b94226b6a1fcd58f06ed6fa. --- cunumeric/module.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/cunumeric/module.py b/cunumeric/module.py index d2c750065..81cb02564 100644 --- a/cunumeric/module.py +++ b/cunumeric/module.py @@ -627,11 +627,7 @@ def logical_not(a, out=None, where=True, dtype=None, **kwargs): @copy_docstring(np.allclose) -def allclose(a, b, rtol=None, atol=1e-8, equal_nan=False): - if rtol is None and a.dtype == np.float16: - rtol = 1e-3 - elif rtol is None: - rtol = 1e-5 +def allclose(a, b, rtol=1e-5, atol=1e-8, equal_nan=False): a_array = ndarray.convert_to_cunumeric_ndarray(a) b_array = ndarray.convert_to_cunumeric_ndarray(b) if equal_nan: @@ -648,7 +644,6 @@ def allclose(a, b, rtol=None, atol=1e-8, equal_nan=False): ) - @copy_docstring(np.array_equal) def array_equal(a, b): a_array = ndarray.convert_to_cunumeric_ndarray(a) From 4167c7ac24a54f896975205dfdf93559f9359394 Mon Sep 17 00:00:00 2001 From: Marcin Zalewski Date: Thu, 28 Oct 2021 21:05:39 -0700 Subject: [PATCH 18/46] Allow greater margin of error for tensordot with float16 --- tests/tensordot.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/tensordot.py b/tests/tensordot.py index bfebfb51b..a98f15fe9 100644 --- a/tests/tensordot.py +++ b/tests/tensordot.py @@ -19,13 +19,14 @@ def test(ty): + rtol=2e-03 if ty == np.float16 else 1e-05 a = num.random.rand(3, 5, 4).astype(ty) b = num.random.rand(4, 5, 3).astype(ty) cn = np.tensordot(a, b, axes=1) c = num.tensordot(a, b, axes=1) - assert np.allclose(cn, c) + assert np.allclose(cn, c, rtol=rtol) a = num.random.rand(3, 5, 4).astype(ty) b = num.random.rand(5, 4, 3).astype(ty) @@ -33,7 +34,7 @@ def test(ty): cn = np.tensordot(a, b) c = num.tensordot(a, b) - assert np.allclose(cn, c) + assert np.allclose(cn, c, rtol=rtol) a = num.arange(60.0).reshape((3, 4, 5)).astype(ty) b = num.arange(24.0).reshape((4, 3, 2)).astype(ty) @@ -41,7 +42,7 @@ def test(ty): cn = np.tensordot(a, b, axes=([1, 0], [0, 1])) c = num.tensordot(a, b, axes=([1, 0], [0, 1])) - assert np.allclose(cn, c) + assert np.allclose(cn, c, rtol=rtol) a = num.random.rand(5, 4).astype(ty) b = num.random.rand(4, 5).astype(ty) @@ -49,7 +50,7 @@ def test(ty): cn = np.tensordot(a, b, axes=1) c = num.tensordot(a, b, axes=1) - assert np.allclose(cn, c) + assert np.allclose(cn, c, rtol=rtol) a = num.random.rand(5, 4).astype(ty) b = num.random.rand(5, 4).astype(ty) @@ -57,7 +58,7 @@ def test(ty): cn = np.tensordot(a, b) c = num.tensordot(a, b) - assert np.allclose(cn, c) + assert np.allclose(cn, c, rtol=rtol) if __name__ == "__main__": From 395ff6dbaaf90ce732667acd9f81b64a56ace838 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 31 Oct 2021 23:48:07 -0700 Subject: [PATCH 19/46] gpu fused op --- src/numpy.mk | 1 + src/numpy/fused/fused_op.cu | 143 ++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 src/numpy/fused/fused_op.cu diff --git a/src/numpy.mk b/src/numpy.mk index d4c3de924..22855ece6 100644 --- a/src/numpy.mk +++ b/src/numpy.mk @@ -70,6 +70,7 @@ endif GEN_GPU_SRC += numpy/ternary/where.cu \ numpy/binary/binary_op.cu \ + numpy/fused/fused_op.cu \ numpy/binary/binary_red.cu \ numpy/unary/scalar_unary_red.cu \ numpy/unary/unary_red.cu \ diff --git a/src/numpy/fused/fused_op.cu b/src/numpy/fused/fused_op.cu new file mode 100644 index 000000000..e4e0f9f21 --- /dev/null +++ b/src/numpy/fused/fused_op.cu @@ -0,0 +1,143 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "numpy/fused/binary_op.h" +#include "numpy/binary/binary_op_template.inl" + +#include "numpy/cuda_help.h" + +namespace legate { +namespace numpy { + +using namespace Legion; +/* +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) + dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + out[idx] = func(in1[idx], in2[idx]); +} + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( + size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + auto point = pitches.unflatten(idx, rect.lo); + out[point] = func(in1[point], in2[point]); +} + +template +struct BinaryOpImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + size_t volume = rect.volume(); + const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); + } else { + generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); + } + } +}; +*/ +/*static*/ void FusedOpTask::gpu_variant(TaskContext& context){ + + int nOps = context.fusionMetadata.nOps; + auto opIDs = context.fusionMetadata.opIDs; + auto offsets = context.fusionMetadata.offsets; + for (int i=0; i regions; + //create new context + const Legion::Task* task = (Legion::Task*) context.task_; + + //pack inputs + std::vector inputs; + auto inputStarts = context.fusionMetadata.inputStarts; + auto outputStarts = context.fusionMetadata.outputStarts; + auto offsetStarts = context.fusionMetadata.offsetStarts; + unsigned nInputs = (inputStarts[i+1]-inputStarts[i]); //want to pack this as a 32 bit uint + for (unsigned j = 0; j outputs; + unsigned nOutputs = (outputStarts[i+1]-outputStarts[i]); //want to pack this as a 32 bit uint + for (unsigned j = 0; j scalars; + auto scalarStarts = context.fusionMetadata.scalarStarts; + int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); + std::vector scalars; + for (unsigned j = 0; j outputs; + outputs.push_back(std::move(context.outputs()[i+0])); + */ + //scalars.push_back(std::move(context.scalars()[i+0])); + + TaskContext context3(task, (const std::vector) regions);// inputs, outputs, scalars); + context3.inputs_ = std::move(inputs); + context3.outputs_ = std::move(outputs); + context3.scalars_ = std::move(scalars); + + //launch + auto descp = Core::gpuDescriptors.find(opIDs[i]); + auto desc = descp->second; + desc(context3); + } + //binary_op_template(context); +} + +} // namespace numpy +} // namespace legate From 465a044e10f9afe312f6dddfc632bcdf3492a0eb Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Fri, 5 Nov 2021 18:13:08 -0700 Subject: [PATCH 20/46] reduction fix --- legate/numpy/runtime.py | 2 +- src/numpy/fused/fused_op.cc | 48 ++++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/legate/numpy/runtime.py b/legate/numpy/runtime.py index 0fca71766..80f153ce8 100644 --- a/legate/numpy/runtime.py +++ b/legate/numpy/runtime.py @@ -394,7 +394,7 @@ def compute_parent_child_mapping(array): assert child_ptr >= parent_ptr ptr_diff = child_ptr - parent_ptr parent_shape = array.base.shape - if parent_shape==(): + if False and parent_shape==(): parent_shape = [1] div = ( reduce(lambda x, y: x * y, parent_shape) diff --git a/src/numpy/fused/fused_op.cc b/src/numpy/fused/fused_op.cc index 4aaec0ced..81db16af5 100644 --- a/src/numpy/fused/fused_op.cc +++ b/src/numpy/fused/fused_op.cc @@ -118,7 +118,24 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) //pack reductions int32_t nReductions = (reductionStarts[opID+1]-reductionStarts[opID]); - ms.pack((uint32_t) nReductions); + for (unsigned i = 0; i reductions; + int32_t nReductions = (reductionStarts[i+1]-reductionStarts[i]); + for (unsigned j = 0; j scalars; + std::vector scalars; auto scalarStarts = context.fusionMetadata.scalarStarts; int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); for (unsigned j = 0; j outputs; outputs.push_back(std::move(context.outputs()[i+0])); */ - std::vector scalars; - scalars.push_back(std::move(context.scalars()[i+0])); + //scalars.push_back(std::move(context.scalars()[i+0])); TaskContext context3(task, (const std::vector) regions);// inputs, outputs, scalars); context3.inputs_ = std::move(inputs); From 615c95ac65a811301847ccb732acc1d8589b8fec Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sat, 13 Nov 2021 13:28:38 -0800 Subject: [PATCH 21/46] re add cuda fused --- src/cunumeric/fused/fused_op.cu | 143 ++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/cunumeric/fused/fused_op.cu diff --git a/src/cunumeric/fused/fused_op.cu b/src/cunumeric/fused/fused_op.cu new file mode 100644 index 000000000..e4e0f9f21 --- /dev/null +++ b/src/cunumeric/fused/fused_op.cu @@ -0,0 +1,143 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#include "numpy/fused/binary_op.h" +#include "numpy/binary/binary_op_template.inl" + +#include "numpy/cuda_help.h" + +namespace legate { +namespace numpy { + +using namespace Legion; +/* +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) + dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + out[idx] = func(in1[idx], in2[idx]); +} + +template +static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( + size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) +{ + const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= volume) return; + auto point = pitches.unflatten(idx, rect.lo); + out[point] = func(in1[point], in2[point]); +} + +template +struct BinaryOpImplBody { + using OP = BinaryOp; + using ARG = legate_type_of; + using RES = std::result_of_t; + + void operator()(OP func, + AccessorWO out, + AccessorRO in1, + AccessorRO in2, + const Pitches& pitches, + const Rect& rect, + bool dense) const + { + size_t volume = rect.volume(); + const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; + if (dense) { + auto outptr = out.ptr(rect); + auto in1ptr = in1.ptr(rect); + auto in2ptr = in2.ptr(rect); + dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); + } else { + generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); + } + } +}; +*/ +/*static*/ void FusedOpTask::gpu_variant(TaskContext& context){ + + int nOps = context.fusionMetadata.nOps; + auto opIDs = context.fusionMetadata.opIDs; + auto offsets = context.fusionMetadata.offsets; + for (int i=0; i regions; + //create new context + const Legion::Task* task = (Legion::Task*) context.task_; + + //pack inputs + std::vector inputs; + auto inputStarts = context.fusionMetadata.inputStarts; + auto outputStarts = context.fusionMetadata.outputStarts; + auto offsetStarts = context.fusionMetadata.offsetStarts; + unsigned nInputs = (inputStarts[i+1]-inputStarts[i]); //want to pack this as a 32 bit uint + for (unsigned j = 0; j outputs; + unsigned nOutputs = (outputStarts[i+1]-outputStarts[i]); //want to pack this as a 32 bit uint + for (unsigned j = 0; j scalars; + auto scalarStarts = context.fusionMetadata.scalarStarts; + int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); + std::vector scalars; + for (unsigned j = 0; j outputs; + outputs.push_back(std::move(context.outputs()[i+0])); + */ + //scalars.push_back(std::move(context.scalars()[i+0])); + + TaskContext context3(task, (const std::vector) regions);// inputs, outputs, scalars); + context3.inputs_ = std::move(inputs); + context3.outputs_ = std::move(outputs); + context3.scalars_ = std::move(scalars); + + //launch + auto descp = Core::gpuDescriptors.find(opIDs[i]); + auto desc = descp->second; + desc(context3); + } + //binary_op_template(context); +} + +} // namespace numpy +} // namespace legate From 13f95adb9625f0a3de33baeac0c7eec4cb57bb22 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sat, 13 Nov 2021 13:30:03 -0800 Subject: [PATCH 22/46] fixing fuse file --- src/cunumeric/fused/fused_op.cc | 61 ++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/src/cunumeric/fused/fused_op.cc b/src/cunumeric/fused/fused_op.cc index f82ebb203..7328515e1 100644 --- a/src/cunumeric/fused/fused_op.cc +++ b/src/cunumeric/fused/fused_op.cc @@ -24,10 +24,10 @@ #include #include -namespace cunumeric { +namespace legate { +namespace cunmeric { using namespace Legion; -using namespace legate; template struct BinaryOpImplBody { @@ -59,7 +59,7 @@ struct BinaryOpImplBody { }; -/* + //op id refers not to the op's type, but the index in the list of fused ops void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) { @@ -117,7 +117,24 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) //pack reductions int32_t nReductions = (reductionStarts[opID+1]-reductionStarts[opID]); - ms.pack((uint32_t) nReductions); + for (unsigned i = 0; i reductions; + int32_t nReductions = (reductionStarts[i+1]-reductionStarts[i]); + for (unsigned j = 0; j scalars; + std::vector scalars; auto scalarStarts = context.fusionMetadata.scalarStarts; int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); for (unsigned j = 0; j outputs; outputs.push_back(std::move(context.outputs()[i+0])); */ - std::vector scalars; - scalars.push_back(std::move(context.scalars()[i+0])); + //scalars.push_back(std::move(context.scalars()[i+0])); TaskContext context3(task, (const std::vector) regions);// inputs, outputs, scalars); context3.inputs_ = std::move(inputs); @@ -242,3 +278,4 @@ static void __attribute__((constructor)) register_tasks(void) { FusedOpTask::reg } // namespace } // namespace numpy +} // namespace legate From ce77d5947fb92433f928ae49e5b9a02de0fa0639 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sat, 13 Nov 2021 13:32:59 -0800 Subject: [PATCH 23/46] more fused stuff --- build.sh | 4 ++-- examples/black_scholes.py | 10 ++++----- examples/cg.py | 9 ++++++++ legate/numpy/array.py | 4 ++-- src/numpy/fused/fused_op.cc | 43 ------------------------------------- src/numpy/fused/fused_op.cu | 26 ++++++++++++++++------ 6 files changed, 38 insertions(+), 58 deletions(-) diff --git a/build.sh b/build.sh index 03eb5e764..b8751463e 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ #touch src/matrix/matvecmul.cc #touch src/fused/fused_op.cc cd ../legate.core/ -python setup.py --no-cuda +python setup.py --cuda --with-cuda /usr/local/cuda/ --arch pascal cd ../legate.numpy/ -python setup.py --with-core ~/legate/legate.core/install/ --verbose +python setup.py --with-core /home/shiv1/truefusedGPU/legate.core/install/ --verbose #../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/examples/black_scholes.py b/examples/black_scholes.py index 1fbb19478..c47363ada 100644 --- a/examples/black_scholes.py +++ b/examples/black_scholes.py @@ -64,9 +64,9 @@ def cnd(d): def black_scholes(S, X, T, R, V): sqrt_t = np.sqrt(T) - sqrt_t = np.sqrt(T) - sqrt_t = np.sqrt(T) - sqrt_t = np.sqrt(T) + #sqrt_t = np.sqrt(T) + #sqrt_t = np.sqrt(T) + #sqrt_t = np.sqrt(T) d1 = np.log(S / X) + (R + 0.5 * V * V) * T / (V * sqrt_t) d2 = d1 - V * sqrt_t cnd_d1 = cnd(d1) @@ -85,9 +85,9 @@ def run_black_scholes(N, D): call, put = black_scholes(S, X, T, R, V) # Check the result for NaNs to synchronize before stopping timing call_sum = np.sum(call) - call_sum2 = np.sum(call) + # call_sum2 = np.sum(call) put_sum = np.sum(put) - put_sum2 = np.sum(put) + # put_sum2 = np.sum(put) #print(call_sum, put_sum) #print(call_sum2, put_sum2) assert not math.isnan(call_sum) and not math.isnan(put_sum) diff --git a/examples/cg.py b/examples/cg.py index f6f9b688c..d3858c03a 100644 --- a/examples/cg.py +++ b/examples/cg.py @@ -84,11 +84,17 @@ def solve(A, b, conv_iters, max_iters, verbose): min(max_iters, b.shape[0]) if max_iters is not None else b.shape[0] ) for i in range(max_iters): + #print("one") Ap = A.dot(p) + #print("2") alpha = rsold / (p.dot(Ap)) + #print("3") x = x + alpha * p + #print("4") r = r - alpha * Ap + #print("5") rsnew = r.dot(r) + #print("6") # We only do the convergence test every conv_iters or on the last # iteration if (i % conv_iters == 0 or i == (max_iters - 1)) and np.sqrt( @@ -98,8 +104,11 @@ def solve(A, b, conv_iters, max_iters, verbose): break if verbose: print("Residual: " + str(rsnew)) + #print("7") beta = rsnew / rsold + #print("8") p = r + beta * p + #print("9") rsold = rsnew if converged < 0: print("Convergence FAILURE!") diff --git a/legate/numpy/array.py b/legate/numpy/array.py index 12fd2f3a2..a12977559 100644 --- a/legate/numpy/array.py +++ b/legate/numpy/array.py @@ -2132,7 +2132,7 @@ def perform_binary_op( if one.dtype != two.dtype: common_type = cls.find_common_type(one, two) if one.dtype != common_type: - if one.shape==(): + if False and one.shape==(): temp = ndarray( shape=one.shape, dtype=common_type, @@ -2152,7 +2152,7 @@ def perform_binary_op( ) one = temp if two.dtype != common_type: - if two.shape==(): + if False and two.shape==(): temp = ndarray( shape=two.shape, dtype=common_type, diff --git a/src/numpy/fused/fused_op.cc b/src/numpy/fused/fused_op.cc index 81db16af5..b354aebe5 100644 --- a/src/numpy/fused/fused_op.cc +++ b/src/numpy/fused/fused_op.cc @@ -156,32 +156,7 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) { ms.zero(); //reset the serializer, but keep the memory packOp(ms, context, i); - /* - TaskLauncher leaf_launcher(opIDs[i], TaskArgument(ms.ptr(), ms.buffSize())); - leaf_launcher.enable_inlining=true; - leaf_launcher.point = context.task_->index_point; - //add appropriate region requirements for this op - std::vector reqIds = ms.getReqIds(); - for (int32_t reqIdx : reqIds) - { - auto& req = context.task_->regions[reqIdx]; - leaf_launcher.add_region_requirement(req); - } - //add appropriate futures - auto futureStarts = context.fusionMetadata.futureStarts; - for (int32_t fuid = futureStarts[i]; fuidfutures[fuid]; - leaf_launcher.add_future(f); - } - - */ std::vector regions; - //for (int k : reqIds) - { - //regions.push_back(context.regions_[k]); - } - //context.runtime_->execute_task(context.context_, leaf_launcher); //create new context @@ -235,7 +210,6 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) } //pack scalars - //std::vector scalars; std::vector scalars; auto scalarStarts = context.fusionMetadata.scalarStarts; int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); @@ -244,12 +218,6 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) scalars.push_back(std::move(context.scalars()[scalarStarts[i]+j])); } - /* - std::vector outputs; - outputs.push_back(std::move(context.outputs()[i+0])); - */ - //scalars.push_back(std::move(context.scalars()[i+0])); - TaskContext context3(task, (const std::vector) regions);// inputs, outputs, scalars); context3.inputs_ = std::move(inputs); context3.outputs_ = std::move(outputs); @@ -259,18 +227,7 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) auto descp = Core::cpuDescriptors.find(opIDs[i]); auto desc = descp->second; desc(context3); - - //move it back?? - //context.outputs_[i] = std::move(context3.outputs_[i]); - - //binary_op_template(context); - //gettimeofday(&start, NULL); - //gettimeofday(&end, NULL); - // printf("%ld\n", ((end.tv_sec * 1000000 + end.tv_usec) -// - (start.tv_sec * 1000000 + start.tv_usec))); } - - } namespace // unnamed diff --git a/src/numpy/fused/fused_op.cu b/src/numpy/fused/fused_op.cu index e4e0f9f21..9de6cf8c4 100644 --- a/src/numpy/fused/fused_op.cu +++ b/src/numpy/fused/fused_op.cu @@ -87,6 +87,7 @@ struct BinaryOpImplBody { auto inputStarts = context.fusionMetadata.inputStarts; auto outputStarts = context.fusionMetadata.outputStarts; auto offsetStarts = context.fusionMetadata.offsetStarts; + auto reductionStarts = context.fusionMetadata.reductionStarts; unsigned nInputs = (inputStarts[i+1]-inputStarts[i]); //want to pack this as a 32 bit uint for (unsigned j = 0; j { outputs.push_back(std::move(output)); } + //pack reductions + std::vector reductions; + int32_t nReductions = (reductionStarts[i+1]-reductionStarts[i]); + for (unsigned j = 0; j scalars; auto scalarStarts = context.fusionMetadata.scalarStarts; @@ -120,15 +139,11 @@ struct BinaryOpImplBody { scalars.push_back(std::move(context.scalars()[scalarStarts[i]+j])); } - /* - std::vector outputs; - outputs.push_back(std::move(context.outputs()[i+0])); - */ - //scalars.push_back(std::move(context.scalars()[i+0])); TaskContext context3(task, (const std::vector) regions);// inputs, outputs, scalars); context3.inputs_ = std::move(inputs); context3.outputs_ = std::move(outputs); + context3.reductions_ = std::move(reductions); context3.scalars_ = std::move(scalars); //launch @@ -136,7 +151,6 @@ struct BinaryOpImplBody { auto desc = descp->second; desc(context3); } - //binary_op_template(context); } } // namespace numpy From 0d60b822bced4d71ad8285611a9e49e2d140e7f8 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sat, 13 Nov 2021 13:48:26 -0800 Subject: [PATCH 24/46] last merge fixes --- build.sh | 2 +- src/cunumeric/fused/fused_op.cc | 11 ++++++----- src/cunumeric/fused/fused_op.cu | 13 +++++++------ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/build.sh b/build.sh index b8751463e..220d29ee6 100755 --- a/build.sh +++ b/build.sh @@ -4,5 +4,5 @@ cd ../legate.core/ python setup.py --cuda --with-cuda /usr/local/cuda/ --arch pascal cd ../legate.numpy/ -python setup.py --with-core /home/shiv1/truefusedGPU/legate.core/install/ --verbose +python setup.py --with-core /home/shiv1/truefusedGPU/legate.core/install/ --verbose #../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/src/cunumeric/fused/fused_op.cc b/src/cunumeric/fused/fused_op.cc index 047ec03d4..b80edc681 100644 --- a/src/cunumeric/fused/fused_op.cc +++ b/src/cunumeric/fused/fused_op.cc @@ -24,10 +24,11 @@ #include #include -namespace legate { -namespace cunmeric { +//namespace legate { +namespace cunumeric { using namespace Legion; +using namespace legate; template struct BinaryOpImplBody { @@ -61,7 +62,7 @@ struct BinaryOpImplBody { //op id refers not to the op's type, but the index in the list of fused ops -void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) +void packOp(legate::MakeshiftSerializer& ms, TaskContext& context, int opID) { auto inputStarts = context.fusionMetadata.inputStarts; auto outputStarts = context.fusionMetadata.outputStarts; @@ -148,7 +149,7 @@ void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) /*static*/ void FusedOpTask::cpu_variant(TaskContext& context) { int nOps = context.fusionMetadata.nOps; - MakeshiftSerializer ms; + legate::MakeshiftSerializer ms; auto opIDs = context.fusionMetadata.opIDs; auto offsets = context.fusionMetadata.offsets; for (int i=0; i static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) @@ -154,4 +155,4 @@ struct BinaryOpImplBody { } } // namespace numpy -} // namespace legate +//} // namespace legate From e840297ae3b67a1b3d2183f9ca8cef3bece0bfb6 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Mon, 15 Nov 2021 15:05:37 -0800 Subject: [PATCH 25/46] constant optimization --- cunumeric/array.py | 5 +++-- cunumeric/deferred.py | 2 ++ cunumeric/runtime.py | 3 ++- examples/black_scholes.py | 8 +++++--- src/cunumeric/fused/fused_op.cc | 15 +++++++++++++-- src/cunumeric/fused/fused_op.cu | 13 +++++++++++++ 6 files changed, 38 insertions(+), 8 deletions(-) diff --git a/cunumeric/array.py b/cunumeric/array.py index 568efd63b..3eaeefe75 100644 --- a/cunumeric/array.py +++ b/cunumeric/array.py @@ -2128,10 +2128,11 @@ def perform_binary_op( if out_dtype is None: out_dtype = cls.find_common_type(one, two) if check_types: + conOpt = False if one.dtype != two.dtype: common_type = cls.find_common_type(one, two) if one.dtype != common_type: - if False and one.shape==(): + if conOpt and one.shape==(): temp = ndarray( shape=one.shape, dtype=common_type, @@ -2151,7 +2152,7 @@ def perform_binary_op( ) one = temp if two.dtype != common_type: - if False and two.shape==(): + if conOpt and two.shape==(): temp = ndarray( shape=two.shape, dtype=common_type, diff --git a/cunumeric/deferred.py b/cunumeric/deferred.py index 6f792affd..9a2922cf4 100644 --- a/cunumeric/deferred.py +++ b/cunumeric/deferred.py @@ -838,6 +838,8 @@ def convert(self, rhs, stacklevel=0, warn=True, callsite=None): task.add_output(lhs) task.add_input(rhs) task.add_dtype_arg(lhs_array.dtype) + task.add_broadcast(rhs) + #task.add_broadcast(lhs) task.add_alignment(lhs, rhs) diff --git a/cunumeric/runtime.py b/cunumeric/runtime.py index 6e9b5ef07..8113c7a15 100644 --- a/cunumeric/runtime.py +++ b/cunumeric/runtime.py @@ -393,7 +393,8 @@ def compute_parent_child_mapping(array): assert child_ptr >= parent_ptr ptr_diff = child_ptr - parent_ptr parent_shape = array.base.shape - if False and parent_shape==(): + #if False and parent_shape==(): + if parent_shape==(): parent_shape = [1] div = ( reduce(lambda x, y: x * y, parent_shape) diff --git a/examples/black_scholes.py b/examples/black_scholes.py index 89eb7dae9..064d3e035 100644 --- a/examples/black_scholes.py +++ b/examples/black_scholes.py @@ -28,6 +28,7 @@ def generate_random(N, min, max, D): diff = D(max) - D(min) + #print("diff", diff) rands = np.random.random(N).astype(D) rands = rands * diff rands = rands + D(min) @@ -82,19 +83,20 @@ def run_black_scholes(N, D): N *= 1000 start = datetime.datetime.now() S, X, T, R, V = initialize(N, D) + #return call, put = black_scholes(S, X, T, R, V) # Check the result for NaNs to synchronize before stopping timing call_sum = np.sum(call) - # call_sum2 = np.sum(call) + #call_sum2 = np.sum(call) put_sum = np.sum(put) - # put_sum2 = np.sum(put) + #put_sum2 = np.sum(put) #print(call_sum, put_sum) #print(call_sum2, put_sum2) assert not math.isnan(call_sum) and not math.isnan(put_sum) stop = datetime.datetime.now() delta = stop - start total = delta.total_seconds() * 1000.0 - #print("Elapsed Time: " + str(total) + " ms") + print("Elapsed Time: " + str(total) + " ms") return total diff --git a/src/cunumeric/fused/fused_op.cc b/src/cunumeric/fused/fused_op.cc index b80edc681..e325f64d7 100644 --- a/src/cunumeric/fused/fused_op.cc +++ b/src/cunumeric/fused/fused_op.cc @@ -154,8 +154,8 @@ void packOp(legate::MakeshiftSerializer& ms, TaskContext& context, int opID) auto offsets = context.fusionMetadata.offsets; for (int i=0; i regions; //context.runtime_->execute_task(context.context_, leaf_launcher); @@ -227,6 +227,17 @@ void packOp(legate::MakeshiftSerializer& ms, TaskContext& context, int opID) auto descp = Core::cpuDescriptors.find(opIDs[i]); auto desc = descp->second; desc(context3); + for (unsigned j = 0; j { //launch auto descp = Core::gpuDescriptors.find(opIDs[i]); + auto desc = descp->second; desc(context3); + for (unsigned j = 0; j Date: Sun, 21 Nov 2021 18:27:12 -0800 Subject: [PATCH 26/46] better constant opt --- cunumeric/array.py | 14 +++++++++++--- cunumeric/deferred.py | 3 ++- cunumeric/runtime.py | 16 +++++++++------- examples/black_scholes.py | 25 ++++++++++++++++--------- test.py | 2 +- 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/cunumeric/array.py b/cunumeric/array.py index 3eaeefe75..f950b2335 100644 --- a/cunumeric/array.py +++ b/cunumeric/array.py @@ -2128,7 +2128,7 @@ def perform_binary_op( if out_dtype is None: out_dtype = cls.find_common_type(one, two) if check_types: - conOpt = False + conOpt = True if one.dtype != two.dtype: common_type = cls.find_common_type(one, two) if one.dtype != common_type: @@ -2136,10 +2136,13 @@ def perform_binary_op( temp = ndarray( shape=one.shape, dtype=common_type, - buffer = one._thunk.array.astype(common_type), + #buffer = one._thunk.array.astype(common_type), stacklevel=(stacklevel + 1), inputs=(one, two, where), ) + temp._thunk= runtime.create_scalar(one._thunk.array.astype(common_type), common_type, shape=one.shape, wrap=True) + #print("ttype", type(temp), type(temp._thunk)) + #print("ctype", common_type) else: temp = ndarray( shape=one.shape, @@ -2156,10 +2159,12 @@ def perform_binary_op( temp = ndarray( shape=two.shape, dtype=common_type, - buffer = two._thunk.array.astype(common_type), + #buffer = two._thunk.array.astype(common_type), stacklevel=(stacklevel + 1), inputs=(one, two, where), ) + temp._thunk = runtime.create_scalar(two._thunk.array.astype(common_type), common_type, shape=two.shape, wrap=True) + #print("ttype2", type(temp), type(temp._thunk)) else: temp = ndarray( shape=two.shape, @@ -2171,6 +2176,9 @@ def perform_binary_op( two._thunk, stacklevel=(stacklevel + 1) ) two = temp + if (two.dtype != one.dtype): + print("u messed up", one.dtype, two.dtype) + #print("final", type(one._thunk), type(two._thunk)) if out.dtype != out_dtype: temp = ndarray( shape=out.shape, diff --git a/cunumeric/deferred.py b/cunumeric/deferred.py index 9a2922cf4..a965eb937 100644 --- a/cunumeric/deferred.py +++ b/cunumeric/deferred.py @@ -838,7 +838,8 @@ def convert(self, rhs, stacklevel=0, warn=True, callsite=None): task.add_output(lhs) task.add_input(rhs) task.add_dtype_arg(lhs_array.dtype) - task.add_broadcast(rhs) + + #task.add_broadcast(rhs) #task.add_broadcast(lhs) task.add_alignment(lhs, rhs) diff --git a/cunumeric/runtime.py b/cunumeric/runtime.py index 8113c7a15..f6bba02c8 100644 --- a/cunumeric/runtime.py +++ b/cunumeric/runtime.py @@ -395,12 +395,14 @@ def compute_parent_child_mapping(array): parent_shape = array.base.shape #if False and parent_shape==(): if parent_shape==(): - parent_shape = [1] - div = ( - reduce(lambda x, y: x * y, parent_shape) - if len(parent_shape) > 1 - else parent_shape[0] - ) + parent_shape = () + div =1 + else: + div = ( + reduce(lambda x, y: x * y, parent_shape) + if len(parent_shape) > 1 + else parent_shape[0] + ) div *= array.dtype.itemsize offsets = list() # Compute the offsets in the parent index @@ -502,7 +504,6 @@ def find_or_create_array_thunk( ): if array.size == 1 and not share: # This is a single value array - import pdb; pdb.set_trace() result = self.create_scalar( array.data, array.dtype, @@ -623,6 +624,7 @@ def to_deferred_array(self, array, stacklevel): elif self.is_lazy_array(array): raise NotImplementedError("convert lazy array to deferred array") else: + print(type(array)) raise RuntimeError("invalid array type") def to_lazy_array(self, array, stacklevel): diff --git a/examples/black_scholes.py b/examples/black_scholes.py index 064d3e035..4acce795c 100644 --- a/examples/black_scholes.py +++ b/examples/black_scholes.py @@ -84,19 +84,26 @@ def run_black_scholes(N, D): start = datetime.datetime.now() S, X, T, R, V = initialize(N, D) #return - call, put = black_scholes(S, X, T, R, V) - # Check the result for NaNs to synchronize before stopping timing - call_sum = np.sum(call) - #call_sum2 = np.sum(call) - put_sum = np.sum(put) - #put_sum2 = np.sum(put) - #print(call_sum, put_sum) - #print(call_sum2, put_sum2) - assert not math.isnan(call_sum) and not math.isnan(put_sum) + trials = 100 + ends = [None for i in range(trials)] + for i in range(trials): + call, put = black_scholes(S, X, T, R, V) + # Check the result for NaNs to synchronize before stopping timing + call_sum = np.sum(call) + #call_sum2 = np.sum(call) + put_sum = np.sum(put) + ends[i] = (call_sum, put_sum) + #assert not math.isnan(call_sum) and not math.isnan(put_sum) + #put_sum2 = np.sum(put) + #print(call_sum2, put_sum2) + for i in range(trials): + call_sum, put_sum = ends[i] + assert not math.isnan(call_sum) and not math.isnan(put_sum) stop = datetime.datetime.now() delta = stop - start total = delta.total_seconds() * 1000.0 print("Elapsed Time: " + str(total) + " ms") + #print(call_sum, put_sum) return total diff --git a/test.py b/test.py index 0d0d26763..e67955bf6 100755 --- a/test.py +++ b/test.py @@ -51,7 +51,7 @@ # draw tests from these directories legate_tests = [] legate_tests.extend(glob.glob("tests/*.py")) -legate_tests.extend(glob.glob("examples/*.py")) +#legate_tests.extend(glob.glob("examples/*.py")) # some test programs have additional command line arguments test_flags = { From becf41a9cf5c1706e64ac05950ded7ef478d1a50 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Mon, 22 Nov 2021 13:58:25 -0800 Subject: [PATCH 27/46] batch syncs for black scholes --- examples/black_scholes.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/black_scholes.py b/examples/black_scholes.py index 4acce795c..5bd808ca7 100644 --- a/examples/black_scholes.py +++ b/examples/black_scholes.py @@ -92,13 +92,13 @@ def run_black_scholes(N, D): call_sum = np.sum(call) #call_sum2 = np.sum(call) put_sum = np.sum(put) - ends[i] = (call_sum, put_sum) - #assert not math.isnan(call_sum) and not math.isnan(put_sum) + #ends[i] = (call_sum, put_sum) + assert not math.isnan(call_sum) and not math.isnan(put_sum) #put_sum2 = np.sum(put) #print(call_sum2, put_sum2) - for i in range(trials): - call_sum, put_sum = ends[i] - assert not math.isnan(call_sum) and not math.isnan(put_sum) + #for i in range(trials): + #call_sum, put_sum = ends[i] + #assert not math.isnan(call_sum) and not math.isnan(put_sum) stop = datetime.datetime.now() delta = stop - start total = delta.total_seconds() * 1000.0 From b52c7bdbfb6d8db61bd3bc6f9b13fe49d1fec26e Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Mon, 22 Nov 2021 14:30:03 -0800 Subject: [PATCH 28/46] fused op cleanup --- src/cunumeric/fused/binary_op.h | 46 --------------------------------- src/cunumeric/fused/fused_op.cc | 8 +++--- src/cunumeric/fused/fused_op.cu | 4 +-- 3 files changed, 6 insertions(+), 52 deletions(-) delete mode 100644 src/cunumeric/fused/binary_op.h diff --git a/src/cunumeric/fused/binary_op.h b/src/cunumeric/fused/binary_op.h deleted file mode 100644 index 81aeb3858..000000000 --- a/src/cunumeric/fused/binary_op.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -#include "cunumeric/cunumeric.h" -#include "cunumeric/fused/binary_op_util.h" - -namespace cunumeric { - -struct BinaryOpArgs { - const Array& in1; - const Array& in2; - const Array& out; - BinaryOpCode op_code; - std::vector args; -}; - -class FusedOpTask : public CuNumericTask { - public: - static const int TASK_ID = CUNUMERIC_FUSED_OP; - - public: - static void cpu_variant(legate::TaskContext& context); -#ifdef LEGATE_USE_OPENMP - static void omp_variant(legate::TaskContext& context); -#endif -#ifdef LEGATE_USE_CUDA - static void gpu_variant(legate::TaskContext& context); -#endif -}; - -} // namespace cunumeric diff --git a/src/cunumeric/fused/fused_op.cc b/src/cunumeric/fused/fused_op.cc index e325f64d7..eedcd2275 100644 --- a/src/cunumeric/fused/fused_op.cc +++ b/src/cunumeric/fused/fused_op.cc @@ -17,8 +17,8 @@ #include "core/utilities/makeshift_serializer.h" #include "core/runtime/runtime.h" #include "core/runtime/context.h" -#include "cunumeric/fused/binary_op.h" -#include "cunumeric/fused/binary_op_template.inl" +#include "cunumeric/fused/fused_op.h" +//#include "cunumeric/fused/binary_op_template.inl" #include "legion.h" #include #include @@ -29,7 +29,7 @@ namespace cunumeric { using namespace Legion; using namespace legate; - +/* template struct BinaryOpImplBody { using OP = BinaryOp; @@ -58,7 +58,7 @@ struct BinaryOpImplBody { } } }; - +*/ //op id refers not to the op's type, but the index in the list of fused ops diff --git a/src/cunumeric/fused/fused_op.cu b/src/cunumeric/fused/fused_op.cu index 098a55a58..2ee1ef39b 100644 --- a/src/cunumeric/fused/fused_op.cu +++ b/src/cunumeric/fused/fused_op.cu @@ -14,8 +14,8 @@ * */ -#include "cunumeric/fused/binary_op.h" -#include "cunumeric/binary/binary_op_template.inl" +#include "cunumeric/fused/fused_op.h" +//#include "cunumeric/binary/binary_op_template.inl" #include "cunumeric/cuda_help.h" From 1ae85c5bb6750864cb712bab21cd49e5bc490236 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Wed, 1 Dec 2021 09:39:07 -0800 Subject: [PATCH 29/46] black scholes adjustment --- build.sh | 2 +- examples/black_scholes.py | 10 +++++----- examples/cg.py | 9 --------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/build.sh b/build.sh index 220d29ee6..c21a8d8cd 100755 --- a/build.sh +++ b/build.sh @@ -4,5 +4,5 @@ cd ../legate.core/ python setup.py --cuda --with-cuda /usr/local/cuda/ --arch pascal cd ../legate.numpy/ -python setup.py --with-core /home/shiv1/truefusedGPU/legate.core/install/ --verbose +#python setup.py --with-core /home/shiv1/truefusedGPU/legate.core/install/ --verbose #../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/examples/black_scholes.py b/examples/black_scholes.py index 5bd808ca7..4acce795c 100644 --- a/examples/black_scholes.py +++ b/examples/black_scholes.py @@ -92,13 +92,13 @@ def run_black_scholes(N, D): call_sum = np.sum(call) #call_sum2 = np.sum(call) put_sum = np.sum(put) - #ends[i] = (call_sum, put_sum) - assert not math.isnan(call_sum) and not math.isnan(put_sum) + ends[i] = (call_sum, put_sum) + #assert not math.isnan(call_sum) and not math.isnan(put_sum) #put_sum2 = np.sum(put) #print(call_sum2, put_sum2) - #for i in range(trials): - #call_sum, put_sum = ends[i] - #assert not math.isnan(call_sum) and not math.isnan(put_sum) + for i in range(trials): + call_sum, put_sum = ends[i] + assert not math.isnan(call_sum) and not math.isnan(put_sum) stop = datetime.datetime.now() delta = stop - start total = delta.total_seconds() * 1000.0 diff --git a/examples/cg.py b/examples/cg.py index 3473c2ee5..a3a447211 100644 --- a/examples/cg.py +++ b/examples/cg.py @@ -84,17 +84,11 @@ def solve(A, b, conv_iters, max_iters, verbose): min(max_iters, b.shape[0]) if max_iters is not None else b.shape[0] ) for i in range(max_iters): - #print("one") Ap = A.dot(p) - #print("2") alpha = rsold / (p.dot(Ap)) - #print("3") x = x + alpha * p - #print("4") r = r - alpha * Ap - #print("5") rsnew = r.dot(r) - #print("6") # We only do the convergence test every conv_iters or on the last # iteration if (i % conv_iters == 0 or i == (max_iters - 1)) and np.sqrt( @@ -104,11 +98,8 @@ def solve(A, b, conv_iters, max_iters, verbose): break if verbose: print("Residual: " + str(rsnew)) - #print("7") beta = rsnew / rsold - #print("8") p = r + beta * p - #print("9") rsold = rsnew if converged < 0: print("Convergence FAILURE!") From 7a58b6d87bacdb849a58765a48541e87df0da0e9 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Wed, 1 Dec 2021 17:06:15 -0800 Subject: [PATCH 30/46] add missing header --- src/cunumeric/fused/fused_op.h | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/cunumeric/fused/fused_op.h diff --git a/src/cunumeric/fused/fused_op.h b/src/cunumeric/fused/fused_op.h new file mode 100644 index 000000000..e71b20eaa --- /dev/null +++ b/src/cunumeric/fused/fused_op.h @@ -0,0 +1,46 @@ +/* Copyright 2021 NVIDIA Corporation + * + * 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. + * + */ + +#pragma once + +#include "cunumeric/cunumeric.h" +//#include "cunumeric/fused/binary_op_util.h" + +namespace cunumeric { +/* +struct BinaryOpArgs { + const Array& in1; + const Array& in2; + const Array& out; + BinaryOpCode op_code; + std::vector args; +}; +*/ +class FusedOpTask : public CuNumericTask { + public: + static const int TASK_ID = CUNUMERIC_FUSED_OP; + + public: + static void cpu_variant(legate::TaskContext& context); +#ifdef LEGATE_USE_OPENMP + static void omp_variant(legate::TaskContext& context); +#endif +#ifdef LEGATE_USE_CUDA + static void gpu_variant(legate::TaskContext& context); +#endif +}; + +} // namespace cunumeric From 5a38ef14ba25b9d4c542fa748042ffefebebf179 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sat, 4 Dec 2021 14:26:38 -0800 Subject: [PATCH 31/46] 27 pt stencil --- examples/stencil_27.py | 159 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 examples/stencil_27.py diff --git a/examples/stencil_27.py b/examples/stencil_27.py new file mode 100644 index 000000000..d7f2b92da --- /dev/null +++ b/examples/stencil_27.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python + +# Copyright 2021 NVIDIA Corporation +# +# 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. +# + +from __future__ import print_function + +import argparse +import datetime +import math + +from benchmark import run_benchmark + +import cunumeric as np + + +def initialize(N): + print("Initializing stencil grid...") + grid = np.zeros((N + 2, N + 2, N+2)) + grid[:,:, 0] = -273.15 + grid[:, 0, :] = -273.15 + grid[0,:, :] = -273.15 + grid[:,:, -1] = 273.15 + grid[:, -1, :] = 273.15 + grid[-1,:, :] = 273.15 + + + return grid + + +def run(grid, I, N): # noqa: E741 + print("Running Jacobi 27 stencil...") + + #one + g000 = grid[0:-2, 0:-2, 0:-2] + g001 = grid[0:-2, 0:-2, 1:-1] + g002 = grid[0:-2, 0:-2, 2: ] + + g010 = grid[0:-2, 1:-1, 0:-2] + g011 = grid[0:-2, 1:-1, 1:-1] + g012 = grid[0:-2, 1:-1, 2: ] + + g020 = grid[0:-2, 2: , 0:-2] + g021 = grid[0:-2, 2: , 1:-1] + g022 = grid[0:-2, 2: , 2: ] + + #two + g100 = grid[1:-1, 0:-2, 0:-2] + g101 = grid[1:-1, 0:-2, 1:-1] + g102 = grid[1:-1, 0:-2, 2: ] + + g110 = grid[1:-1, 1:-1, 0:-2] + g111 = grid[1:-1, 1:-1, 1:-1] + g112 = grid[1:-1, 1:-1, 2: ] + + g120 = grid[1:-1, 2: , 0:-2] + g121 = grid[1:-1, 2: , 1:-1] + g122 = grid[1:-1, 2: , 2: ] + + #three + g200 = grid[2: , 0:-2, 0:-2] + g201 = grid[2: , 0:-2, 1:-1] + g202 = grid[2: , 0:-2, 2: ] + + g210 = grid[2: , 1:-1, 0:-2] + g211 = grid[2: , 1:-1, 1:-1] + g212 = grid[2: , 1:-1, 2: ] + + g220 = grid[2: , 2: , 0:-2] + g221 = grid[2: , 2: , 1:-1] + g222 = grid[2: , 2: , 2: ] + + for i in range(I): + g00 = g000 + g001 + g002 + g01 = g010 + g011 + g012 + g02 = g020 + g021 + g022 + g10 = g100 + g101 + g102 + g11 = g110 + g111 + g112 + g12 = g120 + g121 + g122 + g20 = g200 + g201 + g202 + g21 = g210 + g211 + g212 + g22 = g220 + g221 + g222 + + g0 = g00 + g01 + g02 + g1 = g10 + g11 + g12 + g2 = g20 + g21 + g22 + + res = g0 + g1 + g2 + work = 0.037 * res + g111[:] = work + total = np.sum(g111) + return total / (N ** 2) + + +def run_stencil(N, I, timing): # noqa: E741 + start = datetime.datetime.now() + grid = initialize(N) + average = run(grid, I, N) + # This will sync the timing because we will need to wait for the result + assert not math.isnan(average) + stop = datetime.datetime.now() + print("Average energy is %.8g" % average) + delta = stop - start + total = delta.total_seconds() * 1000.0 + if timing: + print("Elapsed Time: " + str(total) + " ms") + return total + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "-i", + "--iter", + type=int, + default=100, + dest="I", + help="number of iterations to run", + ) + parser.add_argument( + "-n", + "--num", + type=int, + default=100, + dest="N", + help="number of elements in one dimension", + ) + parser.add_argument( + "-t", + "--time", + dest="timing", + action="store_true", + help="perform timing", + ) + parser.add_argument( + "-b", + "--benchmark", + type=int, + default=1, + dest="benchmark", + help="number of times to benchmark this application (default 1 " + "- normal execution)", + ) + args = parser.parse_args() + run_benchmark( + run_stencil, args.benchmark, "Stencil", (args.N, args.I, args.timing) + ) From f230fcb751e595c8561407953c0d6d09963e900d Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 5 Dec 2021 22:42:13 -0800 Subject: [PATCH 32/46] only do constant optimization for deferred arrays for some reason --- cunumeric/array.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/cunumeric/array.py b/cunumeric/array.py index 9e8144f9e..a53db4fad 100644 --- a/cunumeric/array.py +++ b/cunumeric/array.py @@ -28,7 +28,7 @@ from .doc_utils import copy_docstring from .runtime import runtime from .utils import unimplemented - +from .deferred import DeferredArray def add_boilerplate(*array_params: str, mutates_self: bool = False): """ @@ -2174,7 +2174,7 @@ def perform_binary_op( if one.dtype != two.dtype: common_type = cls.find_common_type(one, two) if one.dtype != common_type: - if conOpt and one.shape==(): + if conOpt and isinstance(one._thunk, DeferredArray) and one.shape==(): temp = ndarray( shape=one.shape, dtype=common_type, @@ -2183,8 +2183,6 @@ def perform_binary_op( inputs=(one, two, where), ) temp._thunk= runtime.create_scalar(one._thunk.array.astype(common_type), common_type, shape=one.shape, wrap=True) - #print("ttype", type(temp), type(temp._thunk)) - #print("ctype", common_type) else: temp = ndarray( shape=one.shape, @@ -2197,7 +2195,7 @@ def perform_binary_op( ) one = temp if two.dtype != common_type: - if conOpt and two.shape==(): + if conOpt and isinstance(two._thunk, DeferredArray) and two.shape==(): temp = ndarray( shape=two.shape, dtype=common_type, @@ -2206,7 +2204,6 @@ def perform_binary_op( inputs=(one, two, where), ) temp._thunk = runtime.create_scalar(two._thunk.array.astype(common_type), common_type, shape=two.shape, wrap=True) - #print("ttype2", type(temp), type(temp._thunk)) else: temp = ndarray( shape=two.shape, @@ -2218,9 +2215,6 @@ def perform_binary_op( two._thunk, stacklevel=(stacklevel + 1) ) two = temp - if (two.dtype != one.dtype): - print("u messed up", one.dtype, two.dtype) - #print("final", type(one._thunk), type(two._thunk)) if out.dtype != out_dtype: temp = ndarray( shape=out.shape, From 7922c3d9f221616c7e7e463612105237aa6638d4 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sat, 11 Dec 2021 18:39:36 -0800 Subject: [PATCH 33/46] remove old files, change to constant optimization --- build.sh | 4 +- cunumeric/array.py | 5 +- examples/black_scholes.py | 2 +- src/cunumeric/fused/binary_op.cu | 79 ----- src/cunumeric/fused/binary_op_template.inl | 97 ------- src/cunumeric/fused/binary_op_util.h | 320 --------------------- src/cunumeric/fused/fused_op.cu | 2 - 7 files changed, 5 insertions(+), 504 deletions(-) delete mode 100644 src/cunumeric/fused/binary_op.cu delete mode 100644 src/cunumeric/fused/binary_op_template.inl delete mode 100644 src/cunumeric/fused/binary_op_util.h diff --git a/build.sh b/build.sh index c21a8d8cd..08d4f289a 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ #touch src/matrix/matvecmul.cc #touch src/fused/fused_op.cc cd ../legate.core/ -python setup.py --cuda --with-cuda /usr/local/cuda/ --arch pascal +python setup.py --gasnet --conduit ibv --cuda --with-cuda /usr/local/cuda/ --arch pascal cd ../legate.numpy/ -#python setup.py --with-core /home/shiv1/truefusedGPU/legate.core/install/ --verbose +#python setup.py --with-core ../legate.core/install/ --verbose #../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/cunumeric/array.py b/cunumeric/array.py index a53db4fad..c0b9dfc98 100644 --- a/cunumeric/array.py +++ b/cunumeric/array.py @@ -462,7 +462,6 @@ def __ge__(self, rhs): ) def double_binary(self, rhs1, rhs2): - print(type(self)) rhs_array1 = self.convert_to_legate_ndarray(rhs1) rhs_array2 = self.convert_to_legate_ndarray(rhs2) @@ -2170,11 +2169,11 @@ def perform_binary_op( if out_dtype is None: out_dtype = cls.find_common_type(one, two) if check_types: - conOpt = True + conOpt = isinstance(one._thunk, DeferredArray) or isinstance(two._thunk, DeferredArray) if one.dtype != two.dtype: common_type = cls.find_common_type(one, two) if one.dtype != common_type: - if conOpt and isinstance(one._thunk, DeferredArray) and one.shape==(): + if conOpt and one.shape==(): temp = ndarray( shape=one.shape, dtype=common_type, diff --git a/examples/black_scholes.py b/examples/black_scholes.py index 4acce795c..8ee73eeb1 100644 --- a/examples/black_scholes.py +++ b/examples/black_scholes.py @@ -84,7 +84,7 @@ def run_black_scholes(N, D): start = datetime.datetime.now() S, X, T, R, V = initialize(N, D) #return - trials = 100 + trials = 300 ends = [None for i in range(trials)] for i in range(trials): call, put = black_scholes(S, X, T, R, V) diff --git a/src/cunumeric/fused/binary_op.cu b/src/cunumeric/fused/binary_op.cu deleted file mode 100644 index a83792b69..000000000 --- a/src/cunumeric/fused/binary_op.cu +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "binary/binary_op.h" -#include "binary_op_template.inl" - -#include "cuda_help.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) - dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - out[idx] = func(in1[idx], in2[idx]); -} - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( - size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - auto point = pitches.unflatten(idx, rect.lo); - out[point] = func(in1[point], in2[point]); -} - -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - size_t volume = rect.volume(); - const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); - } else { - generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); - } - } -}; - -/*static*/ void BinaryOpTask::gpu_variant(TaskContext& context) -{ - binary_op_template(context); -} - -} // namespace numpy -} // namespace legate diff --git a/src/cunumeric/fused/binary_op_template.inl b/src/cunumeric/fused/binary_op_template.inl deleted file mode 100644 index 5e769ab76..000000000 --- a/src/cunumeric/fused/binary_op_template.inl +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "cunumeric/fused/binary_op_util.h" -#include "cunumeric/pitches.h" - -namespace cunumeric { - -using namespace Legion; -using namespace legate; - -template -struct BinaryOpImplBody; - -template -struct BinaryOpImpl { - template ::valid>* = nullptr> - void operator()(BinaryOpArgs& args) const - { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - auto rect = args.out.shape(); - - Pitches pitches; - size_t volume = pitches.flatten(rect); - - if (volume == 0) return; - - auto out = args.out.write_accessor(rect); - auto in1 = args.in1.read_accessor(rect); - auto in2 = args.in2.read_accessor(rect); - -#ifndef LEGION_BOUNDS_CHECKS - // Check to see if this is dense or not - bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && - in2.accessor.is_dense_row_major(rect); -#else - // No dense execution if we're doing bounds checks - bool dense = false; -#endif - - OP func{args.args}; - BinaryOpImplBody()(func, out, in1, in2, pitches, rect, dense); - } - - template ::valid>* = nullptr> - void operator()(BinaryOpArgs& args) const - { - assert(false); - } -}; - -template -struct BinaryOpDispatch { - template - void operator()(BinaryOpArgs& args) const - { - auto dim = std::max(1, args.out.dim()); - double_dispatch(dim, args.in1.code(), BinaryOpImpl{}, args); - } -}; - -template -static void binary_op_template(TaskContext& context) -{ - auto& inputs = context.inputs(); - auto& outputs = context.outputs(); - auto& scalars = context.scalars(); - - std::vector extra_args; - for (size_t idx = 2; idx < inputs.size(); ++idx) extra_args.push_back(std::move(inputs[idx])); - - BinaryOpArgs args{ - inputs[0], inputs[1], outputs[0], scalars[0].value(), std::move(extra_args)}; - op_dispatch(args.op_code, BinaryOpDispatch{}, args); -} - -} // namespace cunumeric diff --git a/src/cunumeric/fused/binary_op_util.h b/src/cunumeric/fused/binary_op_util.h deleted file mode 100644 index 71064797d..000000000 --- a/src/cunumeric/fused/binary_op_util.h +++ /dev/null @@ -1,320 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -#include "cunumeric/cunumeric.h" - -namespace cunumeric { - -enum class BinaryOpCode : int { - ADD = 1, - DIVIDE, - EQUAL, - FLOOR_DIVIDE, - GREATER, - GREATER_EQUAL, - LESS, - LESS_EQUAL, - MAXIMUM, - MINIMUM, - MOD, - MULTIPLY, - NOT_EQUAL, - POWER, - SUBTRACT, - ALLCLOSE, -}; - -template -constexpr decltype(auto) op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) -{ - switch (op_code) { - case BinaryOpCode::ADD: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::DIVIDE: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::FLOOR_DIVIDE: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::GREATER: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::GREATER_EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::LESS: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::LESS_EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MAXIMUM: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MINIMUM: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MOD: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MULTIPLY: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::NOT_EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::POWER: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::SUBTRACT: - return f.template operator()(std::forward(args)...); - default: break; - } - assert(false); - return f.template operator()(std::forward(args)...); -} - -template -constexpr decltype(auto) reduce_op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) -{ - switch (op_code) { - case BinaryOpCode::EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::ALLCLOSE: - return f.template operator()(std::forward(args)...); - default: break; - } - assert(false); - return f.template operator()(std::forward(args)...); -} - -template -struct BinaryOp { - static constexpr bool valid = false; -}; - -template -struct BinaryOp : std::plus> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::divides> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::equal_to> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -using std::floor; -template -struct BinaryOp { - using T = legate::legate_type_of; - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return floor(a / b); } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp(const std::vector& args) {} -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::greater> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::greater_equal> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::less> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::less_equal> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp { - using T = legate::legate_type_of; - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return std::max(a, b); } -}; - -template -struct BinaryOp { - using T = legate::legate_type_of; - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return std::min(a, b); } -}; - -template -constexpr T real_mod(const T& a, const T& b) -{ - T res = std::fmod(a, b); - if (res) { - if ((b < static_cast(0)) != (res < static_cast(0))) res += b; - } else { - res = std::copysign(static_cast(0), b); - } - return res; -} - -template -struct BinaryOp { - using T = legate::legate_type_of; - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} - template ::value>* = nullptr> - constexpr _T operator()(const _T& a, const _T& b) const - { - return a % b; - } - - template ::value>* = nullptr> - constexpr _T operator()(const _T& a, const _T& b) const - { - return real_mod(a, b); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const - { - return static_cast<__half>(real_mod(static_cast(a), static_cast(b))); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp(const std::vector& args) {} -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::multiplies> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::not_equal_to> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp { - using VAL = legate::legate_type_of; - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} - constexpr VAL operator()(const VAL& a, const VAL& b) const { return std::pow(a, b); } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const - { - return pow(a, b); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX complex operator()(const complex& a, - const complex& b) const - { - return pow(a, b); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX complex operator()(const complex& a, - const complex& b) const - { - return pow(a, b); - } -}; - -template -struct BinaryOp : std::minus> { - static constexpr bool valid = true; - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp { - using VAL = legate::legate_type_of; - static constexpr bool valid = true; - - BinaryOp(const std::vector& args) - { - assert(args.size() == 2); - rtol_ = args[0].scalar(); - atol_ = args[1].scalar(); - } - - template ::value>* = nullptr> - constexpr bool operator()(const T& a, const T& b) const - { - using std::fabs; - return fabs(static_cast(a) - static_cast(b)) <= - atol_ + rtol_ * static_cast(fabs(b)); - } - - template ::value>* = nullptr> - constexpr bool operator()(const T& a, const T& b) const - { - return static_cast(abs(a - b)) <= atol_ + rtol_ * static_cast(abs(b)); - } - - double rtol_{0}; - double atol_{0}; -}; - -} // namespace cunumeric diff --git a/src/cunumeric/fused/fused_op.cu b/src/cunumeric/fused/fused_op.cu index 2ee1ef39b..a4aedd1c3 100644 --- a/src/cunumeric/fused/fused_op.cu +++ b/src/cunumeric/fused/fused_op.cu @@ -15,8 +15,6 @@ */ #include "cunumeric/fused/fused_op.h" -//#include "cunumeric/binary/binary_op_template.inl" - #include "cunumeric/cuda_help.h" //namespace legate { From d5908e1da1beaeb0d27bbd8b022562dbb373f4b4 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sat, 11 Dec 2021 18:48:17 -0800 Subject: [PATCH 34/46] cleanup --- build.sh | 2 +- cunumeric/array.py | 190 ---------- cunumeric/config.py | 1 - cunumeric/deferred.py | 49 --- src/cunumeric/cunumeric_c.h | 3 +- src/double_binary/double_binary_op.cc | 73 ---- src/double_binary/double_binary_op.cu | 79 ---- src/double_binary/double_binary_op.h | 64 ---- src/double_binary/double_binary_op_omp.cc | 72 ---- .../double_binary_op_template.inl | 103 ------ src/double_binary/double_binary_op_util.h | 346 ------------------ 11 files changed, 2 insertions(+), 980 deletions(-) delete mode 100644 src/double_binary/double_binary_op.cc delete mode 100644 src/double_binary/double_binary_op.cu delete mode 100644 src/double_binary/double_binary_op.h delete mode 100644 src/double_binary/double_binary_op_omp.cc delete mode 100644 src/double_binary/double_binary_op_template.inl delete mode 100644 src/double_binary/double_binary_op_util.h diff --git a/build.sh b/build.sh index 08d4f289a..4fc08b3b7 100755 --- a/build.sh +++ b/build.sh @@ -4,5 +4,5 @@ cd ../legate.core/ python setup.py --gasnet --conduit ibv --cuda --with-cuda /usr/local/cuda/ --arch pascal cd ../legate.numpy/ -#python setup.py --with-core ../legate.core/install/ --verbose +python setup.py --with-core ../legate.core/install/ --verbose #../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/cunumeric/array.py b/cunumeric/array.py index c0b9dfc98..703da256d 100644 --- a/cunumeric/array.py +++ b/cunumeric/array.py @@ -461,31 +461,6 @@ def __ge__(self, rhs): out_dtype=np.dtype(np.bool_), ) - def double_binary(self, rhs1, rhs2): - rhs_array1 = self.convert_to_legate_ndarray(rhs1) - rhs_array2 = self.convert_to_legate_ndarray(rhs2) - - #a,b,c - arrs = [self.convert_to_legate_ndarray(self), rhs_array1, rhs_array2] - in_starts = np.ndarray([0,1]) - in_ends = [1,2] - in_starts = self.convert_to_legate_ndarray(in_starts) - in_ends = self.convert_to_legate_ndarray(in_starts) - #in_ends = self.convert_to_legate_ndarray(in_ends) - - out_starts = [3] - out_end = [3] - #out_starts = self.convert_to_legate_ndarray(out_starts) - #out_end = self.convert_to_legate_ndarray(out_ends) - - return self.perform_double_binary_op( - DoubleBinaryOpCode.DOUBLE_BINARY, - self, - rhs_array1, - rhs_array2, - check_types=False - ) - # __getattribute__ def _convert_key(self, key, stacklevel=2, first=True): # Convert any arrays stored in a key to a cuNumeric array @@ -1939,171 +1914,6 @@ def perform_unary_reduction( ) return dst - # Return a new cuNumeric array for a binary operation - @classmethod - def perform_double_binary_op( - cls, - op, - one, - two, - three, - out=None, - dtype=None, - args=None, - where=True, - out_dtype=None, - check_types=False, - stacklevel=2, - ): - temp_dtype = cls.find_common_type(one, two) - # Compute the output shape - if out is None: - # Compute the output shape and confirm any broadcasting - if isinstance(where, ndarray): - print("using where array.py") - temp_shape = broadcast_shapes(one.shape, where.shape) - out_shape = broadcast_shapes(one.shape, two.shape, where.shape) - else: - print("not using where array.py") - temp_shape = broadcast_shapes(one.shape, two.shape) - out_shape = broadcast_shapes(one.shape, two.shape, three.shape) - print("out_shape", out_shape) - print("temp_shape", temp_shape) - if dtype is not None: - temprw = ndarray( - shape=temp_shape, - dtype=temp_dtype, - stacklevel=(stacklevel + 1), - inputs=(one, two, where), - ) - out = ndarray( - shape=out_shape, - dtype=dtype, - stacklevel=(stacklevel + 1), - inputs=(temp, three, where), - ) - elif out_dtype is not None: - temprw = ndarray( - shape=temp_shape, - dtype=temp_dtype, - stacklevel=(stacklevel + 1), - inputs=(one, two, where), - ) - - out = ndarray( - shape=out_shape, - dtype=out_dtype, - stacklevel=(stacklevel + 1), - inputs=(one, two,three, where), - ) - else: - out_dtype = cls.find_common_type(one, two,three) - temprw = ndarray( - shape=temp_shape, - dtype=temp_dtype, - stacklevel=(stacklevel + 1), - inputs=(one, two, where), - ) - out = ndarray( - shape=out_shape, - dtype=out_dtype, - stacklevel=(stacklevel + 1), - inputs=(one, two,three, where), - ) - else: - if isinstance(where, ndarray): - out_shape = broadcast_shapes( - one.shape, two.shape,three.shape, out.shape, where.shape - ) - else: - out_shape = broadcast_shapes(one.shape, two.shape, three.shape, out.shape) - if out.shape != out_shape: - raise ValueError( - "non-broadcastable output operand with shape " - + str(out.shape) - + " doesn't match the broadcast shape " - + str(out_shape) - ) - # Quick exit - if where is False: - return out - if out_dtype is None: - out_dtype = cls.find_common_type(one, two) - out_dtype = cls.find_common_type(out_dtype, three) - if check_types: - if one.dtype != two.dtype: - common_type = cls.find_common_type(one, two) - if one.dtype != common_type: - temp = ndarray( - shape=one.shape, - dtype=common_type, - stacklevel=(stacklevel + 1), - inputs=(one, two, where), - ) - temp._thunk.convert( - one._thunk, stacklevel=(stacklevel + 1) - ) - one = temp - if two.dtype != common_type: - temp = ndarray( - shape=two.shape, - dtype=common_type, - stacklevel=(stacklevel + 1), - inputs=(one, two, where), - ) - temp._thunk.convert( - two._thunk, stacklevel=(stacklevel + 1) - ) - two = temp - if out.dtype != out_dtype: - temp = ndarray( - shape=out.shape, - dtype=out_dtype, - stacklevel=(stacklevel + 1), - inputs=(one, two, where), - ) - temp._thunk.binary_op( - op, - one._thunk, - two._thunk, - cls.get_where_thunk( - where, out.shape, stacklevel=(stacklevel + 1) - ), - args, - stacklevel=(stacklevel + 1), - ) - out._thunk.convert(temp._thunk, stacklevel=(stacklevel + 1)) - else: - out._thunk.binary_op( - op, - one._thunk, - two._thunk, - cls.get_where_thunk( - where, out.shape, stacklevel=(stacklevel + 1) - ), - args, - stacklevel=(stacklevel + 1), - ) - #if check_types - else: - thunks = [one._thunk, two._thunk, three._thunk] - print("running double binary op with out_shape=", out.shape) - out._thunk.double_binary_op( - op, - one._thunk, - two._thunk, - temprw._thunk, - three._thunk, - cls.get_where_thunk( - where, out.shape, stacklevel=(stacklevel + 1) - ), - args, - stacklevel=(stacklevel + 1), - ) - return out - - - # Return a new legate array for a binary operation @classmethod diff --git a/cunumeric/config.py b/cunumeric/config.py index 4664b0331..44c0a490f 100644 --- a/cunumeric/config.py +++ b/cunumeric/config.py @@ -103,7 +103,6 @@ class CuNumericOpCode(IntEnum): UNARY_RED = _cunumeric.CUNUMERIC_UNARY_RED WHERE = _cunumeric.CUNUMERIC_WHERE WRITE = _cunumeric.CUNUMERIC_WRITE - DOUBLE_BINARY_OP = _cunumeric.CUNUMERIC_DOUBLE_BINARY FUSED_OP = _cunumeric.CUNUMERIC_FUSED_OP @unique diff --git a/cunumeric/deferred.py b/cunumeric/deferred.py index 587322489..55aa137a0 100644 --- a/cunumeric/deferred.py +++ b/cunumeric/deferred.py @@ -1530,55 +1530,6 @@ def unary_reduction( callsite=callsite, ) -# Perform the fused operation and put the result in the lhs array - @profile - @auto_convert([2, 3, 4,5]) - @shadow_debug("double_binary_op", [2, 3, 4,5]) - def double_binary_op( - self, op_code, src1, src2, temp, src3, where, args, stacklevel=0, callsite=None - ): - lhs = self.base - - rhs1 = src1._broadcast(lhs.shape) - rhs2 = src2._broadcast(lhs.shape) - rhs3 = src3._broadcast(lhs.shape) - temp1 = temp._broadcast(lhs.shape) - # Populate the Legate launcher - all_scalar_rhs = rhs1.scalar and rhs2.scalar - - if all_scalar_rhs: - task_id = NumPyOpCode.SCALAR_BINARY_OP - else: - task_id = NumPyOpCode.DOUBLE_BINARY_OP - - task = self.context.create_task(task_id) - task.add_output(temp1) - task.add_output(lhs) - - #task.add_temp(temp1) - - task.add_input(rhs1) - task.add_input(rhs2) - task.add_input(rhs3) - task.add_scalar_arg(op_code.value, ty.int32) - self.add_arguments(task, args) - - #task.add_broadcast(rhs.base) - - task.add_alignment(lhs, rhs1) - task.add_alignment(lhs, rhs2) - task.add_alignment(lhs, rhs3) - - task.add_alignment(lhs, temp1) - print("about to execute double_binary_op!!", task_id) - print("the shapes:") - print(rhs1.shape) - print(rhs2.shape) - print(rhs3.shape) - print("temp1", temp1.shape) - task.execute() - - # Perform the binary operation and put the result in the lhs array @profile diff --git a/src/cunumeric/cunumeric_c.h b/src/cunumeric/cunumeric_c.h index f3b80aa6f..be431c2fd 100644 --- a/src/cunumeric/cunumeric_c.h +++ b/src/cunumeric/cunumeric_c.h @@ -44,8 +44,7 @@ enum CuNumericOpCode { CUNUMERIC_UNARY_RED = 21, CUNUMERIC_WHERE = 22, CUNUMERIC_WRITE = 23, - CUNUMERIC_DOUBLE_BINARY = 24, - CUNUMERIC_FUSED_OP = 25, + CUNUMERIC_FUSED_OP = 24, }; // Match these to CuNumericRedopCode in cunumeric/config.py diff --git a/src/double_binary/double_binary_op.cc b/src/double_binary/double_binary_op.cc deleted file mode 100644 index 4cf0b2e6a..000000000 --- a/src/double_binary/double_binary_op.cc +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "double_binary/double_binary_op.h" -#include "double_binary/double_binary_op_template.inl" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct DoubleBinaryOpImplBody { - using OP = DoubleBinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRW temp, - AccessorRO in1, - AccessorRO in2, - AccessorRO in3, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - const size_t volume = rect.volume(); - if (dense) { - auto outptr = out.ptr(rect); - auto tempptr = temp.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - auto in3ptr = in3.ptr(rect); - for (size_t idx = 0; idx < volume; ++idx) { - tempptr[idx] = func(in1ptr[idx], in2ptr[idx]); - outptr[idx] = func(tempptr[idx], in3ptr[idx]); - } - } else { - for (size_t idx = 0; idx < volume; ++idx) { - auto p = pitches.unflatten(idx, rect.lo); - temp[p] = func(in1[p], in2[p]); - out[p] = func(temp[p], in3[p]); - } - } - } -}; - -/*static*/ void DoubleBinaryOpTask::cpu_variant(TaskContext& context) -{ - double_binary_op_template(context); -} - -namespace // unnamed -{ -static void __attribute__((constructor)) register_tasks(void) { DoubleBinaryOpTask::register_variants(); } -} // namespace - -} // namespace numpy -} // namespace legate diff --git a/src/double_binary/double_binary_op.cu b/src/double_binary/double_binary_op.cu deleted file mode 100644 index 1d0bfc349..000000000 --- a/src/double_binary/double_binary_op.cu +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "double_binary/binary_op.h" -#include "double_binary_op_template.inl" - -#include "cuda_help.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) - dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - out[idx] = func(in1[idx], in2[idx]); -} - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( - size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - auto point = pitches.unflatten(idx, rect.lo); - out[point] = func(in1[point], in2[point]); -} - -template -struct DoubleBinaryOpImplBody { - using OP = DoubleBinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - size_t volume = rect.volume(); - const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); - } else { - generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); - } - } -}; - -/*static*/ void DoubleBinaryOpTask::gpu_variant(TaskContext& context) -{ - double_binary_op_template(context); -} - -} // namespace numpy -} // namespace legate diff --git a/src/double_binary/double_binary_op.h b/src/double_binary/double_binary_op.h deleted file mode 100644 index 35cb311a1..000000000 --- a/src/double_binary/double_binary_op.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -#include "numpy.h" -#include "double_binary/double_binary_op_util.h" - -namespace legate { -namespace numpy { - -struct DoubleBinaryOpArgs { - const Array& in1; - const Array& in2; - const Array& in3; - const Array& temp; - const Array& out; - DoubleBinaryOpCode op_code; - std::vector args; -}; - - -struct DoubleBinaryOpArgs2 { - std::vector ins; - std::vector outs; - std::vector inStarts; - std::vector inSizes; - std::vector outStarts; - std::vector outSizes; - std::vector op_codes; - std::vector args; -}; - - - -class DoubleBinaryOpTask : public NumPyTask { - public: - static const int TASK_ID = NUMPY_DOUBLE_BINARY_OP; - - public: - static void cpu_variant(TaskContext& context); -#ifdef LEGATE_USE_OPENMP - static void omp_variant(TaskContext& context); -#endif -#ifdef LEGATE_USE_CUDA - static void gpu_variant(TaskContext& context); -#endif -}; - -} // namespace numpy -} // namespace legate diff --git a/src/double_binary/double_binary_op_omp.cc b/src/double_binary/double_binary_op_omp.cc deleted file mode 100644 index 652424b25..000000000 --- a/src/double_binary/double_binary_op_omp.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "double_binary/double_binary_op.h" -#include "double_binary_op_template.inl" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct DoubleBinaryOpImplBody { - using OP = DoubleBinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRW temp, - AccessorRO in1, - AccessorRO in2, - AccessorRO in3, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - const size_t volume = rect.volume(); - if (dense) { - auto outptr = out.ptr(rect); - auto tempptr = temp.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - auto in3ptr = in3.ptr(rect); -#pragma omp parallel for schedule(static) - for (size_t idx = 0; idx < volume; ++idx) { - tempptr[idx] = func(in1ptr[idx], in2ptr[idx]); - outptr[idx] = func(tempptr[idx], in3ptr[idx]); - //outptr[idx] = func(func(in1ptr[idx], in2ptr[idx]), in3ptr[idx]); - } - } else { -#pragma omp parallel for schedule(static) - for (size_t idx = 0; idx < volume; ++idx) { - auto p = pitches.unflatten(idx, rect.lo); - //out[p] = func(func(in1[p], in2[p]), in3[p]); - temp[p] = func(in1[p], in2[p]); - out[p] = func(temp[p], in3[p]); - } - } - } -}; - -/*static*/ void DoubleBinaryOpTask::omp_variant(TaskContext& context) -{ - double_binary_op_template(context); -} - -} // namespace numpy -} // namespace legate diff --git a/src/double_binary/double_binary_op_template.inl b/src/double_binary/double_binary_op_template.inl deleted file mode 100644 index 28ebbe792..000000000 --- a/src/double_binary/double_binary_op_template.inl +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "double_binary/double_binary_op_util.h" -#include "pitches.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct DoubleBinaryOpImplBody; - -template -struct DoubleBinaryOpImpl { - template ::valid>* = nullptr> - void operator()(DoubleBinaryOpArgs& args) const - { - using OP = DoubleBinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - auto rect = args.out.shape(); - - Pitches pitches; - size_t volume = pitches.flatten(rect); - - if (volume == 0) return; - - auto out = args.out.write_accessor(rect); - auto temp = args.temp.read_write_accessor(rect); - auto in1 = args.in1.read_accessor(rect); - auto in2 = args.in2.read_accessor(rect); - auto in3 = args.in2.read_accessor(rect); - -#ifndef LEGION_BOUNDS_CHECKS - // Check to see if this is dense or not - bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && - in2.accessor.is_dense_row_major(rect) && in3.accessor.is_dense_row_major(rect) && - temp.accessor.is_dense_row_major(rect); -#else - // No dense execution if we're doing bounds checks - bool dense = false; -#endif - - OP func{args.args}; - DoubleBinaryOpImplBody()(func, out,temp, in1, in2,in3, pitches, rect, dense); - } - - template ::valid>* = nullptr> - void operator()(DoubleBinaryOpArgs& args) const - { - assert(false); - } -}; - -template -struct DoubleBinaryOpDispatch { - template - void operator()(DoubleBinaryOpArgs& args) const - { - auto dim = std::max(args.in1.dim(), args.in2.dim()); - dim = std::max(args.in3.dim(), dim); - double_dispatch(dim, args.in1.code(), DoubleBinaryOpImpl{}, args); - } -}; - -template -static void double_binary_op_template(TaskContext& context) -{ - auto& inputs = context.inputs(); - auto& outputs = context.outputs(); - auto& scalars = context.scalars(); - - std::vector extra_args; - for (size_t idx = 3; idx < inputs.size(); ++idx) - extra_args.push_back(inputs[idx].scalar()); - - DoubleBinaryOpArgs args{ - inputs[0], inputs[1], inputs[2], outputs[0], outputs[1], scalars[0].value(), std::move(extra_args)}; - op_dispatch(args.op_code, DoubleBinaryOpDispatch{}, args); -} - -} // namespace numpy -} // namespace legate diff --git a/src/double_binary/double_binary_op_util.h b/src/double_binary/double_binary_op_util.h deleted file mode 100644 index 064e63fc5..000000000 --- a/src/double_binary/double_binary_op_util.h +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -#include "numpy.h" - -namespace legate { -namespace numpy { - -enum class DoubleBinaryOpCode : int { - ADD = 1, - DIVIDE, - EQUAL, - FLOOR_DIVIDE, - GREATER, - GREATER_EQUAL, - LESS, - LESS_EQUAL, - MAXIMUM, - MINIMUM, - MOD, - MULTIPLY, - NOT_EQUAL, - POWER, - SUBTRACT, - ALLCLOSE, -}; - -template -constexpr decltype(auto) op_dispatch(DoubleBinaryOpCode op_code, Functor f, Fnargs&&... args) -{ - switch (op_code) { - case DoubleBinaryOpCode::ADD: - return f.template operator()(std::forward(args)...); - case DoubleBinaryOpCode::DIVIDE: - return f.template operator()(std::forward(args)...); - //case DoubleBinaryOpCode::EQUAL: - // return f.template operator()(std::forward(args)...); - case DoubleBinaryOpCode::FLOOR_DIVIDE: - return f.template operator()(std::forward(args)...); - //case DoubleBinaryOpCode::GREATER: - // return f.template operator()(std::forward(args)...); - //case DoubleBinaryOpCode::GREATER_EQUAL: - // return f.template operator()(std::forward(args)...); - //case DoubleBinaryOpCode::LESS: - // return f.template operator()(std::forward(args)...); - //case DoubleBinaryOpCode::LESS_EQUAL: - // return f.template operator()(std::forward(args)...); - case DoubleBinaryOpCode::MAXIMUM: - return f.template operator()(std::forward(args)...); - case DoubleBinaryOpCode::MINIMUM: - return f.template operator()(std::forward(args)...); - case DoubleBinaryOpCode::MOD: - return f.template operator()(std::forward(args)...); - case DoubleBinaryOpCode::MULTIPLY: - return f.template operator()(std::forward(args)...); - //case DoubleBinaryOpCode::NOT_EQUAL: - // return f.template operator()(std::forward(args)...); - case DoubleBinaryOpCode::POWER: - return f.template operator()(std::forward(args)...); - case DoubleBinaryOpCode::SUBTRACT: - return f.template operator()(std::forward(args)...); - default: break; - } - assert(false); - return f.template operator()(std::forward(args)...); -} - -template -constexpr decltype(auto) reduce_op_dispatch(DoubleBinaryOpCode op_code, Functor f, Fnargs&&... args) -{ - switch (op_code) { - //case DoubleBinaryOpCode::EQUAL: - // return f.template operator()(std::forward(args)...); - //case DoubleBinaryOpCode::ALLCLOSE: - // return f.template operator()(std::forward(args)...); - default: break; - } - assert(false); - //return f.template operator()(std::forward(args)...); -} - -template -struct DoubleBinaryOp { - static constexpr bool valid = false; -}; - -template -struct DoubleBinaryOp : std::plus> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; - -template -struct DoubleBinaryOp : std::divides> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; -/* -template -struct DoubleBinaryOp : std::equal_to> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; -*/ -using std::floor; -template -struct DoubleBinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return floor(a / b); } -}; - -template <> -struct DoubleBinaryOp { - static constexpr bool valid = false; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; - -template <> -struct DoubleBinaryOp { - static constexpr bool valid = false; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; -/* -template -struct DoubleBinaryOp : std::greater> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; - -template -struct DoubleBinaryOp : std::greater_equal> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; - -template -struct DoubleBinaryOp : std::less> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; - -template -struct DoubleBinaryOp : std::less_equal> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; -*/ -template -struct DoubleBinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return std::max(a, b); } -}; - -template -struct DoubleBinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return std::min(a, b); } -}; - -template -constexpr T real_mod(const T& a, const T& b) -{ - T res = std::fmod(a, b); - if (res) { - if ((b < static_cast(0)) != (res < static_cast(0))) res += b; - } else { - res = std::copysign(static_cast(0), b); - } - return res; -} - -template -struct DoubleBinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} - template ::value>* = nullptr> - constexpr _T operator()(const _T& a, const _T& b) const - { - return a % b; - } - - template ::value>* = nullptr> - constexpr _T operator()(const _T& a, const _T& b) const - { - return real_mod(a, b); - } -}; - -template <> -struct DoubleBinaryOp { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const - { - return static_cast<__half>(real_mod(static_cast(a), static_cast(b))); - } -}; - -template <> -struct DoubleBinaryOp { - static constexpr bool valid = false; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; - -template <> -struct DoubleBinaryOp { - static constexpr bool valid = false; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; - -template -struct DoubleBinaryOp : std::multiplies> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; -/* -template -struct DoubleBinaryOp : std::not_equal_to> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; -*/ -template -struct DoubleBinaryOp { - using VAL = legate_type_of; - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} - constexpr VAL operator()(const VAL& a, const VAL& b) const { return std::pow(a, b); } -}; - -template <> -struct DoubleBinaryOp { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const - { - return pow(a, b); - } -}; - -template <> -struct DoubleBinaryOp { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX complex operator()(const complex& a, - const complex& b) const - { - return pow(a, b); - } -}; - -template <> -struct DoubleBinaryOp { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX complex operator()(const complex& a, - const complex& b) const - { - return pow(a, b); - } -}; - -template -struct DoubleBinaryOp : std::minus> { - static constexpr bool valid = true; - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) {} -}; -/* -template -struct DoubleBinaryOp { - using VAL = legate_type_of; - static constexpr bool valid = true; - - DoubleBinaryOp() {} - DoubleBinaryOp(const std::vector& args) - { - assert(args.size() == 2); - rtol_ = args[0].value(); - atol_ = args[1].value(); - } - - template ::value>* = nullptr> - constexpr bool operator()(const T& a, const T& b) const - { - using std::fabs; - return fabs(static_cast(a) - static_cast(b)) <= - atol_ + rtol_ * static_cast(fabs(b)); - } - - template ::value>* = nullptr> - constexpr bool operator()(const T& a, const T& b) const - { - return static_cast(abs(a - b)) <= atol_ + rtol_ * static_cast(abs(b)); - } - - double rtol_{0}; - double atol_{0}; -}; -*/ -} // namespace numpy -} // namespace legate From dce6226a163a0b7e1af9675437c2805e2b8941aa Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sat, 11 Dec 2021 18:49:22 -0800 Subject: [PATCH 35/46] cleanup --- src/fused/binary_op.cu | 79 ------- src/fused/binary_op.h | 48 ----- src/fused/binary_op_template.inl | 136 ------------ src/fused/binary_op_util.h | 345 ------------------------------- src/fused/fused_op.cc | 182 ---------------- src/fused/fused_op_omp.cc | 62 ------ 6 files changed, 852 deletions(-) delete mode 100644 src/fused/binary_op.cu delete mode 100644 src/fused/binary_op.h delete mode 100644 src/fused/binary_op_template.inl delete mode 100644 src/fused/binary_op_util.h delete mode 100644 src/fused/fused_op.cc delete mode 100644 src/fused/fused_op_omp.cc diff --git a/src/fused/binary_op.cu b/src/fused/binary_op.cu deleted file mode 100644 index a83792b69..000000000 --- a/src/fused/binary_op.cu +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "binary/binary_op.h" -#include "binary_op_template.inl" - -#include "cuda_help.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) - dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - out[idx] = func(in1[idx], in2[idx]); -} - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( - size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - auto point = pitches.unflatten(idx, rect.lo); - out[point] = func(in1[point], in2[point]); -} - -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - size_t volume = rect.volume(); - const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); - } else { - generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); - } - } -}; - -/*static*/ void BinaryOpTask::gpu_variant(TaskContext& context) -{ - binary_op_template(context); -} - -} // namespace numpy -} // namespace legate diff --git a/src/fused/binary_op.h b/src/fused/binary_op.h deleted file mode 100644 index 778ad3a84..000000000 --- a/src/fused/binary_op.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -//#include "numpy.h" -//#include "fused/binary_op_util.h" - -namespace legate { -namespace numpy { -/* -struct BinaryOpArgs { - const Array& in1; - const Array& in2; - const Array& out; - BinaryOpCode op_code; - std::vector args; -}; -*/ -class FusedOpTask : public NumPyTask { - public: - static const int TASK_ID = NUMPY_FUSED_OP; - - public: - static void cpu_variant(TaskContext& context); -#ifdef LEGATE_USE_OPENMP - static void omp_variant(TaskContext& context); -#endif -#ifdef LEGATE_USE_CUDA - static void gpu_variant(TaskContext& context); -#endif -}; - -} // namespace numpy -} // namespace legate diff --git a/src/fused/binary_op_template.inl b/src/fused/binary_op_template.inl deleted file mode 100644 index d1bed7592..000000000 --- a/src/fused/binary_op_template.inl +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "fused/binary_op_util.h" -//#include "pitches.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct BinaryOpImplBody; - -template -struct BinaryOpImpl { - template ::valid>* = nullptr> - void operator()(BinaryOpArgs& args) const - { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - auto rect = args.out.shape(); - - Pitches pitches; - size_t volume = pitches.flatten(rect); - - if (volume == 0) return; - - auto out = args.out.write_accessor(rect); - auto in1 = args.in1.read_accessor(rect); - auto in2 = args.in2.read_accessor(rect); - -#ifndef LEGION_BOUNDS_CHECKS - // Check to see if this is dense or not - bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && - in2.accessor.is_dense_row_major(rect); -#else - // No dense execution if we're doing bounds checks - bool dense = false; -#endif - - OP func{args.args}; - BinaryOpImplBody()(func, out, in1, in2, pitches, rect, dense); - } - - template ::valid>* = nullptr> - void operator()(BinaryOpArgs& args) const - { - assert(false); - } -}; - -template -struct BinaryOpDispatch { - template - void operator()(BinaryOpArgs& args) const - { - auto dim = std::max(args.in1.dim(), args.in2.dim()); - double_dispatch(dim, args.in1.code(), BinaryOpImpl{}, args); - } -}; - - - -template -static void binary_op_template(TaskContext& context) -{ - auto& inputs = context.inputs(); - auto& outputs = context.outputs(); - auto& scalars = context.scalars(); -/* - std::vector extra_args; - for (size_t idx = 2; idx < inputs.size(); ++idx) - extra_args.push_back(inputs[idx].scalar()); - std::cout<<"extra args size"<(), std::move(extra_args)}; - op_dispatch(args.op_code, BinaryOpDispatch{}, args); -*/ - //std::cout<<"fused inputs"<().hi.x; - //std::cout<<"nops "<(); - auto opcode_i = static_cast::type>(opcode); - //std::cout<<"opcode "<().lo.x<<" "<().hi.x< extra_args; - //for (size_t idx = 3; idx < inputs.size(); ++idx) - // extra_args.push_back(inputs[idx].scalar()); - - int inputStart=0; - int outputStart=0; - - for (int i=0; i<1; i++) - { - BinaryOpArgs args{ - inputs[inputStart+0], inputs[inputStart+1], outputs[outputStart], scalars[outputStart].value(), std::move(extra_args)}; - op_dispatch(args.op_code, BinaryOpDispatch{}, args); - inputStart+=2; - outputStart+=1; - } - /* - BinaryOpArgs args2{ - inputs[6], inputs[7], outputs[1], scalars[1].value(), std::move(extra_args)}; - op_dispatch(args2.op_code, BinaryOpDispatch{}, args2); - */ -} - -} // namespace numpy -} // namespace legate diff --git a/src/fused/binary_op_util.h b/src/fused/binary_op_util.h deleted file mode 100644 index 9912cf7df..000000000 --- a/src/fused/binary_op_util.h +++ /dev/null @@ -1,345 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -//#include "numpy.h" - -namespace legate { -namespace numpy { - -enum class BinaryOpCode : int { - ADD = 1, - DIVIDE, - EQUAL, - FLOOR_DIVIDE, - GREATER, - GREATER_EQUAL, - LESS, - LESS_EQUAL, - MAXIMUM, - MINIMUM, - MOD, - MULTIPLY, - NOT_EQUAL, - POWER, - SUBTRACT, - ALLCLOSE, -}; - -template -constexpr decltype(auto) op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) -{ - switch (op_code) { - case BinaryOpCode::ADD: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::DIVIDE: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::FLOOR_DIVIDE: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::GREATER: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::GREATER_EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::LESS: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::LESS_EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MAXIMUM: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MINIMUM: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MOD: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MULTIPLY: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::NOT_EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::POWER: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::SUBTRACT: - return f.template operator()(std::forward(args)...); - default: break; - } - assert(false); - return f.template operator()(std::forward(args)...); -} - -template -constexpr decltype(auto) reduce_op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) -{ - switch (op_code) { - case BinaryOpCode::EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::ALLCLOSE: - return f.template operator()(std::forward(args)...); - default: break; - } - assert(false); - return f.template operator()(std::forward(args)...); -} - -template -struct BinaryOp { - static constexpr bool valid = false; -}; - -template -struct BinaryOp : std::plus> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::divides> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::equal_to> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -using std::floor; -template -struct BinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return floor(a / b); } -}; -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::greater> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::greater_equal> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::less> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::less_equal> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return std::max(a, b); } -}; - -template -struct BinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return std::min(a, b); } -}; - -template -constexpr T real_mod(const T& a, const T& b) -{ - T res = std::fmod(a, b); - if (res) { - if ((b < static_cast(0)) != (res < static_cast(0))) res += b; - } else { - res = std::copysign(static_cast(0), b); - } - return res; -} - -template -struct BinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - template ::value>* = nullptr> - constexpr _T operator()(const _T& a, const _T& b) const - { - return a % b; - } - - template ::value>* = nullptr> - constexpr _T operator()(const _T& a, const _T& b) const - { - return real_mod(a, b); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const - { - return static_cast<__half>(real_mod(static_cast(a), static_cast(b))); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::multiplies> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::not_equal_to> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp { - using VAL = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - constexpr VAL operator()(const VAL& a, const VAL& b) const { return std::pow(a, b); } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const - { - return pow(a, b); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX complex operator()(const complex& a, - const complex& b) const - { - return pow(a, b); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX complex operator()(const complex& a, - const complex& b) const - { - return pow(a, b); - } -}; - -template -struct BinaryOp : std::minus> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp { - using VAL = legate_type_of; - static constexpr bool valid = true; - - BinaryOp() {} - BinaryOp(const std::vector& args) - { - assert(args.size() == 2); - rtol_ = args[0].value(); - atol_ = args[1].value(); - } - - template ::value>* = nullptr> - constexpr bool operator()(const T& a, const T& b) const - { - using std::fabs; - return fabs(static_cast(a) - static_cast(b)) <= - atol_ + rtol_ * static_cast(fabs(b)); - } - - template ::value>* = nullptr> - constexpr bool operator()(const T& a, const T& b) const - { - return static_cast(abs(a - b)) <= atol_ + rtol_ * static_cast(abs(b)); - } - - double rtol_{0}; - double atol_{0}; -}; - -} // namespace numpy -} // namespace legate diff --git a/src/fused/fused_op.cc b/src/fused/fused_op.cc deleted file mode 100644 index fa3a4c7b5..000000000 --- a/src/fused/fused_op.cc +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "utilities/makeshift_serializer.h" -#include "fused/binary_op.h" -#include "fused/binary_op_template.inl" -#include "legion.h" -#include -#include -#include -#include - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - const size_t volume = rect.volume(); - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); - } else { - for (size_t idx = 0; idx < volume; ++idx) { - auto p = pitches.unflatten(idx, rect.lo); - out[p] = func(in1[p], in2[p]); - } - } - } -}; - - - -//op id refers not to the op's type, but the index in the list of fused ops -void packOp(MakeshiftSerializer& ms, TaskContext& context, int opID) -{ - auto inputStarts = context.fusionMetadata.inputStarts; - auto outputStarts = context.fusionMetadata.outputStarts; - auto offsetStarts = context.fusionMetadata.offsetStarts; - auto offsets = context.fusionMetadata.offsets; - auto reductionStarts = context.fusionMetadata.reductionStarts; - auto scalarStarts = context.fusionMetadata.scalarStarts; - - //the leaf task cannot be fused ops currently - ms.pack((bool) false); - - //pack inputs - unsigned nInputs = (inputStarts[opID+1]-inputStarts[opID]); //want to pack this as a 32 bit uint - ms.pack((uint32_t) nInputs); - //std::cout<<"inputs "<0) - { - bufferID--; - //std::cout<<"packing input "<find_variant(1074141829, 0); - //bool isLeaf = variant_impl->is_leaf(); - auto opIDs = context.fusionMetadata.opIDs; - for (int i=0; iindex_point; - - //add appropriate region requirements for this op - std::vector reqIds = ms.getReqIds(); - for (int32_t reqIdx : reqIds) - { - std::cout<<"req "<regions[reqIdx]; - leaf_launcher.add_region_requirement(req); - } - //add appropriate futures - auto futureStarts = context.fusionMetadata.futureStarts; - for (int32_t fuid = futureStarts[i]; fuidfutures[fuid]; - leaf_launcher.add_future(f); - } - - context.runtime_->execute_task(context.context_, leaf_launcher); - //gettimeofday(&start, NULL); - //binary_op_template(context); - //gettimeofday(&end, NULL); - // printf("%ld\n", ((end.tv_sec * 1000000 + end.tv_usec) -// - (start.tv_sec * 1000000 + start.tv_usec))); - } - - //gettimeofday(&end, NULL); - -} - -namespace // unnamed -{ -static void __attribute__((constructor)) register_tasks(void) { FusedOpTask::register_variants(); } -} // namespace - -} // namespace numpy -} // namespace legate diff --git a/src/fused/fused_op_omp.cc b/src/fused/fused_op_omp.cc deleted file mode 100644 index 0d4151442..000000000 --- a/src/fused/fused_op_omp.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "fused/binary_op.h" -#include "fused/binary_op_template.inl" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - const size_t volume = rect.volume(); - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); -#pragma omp parallel for schedule(static) - for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); - } else { -#pragma omp parallel for schedule(static) - for (size_t idx = 0; idx < volume; ++idx) { - auto p = pitches.unflatten(idx, rect.lo); - out[p] = func(in1[p], in2[p]); - } - } - } -}; - -/*static*/ void FusedOpTask::omp_variant(TaskContext& context) -{ - binary_op_template(context); -} - -} // namespace numpy -} // namespace legate From 1c9fd1fd3ef11289ace38ed8f1605510c0ac97bf Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sat, 11 Dec 2021 18:50:23 -0800 Subject: [PATCH 36/46] cleanup --- src/fused_binary/binary_op.cu | 79 ------ src/fused_binary/binary_op.h | 48 ---- src/fused_binary/binary_op_template.inl | 136 --------- src/fused_binary/binary_op_util.h | 345 ----------------------- src/fused_binary/binary_red.cc | 68 ----- src/fused_binary/binary_red.cu | 85 ------ src/fused_binary/binary_red.h | 48 ---- src/fused_binary/binary_red_omp.cc | 63 ----- src/fused_binary/binary_red_template.inl | 95 ------- src/fused_binary/fused_op.cc | 117 -------- src/fused_binary/fused_op_omp.cc | 62 ---- src/fused_binary/makeshift_serializer.h | 80 ------ src/fused_binary/scalar_binary_op.cc | 96 ------- src/fused_binary/scalar_binary_op.h | 34 --- 14 files changed, 1356 deletions(-) delete mode 100644 src/fused_binary/binary_op.cu delete mode 100644 src/fused_binary/binary_op.h delete mode 100644 src/fused_binary/binary_op_template.inl delete mode 100644 src/fused_binary/binary_op_util.h delete mode 100644 src/fused_binary/binary_red.cc delete mode 100644 src/fused_binary/binary_red.cu delete mode 100644 src/fused_binary/binary_red.h delete mode 100644 src/fused_binary/binary_red_omp.cc delete mode 100644 src/fused_binary/binary_red_template.inl delete mode 100644 src/fused_binary/fused_op.cc delete mode 100644 src/fused_binary/fused_op_omp.cc delete mode 100644 src/fused_binary/makeshift_serializer.h delete mode 100644 src/fused_binary/scalar_binary_op.cc delete mode 100644 src/fused_binary/scalar_binary_op.h diff --git a/src/fused_binary/binary_op.cu b/src/fused_binary/binary_op.cu deleted file mode 100644 index a83792b69..000000000 --- a/src/fused_binary/binary_op.cu +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "binary/binary_op.h" -#include "binary_op_template.inl" - -#include "cuda_help.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) - dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - out[idx] = func(in1[idx], in2[idx]); -} - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( - size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - auto point = pitches.unflatten(idx, rect.lo); - out[point] = func(in1[point], in2[point]); -} - -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - size_t volume = rect.volume(); - const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); - } else { - generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); - } - } -}; - -/*static*/ void BinaryOpTask::gpu_variant(TaskContext& context) -{ - binary_op_template(context); -} - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/binary_op.h b/src/fused_binary/binary_op.h deleted file mode 100644 index 91da88101..000000000 --- a/src/fused_binary/binary_op.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -#include "numpy.h" -#include "fused/binary_op_util.h" - -namespace legate { -namespace numpy { - -struct BinaryOpArgs { - const Array& in1; - const Array& in2; - const Array& out; - BinaryOpCode op_code; - std::vector args; -}; - -class FusedOpTask : public NumPyTask { - public: - static const int TASK_ID = NUMPY_FUSED_OP; - - public: - static void cpu_variant(TaskContext& context); -#ifdef LEGATE_USE_OPENMP - static void omp_variant(TaskContext& context); -#endif -#ifdef LEGATE_USE_CUDA - static void gpu_variant(TaskContext& context); -#endif -}; - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/binary_op_template.inl b/src/fused_binary/binary_op_template.inl deleted file mode 100644 index d3ab7e975..000000000 --- a/src/fused_binary/binary_op_template.inl +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "fused/binary_op_util.h" -#include "pitches.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct BinaryOpImplBody; - -template -struct BinaryOpImpl { - template ::valid>* = nullptr> - void operator()(BinaryOpArgs& args) const - { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - auto rect = args.out.shape(); - - Pitches pitches; - size_t volume = pitches.flatten(rect); - - if (volume == 0) return; - - auto out = args.out.write_accessor(rect); - auto in1 = args.in1.read_accessor(rect); - auto in2 = args.in2.read_accessor(rect); - -#ifndef LEGION_BOUNDS_CHECKS - // Check to see if this is dense or not - bool dense = out.accessor.is_dense_row_major(rect) && in1.accessor.is_dense_row_major(rect) && - in2.accessor.is_dense_row_major(rect); -#else - // No dense execution if we're doing bounds checks - bool dense = false; -#endif - - OP func{args.args}; - BinaryOpImplBody()(func, out, in1, in2, pitches, rect, dense); - } - - template ::valid>* = nullptr> - void operator()(BinaryOpArgs& args) const - { - assert(false); - } -}; - -template -struct BinaryOpDispatch { - template - void operator()(BinaryOpArgs& args) const - { - auto dim = std::max(args.in1.dim(), args.in2.dim()); - double_dispatch(dim, args.in1.code(), BinaryOpImpl{}, args); - } -}; - - - -template -static void binary_op_template(TaskContext& context) -{ - auto& inputs = context.inputs(); - auto& outputs = context.outputs(); - auto& scalars = context.scalars(); -/* - std::vector extra_args; - for (size_t idx = 2; idx < inputs.size(); ++idx) - extra_args.push_back(inputs[idx].scalar()); - std::cout<<"extra args size"<(), std::move(extra_args)}; - op_dispatch(args.op_code, BinaryOpDispatch{}, args); -*/ - //std::cout<<"fused inputs"<().hi.x; - //std::cout<<"nops "<(); - auto opcode_i = static_cast::type>(opcode); - //std::cout<<"opcode "<().lo.x<<" "<().hi.x< extra_args; - //for (size_t idx = 3; idx < inputs.size(); ++idx) - // extra_args.push_back(inputs[idx].scalar()); - - int inputStart=4; - int outputStart=0; - - for (int i=0; i(), std::move(extra_args)}; - op_dispatch(args.op_code, BinaryOpDispatch{}, args); - inputStart+=2; - outputStart+=1; - } - /* - BinaryOpArgs args2{ - inputs[6], inputs[7], outputs[1], scalars[1].value(), std::move(extra_args)}; - op_dispatch(args2.op_code, BinaryOpDispatch{}, args2); - */ -} - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/binary_op_util.h b/src/fused_binary/binary_op_util.h deleted file mode 100644 index 08f85ad2e..000000000 --- a/src/fused_binary/binary_op_util.h +++ /dev/null @@ -1,345 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -#include "numpy.h" - -namespace legate { -namespace numpy { - -enum class BinaryOpCode : int { - ADD = 1, - DIVIDE, - EQUAL, - FLOOR_DIVIDE, - GREATER, - GREATER_EQUAL, - LESS, - LESS_EQUAL, - MAXIMUM, - MINIMUM, - MOD, - MULTIPLY, - NOT_EQUAL, - POWER, - SUBTRACT, - ALLCLOSE, -}; - -template -constexpr decltype(auto) op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) -{ - switch (op_code) { - case BinaryOpCode::ADD: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::DIVIDE: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::FLOOR_DIVIDE: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::GREATER: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::GREATER_EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::LESS: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::LESS_EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MAXIMUM: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MINIMUM: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MOD: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::MULTIPLY: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::NOT_EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::POWER: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::SUBTRACT: - return f.template operator()(std::forward(args)...); - default: break; - } - assert(false); - return f.template operator()(std::forward(args)...); -} - -template -constexpr decltype(auto) reduce_op_dispatch(BinaryOpCode op_code, Functor f, Fnargs&&... args) -{ - switch (op_code) { - case BinaryOpCode::EQUAL: - return f.template operator()(std::forward(args)...); - case BinaryOpCode::ALLCLOSE: - return f.template operator()(std::forward(args)...); - default: break; - } - assert(false); - return f.template operator()(std::forward(args)...); -} - -template -struct BinaryOp { - static constexpr bool valid = false; -}; - -template -struct BinaryOp : std::plus> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::divides> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::equal_to> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -using std::floor; -template -struct BinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return floor(a / b); } -}; -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::greater> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::greater_equal> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::less> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::less_equal> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return std::max(a, b); } -}; - -template -struct BinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - constexpr T operator()(const T& a, const T& b) const { return std::min(a, b); } -}; - -template -constexpr T real_mod(const T& a, const T& b) -{ - T res = std::fmod(a, b); - if (res) { - if ((b < static_cast(0)) != (res < static_cast(0))) res += b; - } else { - res = std::copysign(static_cast(0), b); - } - return res; -} - -template -struct BinaryOp { - using T = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - template ::value>* = nullptr> - constexpr _T operator()(const _T& a, const _T& b) const - { - return a % b; - } - - template ::value>* = nullptr> - constexpr _T operator()(const _T& a, const _T& b) const - { - return real_mod(a, b); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const - { - return static_cast<__half>(real_mod(static_cast(a), static_cast(b))); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template <> -struct BinaryOp { - static constexpr bool valid = false; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::multiplies> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp : std::not_equal_to> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp { - using VAL = legate_type_of; - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - constexpr VAL operator()(const VAL& a, const VAL& b) const { return std::pow(a, b); } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX __half operator()(const __half& a, const __half& b) const - { - return pow(a, b); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX complex operator()(const complex& a, - const complex& b) const - { - return pow(a, b); - } -}; - -template <> -struct BinaryOp { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} - LEGATE_DEVICE_PREFIX complex operator()(const complex& a, - const complex& b) const - { - return pow(a, b); - } -}; - -template -struct BinaryOp : std::minus> { - static constexpr bool valid = true; - BinaryOp() {} - BinaryOp(const std::vector& args) {} -}; - -template -struct BinaryOp { - using VAL = legate_type_of; - static constexpr bool valid = true; - - BinaryOp() {} - BinaryOp(const std::vector& args) - { - assert(args.size() == 2); - rtol_ = args[0].value(); - atol_ = args[1].value(); - } - - template ::value>* = nullptr> - constexpr bool operator()(const T& a, const T& b) const - { - using std::fabs; - return fabs(static_cast(a) - static_cast(b)) <= - atol_ + rtol_ * static_cast(fabs(b)); - } - - template ::value>* = nullptr> - constexpr bool operator()(const T& a, const T& b) const - { - return static_cast(abs(a - b)) <= atol_ + rtol_ * static_cast(abs(b)); - } - - double rtol_{0}; - double atol_{0}; -}; - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/binary_red.cc b/src/fused_binary/binary_red.cc deleted file mode 100644 index efb72bf83..000000000 --- a/src/fused_binary/binary_red.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "binary/binary_red.h" -#include "binary/binary_red_template.inl" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct BinaryRedImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - - UntypedScalar operator()(OP func, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - size_t volume = rect.volume(); - if (dense) { - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - for (size_t idx = 0; idx < volume; ++idx) - if (!func(in1ptr[idx], in2ptr[idx])) return UntypedScalar(false); - } else { - for (size_t idx = 0; idx < volume; ++idx) { - auto point = pitches.unflatten(idx, rect.lo); - if (!func(in1[point], in2[point])) return UntypedScalar(false); - } - } - - return UntypedScalar(true); - } -}; - -/*static*/ UntypedScalar BinaryRedTask::cpu_variant(TaskContext& context) -{ - return binary_red_template(context); -} - -namespace // unnamed -{ -static void __attribute__((constructor)) register_tasks(void) -{ - BinaryRedTask::register_variants_with_return(); -} -} // namespace - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/binary_red.cu b/src/fused_binary/binary_red.cu deleted file mode 100644 index e05d47325..000000000 --- a/src/fused_binary/binary_red.cu +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "binary/binary_red.h" -#include "binary/binary_red_template.inl" - -#include "cuda_help.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) - dense_kernel(size_t volume, Function func, RES out, const ARG* in1, const ARG* in2) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - if (!func(in1[idx], in2[idx])) out <<= false; -} - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( - size_t volume, Function func, RES out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - auto point = pitches.unflatten(idx, rect.lo); - if (!func(in1[point], in2[point])) out <<= false; -} - -template -struct BinaryRedImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - - UntypedScalar operator()(OP func, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - size_t volume = rect.volume(); - const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; - DeferredReduction> result; - cudaStream_t stream; - cudaStreamCreate(&stream); - if (dense) { - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - dense_kernel<<>>(volume, func, result, in1ptr, in2ptr); - } else { - generic_kernel<<>>( - volume, func, result, in1, in2, pitches, rect); - } - - cudaStreamSynchronize(stream); - cudaStreamDestroy(stream); - - return UntypedScalar(result.read()); - } -}; - -/*static*/ UntypedScalar BinaryRedTask::gpu_variant(TaskContext& context) -{ - return binary_red_template(context); -} - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/binary_red.h b/src/fused_binary/binary_red.h deleted file mode 100644 index 3f5300889..000000000 --- a/src/fused_binary/binary_red.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -#include "numpy.h" -#include "scalar.h" -#include "binary/binary_op_util.h" - -namespace legate { -namespace numpy { - -struct BinaryRedArgs { - const Array& in1; - const Array& in2; - BinaryOpCode op_code; - std::vector args; -}; - -class BinaryRedTask : public NumPyTask { - public: - static const int TASK_ID = NUMPY_BINARY_RED; - - public: - static UntypedScalar cpu_variant(TaskContext& context); -#ifdef LEGATE_USE_OPENMP - static UntypedScalar omp_variant(TaskContext& context); -#endif -#ifdef LEGATE_USE_CUDA - static UntypedScalar gpu_variant(TaskContext& context); -#endif -}; - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/binary_red_omp.cc b/src/fused_binary/binary_red_omp.cc deleted file mode 100644 index 3e9c912b7..000000000 --- a/src/fused_binary/binary_red_omp.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "binary/binary_red.h" -#include "binary/binary_red_template.inl" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct BinaryRedImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - - UntypedScalar operator()(OP func, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - size_t volume = rect.volume(); - bool result = true; - if (dense) { - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); -#pragma omp parallel for schedule(static) - for (size_t idx = 0; idx < volume; ++idx) - if (!func(in1ptr[idx], in2ptr[idx])) result = false; - } else { -#pragma omp parallel for schedule(static) - for (size_t idx = 0; idx < volume; ++idx) { - auto point = pitches.unflatten(idx, rect.lo); - if (!func(in1[point], in2[point])) result = false; - } - } - - return UntypedScalar(result); - } -}; - -/*static*/ UntypedScalar BinaryRedTask::omp_variant(TaskContext& context) -{ - return binary_red_template(context); -} - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/binary_red_template.inl b/src/fused_binary/binary_red_template.inl deleted file mode 100644 index ef9d75094..000000000 --- a/src/fused_binary/binary_red_template.inl +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "binary/binary_op_util.h" -#include "pitches.h" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct BinaryRedImplBody; - -template -struct BinaryRedImpl { - template ::valid>* = nullptr> - UntypedScalar operator()(BinaryRedArgs& args) const - { - using OP = BinaryOp; - using ARG = legate_type_of; - - auto rect = args.in1.shape(); - - Pitches pitches; - size_t volume = pitches.flatten(rect); - - if (volume == 0) return UntypedScalar(true); - - auto in1 = args.in1.read_accessor(rect); - auto in2 = args.in2.read_accessor(rect); - -#ifndef LEGION_BOUNDS_CHECKS - // Check to see if this is dense or not - bool dense = in1.accessor.is_dense_row_major(rect) && in2.accessor.is_dense_row_major(rect); -#else - // No dense execution if we're doing bounds checks - bool dense = false; -#endif - - OP func(args.args); - return BinaryRedImplBody()(func, in1, in2, pitches, rect, dense); - } - - template ::valid>* = nullptr> - UntypedScalar operator()(BinaryRedArgs& args) const - { - assert(false); - return UntypedScalar(); - } -}; - -template -struct BinaryRedDispatch { - template - UntypedScalar operator()(BinaryRedArgs& args) const - { - auto dim = std::max(args.in1.dim(), args.in2.dim()); - return double_dispatch(dim, args.in1.code(), BinaryRedImpl{}, args); - } -}; - -template -static UntypedScalar binary_red_template(TaskContext& context) -{ - auto& inputs = context.inputs(); - auto& scalars = context.scalars(); - - std::vector extra_args; - for (size_t idx = 2; idx < inputs.size(); ++idx) - extra_args.push_back(inputs[idx].scalar()); - - BinaryRedArgs args{inputs[0], inputs[1], scalars[0].value(), std::move(extra_args)}; - return reduce_op_dispatch(args.op_code, BinaryRedDispatch{}, args); -} - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/fused_op.cc b/src/fused_binary/fused_op.cc deleted file mode 100644 index 6897f1aa4..000000000 --- a/src/fused_binary/fused_op.cc +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "fused/makeshift_serializer.h" -#include "fused/binary_op.h" -#include "fused/binary_op_template.inl" -#include "legion.h" -//#include "legion/legion_utilities.h" -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - const size_t volume = rect.volume(); - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); - } else { - for (size_t idx = 0; idx < volume; ++idx) { - auto p = pitches.unflatten(idx, rect.lo); - out[p] = func(in1[p], in2[p]); - } - } - } -}; - -void inline_leaf_task(const Task *task, - const std::vector ®ions, - Context ctx, Runtime *runtime) -{ - printf("Hello from 'inline_leaf_task' being inlined into leaf 'fused op'\n"); -} - -/*static*/ void FusedOpTask::cpu_variant(TaskContext& context) -{ -/* -TaskLauncher(TaskID tid, - TaskArgument arg, - Predicate pred = Predicate::TRUE_PRED, - MapperID id = 0, - MappingTagID tag = 0); - - Deserializer dez(task, regions); - inputs_ = dez.unpack>(); - outputs_ = dez.unpack>(); - reductions_ = dez.unpack>(); - scalars_ = dez.unpack>(); -*/ - const int INLINE_LEAF_TASK_ID =0; - MakeshiftSerializer ms; - - //pack inputs - ms.pack(context.inputs().size()); - for (auto& input : context.inputs()) - { - ms.pack(input.is_future()); //is_future - ms.pack(input.dim()); - int code = input.code(); - ms.pack(code); - } - //pack inputs - //pack outputs - //pack reductions - //pack scalars - - - TaskLauncher inline_leaf_launcher(INLINE_LEAF_TASK_ID, TaskArgument()); - std::cout<<"trying to launch leaf task"<execute_task(ctx, inline_leaf_launcher); - - - //../legate.core/legion//examples/local_function_tasks/local_function_tasks.cc - binary_op_template(context); -} - -namespace // unnamed -{ -static void __attribute__((constructor)) register_tasks(void) { FusedOpTask::register_variants(); } -} // namespace - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/fused_op_omp.cc b/src/fused_binary/fused_op_omp.cc deleted file mode 100644 index 0d4151442..000000000 --- a/src/fused_binary/fused_op_omp.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#include "fused/binary_op.h" -#include "fused/binary_op_template.inl" - -namespace legate { -namespace numpy { - -using namespace Legion; - -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - const size_t volume = rect.volume(); - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); -#pragma omp parallel for schedule(static) - for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); - } else { -#pragma omp parallel for schedule(static) - for (size_t idx = 0; idx < volume; ++idx) { - auto p = pitches.unflatten(idx, rect.lo); - out[p] = func(in1[p], in2[p]); - } - } - } -}; - -/*static*/ void FusedOpTask::omp_variant(TaskContext& context) -{ - binary_op_template(context); -} - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/makeshift_serializer.h b/src/fused_binary/makeshift_serializer.h deleted file mode 100644 index ac8abf004..000000000 --- a/src/fused_binary/makeshift_serializer.h +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include - -class MakeshiftSerializer{ - - public: - MakeshiftSerializer(){ - size=4; - raw.resize(size); - write_offset=0; - read_offset=0; - } - - template void pack(T& arg) - { - if (size<=write_offset+sizeof(T)) - { - resize(sizeof(T)); - } - raw[write_offset] = *reinterpret_cast(&arg); - write_offset+=sizeof(T); - } - - template void pack(T&& arg) - { - T copy = arg; - pack(copy); - } - - template T read() - { - if (read_offset(raw.data()+read_offset); - read_offset+=sizeof(T); - return datum; - } - else{ - std::cout<<"finished reading buffer"< raw; -}; -/* -int main(){ - MakeshiftSerializer ms; - int a=3; - char g='a'; - ms.pack(a); - ms.pack(g); - ms.pack(a); - ms.pack(g); - std::cout<()<()<()<()<()<()< -struct BinaryOpImpl { - template ::valid>* = nullptr> - UntypedScalar operator()(const UntypedScalar& in1, - const UntypedScalar& in2, - const std::vector& args) const - { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - OP func{args}; - - auto a = in1.value(); - auto b = in2.value(); - auto result = func(a, b); - - return UntypedScalar(result); - } - - template ::valid>* = nullptr> - UntypedScalar operator()(const UntypedScalar& in1, - const UntypedScalar& in2, - const std::vector& args) const - { - assert(false); - return UntypedScalar(); - } -}; - -struct BinaryOpDispatch { - template - UntypedScalar operator()(const UntypedScalar& in1, - const UntypedScalar& in2, - const std::vector& args) const - { - return type_dispatch(in1.code(), BinaryOpImpl{}, in1, in2, args); - } -}; - -/*static*/ UntypedScalar ScalarBinaryOpTask::cpu_variant(TaskContext& context) -{ - auto op_code = context.scalars()[0].value(); - - auto& inputs = context.inputs(); - - auto& in1 = inputs[0]; - auto& in2 = inputs[1]; - - std::vector args; - for (auto idx = 2; idx < inputs.size(); ++idx) - args.push_back(inputs[idx].scalar()); - - if (op_code == BinaryOpCode::ALLCLOSE) - return BinaryOpDispatch{}.operator()( - in1.scalar(), in2.scalar(), args); - else - return op_dispatch( - op_code, BinaryOpDispatch{}, in1.scalar(), in2.scalar(), args); -} - -namespace // unnamed -{ -static void __attribute__((constructor)) register_tasks(void) -{ - ScalarBinaryOpTask::register_variants_with_return(); -} -} // namespace - -} // namespace numpy -} // namespace legate diff --git a/src/fused_binary/scalar_binary_op.h b/src/fused_binary/scalar_binary_op.h deleted file mode 100644 index 04c55806c..000000000 --- a/src/fused_binary/scalar_binary_op.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2021 NVIDIA Corporation - * - * 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. - * - */ - -#pragma once - -#include "numpy.h" -#include "scalar.h" - -namespace legate { -namespace numpy { - -class ScalarBinaryOpTask : public NumPyTask { - public: - static const int TASK_ID = NUMPY_SCALAR_BINARY_OP; - - public: - static UntypedScalar cpu_variant(TaskContext& contex); -}; - -} // namespace numpy -} // namespace legate From 1665cb5106a3069c97a2cd5ecefeb9fcd2f093a8 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 12 Dec 2021 12:28:15 -0800 Subject: [PATCH 37/46] constant opt adjustment --- cunumeric/array.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cunumeric/array.py b/cunumeric/array.py index 703da256d..bccc68dbd 100644 --- a/cunumeric/array.py +++ b/cunumeric/array.py @@ -1979,11 +1979,12 @@ def perform_binary_op( if out_dtype is None: out_dtype = cls.find_common_type(one, two) if check_types: - conOpt = isinstance(one._thunk, DeferredArray) or isinstance(two._thunk, DeferredArray) + isDeferred =isinstance(one._thunk, DeferredArray) or isinstance(two._thunk, DeferredArray) if one.dtype != two.dtype: common_type = cls.find_common_type(one, two) if one.dtype != common_type: - if conOpt and one.shape==(): + #remove convert ops + if isDeferred and one.shape==(): temp = ndarray( shape=one.shape, dtype=common_type, @@ -2004,7 +2005,8 @@ def perform_binary_op( ) one = temp if two.dtype != common_type: - if conOpt and isinstance(two._thunk, DeferredArray) and two.shape==(): + #remove convert ops + if isDeferred and two.shape==(): temp = ndarray( shape=two.shape, dtype=common_type, From aedf22dc4e1428f6f47499c1cd11a26bb10ea2e2 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 12 Dec 2021 12:34:08 -0800 Subject: [PATCH 38/46] merging --- src/cunumeric/cunumeric_c.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cunumeric/cunumeric_c.h b/src/cunumeric/cunumeric_c.h index 41cc6baee..5f78c5631 100644 --- a/src/cunumeric/cunumeric_c.h +++ b/src/cunumeric/cunumeric_c.h @@ -46,6 +46,7 @@ enum CuNumericOpCode { CUNUMERIC_UNARY_RED, CUNUMERIC_WHERE, CUNUMERIC_WRITE, + CUNUMERIC_FUSED_OP, }; // Match these to CuNumericRedopCode in cunumeric/config.py From a3dd95a1fc0aa60b06508c7c8286f6c85b48a408 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 12 Dec 2021 13:37:25 -0800 Subject: [PATCH 39/46] undo last change --- build.sh | 2 +- src/cunumeric/unary/unary_op_template.inl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 4fc08b3b7..91830a0b1 100755 --- a/build.sh +++ b/build.sh @@ -4,5 +4,5 @@ cd ../legate.core/ python setup.py --gasnet --conduit ibv --cuda --with-cuda /usr/local/cuda/ --arch pascal cd ../legate.numpy/ -python setup.py --with-core ../legate.core/install/ --verbose +python setup.py --with-core ../legate.core/install/ --verbose --clean #../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/src/cunumeric/unary/unary_op_template.inl b/src/cunumeric/unary/unary_op_template.inl index 6954c52ab..f3ba3c122 100644 --- a/src/cunumeric/unary/unary_op_template.inl +++ b/src/cunumeric/unary/unary_op_template.inl @@ -56,7 +56,7 @@ struct UnaryOpImpl { OP func{args.args}; UnaryOpImplBody()(func, out, in, pitches, rect, dense); } - + template ::valid>* = nullptr> @@ -64,6 +64,7 @@ struct UnaryOpImpl { { assert(false); } + }; template From 1fe56d39dc4cb0eca000b77c0699340fb5cf818a Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 12 Dec 2021 17:17:23 -0800 Subject: [PATCH 40/46] cleanup fused op --- src/cunumeric/fused/fused_op.cc | 121 -------------------------------- 1 file changed, 121 deletions(-) diff --git a/src/cunumeric/fused/fused_op.cc b/src/cunumeric/fused/fused_op.cc index eedcd2275..102b084c5 100644 --- a/src/cunumeric/fused/fused_op.cc +++ b/src/cunumeric/fused/fused_op.cc @@ -14,11 +14,9 @@ * */ -#include "core/utilities/makeshift_serializer.h" #include "core/runtime/runtime.h" #include "core/runtime/context.h" #include "cunumeric/fused/fused_op.h" -//#include "cunumeric/fused/binary_op_template.inl" #include "legion.h" #include #include @@ -29,133 +27,14 @@ namespace cunumeric { using namespace Legion; using namespace legate; -/* -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - const size_t volume = rect.volume(); - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - for (size_t idx = 0; idx < volume; ++idx) outptr[idx] = func(in1ptr[idx], in2ptr[idx]); - } else { - for (size_t idx = 0; idx < volume; ++idx) { - auto p = pitches.unflatten(idx, rect.lo); - out[p] = func(in1[p], in2[p]); - } - } - } -}; -*/ - - -//op id refers not to the op's type, but the index in the list of fused ops -void packOp(legate::MakeshiftSerializer& ms, TaskContext& context, int opID) -{ - auto inputStarts = context.fusionMetadata.inputStarts; - auto outputStarts = context.fusionMetadata.outputStarts; - auto offsetStarts = context.fusionMetadata.offsetStarts; - auto offsets = context.fusionMetadata.offsets; - auto reductionStarts = context.fusionMetadata.reductionStarts; - auto scalarStarts = context.fusionMetadata.scalarStarts; - - //the leaf task cannot be fused ops currently - ms.pack((bool) false); - - //pack inputs - unsigned nInputs = (inputStarts[opID+1]-inputStarts[opID]); //want to pack this as a 32 bit uint - ms.pack((uint32_t) nInputs); - //std::cout<<"inputs "<0) - { - bufferID--; - //std::cout<<"packing input "< regions; //context.runtime_->execute_task(context.context_, leaf_launcher); From c8c69b8ce90700f7c3000a331bdee047620e88ee Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 12 Dec 2021 17:29:01 -0800 Subject: [PATCH 41/46] more cleanup --- bench.sh | 1 - build.sh | 8 -- cunumeric/array.py | 2 +- cunumeric/deferred.py | 4 - cunumeric/runtime.py | 17 ++-- examples/black_scholes.py | 12 +-- examples/stencil.py | 2 +- setup.py | 2 +- src/cunumeric/fused/fused_op.cu | 52 ------------ src/cunumeric/fused/fused_op.h | 11 +-- src/cunumeric/matrix/matvecmul_template.inl | 7 +- src/cunumeric/unary/unary_op_template.inl | 4 +- src/numpy.mk | 93 --------------------- test.py | 2 +- time.sh | 1 - 15 files changed, 14 insertions(+), 204 deletions(-) delete mode 100644 bench.sh delete mode 100755 build.sh delete mode 100644 src/numpy.mk delete mode 100644 time.sh diff --git a/bench.sh b/bench.sh deleted file mode 100644 index 54cda33f6..000000000 --- a/bench.sh +++ /dev/null @@ -1 +0,0 @@ -time ../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/build.sh b/build.sh deleted file mode 100755 index 91830a0b1..000000000 --- a/build.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -#touch src/matrix/matvecmul.cc -#touch src/fused/fused_op.cc -cd ../legate.core/ -python setup.py --gasnet --conduit ibv --cuda --with-cuda /usr/local/cuda/ --arch pascal -cd ../legate.numpy/ -python setup.py --with-core ../legate.core/install/ --verbose --clean -#../legate.core/install/bin/legate examples/testbench/test.py --cpus 2 diff --git a/cunumeric/array.py b/cunumeric/array.py index a10474098..a162e8e58 100644 --- a/cunumeric/array.py +++ b/cunumeric/array.py @@ -24,7 +24,7 @@ from legate.core import Array -from .config import BinaryOpCode, CuNumericOpCode, UnaryOpCode, UnaryRedCode, FusedOpCode#, DoubleBinaryOpCode +from .config import BinaryOpCode, CuNumericOpCode, UnaryOpCode, UnaryRedCode, FusedOpCode from .doc_utils import copy_docstring from .runtime import runtime from .utils import unimplemented diff --git a/cunumeric/deferred.py b/cunumeric/deferred.py index 5b12d0a6d..95ba5aa4c 100644 --- a/cunumeric/deferred.py +++ b/cunumeric/deferred.py @@ -844,9 +844,6 @@ def convert(self, rhs, stacklevel=0, warn=True, callsite=None): task.add_input(rhs) task.add_dtype_arg(lhs_array.dtype) - #task.add_broadcast(rhs) - #task.add_broadcast(lhs) - task.add_alignment(lhs, rhs) task.execute() @@ -1552,7 +1549,6 @@ def unary_reduction( callsite=callsite, ) - # Perform the binary operation and put the result in the lhs array @profile @auto_convert([2, 3]) diff --git a/cunumeric/runtime.py b/cunumeric/runtime.py index 96526d93c..0a5bf1aa9 100644 --- a/cunumeric/runtime.py +++ b/cunumeric/runtime.py @@ -351,16 +351,11 @@ def compute_parent_child_mapping(array): assert child_ptr >= parent_ptr ptr_diff = child_ptr - parent_ptr parent_shape = array.base.shape - #if False and parent_shape==(): - if parent_shape==(): - parent_shape = () - div =1 - else: - div = ( - reduce(lambda x, y: x * y, parent_shape) - if len(parent_shape) > 1 - else parent_shape[0] - ) + div = ( + reduce(lambda x, y: x * y, parent_shape) + if len(parent_shape) > 1 + else parent_shape[0] + ) div *= array.dtype.itemsize offsets = list() # Compute the offsets in the parent index @@ -507,7 +502,6 @@ def create_empty_thunk(self, shape, dtype, inputs=None): store = self.legate_context.create_store( dtype, shape=shape, optimize_scalar=True ) - result = DeferredArray(self, store, dtype=dtype) # If we're doing shadow debug make an EagerArray shadow if self.shadow_debug: @@ -582,7 +576,6 @@ def to_deferred_array(self, array, stacklevel): elif self.is_lazy_array(array): raise NotImplementedError("convert lazy array to deferred array") else: - print(type(array)) raise RuntimeError("invalid array type") def to_lazy_array(self, array, stacklevel): diff --git a/examples/black_scholes.py b/examples/black_scholes.py index 8ee73eeb1..02b3a2e7d 100644 --- a/examples/black_scholes.py +++ b/examples/black_scholes.py @@ -28,7 +28,6 @@ def generate_random(N, min, max, D): diff = D(max) - D(min) - #print("diff", diff) rands = np.random.random(N).astype(D) rands = rands * diff rands = rands + D(min) @@ -65,9 +64,6 @@ def cnd(d): def black_scholes(S, X, T, R, V): sqrt_t = np.sqrt(T) - #sqrt_t = np.sqrt(T) - #sqrt_t = np.sqrt(T) - #sqrt_t = np.sqrt(T) d1 = np.log(S / X) + (R + 0.5 * V * V) * T / (V * sqrt_t) d2 = d1 - V * sqrt_t cnd_d1 = cnd(d1) @@ -79,23 +75,18 @@ def black_scholes(S, X, T, R, V): def run_black_scholes(N, D): - #print("Running black scholes on %dK options..." % N) + print("Running black scholes on %dK options..." % N) N *= 1000 start = datetime.datetime.now() S, X, T, R, V = initialize(N, D) - #return trials = 300 ends = [None for i in range(trials)] for i in range(trials): call, put = black_scholes(S, X, T, R, V) # Check the result for NaNs to synchronize before stopping timing call_sum = np.sum(call) - #call_sum2 = np.sum(call) put_sum = np.sum(put) ends[i] = (call_sum, put_sum) - #assert not math.isnan(call_sum) and not math.isnan(put_sum) - #put_sum2 = np.sum(put) - #print(call_sum2, put_sum2) for i in range(trials): call_sum, put_sum = ends[i] assert not math.isnan(call_sum) and not math.isnan(put_sum) @@ -103,7 +94,6 @@ def run_black_scholes(N, D): delta = stop - start total = delta.total_seconds() * 1000.0 print("Elapsed Time: " + str(total) + " ms") - #print(call_sum, put_sum) return total diff --git a/examples/stencil.py b/examples/stencil.py index 329410b0b..9850a856f 100644 --- a/examples/stencil.py +++ b/examples/stencil.py @@ -44,7 +44,7 @@ def run(grid, I, N): # noqa: E741 west = grid[1:-1, 0:-2] south = grid[2:, 1:-1] for i in range(I): - average = center + north + south + east + west + average = center + north + east + west + south work = 0.2 * average # delta = np.sum(np.absolute(work - center)) center[:] = work diff --git a/setup.py b/setup.py index 6bdcd4b8d..85cee9bce 100755 --- a/setup.py +++ b/setup.py @@ -74,7 +74,7 @@ def run(self): sys.argv.remove("--recurse") setup( name="cunumeric", - version="21.10.00", + version="0.1", packages=[ "cunumeric", "cunumeric.linalg", diff --git a/src/cunumeric/fused/fused_op.cu b/src/cunumeric/fused/fused_op.cu index a4aedd1c3..8aa9a36ab 100644 --- a/src/cunumeric/fused/fused_op.cu +++ b/src/cunumeric/fused/fused_op.cu @@ -22,53 +22,7 @@ namespace cunumeric { using namespace Legion; using namespace legate; -/* -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) - dense_kernel(size_t volume, Function func, RES* out, const ARG* in1, const ARG* in2) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - out[idx] = func(in1[idx], in2[idx]); -} - -template -static __global__ void __launch_bounds__(THREADS_PER_BLOCK, MIN_CTAS_PER_SM) generic_kernel( - size_t volume, Function func, WriteAcc out, ReadAcc in1, ReadAcc in2, Pitches pitches, Rect rect) -{ - const size_t idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx >= volume) return; - auto point = pitches.unflatten(idx, rect.lo); - out[point] = func(in1[point], in2[point]); -} - -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const - { - size_t volume = rect.volume(); - const size_t blocks = (volume + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK; - if (dense) { - auto outptr = out.ptr(rect); - auto in1ptr = in1.ptr(rect); - auto in2ptr = in2.ptr(rect); - dense_kernel<<>>(volume, func, outptr, in1ptr, in2ptr); - } else { - generic_kernel<<>>(volume, func, out, in1, in2, pitches, rect); - } - } -}; -*/ /*static*/ void FusedOpTask::gpu_variant(TaskContext& context){ int nOps = context.fusionMetadata.nOps; @@ -76,7 +30,6 @@ struct BinaryOpImplBody { auto offsets = context.fusionMetadata.offsets; for (int i=0; i regions; //create new context const Legion::Task* task = (Legion::Task*) context.task_; @@ -129,7 +82,6 @@ struct BinaryOpImplBody { } //pack scalars - //std::vector scalars; auto scalarStarts = context.fusionMetadata.scalarStarts; int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); std::vector scalars; @@ -158,10 +110,6 @@ struct BinaryOpImplBody { bufferID = (-bufferID)-1; context.outputs_[outputStart+bufferID] = std::move(context3.outputs_[j]); } - - - //context3.pack_return_values(); - //context.pack_return_values(); } } diff --git a/src/cunumeric/fused/fused_op.h b/src/cunumeric/fused/fused_op.h index e71b20eaa..e568e8515 100644 --- a/src/cunumeric/fused/fused_op.h +++ b/src/cunumeric/fused/fused_op.h @@ -17,18 +17,9 @@ #pragma once #include "cunumeric/cunumeric.h" -//#include "cunumeric/fused/binary_op_util.h" namespace cunumeric { -/* -struct BinaryOpArgs { - const Array& in1; - const Array& in2; - const Array& out; - BinaryOpCode op_code; - std::vector args; -}; -*/ + class FusedOpTask : public CuNumericTask { public: static const int TASK_ID = CUNUMERIC_FUSED_OP; diff --git a/src/cunumeric/matrix/matvecmul_template.inl b/src/cunumeric/matrix/matvecmul_template.inl index 383f203e7..4c4b8b296 100644 --- a/src/cunumeric/matrix/matvecmul_template.inl +++ b/src/cunumeric/matrix/matvecmul_template.inl @@ -83,12 +83,7 @@ struct MatVecMulImpl { size_t lhs_strides[2]; auto lhs = args.lhs.reduce_accessor, true, 2>().ptr(shape, lhs_strides); - //std::cout<()<()<<" "<()(m, n, lhs, mat, vec, mat_stride, transpose_mat); } diff --git a/src/cunumeric/unary/unary_op_template.inl b/src/cunumeric/unary/unary_op_template.inl index f3ba3c122..c85db61e1 100644 --- a/src/cunumeric/unary/unary_op_template.inl +++ b/src/cunumeric/unary/unary_op_template.inl @@ -56,7 +56,7 @@ struct UnaryOpImpl { OP func{args.args}; UnaryOpImplBody()(func, out, in, pitches, rect, dense); } - + template ::valid>* = nullptr> @@ -64,7 +64,7 @@ struct UnaryOpImpl { { assert(false); } - + }; template diff --git a/src/numpy.mk b/src/numpy.mk deleted file mode 100644 index 22855ece6..000000000 --- a/src/numpy.mk +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2021 NVIDIA Corporation -# -# 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. -# - -# List all the application source files that need OpenMP separately -# since we have to add the -fopenmp flag to CC_FLAGS for them -GEN_CPU_SRC += numpy/ternary/where.cc \ - numpy/binary/binary_op.cc \ - numpy/fused/fused_op.cc \ - numpy/binary/binary_red.cc \ - numpy/unary/scalar_unary_red.cc \ - numpy/unary/unary_op.cc \ - numpy/unary/unary_red.cc \ - numpy/unary/convert.cc \ - numpy/nullary/arange.cc \ - numpy/nullary/eye.cc \ - numpy/nullary/fill.cc \ - numpy/item/read.cc \ - numpy/item/write.cc \ - numpy/matrix/diag.cc \ - numpy/matrix/matmul.cc \ - numpy/matrix/matvecmul.cc \ - numpy/matrix/dot.cc \ - numpy/matrix/tile.cc \ - numpy/matrix/transpose.cc \ - numpy/matrix/util.cc \ - numpy/random/rand.cc \ - numpy/search/nonzero.cc \ - numpy/stat/bincount.cc \ - numpy/arg.cc \ - numpy/mapper.cc \ - numpy/numpy.cc # This must always be the last file! - # It guarantees we do our registration callback - # only after all task variants are recorded - -ifeq ($(strip $(USE_OPENMP)),1) -GEN_CPU_SRC += numpy/ternary/where_omp.cc \ - numpy/binary/binary_op_omp.cc \ - numpy/fused/fused_op_omp.cc \ - numpy/binary/binary_red_omp.cc \ - numpy/unary/unary_op_omp.cc \ - numpy/unary/scalar_unary_red_omp.cc \ - numpy/unary/unary_red_omp.cc \ - numpy/unary/convert_omp.cc \ - numpy/nullary/arange_omp.cc \ - numpy/nullary/eye_omp.cc \ - numpy/nullary/fill_omp.cc \ - numpy/matrix/diag_omp.cc \ - numpy/matrix/matmul_omp.cc \ - numpy/matrix/matvecmul_omp.cc \ - numpy/matrix/dot_omp.cc \ - numpy/matrix/tile_omp.cc \ - numpy/matrix/transpose_omp.cc \ - numpy/matrix/util_omp.cc \ - numpy/random/rand_omp.cc \ - numpy/search/nonzero_omp.cc \ - numpy/stat/bincount_omp.cc -endif - -GEN_GPU_SRC += numpy/ternary/where.cu \ - numpy/binary/binary_op.cu \ - numpy/fused/fused_op.cu \ - numpy/binary/binary_red.cu \ - numpy/unary/scalar_unary_red.cu \ - numpy/unary/unary_red.cu \ - numpy/unary/unary_op.cu \ - numpy/unary/convert.cu \ - numpy/nullary/arange.cu \ - numpy/nullary/eye.cu \ - numpy/nullary/fill.cu \ - numpy/item/read.cu \ - numpy/item/write.cu \ - numpy/matrix/diag.cu \ - numpy/matrix/matmul.cu \ - numpy/matrix/matvecmul.cu \ - numpy/matrix/dot.cu \ - numpy/matrix/tile.cu \ - numpy/matrix/transpose.cu \ - numpy/random/rand.cu \ - numpy/search/nonzero.cu \ - numpy/stat/bincount.cu \ - numpy/numpy.cu diff --git a/test.py b/test.py index 31957855b..6f58ccb98 100755 --- a/test.py +++ b/test.py @@ -51,7 +51,7 @@ # draw tests from these directories legate_tests = [] legate_tests.extend(glob.glob("tests/*.py")) -#legate_tests.extend(glob.glob("examples/*.py")) +legate_tests.extend(glob.glob("examples/*.py")) # some test programs have additional command line arguments test_flags = { diff --git a/time.sh b/time.sh deleted file mode 100644 index ba3194669..000000000 --- a/time.sh +++ /dev/null @@ -1 +0,0 @@ -time ../legate.core/install/bin/legate -m cProfile -s tottime examples/testbench/test.py --cpus 2 > temp_file && head -n 20 temp_file From 4c104dde6d8d3b15c8cbe60f57d2c997604a9033 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Dec 2021 01:34:07 +0000 Subject: [PATCH 42/46] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- cunumeric/array.py | 48 ++++++--- cunumeric/config.py | 7 +- cunumeric/deferred.py | 1 + examples/black_scholes.py | 2 +- examples/stencil.py | 2 +- examples/stencil_27.py | 75 +++++++------- src/cunumeric/fused/fused_op.cc | 155 ++++++++++++++-------------- src/cunumeric/fused/fused_op_omp.cc | 2 +- tests/tensordot.py | 2 +- 9 files changed, 155 insertions(+), 139 deletions(-) diff --git a/cunumeric/array.py b/cunumeric/array.py index a162e8e58..05ffce505 100644 --- a/cunumeric/array.py +++ b/cunumeric/array.py @@ -24,11 +24,18 @@ from legate.core import Array -from .config import BinaryOpCode, CuNumericOpCode, UnaryOpCode, UnaryRedCode, FusedOpCode +from .config import ( + BinaryOpCode, + CuNumericOpCode, + FusedOpCode, + UnaryOpCode, + UnaryRedCode, +) +from .deferred import DeferredArray from .doc_utils import copy_docstring from .runtime import runtime from .utils import unimplemented -from .deferred import DeferredArray + def add_boilerplate(*array_params: str, mutates_self: bool = False): """ @@ -1952,7 +1959,6 @@ def perform_unary_reduction( ) return dst - # Return a new legate array for a binary operation @classmethod def perform_binary_op( @@ -2017,24 +2023,31 @@ def perform_binary_op( if out_dtype is None: out_dtype = cls.find_common_type(one, two) if check_types: - isDeferred =isinstance(one._thunk, DeferredArray) or isinstance(two._thunk, DeferredArray) + isDeferred = isinstance(one._thunk, DeferredArray) or isinstance( + two._thunk, DeferredArray + ) if one.dtype != two.dtype: common_type = cls.find_common_type(one, two) if one.dtype != common_type: - #remove convert ops - if isDeferred and one.shape==(): + # remove convert ops + if isDeferred and one.shape == (): temp = ndarray( shape=one.shape, - dtype=common_type, - #buffer = one._thunk.array.astype(common_type), + dtype=common_type, + # buffer = one._thunk.array.astype(common_type), stacklevel=(stacklevel + 1), inputs=(one, two, where), ) - temp._thunk= runtime.create_scalar(one._thunk.array.astype(common_type), common_type, shape=one.shape, wrap=True) + temp._thunk = runtime.create_scalar( + one._thunk.array.astype(common_type), + common_type, + shape=one.shape, + wrap=True, + ) else: temp = ndarray( shape=one.shape, - dtype=common_type, + dtype=common_type, stacklevel=(stacklevel + 1), inputs=(one, two, where), ) @@ -2043,16 +2056,21 @@ def perform_binary_op( ) one = temp if two.dtype != common_type: - #remove convert ops - if isDeferred and two.shape==(): + # remove convert ops + if isDeferred and two.shape == (): temp = ndarray( shape=two.shape, - dtype=common_type, - #buffer = two._thunk.array.astype(common_type), + dtype=common_type, + # buffer = two._thunk.array.astype(common_type), stacklevel=(stacklevel + 1), inputs=(one, two, where), ) - temp._thunk = runtime.create_scalar(two._thunk.array.astype(common_type), common_type, shape=two.shape, wrap=True) + temp._thunk = runtime.create_scalar( + two._thunk.array.astype(common_type), + common_type, + shape=two.shape, + wrap=True, + ) else: temp = ndarray( shape=two.shape, diff --git a/cunumeric/config.py b/cunumeric/config.py index e96cb6206..1aa74d631 100644 --- a/cunumeric/config.py +++ b/cunumeric/config.py @@ -106,6 +106,7 @@ class CuNumericOpCode(IntEnum): WRITE = _cunumeric.CUNUMERIC_WRITE FUSED_OP = _cunumeric.CUNUMERIC_FUSED_OP + @unique class FusedOpCode(IntEnum): FUSE = 1 @@ -202,5 +203,7 @@ class CuNumericRedopCode(IntEnum): class CuNumericTunable(IntEnum): NUM_GPUS = _cunumeric.CUNUMERIC_TUNABLE_NUM_GPUS MAX_EAGER_VOLUME = _cunumeric.CUNUMERIC_TUNABLE_MAX_EAGER_VOLUME -#hack!!! this is for prototyping reason and needs to be addressed before making a PR -cunumeric_context.fused_id = CuNumericOpCode.FUSED_OP + + +# hack!!! this is for prototyping reason and needs to be addressed before making a PR +cunumeric_context.fused_id = CuNumericOpCode.FUSED_OP diff --git a/cunumeric/deferred.py b/cunumeric/deferred.py index 95ba5aa4c..ed797f6b7 100644 --- a/cunumeric/deferred.py +++ b/cunumeric/deferred.py @@ -28,6 +28,7 @@ from .thunk import NumPyThunk from .utils import get_arg_value_dtype + def _complex_field_dtype(dtype): if dtype == np.complex64: return np.dtype(np.float32) diff --git a/examples/black_scholes.py b/examples/black_scholes.py index 02b3a2e7d..02780653c 100644 --- a/examples/black_scholes.py +++ b/examples/black_scholes.py @@ -88,7 +88,7 @@ def run_black_scholes(N, D): put_sum = np.sum(put) ends[i] = (call_sum, put_sum) for i in range(trials): - call_sum, put_sum = ends[i] + call_sum, put_sum = ends[i] assert not math.isnan(call_sum) and not math.isnan(put_sum) stop = datetime.datetime.now() delta = stop - start diff --git a/examples/stencil.py b/examples/stencil.py index 9850a856f..5552c2124 100644 --- a/examples/stencil.py +++ b/examples/stencil.py @@ -49,7 +49,7 @@ def run(grid, I, N): # noqa: E741 # delta = np.sum(np.absolute(work - center)) center[:] = work total = np.sum(center) - #return total + # return total return total / (N ** 2) diff --git a/examples/stencil_27.py b/examples/stencil_27.py index d7f2b92da..28476d791 100644 --- a/examples/stencil_27.py +++ b/examples/stencil_27.py @@ -28,14 +28,13 @@ def initialize(N): print("Initializing stencil grid...") - grid = np.zeros((N + 2, N + 2, N+2)) - grid[:,:, 0] = -273.15 + grid = np.zeros((N + 2, N + 2, N + 2)) + grid[:, :, 0] = -273.15 grid[:, 0, :] = -273.15 - grid[0,:, :] = -273.15 - grid[:,:, -1] = 273.15 + grid[0, :, :] = -273.15 + grid[:, :, -1] = 273.15 grid[:, -1, :] = 273.15 - grid[-1,:, :] = 273.15 - + grid[-1, :, :] = 273.15 return grid @@ -43,60 +42,60 @@ def initialize(N): def run(grid, I, N): # noqa: E741 print("Running Jacobi 27 stencil...") - #one + # one g000 = grid[0:-2, 0:-2, 0:-2] g001 = grid[0:-2, 0:-2, 1:-1] - g002 = grid[0:-2, 0:-2, 2: ] + g002 = grid[0:-2, 0:-2, 2:] g010 = grid[0:-2, 1:-1, 0:-2] g011 = grid[0:-2, 1:-1, 1:-1] - g012 = grid[0:-2, 1:-1, 2: ] + g012 = grid[0:-2, 1:-1, 2:] - g020 = grid[0:-2, 2: , 0:-2] - g021 = grid[0:-2, 2: , 1:-1] - g022 = grid[0:-2, 2: , 2: ] + g020 = grid[0:-2, 2:, 0:-2] + g021 = grid[0:-2, 2:, 1:-1] + g022 = grid[0:-2, 2:, 2:] - #two + # two g100 = grid[1:-1, 0:-2, 0:-2] g101 = grid[1:-1, 0:-2, 1:-1] - g102 = grid[1:-1, 0:-2, 2: ] + g102 = grid[1:-1, 0:-2, 2:] g110 = grid[1:-1, 1:-1, 0:-2] g111 = grid[1:-1, 1:-1, 1:-1] - g112 = grid[1:-1, 1:-1, 2: ] + g112 = grid[1:-1, 1:-1, 2:] - g120 = grid[1:-1, 2: , 0:-2] - g121 = grid[1:-1, 2: , 1:-1] - g122 = grid[1:-1, 2: , 2: ] + g120 = grid[1:-1, 2:, 0:-2] + g121 = grid[1:-1, 2:, 1:-1] + g122 = grid[1:-1, 2:, 2:] - #three - g200 = grid[2: , 0:-2, 0:-2] - g201 = grid[2: , 0:-2, 1:-1] - g202 = grid[2: , 0:-2, 2: ] + # three + g200 = grid[2:, 0:-2, 0:-2] + g201 = grid[2:, 0:-2, 1:-1] + g202 = grid[2:, 0:-2, 2:] - g210 = grid[2: , 1:-1, 0:-2] - g211 = grid[2: , 1:-1, 1:-1] - g212 = grid[2: , 1:-1, 2: ] + g210 = grid[2:, 1:-1, 0:-2] + g211 = grid[2:, 1:-1, 1:-1] + g212 = grid[2:, 1:-1, 2:] - g220 = grid[2: , 2: , 0:-2] - g221 = grid[2: , 2: , 1:-1] - g222 = grid[2: , 2: , 2: ] + g220 = grid[2:, 2:, 0:-2] + g221 = grid[2:, 2:, 1:-1] + g222 = grid[2:, 2:, 2:] for i in range(I): - g00 = g000 + g001 + g002 - g01 = g010 + g011 + g012 - g02 = g020 + g021 + g022 - g10 = g100 + g101 + g102 - g11 = g110 + g111 + g112 - g12 = g120 + g121 + g122 - g20 = g200 + g201 + g202 - g21 = g210 + g211 + g212 - g22 = g220 + g221 + g222 + g00 = g000 + g001 + g002 + g01 = g010 + g011 + g012 + g02 = g020 + g021 + g022 + g10 = g100 + g101 + g102 + g11 = g110 + g111 + g112 + g12 = g120 + g121 + g122 + g20 = g200 + g201 + g202 + g21 = g210 + g211 + g212 + g22 = g220 + g221 + g222 g0 = g00 + g01 + g02 g1 = g10 + g11 + g12 g2 = g20 + g21 + g22 - + res = g0 + g1 + g2 work = 0.037 * res g111[:] = work diff --git a/src/cunumeric/fused/fused_op.cc b/src/cunumeric/fused/fused_op.cc index 102b084c5..658870f6f 100644 --- a/src/cunumeric/fused/fused_op.cc +++ b/src/cunumeric/fused/fused_op.cc @@ -22,7 +22,7 @@ #include #include -//namespace legate { +// namespace legate { namespace cunumeric { using namespace Legion; @@ -30,93 +30,88 @@ using namespace legate; /*static*/ void FusedOpTask::cpu_variant(TaskContext& context) { - int nOps = context.fusionMetadata.nOps; - auto opIDs = context.fusionMetadata.opIDs; + int nOps = context.fusionMetadata.nOps; + auto opIDs = context.fusionMetadata.opIDs; auto offsets = context.fusionMetadata.offsets; - for (int i=0; i regions; - //context.runtime_->execute_task(context.context_, leaf_launcher); + for (int i = 0; i < nOps; i++) { + std::vector regions; + // context.runtime_->execute_task(context.context_, leaf_launcher); - //create new context - const Legion::Task* task = (Legion::Task*) context.task_; + // create new context + const Legion::Task* task = (Legion::Task*)context.task_; - //pack inputs - std::vector inputs; - auto inputStarts = context.fusionMetadata.inputStarts; - auto outputStarts = context.fusionMetadata.outputStarts; - auto offsetStarts = context.fusionMetadata.offsetStarts; - auto reductionStarts = context.fusionMetadata.reductionStarts; - unsigned nInputs = (inputStarts[i+1]-inputStarts[i]); //want to pack this as a 32 bit uint - for (unsigned j = 0; j inputs; + auto inputStarts = context.fusionMetadata.inputStarts; + auto outputStarts = context.fusionMetadata.outputStarts; + auto offsetStarts = context.fusionMetadata.offsetStarts; + auto reductionStarts = context.fusionMetadata.reductionStarts; + unsigned nInputs = (inputStarts[i + 1] - inputStarts[i]); // want to pack this as a 32 bit uint + for (unsigned j = 0; j < nInputs; j++) { + int offsetStart = offsetStarts[i]; + int inputStart = inputStarts[i]; + int bufferID = offsets[offsetStart + j] - 1; + Store& input = context.inputs()[inputStart + bufferID]; + inputs.push_back(std::move(input)); + } - //pack outputs - std::vector outputs; - unsigned nOutputs = (outputStarts[i+1]-outputStarts[i]); //want to pack this as a 32 bit uint - for (unsigned j = 0; j outputs; + unsigned nOutputs = + (outputStarts[i + 1] - outputStarts[i]); // want to pack this as a 32 bit uint + for (unsigned j = 0; j < nOutputs; j++) { + int offsetStart = offsetStarts[i]; + int outputStart = outputStarts[i]; + int bufferID = offsets[offsetStart + nInputs + j]; + bufferID = (-bufferID) - 1; + Store& output = context.outputs()[outputStart + bufferID]; + outputs.push_back(std::move(output)); + } - //pack reductions - std::vector reductions; - int32_t nReductions = (reductionStarts[i+1]-reductionStarts[i]); - for (unsigned j = 0; j reductions; + int32_t nReductions = (reductionStarts[i + 1] - reductionStarts[i]); + for (unsigned j = 0; j < nReductions; j++) { + int offsetStart = offsetStarts[i]; + int reductionStart = reductionStarts[i]; + int bufferID = offsets[offsetStart + nInputs + nOutputs + j]; + // all buffer ids are 1 -indexed + // negative id is an output, while a positive id is an output + if (bufferID < 0) { + bufferID = (-bufferID) - 1; + Store& reduction = context.reductions()[reductionStart + bufferID]; + reductions.push_back(std::move(reduction)); } + } - //pack scalars - std::vector scalars; - auto scalarStarts = context.fusionMetadata.scalarStarts; - int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); - for (unsigned j = 0; j scalars; + auto scalarStarts = context.fusionMetadata.scalarStarts; + int32_t nScalars = (scalarStarts[i + 1] - scalarStarts[i]); + for (unsigned j = 0; j < nScalars; j++) { + scalars.push_back(std::move(context.scalars()[scalarStarts[i] + j])); + } - TaskContext context3(task, (const std::vector) regions);// inputs, outputs, scalars); - context3.inputs_ = std::move(inputs); - context3.outputs_ = std::move(outputs); - context3.scalars_ = std::move(scalars); + TaskContext context3( + task, (const std::vector)regions); // inputs, outputs, scalars); + context3.inputs_ = std::move(inputs); + context3.outputs_ = std::move(outputs); + context3.scalars_ = std::move(scalars); - //launch - auto descp = Core::cpuDescriptors.find(opIDs[i]); - auto desc = descp->second; - desc(context3); - for (unsigned j = 0; jsecond; + desc(context3); + for (unsigned j = 0; j < nOutputs; j++) { + int offsetStart = offsetStarts[i]; + int outputStart = outputStarts[i]; + int bufferID = offsets[offsetStart + nInputs + j]; + bufferID = (-bufferID) - 1; + context.outputs_[outputStart + bufferID] = std::move(context3.outputs_[j]); + } + + context3.pack_return_values(); + context.pack_return_values(); } } @@ -126,4 +121,4 @@ static void __attribute__((constructor)) register_tasks(void) { FusedOpTask::reg } // namespace //} // namespace numpy -} // namespace legate +} // namespace cunumeric diff --git a/src/cunumeric/fused/fused_op_omp.cc b/src/cunumeric/fused/fused_op_omp.cc index 4af8a637c..ce6720dc1 100644 --- a/src/cunumeric/fused/fused_op_omp.cc +++ b/src/cunumeric/fused/fused_op_omp.cc @@ -58,5 +58,5 @@ struct BinaryOpImplBody { binary_op_template(context); } -} // namespace numpy +} // namespace cunumeric } // namespace legate diff --git a/tests/tensordot.py b/tests/tensordot.py index a98f15fe9..1b137eb75 100644 --- a/tests/tensordot.py +++ b/tests/tensordot.py @@ -19,7 +19,7 @@ def test(ty): - rtol=2e-03 if ty == np.float16 else 1e-05 + rtol = 2e-03 if ty == np.float16 else 1e-05 a = num.random.rand(3, 5, 4).astype(ty) b = num.random.rand(4, 5, 3).astype(ty) From b4302a33937f7426f195859e7ddc7836be5c8709 Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 12 Dec 2021 18:37:01 -0800 Subject: [PATCH 43/46] omp changes --- cunumeric/config.py | 1 - src/cunumeric/fused/fused_op_omp.cc | 123 ++++++++++++++++------ src/cunumeric/unary/unary_op_template.inl | 1 - 3 files changed, 88 insertions(+), 37 deletions(-) diff --git a/cunumeric/config.py b/cunumeric/config.py index e96cb6206..22fe54e5f 100644 --- a/cunumeric/config.py +++ b/cunumeric/config.py @@ -202,5 +202,4 @@ class CuNumericRedopCode(IntEnum): class CuNumericTunable(IntEnum): NUM_GPUS = _cunumeric.CUNUMERIC_TUNABLE_NUM_GPUS MAX_EAGER_VOLUME = _cunumeric.CUNUMERIC_TUNABLE_MAX_EAGER_VOLUME -#hack!!! this is for prototyping reason and needs to be addressed before making a PR cunumeric_context.fused_id = CuNumericOpCode.FUSED_OP diff --git a/src/cunumeric/fused/fused_op_omp.cc b/src/cunumeric/fused/fused_op_omp.cc index 4af8a637c..11cc025cb 100644 --- a/src/cunumeric/fused/fused_op_omp.cc +++ b/src/cunumeric/fused/fused_op_omp.cc @@ -14,49 +14,102 @@ * */ -#include "fused/binary_op.h" -#include "fused/binary_op_template.inl" +#include "cunumeric/fused/fused_op.h" -namespace legate { namespace cunumeric { using namespace Legion; +using namespace legate; -template -struct BinaryOpImplBody { - using OP = BinaryOp; - using ARG = legate_type_of; - using RES = std::result_of_t; - - void operator()(OP func, - AccessorWO out, - AccessorRO in1, - AccessorRO in2, - const Pitches& pitches, - const Rect& rect, - bool dense) const +/*static*/ void FusedOpTask::gpu_variant(TaskContext& context){ + + int nOps = context.fusionMetadata.nOps; + auto opIDs = context.fusionMetadata.opIDs; + auto offsets = context.fusionMetadata.offsets; + for (int i=0; i regions; + //create new context + const Legion::Task* task = (Legion::Task*) context.task_; + + //pack inputs + std::vector inputs; + auto inputStarts = context.fusionMetadata.inputStarts; + auto outputStarts = context.fusionMetadata.outputStarts; + auto offsetStarts = context.fusionMetadata.offsetStarts; + auto reductionStarts = context.fusionMetadata.reductionStarts; + unsigned nInputs = (inputStarts[i+1]-inputStarts[i]); //want to pack this as a 32 bit uint + for (unsigned j = 0; j outputs; + unsigned nOutputs = (outputStarts[i+1]-outputStarts[i]); //want to pack this as a 32 bit uint + for (unsigned j = 0; j reductions; + int32_t nReductions = (reductionStarts[i+1]-reductionStarts[i]); + for (unsigned j = 0; j(context); + //pack scalars + auto scalarStarts = context.fusionMetadata.scalarStarts; + int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); + std::vector scalars; + for (unsigned j = 0; j) regions);// inputs, outputs, scalars); + context3.inputs_ = std::move(inputs); + context3.outputs_ = std::move(outputs); + context3.reductions_ = std::move(reductions); + context3.scalars_ = std::move(scalars); + + //launch + auto descp = Core::ompDescriptors.find(opIDs[i]); + + auto desc = descp->second; + desc(context3); + for (unsigned j = 0; j From 92d859017cadab16a67e15b8cf0390fa91813459 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Dec 2021 02:38:32 +0000 Subject: [PATCH 44/46] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- cunumeric/config.py | 3 +- src/cunumeric/fused/fused_op_omp.cc | 150 +++++++++++++--------------- 2 files changed, 74 insertions(+), 79 deletions(-) diff --git a/cunumeric/config.py b/cunumeric/config.py index 1d717f7b3..c064059eb 100644 --- a/cunumeric/config.py +++ b/cunumeric/config.py @@ -203,5 +203,6 @@ class CuNumericRedopCode(IntEnum): class CuNumericTunable(IntEnum): NUM_GPUS = _cunumeric.CUNUMERIC_TUNABLE_NUM_GPUS MAX_EAGER_VOLUME = _cunumeric.CUNUMERIC_TUNABLE_MAX_EAGER_VOLUME -cunumeric_context.fused_id = CuNumericOpCode.FUSED_OP + +cunumeric_context.fused_id = CuNumericOpCode.FUSED_OP diff --git a/src/cunumeric/fused/fused_op_omp.cc b/src/cunumeric/fused/fused_op_omp.cc index cc1d3cc09..27b535238 100644 --- a/src/cunumeric/fused/fused_op_omp.cc +++ b/src/cunumeric/fused/fused_op_omp.cc @@ -21,93 +21,87 @@ namespace cunumeric { using namespace Legion; using namespace legate; -/*static*/ void FusedOpTask::gpu_variant(TaskContext& context){ - - int nOps = context.fusionMetadata.nOps; - auto opIDs = context.fusionMetadata.opIDs; +/*static*/ void FusedOpTask::gpu_variant(TaskContext& context) +{ + int nOps = context.fusionMetadata.nOps; + auto opIDs = context.fusionMetadata.opIDs; auto offsets = context.fusionMetadata.offsets; - for (int i=0; i regions; - //create new context - const Legion::Task* task = (Legion::Task*) context.task_; - - //pack inputs - std::vector inputs; - auto inputStarts = context.fusionMetadata.inputStarts; - auto outputStarts = context.fusionMetadata.outputStarts; - auto offsetStarts = context.fusionMetadata.offsetStarts; - auto reductionStarts = context.fusionMetadata.reductionStarts; - unsigned nInputs = (inputStarts[i+1]-inputStarts[i]); //want to pack this as a 32 bit uint - for (unsigned j = 0; j regions; + // create new context + const Legion::Task* task = (Legion::Task*)context.task_; - //pack outputs - std::vector outputs; - unsigned nOutputs = (outputStarts[i+1]-outputStarts[i]); //want to pack this as a 32 bit uint - for (unsigned j = 0; j inputs; + auto inputStarts = context.fusionMetadata.inputStarts; + auto outputStarts = context.fusionMetadata.outputStarts; + auto offsetStarts = context.fusionMetadata.offsetStarts; + auto reductionStarts = context.fusionMetadata.reductionStarts; + unsigned nInputs = (inputStarts[i + 1] - inputStarts[i]); // want to pack this as a 32 bit uint + for (unsigned j = 0; j < nInputs; j++) { + int offsetStart = offsetStarts[i]; + int inputStart = inputStarts[i]; + int bufferID = offsets[offsetStart + j] - 1; + Store& input = context.inputs()[inputStart + bufferID]; + inputs.push_back(std::move(input)); + } - //pack reductions - std::vector reductions; - int32_t nReductions = (reductionStarts[i+1]-reductionStarts[i]); - for (unsigned j = 0; j outputs; + unsigned nOutputs = + (outputStarts[i + 1] - outputStarts[i]); // want to pack this as a 32 bit uint + for (unsigned j = 0; j < nOutputs; j++) { + int offsetStart = offsetStarts[i]; + int outputStart = outputStarts[i]; + int bufferID = offsets[offsetStart + nInputs + j]; + bufferID = (-bufferID) - 1; + Store& output = context.outputs()[outputStart + bufferID]; + outputs.push_back(std::move(output)); + } - //pack scalars - auto scalarStarts = context.fusionMetadata.scalarStarts; - int32_t nScalars = (scalarStarts[i+1]-scalarStarts[i]); - std::vector scalars; - for (unsigned j = 0; j reductions; + int32_t nReductions = (reductionStarts[i + 1] - reductionStarts[i]); + for (unsigned j = 0; j < nReductions; j++) { + int offsetStart = offsetStarts[i]; + int reductionStart = reductionStarts[i]; + int bufferID = offsets[offsetStart + nInputs + nOutputs + j]; + // all buffer ids are 1 -indexed + // negative id is an output, while a positive id is an output + if (bufferID < 0) { + bufferID = (-bufferID) - 1; + Store& reduction = context.reductions()[reductionStart + bufferID]; + reductions.push_back(std::move(reduction)); } + } + // pack scalars + auto scalarStarts = context.fusionMetadata.scalarStarts; + int32_t nScalars = (scalarStarts[i + 1] - scalarStarts[i]); + std::vector scalars; + for (unsigned j = 0; j < nScalars; j++) { + scalars.push_back(std::move(context.scalars()[scalarStarts[i] + j])); + } - TaskContext context3(task, (const std::vector) regions);// inputs, outputs, scalars); - context3.inputs_ = std::move(inputs); - context3.outputs_ = std::move(outputs); - context3.reductions_ = std::move(reductions); - context3.scalars_ = std::move(scalars); + TaskContext context3( + task, (const std::vector)regions); // inputs, outputs, scalars); + context3.inputs_ = std::move(inputs); + context3.outputs_ = std::move(outputs); + context3.reductions_ = std::move(reductions); + context3.scalars_ = std::move(scalars); - //launch - auto descp = Core::ompDescriptors.find(opIDs[i]); + // launch + auto descp = Core::ompDescriptors.find(opIDs[i]); - auto desc = descp->second; - desc(context3); - for (unsigned j = 0; jsecond; + desc(context3); + for (unsigned j = 0; j < nOutputs; j++) { + int offsetStart = offsetStarts[i]; + int outputStart = outputStarts[i]; + int bufferID = offsets[offsetStart + nInputs + j]; + bufferID = (-bufferID) - 1; + context.outputs_[outputStart + bufferID] = std::move(context3.outputs_[j]); + } } } From 7391628b0e1dad7637cba26c3976d176ba1e664e Mon Sep 17 00:00:00 2001 From: Shiv Sundram Date: Sun, 12 Dec 2021 18:40:51 -0800 Subject: [PATCH 45/46] one more merge conflict --- src/cunumeric/fused/fused_op_omp.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/cunumeric/fused/fused_op_omp.cc b/src/cunumeric/fused/fused_op_omp.cc index cc1d3cc09..94166769b 100644 --- a/src/cunumeric/fused/fused_op_omp.cc +++ b/src/cunumeric/fused/fused_op_omp.cc @@ -21,7 +21,7 @@ namespace cunumeric { using namespace Legion; using namespace legate; -/*static*/ void FusedOpTask::gpu_variant(TaskContext& context){ +/*static*/ void FusedOpTask::omp_variant(TaskContext& context){ int nOps = context.fusionMetadata.nOps; auto opIDs = context.fusionMetadata.opIDs; @@ -111,10 +111,4 @@ using namespace legate; } } -<<<<<<< HEAD -} // namespace numpy -//} // namespace legate -======= } // namespace cunumeric -} // namespace legate ->>>>>>> 4c104dde6d8d3b15c8cbe60f57d2c997604a9033 From 1783d65a50e6613f18da1a199d1927a323cf3663 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Dec 2021 02:42:09 +0000 Subject: [PATCH 46/46] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/cunumeric/fused/fused_op_omp.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cunumeric/fused/fused_op_omp.cc b/src/cunumeric/fused/fused_op_omp.cc index 5f41e4b7f..22e13997a 100644 --- a/src/cunumeric/fused/fused_op_omp.cc +++ b/src/cunumeric/fused/fused_op_omp.cc @@ -21,10 +21,10 @@ namespace cunumeric { using namespace Legion; using namespace legate; -/*static*/ void FusedOpTask::omp_variant(TaskContext& context){ - - int nOps = context.fusionMetadata.nOps; - auto opIDs = context.fusionMetadata.opIDs; +/*static*/ void FusedOpTask::omp_variant(TaskContext& context) +{ + int nOps = context.fusionMetadata.nOps; + auto opIDs = context.fusionMetadata.opIDs; auto offsets = context.fusionMetadata.offsets; for (int i = 0; i < nOps; i++) { std::vector regions;