mirror of
https://github.com/wassname/ray.git
synced 2026-07-06 05:16:30 +08:00
Lint Python files with Yapf (#1872)
This commit is contained in:
committed by
Robert Nishihara
parent
a3ddde398c
commit
74162d1492
@@ -5,5 +5,7 @@ from __future__ import print_function
|
||||
from .tfutils import TensorFlowVariables
|
||||
from .features import flush_redis_unsafe, flush_task_and_object_metadata_unsafe
|
||||
|
||||
__all__ = ["TensorFlowVariables", "flush_redis_unsafe",
|
||||
"flush_task_and_object_metadata_unsafe"]
|
||||
__all__ = [
|
||||
"TensorFlowVariables", "flush_redis_unsafe",
|
||||
"flush_task_and_object_metadata_unsafe"
|
||||
]
|
||||
|
||||
@@ -8,6 +8,8 @@ from .core import (BLOCK_SIZE, DistArray, assemble, zeros, ones, copy, eye,
|
||||
triu, tril, blockwise_dot, dot, transpose, add, subtract,
|
||||
numpy_to_dist, subblocks)
|
||||
|
||||
__all__ = ["random", "linalg", "BLOCK_SIZE", "DistArray", "assemble", "zeros",
|
||||
"ones", "copy", "eye", "triu", "tril", "blockwise_dot", "dot",
|
||||
"transpose", "add", "subtract", "numpy_to_dist", "subblocks"]
|
||||
__all__ = [
|
||||
"random", "linalg", "BLOCK_SIZE", "DistArray", "assemble", "zeros", "ones",
|
||||
"copy", "eye", "triu", "tril", "blockwise_dot", "dot", "transpose", "add",
|
||||
"subtract", "numpy_to_dist", "subblocks"
|
||||
]
|
||||
|
||||
@@ -13,8 +13,9 @@ class DistArray(object):
|
||||
def __init__(self, shape, objectids=None):
|
||||
self.shape = shape
|
||||
self.ndim = len(shape)
|
||||
self.num_blocks = [int(np.ceil(1.0 * a / BLOCK_SIZE))
|
||||
for a in self.shape]
|
||||
self.num_blocks = [
|
||||
int(np.ceil(1.0 * a / BLOCK_SIZE)) for a in self.shape
|
||||
]
|
||||
if objectids is not None:
|
||||
self.objectids = objectids
|
||||
else:
|
||||
@@ -56,7 +57,7 @@ class DistArray(object):
|
||||
|
||||
def assemble(self):
|
||||
"""Assemble an array from a distributed array of object IDs."""
|
||||
first_block = ray.get(self.objectids[(0,) * self.ndim])
|
||||
first_block = ray.get(self.objectids[(0, ) * self.ndim])
|
||||
dtype = first_block.dtype
|
||||
result = np.zeros(self.shape, dtype=dtype)
|
||||
for index in np.ndindex(*self.num_blocks):
|
||||
@@ -85,8 +86,8 @@ def numpy_to_dist(a):
|
||||
for index in np.ndindex(*result.num_blocks):
|
||||
lower = DistArray.compute_block_lower(index, a.shape)
|
||||
upper = DistArray.compute_block_upper(index, a.shape)
|
||||
result.objectids[index] = ray.put(a[[slice(l, u) for (l, u)
|
||||
in zip(lower, upper)]])
|
||||
result.objectids[index] = ray.put(
|
||||
a[[slice(l, u) for (l, u) in zip(lower, upper)]])
|
||||
return result
|
||||
|
||||
|
||||
@@ -126,12 +127,11 @@ def eye(dim1, dim2=-1, dtype_name="float"):
|
||||
for (i, j) in np.ndindex(*result.num_blocks):
|
||||
block_shape = DistArray.compute_block_shape([i, j], shape)
|
||||
if i == j:
|
||||
result.objectids[i, j] = ra.eye.remote(block_shape[0],
|
||||
block_shape[1],
|
||||
dtype_name=dtype_name)
|
||||
result.objectids[i, j] = ra.eye.remote(
|
||||
block_shape[0], block_shape[1], dtype_name=dtype_name)
|
||||
else:
|
||||
result.objectids[i, j] = ra.zeros.remote(block_shape,
|
||||
dtype_name=dtype_name)
|
||||
result.objectids[i, j] = ra.zeros.remote(
|
||||
block_shape, dtype_name=dtype_name)
|
||||
return result
|
||||
|
||||
|
||||
@@ -190,8 +190,8 @@ def dot(a, b):
|
||||
"b.ndim = {}.".format(b.ndim))
|
||||
if a.shape[1] != b.shape[0]:
|
||||
raise Exception("dot expects a.shape[1] to equal b.shape[0], but "
|
||||
"a.shape = {} and b.shape = {}.".format(a.shape,
|
||||
b.shape))
|
||||
"a.shape = {} and b.shape = {}.".format(
|
||||
a.shape, b.shape))
|
||||
shape = [a.shape[0], b.shape[1]]
|
||||
result = DistArray(shape)
|
||||
for (i, j) in np.ndindex(*result.num_blocks):
|
||||
@@ -227,8 +227,8 @@ def subblocks(a, *ranges):
|
||||
"the {}th range is {}.".format(i, ranges[i]))
|
||||
if ranges[i][0] < 0:
|
||||
raise Exception("Values in the ranges passed to sub_blocks must "
|
||||
"be at least 0, but the {}th range is {}."
|
||||
.format(i, ranges[i]))
|
||||
"be at least 0, but the {}th range is {}.".format(
|
||||
i, ranges[i]))
|
||||
if ranges[i][-1] >= a.num_blocks[i]:
|
||||
raise Exception("Values in the ranges passed to sub_blocks must "
|
||||
"be less than the relevant number of blocks, but "
|
||||
@@ -240,8 +240,8 @@ def subblocks(a, *ranges):
|
||||
for i in range(a.ndim)]
|
||||
result = DistArray(shape)
|
||||
for index in np.ndindex(*result.num_blocks):
|
||||
result.objectids[index] = a.objectids[tuple([ranges[i][index[i]]
|
||||
for i in range(a.ndim)])]
|
||||
result.objectids[index] = a.objectids[tuple(
|
||||
[ranges[i][index[i]] for i in range(a.ndim)])]
|
||||
return result
|
||||
|
||||
|
||||
@@ -249,8 +249,8 @@ def subblocks(a, *ranges):
|
||||
def transpose(a):
|
||||
if a.ndim != 2:
|
||||
raise Exception("transpose expects its argument to be 2-dimensional, "
|
||||
"but a.ndim = {}, a.shape = {}.".format(a.ndim,
|
||||
a.shape))
|
||||
"but a.ndim = {}, a.shape = {}.".format(
|
||||
a.ndim, a.shape))
|
||||
result = DistArray([a.shape[1], a.shape[0]])
|
||||
for i in range(result.num_blocks[0]):
|
||||
for j in range(result.num_blocks[1]):
|
||||
@@ -263,8 +263,8 @@ def transpose(a):
|
||||
def add(x1, x2):
|
||||
if x1.shape != x2.shape:
|
||||
raise Exception("add expects arguments `x1` and `x2` to have the same "
|
||||
"shape, but x1.shape = {}, and x2.shape = {}."
|
||||
.format(x1.shape, x2.shape))
|
||||
"shape, but x1.shape = {}, and x2.shape = {}.".format(
|
||||
x1.shape, x2.shape))
|
||||
result = DistArray(x1.shape)
|
||||
for index in np.ndindex(*result.num_blocks):
|
||||
result.objectids[index] = ra.add.remote(x1.objectids[index],
|
||||
|
||||
@@ -76,9 +76,10 @@ def tsqr(a):
|
||||
lower = [a.shape[1], 0]
|
||||
upper = [2 * a.shape[1], core.BLOCK_SIZE]
|
||||
ith_index //= 2
|
||||
q_block_current = ra.dot.remote(
|
||||
q_block_current, ra.subarray.remote(q_tree[ith_index, j],
|
||||
lower, upper))
|
||||
q_block_current = ra.dot.remote(q_block_current,
|
||||
ra.subarray.remote(
|
||||
q_tree[ith_index, j], lower,
|
||||
upper))
|
||||
q_result.objectids[i] = q_block_current
|
||||
r = current_rs[0]
|
||||
return q_result, ray.get(r)
|
||||
@@ -196,8 +197,8 @@ def qr(a):
|
||||
if a.shape[0] > a.shape[1]:
|
||||
# in this case, R needs to be square
|
||||
R_shape = ray.get(ra.shape.remote(R))
|
||||
eye_temp = ra.eye.remote(R_shape[1], R_shape[0],
|
||||
dtype_name=result_dtype)
|
||||
eye_temp = ra.eye.remote(
|
||||
R_shape[1], R_shape[0], dtype_name=result_dtype)
|
||||
r_res.objectids[i, i] = ra.dot.remote(eye_temp, R)
|
||||
else:
|
||||
r_res.objectids[i, i] = R
|
||||
@@ -220,10 +221,11 @@ def qr(a):
|
||||
for i in range(len(Ts))[::-1]:
|
||||
y_col_block = core.subblocks.remote(y_res, [], [i])
|
||||
q = core.subtract.remote(
|
||||
q, core.dot.remote(
|
||||
y_col_block,
|
||||
core.dot.remote(
|
||||
Ts[i],
|
||||
core.dot.remote(core.transpose.remote(y_col_block), q))))
|
||||
q,
|
||||
core.dot.remote(y_col_block,
|
||||
core.dot.remote(
|
||||
Ts[i],
|
||||
core.dot.remote(
|
||||
core.transpose.remote(y_col_block), q))))
|
||||
|
||||
return ray.get(q), r_res
|
||||
|
||||
@@ -8,6 +8,8 @@ from .core import (zeros, zeros_like, ones, eye, dot, vstack, hstack, subarray,
|
||||
copy, tril, triu, diag, transpose, add, subtract, sum,
|
||||
shape, sum_list)
|
||||
|
||||
__all__ = ["random", "linalg", "zeros", "zeros_like", "ones", "eye", "dot",
|
||||
"vstack", "hstack", "subarray", "copy", "tril", "triu", "diag",
|
||||
"transpose", "add", "subtract", "sum", "shape", "sum_list"]
|
||||
__all__ = [
|
||||
"random", "linalg", "zeros", "zeros_like", "ones", "eye", "dot", "vstack",
|
||||
"hstack", "subarray", "copy", "tril", "triu", "diag", "transpose", "add",
|
||||
"subtract", "sum", "shape", "sum_list"
|
||||
]
|
||||
|
||||
@@ -5,10 +5,11 @@ from __future__ import print_function
|
||||
import numpy as np
|
||||
import ray
|
||||
|
||||
__all__ = ["matrix_power", "solve", "tensorsolve", "tensorinv", "inv",
|
||||
"cholesky", "eigvals", "eigvalsh", "pinv", "slogdet", "det",
|
||||
"svd", "eig", "eigh", "lstsq", "norm", "qr", "cond", "matrix_rank",
|
||||
"multi_dot"]
|
||||
__all__ = [
|
||||
"matrix_power", "solve", "tensorsolve", "tensorinv", "inv", "cholesky",
|
||||
"eigvals", "eigvalsh", "pinv", "slogdet", "det", "svd", "eig", "eigh",
|
||||
"lstsq", "norm", "qr", "cond", "matrix_rank", "multi_dot"
|
||||
]
|
||||
|
||||
|
||||
@ray.remote
|
||||
|
||||
@@ -69,14 +69,14 @@ def flush_task_and_object_metadata_unsafe():
|
||||
for key in redis_client.scan_iter(match=OBJECT_INFO_PREFIX + b"*"):
|
||||
num_object_keys_deleted += redis_client.delete(key)
|
||||
print("Deleted {} object info keys from Redis.".format(
|
||||
num_object_keys_deleted))
|
||||
num_object_keys_deleted))
|
||||
|
||||
# Flush the object locations.
|
||||
num_object_location_keys_deleted = 0
|
||||
for key in redis_client.scan_iter(match=OBJECT_LOCATION_PREFIX + b"*"):
|
||||
num_object_location_keys_deleted += redis_client.delete(key)
|
||||
print("Deleted {} object location keys from Redis.".format(
|
||||
num_object_location_keys_deleted))
|
||||
num_object_location_keys_deleted))
|
||||
|
||||
# Loop over the shards and flush all of them.
|
||||
for redis_client in ray.worker.global_state.redis_clients:
|
||||
|
||||
+279
-192
@@ -59,6 +59,7 @@ class GlobalState(object):
|
||||
Attributes:
|
||||
redis_client: The redis client used to query the redis server.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Create a GlobalState object."""
|
||||
# The redis server storing metadata, such as function table, client
|
||||
@@ -82,7 +83,9 @@ class GlobalState(object):
|
||||
raise Exception("The ray.global_state API cannot be used before "
|
||||
"ray.init has been called.")
|
||||
|
||||
def _initialize_global_state(self, redis_ip_address, redis_port,
|
||||
def _initialize_global_state(self,
|
||||
redis_ip_address,
|
||||
redis_port,
|
||||
timeout=20):
|
||||
"""Initialize the GlobalState object by connecting to Redis.
|
||||
|
||||
@@ -97,8 +100,8 @@ class GlobalState(object):
|
||||
timeout: The maximum amount of time (in seconds) that we should
|
||||
wait for the keys in Redis to be populated.
|
||||
"""
|
||||
self.redis_client = redis.StrictRedis(host=redis_ip_address,
|
||||
port=redis_port)
|
||||
self.redis_client = redis.StrictRedis(
|
||||
host=redis_ip_address, port=redis_port)
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
@@ -118,8 +121,8 @@ class GlobalState(object):
|
||||
"{}.".format(num_redis_shards))
|
||||
|
||||
# Attempt to get all of the Redis shards.
|
||||
ip_address_ports = self.redis_client.lrange("RedisShards", start=0,
|
||||
end=-1)
|
||||
ip_address_ports = self.redis_client.lrange(
|
||||
"RedisShards", start=0, end=-1)
|
||||
if len(ip_address_ports) != num_redis_shards:
|
||||
print("Waiting longer for RedisShards to be populated.")
|
||||
time.sleep(1)
|
||||
@@ -132,15 +135,15 @@ class GlobalState(object):
|
||||
if time.time() - start_time >= timeout:
|
||||
raise Exception("Timed out while attempting to initialize the "
|
||||
"global state. num_redis_shards = {}, "
|
||||
"ip_address_ports = {}"
|
||||
.format(num_redis_shards, ip_address_ports))
|
||||
"ip_address_ports = {}".format(
|
||||
num_redis_shards, ip_address_ports))
|
||||
|
||||
# Get the rest of the information.
|
||||
self.redis_clients = []
|
||||
for ip_address_port in ip_address_ports:
|
||||
shard_address, shard_port = ip_address_port.split(b":")
|
||||
self.redis_clients.append(redis.StrictRedis(host=shard_address,
|
||||
port=shard_port))
|
||||
self.redis_clients.append(
|
||||
redis.StrictRedis(host=shard_address, port=shard_port))
|
||||
|
||||
def _execute_command(self, key, *args):
|
||||
"""Execute a Redis command on the appropriate Redis shard based on key.
|
||||
@@ -152,8 +155,8 @@ class GlobalState(object):
|
||||
Returns:
|
||||
The value returned by the Redis command.
|
||||
"""
|
||||
client = self.redis_clients[key.redis_shard_hash() %
|
||||
len(self.redis_clients)]
|
||||
client = self.redis_clients[key.redis_shard_hash() % len(
|
||||
self.redis_clients)]
|
||||
return client.execute_command(*args)
|
||||
|
||||
def _keys(self, pattern):
|
||||
@@ -189,8 +192,9 @@ class GlobalState(object):
|
||||
"RAY.OBJECT_TABLE_LOOKUP",
|
||||
object_id.id())
|
||||
if object_locations is not None:
|
||||
manager_ids = [binary_to_hex(manager_id)
|
||||
for manager_id in object_locations]
|
||||
manager_ids = [
|
||||
binary_to_hex(manager_id) for manager_id in object_locations
|
||||
]
|
||||
else:
|
||||
manager_ids = None
|
||||
|
||||
@@ -199,11 +203,13 @@ class GlobalState(object):
|
||||
result_table_message = ResultTableReply.GetRootAsResultTableReply(
|
||||
result_table_response, 0)
|
||||
|
||||
result = {"ManagerIDs": manager_ids,
|
||||
"TaskID": binary_to_hex(result_table_message.TaskId()),
|
||||
"IsPut": bool(result_table_message.IsPut()),
|
||||
"DataSize": result_table_message.DataSize(),
|
||||
"Hash": binary_to_hex(result_table_message.Hash())}
|
||||
result = {
|
||||
"ManagerIDs": manager_ids,
|
||||
"TaskID": binary_to_hex(result_table_message.TaskId()),
|
||||
"IsPut": bool(result_table_message.IsPut()),
|
||||
"DataSize": result_table_message.DataSize(),
|
||||
"Hash": binary_to_hex(result_table_message.Hash())
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -227,9 +233,10 @@ class GlobalState(object):
|
||||
object_info_keys = self._keys(OBJECT_INFO_PREFIX + "*")
|
||||
object_location_keys = self._keys(OBJECT_LOCATION_PREFIX + "*")
|
||||
object_ids_binary = set(
|
||||
[key[len(OBJECT_INFO_PREFIX):] for key in object_info_keys] +
|
||||
[key[len(OBJECT_LOCATION_PREFIX):]
|
||||
for key in object_location_keys])
|
||||
[key[len(OBJECT_INFO_PREFIX):] for key in object_info_keys] + [
|
||||
key[len(OBJECT_LOCATION_PREFIX):]
|
||||
for key in object_location_keys
|
||||
])
|
||||
results = {}
|
||||
for object_id_binary in object_ids_binary:
|
||||
results[binary_to_object_id(object_id_binary)] = (
|
||||
@@ -254,26 +261,37 @@ class GlobalState(object):
|
||||
if task_table_response is None:
|
||||
raise Exception("There is no entry for task ID {} in the task "
|
||||
"table.".format(binary_to_hex(task_id.id())))
|
||||
task_table_message = TaskReply.GetRootAsTaskReply(task_table_response,
|
||||
0)
|
||||
task_table_message = TaskReply.GetRootAsTaskReply(
|
||||
task_table_response, 0)
|
||||
task_spec = task_table_message.TaskSpec()
|
||||
task_spec = ray.local_scheduler.task_from_string(task_spec)
|
||||
|
||||
task_spec_info = {
|
||||
"DriverID": binary_to_hex(task_spec.driver_id().id()),
|
||||
"TaskID": binary_to_hex(task_spec.task_id().id()),
|
||||
"ParentTaskID": binary_to_hex(task_spec.parent_task_id().id()),
|
||||
"ParentCounter": task_spec.parent_counter(),
|
||||
"ActorID": binary_to_hex(task_spec.actor_id().id()),
|
||||
"DriverID":
|
||||
binary_to_hex(task_spec.driver_id().id()),
|
||||
"TaskID":
|
||||
binary_to_hex(task_spec.task_id().id()),
|
||||
"ParentTaskID":
|
||||
binary_to_hex(task_spec.parent_task_id().id()),
|
||||
"ParentCounter":
|
||||
task_spec.parent_counter(),
|
||||
"ActorID":
|
||||
binary_to_hex(task_spec.actor_id().id()),
|
||||
"ActorCreationID":
|
||||
binary_to_hex(task_spec.actor_creation_id().id()),
|
||||
binary_to_hex(task_spec.actor_creation_id().id()),
|
||||
"ActorCreationDummyObjectID":
|
||||
binary_to_hex(task_spec.actor_creation_dummy_object_id().id()),
|
||||
"ActorCounter": task_spec.actor_counter(),
|
||||
"FunctionID": binary_to_hex(task_spec.function_id().id()),
|
||||
"Args": task_spec.arguments(),
|
||||
"ReturnObjectIDs": task_spec.returns(),
|
||||
"RequiredResources": task_spec.required_resources()}
|
||||
binary_to_hex(task_spec.actor_creation_dummy_object_id().id()),
|
||||
"ActorCounter":
|
||||
task_spec.actor_counter(),
|
||||
"FunctionID":
|
||||
binary_to_hex(task_spec.function_id().id()),
|
||||
"Args":
|
||||
task_spec.arguments(),
|
||||
"ReturnObjectIDs":
|
||||
task_spec.returns(),
|
||||
"RequiredResources":
|
||||
task_spec.required_resources()
|
||||
}
|
||||
|
||||
execution_dependencies_message = (
|
||||
TaskExecutionDependencies.GetRootAsTaskExecutionDependencies(
|
||||
@@ -282,21 +300,27 @@ class GlobalState(object):
|
||||
ray.local_scheduler.ObjectID(
|
||||
execution_dependencies_message.ExecutionDependencies(i))
|
||||
for i in range(
|
||||
execution_dependencies_message.ExecutionDependenciesLength())]
|
||||
execution_dependencies_message.ExecutionDependenciesLength())
|
||||
]
|
||||
|
||||
# TODO(rkn): The return fields ExecutionDependenciesString and
|
||||
# ExecutionDependencies are redundant, so we should remove
|
||||
# ExecutionDependencies. However, it is currently used in monitor.py.
|
||||
|
||||
return {"State": task_table_message.State(),
|
||||
"LocalSchedulerID": binary_to_hex(
|
||||
task_table_message.LocalSchedulerId()),
|
||||
"ExecutionDependenciesString":
|
||||
task_table_message.ExecutionDependencies(),
|
||||
"ExecutionDependencies": execution_dependencies,
|
||||
"SpillbackCount":
|
||||
task_table_message.SpillbackCount(),
|
||||
"TaskSpec": task_spec_info}
|
||||
return {
|
||||
"State":
|
||||
task_table_message.State(),
|
||||
"LocalSchedulerID":
|
||||
binary_to_hex(task_table_message.LocalSchedulerId()),
|
||||
"ExecutionDependenciesString":
|
||||
task_table_message.ExecutionDependencies(),
|
||||
"ExecutionDependencies":
|
||||
execution_dependencies,
|
||||
"SpillbackCount":
|
||||
task_table_message.SpillbackCount(),
|
||||
"TaskSpec":
|
||||
task_spec_info
|
||||
}
|
||||
|
||||
def task_table(self, task_id=None):
|
||||
"""Fetch and parse the task table information for one or more task IDs.
|
||||
@@ -337,7 +361,8 @@ class GlobalState(object):
|
||||
function_info_parsed = {
|
||||
"DriverID": binary_to_hex(info[b"driver_id"]),
|
||||
"Module": decode(info[b"module"]),
|
||||
"Name": decode(info[b"name"])}
|
||||
"Name": decode(info[b"name"])
|
||||
}
|
||||
results[binary_to_hex(info[b"function_id"])] = function_info_parsed
|
||||
return results
|
||||
|
||||
@@ -469,21 +494,17 @@ class GlobalState(object):
|
||||
if start is None and end is None:
|
||||
if fwd:
|
||||
event_list = self.redis_client.zrange(
|
||||
event_log_set,
|
||||
**params)
|
||||
event_log_set, **params)
|
||||
else:
|
||||
event_list = self.redis_client.zrevrange(
|
||||
event_log_set,
|
||||
**params)
|
||||
event_log_set, **params)
|
||||
else:
|
||||
if fwd:
|
||||
event_list = self.redis_client.zrangebyscore(
|
||||
event_log_set,
|
||||
**params)
|
||||
event_log_set, **params)
|
||||
else:
|
||||
event_list = self.redis_client.zrevrangebyscore(
|
||||
event_log_set,
|
||||
**params)
|
||||
event_log_set, **params)
|
||||
|
||||
for (event, score) in event_list:
|
||||
event_dict = json.loads(event.decode())
|
||||
@@ -503,11 +524,11 @@ class GlobalState(object):
|
||||
task_info[task_id]["get_task_start"] = event[0]
|
||||
if event[1] == "ray:get_task" and event[2] == 2:
|
||||
task_info[task_id]["get_task_end"] = event[0]
|
||||
if (event[1] == "ray:import_remote_function" and
|
||||
event[2] == 1):
|
||||
if (event[1] == "ray:import_remote_function"
|
||||
and event[2] == 1):
|
||||
task_info[task_id]["import_remote_start"] = event[0]
|
||||
if (event[1] == "ray:import_remote_function" and
|
||||
event[2] == 2):
|
||||
if (event[1] == "ray:import_remote_function"
|
||||
and event[2] == 2):
|
||||
task_info[task_id]["import_remote_end"] = event[0]
|
||||
if event[1] == "ray:acquire_lock" and event[2] == 1:
|
||||
task_info[task_id]["acquire_lock_start"] = event[0]
|
||||
@@ -547,7 +568,6 @@ class GlobalState(object):
|
||||
breakdowns=True,
|
||||
task_dep=True,
|
||||
obj_dep=True):
|
||||
|
||||
"""Dump task profiling information to a file.
|
||||
|
||||
This information can be viewed as a timeline of profiling information
|
||||
@@ -604,72 +624,103 @@ class GlobalState(object):
|
||||
# modify it in place since we will use the original values later.
|
||||
total_info = copy.copy(task_table[task_id]["TaskSpec"])
|
||||
total_info["Args"] = [
|
||||
oid.hex() if isinstance(oid, ray.local_scheduler.ObjectID)
|
||||
else oid for oid in task_t_info["TaskSpec"]["Args"]]
|
||||
oid.hex()
|
||||
if isinstance(oid, ray.local_scheduler.ObjectID) else oid
|
||||
for oid in task_t_info["TaskSpec"]["Args"]
|
||||
]
|
||||
total_info["ReturnObjectIDs"] = [
|
||||
oid.hex() for oid
|
||||
in task_t_info["TaskSpec"]["ReturnObjectIDs"]]
|
||||
oid.hex() for oid in task_t_info["TaskSpec"]["ReturnObjectIDs"]
|
||||
]
|
||||
total_info["LocalSchedulerID"] = task_t_info["LocalSchedulerID"]
|
||||
total_info["get_arguments"] = (info["get_arguments_end"] -
|
||||
info["get_arguments_start"])
|
||||
total_info["execute"] = (info["execute_end"] -
|
||||
info["execute_start"])
|
||||
total_info["store_outputs"] = (info["store_outputs_end"] -
|
||||
info["store_outputs_start"])
|
||||
total_info["get_arguments"] = (
|
||||
info["get_arguments_end"] - info["get_arguments_start"])
|
||||
total_info["execute"] = (
|
||||
info["execute_end"] - info["execute_start"])
|
||||
total_info["store_outputs"] = (
|
||||
info["store_outputs_end"] - info["store_outputs_start"])
|
||||
total_info["function_name"] = info["function_name"]
|
||||
total_info["worker_id"] = info["worker_id"]
|
||||
|
||||
parent_info = task_info.get(
|
||||
task_table[task_id]["TaskSpec"]["ParentTaskID"])
|
||||
task_table[task_id]["TaskSpec"]["ParentTaskID"])
|
||||
worker = workers[info["worker_id"]]
|
||||
# The catapult trace format documentation can be found here:
|
||||
# https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview # noqa: E501
|
||||
if breakdowns:
|
||||
if "get_arguments_end" in info:
|
||||
get_args_trace = {
|
||||
"cat": "get_arguments",
|
||||
"pid": "Node " + worker["node_ip_address"],
|
||||
"tid": info["worker_id"],
|
||||
"id": task_id,
|
||||
"ts": micros_rel(info["get_arguments_start"]),
|
||||
"ph": "X",
|
||||
"name": info["function_name"] + ":get_arguments",
|
||||
"args": total_info,
|
||||
"dur": micros(info["get_arguments_end"] -
|
||||
info["get_arguments_start"]),
|
||||
"cname": "rail_idle"
|
||||
"cat":
|
||||
"get_arguments",
|
||||
"pid":
|
||||
"Node " + worker["node_ip_address"],
|
||||
"tid":
|
||||
info["worker_id"],
|
||||
"id":
|
||||
task_id,
|
||||
"ts":
|
||||
micros_rel(info["get_arguments_start"]),
|
||||
"ph":
|
||||
"X",
|
||||
"name":
|
||||
info["function_name"] + ":get_arguments",
|
||||
"args":
|
||||
total_info,
|
||||
"dur":
|
||||
micros(info["get_arguments_end"] -
|
||||
info["get_arguments_start"]),
|
||||
"cname":
|
||||
"rail_idle"
|
||||
}
|
||||
full_trace.append(get_args_trace)
|
||||
|
||||
if "store_outputs_end" in info:
|
||||
outputs_trace = {
|
||||
"cat": "store_outputs",
|
||||
"pid": "Node " + worker["node_ip_address"],
|
||||
"tid": info["worker_id"],
|
||||
"id": task_id,
|
||||
"ts": micros_rel(info["store_outputs_start"]),
|
||||
"ph": "X",
|
||||
"name": info["function_name"] + ":store_outputs",
|
||||
"args": total_info,
|
||||
"dur": micros(info["store_outputs_end"] -
|
||||
info["store_outputs_start"]),
|
||||
"cname": "thread_state_runnable"
|
||||
"cat":
|
||||
"store_outputs",
|
||||
"pid":
|
||||
"Node " + worker["node_ip_address"],
|
||||
"tid":
|
||||
info["worker_id"],
|
||||
"id":
|
||||
task_id,
|
||||
"ts":
|
||||
micros_rel(info["store_outputs_start"]),
|
||||
"ph":
|
||||
"X",
|
||||
"name":
|
||||
info["function_name"] + ":store_outputs",
|
||||
"args":
|
||||
total_info,
|
||||
"dur":
|
||||
micros(info["store_outputs_end"] -
|
||||
info["store_outputs_start"]),
|
||||
"cname":
|
||||
"thread_state_runnable"
|
||||
}
|
||||
full_trace.append(outputs_trace)
|
||||
|
||||
if "execute_end" in info:
|
||||
execute_trace = {
|
||||
"cat": "execute",
|
||||
"pid": "Node " + worker["node_ip_address"],
|
||||
"tid": info["worker_id"],
|
||||
"id": task_id,
|
||||
"ts": micros_rel(info["execute_start"]),
|
||||
"ph": "X",
|
||||
"name": info["function_name"] + ":execute",
|
||||
"args": total_info,
|
||||
"dur": micros(info["execute_end"] -
|
||||
info["execute_start"]),
|
||||
"cname": "rail_animation"
|
||||
"cat":
|
||||
"execute",
|
||||
"pid":
|
||||
"Node " + worker["node_ip_address"],
|
||||
"tid":
|
||||
info["worker_id"],
|
||||
"id":
|
||||
task_id,
|
||||
"ts":
|
||||
micros_rel(info["execute_start"]),
|
||||
"ph":
|
||||
"X",
|
||||
"name":
|
||||
info["function_name"] + ":execute",
|
||||
"args":
|
||||
total_info,
|
||||
"dur":
|
||||
micros(info["execute_end"] - info["execute_start"]),
|
||||
"cname":
|
||||
"rail_animation"
|
||||
}
|
||||
full_trace.append(execute_trace)
|
||||
|
||||
@@ -680,15 +731,20 @@ class GlobalState(object):
|
||||
parent_profile = task_info.get(
|
||||
task_table[task_id]["TaskSpec"]["ParentTaskID"])
|
||||
parent = {
|
||||
"cat": "submit_task",
|
||||
"pid": "Node " + parent_worker["node_ip_address"],
|
||||
"tid": parent_info["worker_id"],
|
||||
"ts": micros_rel(
|
||||
parent_profile and
|
||||
parent_profile["get_arguments_start"] or
|
||||
start_time),
|
||||
"ph": "s",
|
||||
"name": "SubmitTask",
|
||||
"cat":
|
||||
"submit_task",
|
||||
"pid":
|
||||
"Node " + parent_worker["node_ip_address"],
|
||||
"tid":
|
||||
parent_info["worker_id"],
|
||||
"ts":
|
||||
micros_rel(parent_profile
|
||||
and parent_profile["get_arguments_start"]
|
||||
or start_time),
|
||||
"ph":
|
||||
"s",
|
||||
"name":
|
||||
"SubmitTask",
|
||||
"args": {},
|
||||
"id": (parent_info["worker_id"] +
|
||||
str(micros(min(parent_times))))
|
||||
@@ -696,32 +752,50 @@ class GlobalState(object):
|
||||
full_trace.append(parent)
|
||||
|
||||
task_trace = {
|
||||
"cat": "submit_task",
|
||||
"pid": "Node " + worker["node_ip_address"],
|
||||
"tid": info["worker_id"],
|
||||
"ts": micros_rel(info["get_arguments_start"]),
|
||||
"ph": "f",
|
||||
"name": "SubmitTask",
|
||||
"cat":
|
||||
"submit_task",
|
||||
"pid":
|
||||
"Node " + worker["node_ip_address"],
|
||||
"tid":
|
||||
info["worker_id"],
|
||||
"ts":
|
||||
micros_rel(info["get_arguments_start"]),
|
||||
"ph":
|
||||
"f",
|
||||
"name":
|
||||
"SubmitTask",
|
||||
"args": {},
|
||||
"id": (info["worker_id"] +
|
||||
str(micros(min(parent_times)))),
|
||||
"bp": "e",
|
||||
"cname": "olive"
|
||||
"id":
|
||||
(info["worker_id"] + str(micros(min(parent_times)))),
|
||||
"bp":
|
||||
"e",
|
||||
"cname":
|
||||
"olive"
|
||||
}
|
||||
full_trace.append(task_trace)
|
||||
|
||||
task = {
|
||||
"cat": "task",
|
||||
"pid": "Node " + worker["node_ip_address"],
|
||||
"tid": info["worker_id"],
|
||||
"id": task_id,
|
||||
"ts": micros_rel(info["get_arguments_start"]),
|
||||
"ph": "X",
|
||||
"name": info["function_name"],
|
||||
"args": total_info,
|
||||
"dur": micros(info["store_outputs_end"] -
|
||||
info["get_arguments_start"]),
|
||||
"cname": "thread_state_runnable"
|
||||
"cat":
|
||||
"task",
|
||||
"pid":
|
||||
"Node " + worker["node_ip_address"],
|
||||
"tid":
|
||||
info["worker_id"],
|
||||
"id":
|
||||
task_id,
|
||||
"ts":
|
||||
micros_rel(info["get_arguments_start"]),
|
||||
"ph":
|
||||
"X",
|
||||
"name":
|
||||
info["function_name"],
|
||||
"args":
|
||||
total_info,
|
||||
"dur":
|
||||
micros(info["store_outputs_end"] -
|
||||
info["get_arguments_start"]),
|
||||
"cname":
|
||||
"thread_state_runnable"
|
||||
}
|
||||
full_trace.append(task)
|
||||
|
||||
@@ -732,15 +806,20 @@ class GlobalState(object):
|
||||
parent_profile = task_info.get(
|
||||
task_table[task_id]["TaskSpec"]["ParentTaskID"])
|
||||
parent = {
|
||||
"cat": "submit_task",
|
||||
"pid": "Node " + parent_worker["node_ip_address"],
|
||||
"tid": parent_info["worker_id"],
|
||||
"ts": micros_rel(
|
||||
parent_profile and
|
||||
parent_profile["get_arguments_start"] or
|
||||
start_time),
|
||||
"ph": "s",
|
||||
"name": "SubmitTask",
|
||||
"cat":
|
||||
"submit_task",
|
||||
"pid":
|
||||
"Node " + parent_worker["node_ip_address"],
|
||||
"tid":
|
||||
parent_info["worker_id"],
|
||||
"ts":
|
||||
micros_rel(parent_profile
|
||||
and parent_profile["get_arguments_start"]
|
||||
or start_time),
|
||||
"ph":
|
||||
"s",
|
||||
"name":
|
||||
"SubmitTask",
|
||||
"args": {},
|
||||
"id": (parent_info["worker_id"] +
|
||||
str(micros(min(parent_times))))
|
||||
@@ -748,16 +827,23 @@ class GlobalState(object):
|
||||
full_trace.append(parent)
|
||||
|
||||
task_trace = {
|
||||
"cat": "submit_task",
|
||||
"pid": "Node " + worker["node_ip_address"],
|
||||
"tid": info["worker_id"],
|
||||
"ts": micros_rel(info["get_arguments_start"]),
|
||||
"ph": "f",
|
||||
"name": "SubmitTask",
|
||||
"cat":
|
||||
"submit_task",
|
||||
"pid":
|
||||
"Node " + worker["node_ip_address"],
|
||||
"tid":
|
||||
info["worker_id"],
|
||||
"ts":
|
||||
micros_rel(info["get_arguments_start"]),
|
||||
"ph":
|
||||
"f",
|
||||
"name":
|
||||
"SubmitTask",
|
||||
"args": {},
|
||||
"id": (info["worker_id"] +
|
||||
str(micros(min(parent_times)))),
|
||||
"bp": "e"
|
||||
"id":
|
||||
(info["worker_id"] + str(micros(min(parent_times)))),
|
||||
"bp":
|
||||
"e"
|
||||
}
|
||||
full_trace.append(task_trace)
|
||||
|
||||
@@ -775,8 +861,8 @@ class GlobalState(object):
|
||||
seen_obj[arg] += 1
|
||||
owner_task = self._object_table(arg)["TaskID"]
|
||||
if owner_task in task_info:
|
||||
owner_worker = (workers[
|
||||
task_info[owner_task]["worker_id"]])
|
||||
owner_worker = (workers[task_info[owner_task][
|
||||
"worker_id"]])
|
||||
# Adding/subtracting 2 to the time associated
|
||||
# with the beginning/ending of the flow event
|
||||
# is necessary to make the flow events show up
|
||||
@@ -790,27 +876,35 @@ class GlobalState(object):
|
||||
# duration event that it's associated with, and
|
||||
# the flow event therefore always gets drawn.
|
||||
owner = {
|
||||
"cat": "obj_dependency",
|
||||
"cat":
|
||||
"obj_dependency",
|
||||
"pid": ("Node " +
|
||||
owner_worker["node_ip_address"]),
|
||||
"tid": task_info[owner_task]["worker_id"],
|
||||
"ts": micros_rel(task_info[
|
||||
owner_task]["store_outputs_end"]) - 2,
|
||||
"ph": "s",
|
||||
"name": "ObjectDependency",
|
||||
"tid":
|
||||
task_info[owner_task]["worker_id"],
|
||||
"ts":
|
||||
micros_rel(task_info[owner_task]
|
||||
["store_outputs_end"]) - 2,
|
||||
"ph":
|
||||
"s",
|
||||
"name":
|
||||
"ObjectDependency",
|
||||
"args": {},
|
||||
"bp": "e",
|
||||
"cname": "cq_build_attempt_failed",
|
||||
"id": "obj" + str(arg) + str(seen_obj[arg])
|
||||
"bp":
|
||||
"e",
|
||||
"cname":
|
||||
"cq_build_attempt_failed",
|
||||
"id":
|
||||
"obj" + str(arg) + str(seen_obj[arg])
|
||||
}
|
||||
full_trace.append(owner)
|
||||
|
||||
dependent = {
|
||||
"cat": "obj_dependency",
|
||||
"pid": "Node " + worker["node_ip_address"],
|
||||
"pid": "Node " + worker["node_ip_address"],
|
||||
"tid": info["worker_id"],
|
||||
"ts": micros_rel(
|
||||
info["get_arguments_start"]) + 2,
|
||||
"ts":
|
||||
micros_rel(info["get_arguments_start"]) + 2,
|
||||
"ph": "f",
|
||||
"name": "ObjectDependency",
|
||||
"args": {},
|
||||
@@ -852,14 +946,10 @@ class GlobalState(object):
|
||||
"""
|
||||
|
||||
keys = [
|
||||
"acquire_lock_start",
|
||||
"acquire_lock_end",
|
||||
"get_arguments_start",
|
||||
"get_arguments_end",
|
||||
"execute_start",
|
||||
"execute_end",
|
||||
"store_outputs_start",
|
||||
"store_outputs_end"]
|
||||
"acquire_lock_start", "acquire_lock_end", "get_arguments_start",
|
||||
"get_arguments_end", "execute_start", "execute_end",
|
||||
"store_outputs_start", "store_outputs_end"
|
||||
]
|
||||
|
||||
latest_timestamp = 0
|
||||
for key in keys:
|
||||
@@ -877,8 +967,8 @@ class GlobalState(object):
|
||||
local_schedulers = []
|
||||
for ip_address, client_list in clients.items():
|
||||
for client in client_list:
|
||||
if (client["ClientType"] == "local_scheduler" and
|
||||
not client["Deleted"]):
|
||||
if (client["ClientType"] == "local_scheduler"
|
||||
and not client["Deleted"]):
|
||||
local_schedulers.append(client)
|
||||
return local_schedulers
|
||||
|
||||
@@ -893,8 +983,7 @@ class GlobalState(object):
|
||||
|
||||
workers_data[worker_id] = {
|
||||
"local_scheduler_socket":
|
||||
(worker_info[b"local_scheduler_socket"]
|
||||
.decode("ascii")),
|
||||
(worker_info[b"local_scheduler_socket"].decode("ascii")),
|
||||
"node_ip_address": (worker_info[b"node_ip_address"]
|
||||
.decode("ascii")),
|
||||
"plasma_manager_socket": (worker_info[b"plasma_manager_socket"]
|
||||
@@ -921,9 +1010,10 @@ class GlobalState(object):
|
||||
"class_id": binary_to_hex(info[b"class_id"]),
|
||||
"driver_id": binary_to_hex(info[b"driver_id"]),
|
||||
"local_scheduler_id":
|
||||
binary_to_hex(info[b"local_scheduler_id"]),
|
||||
binary_to_hex(info[b"local_scheduler_id"]),
|
||||
"num_gpus": int(info[b"num_gpus"]),
|
||||
"removed": decode(info[b"removed"]) == "True"}
|
||||
"removed": decode(info[b"removed"]) == "True"
|
||||
}
|
||||
return actor_info
|
||||
|
||||
def _job_length(self):
|
||||
@@ -932,21 +1022,16 @@ class GlobalState(object):
|
||||
overall_largest = 0
|
||||
num_tasks = 0
|
||||
for event_log_set in event_log_sets:
|
||||
fwd_range = self.redis_client.zrange(event_log_set,
|
||||
start=0,
|
||||
end=0,
|
||||
withscores=True)
|
||||
fwd_range = self.redis_client.zrange(
|
||||
event_log_set, start=0, end=0, withscores=True)
|
||||
overall_smallest = min(overall_smallest, fwd_range[0][1])
|
||||
|
||||
rev_range = self.redis_client.zrevrange(event_log_set,
|
||||
start=0,
|
||||
end=0,
|
||||
withscores=True)
|
||||
rev_range = self.redis_client.zrevrange(
|
||||
event_log_set, start=0, end=0, withscores=True)
|
||||
overall_largest = max(overall_largest, rev_range[0][1])
|
||||
|
||||
num_tasks += self.redis_client.zcount(event_log_set,
|
||||
min=0,
|
||||
max=time.time())
|
||||
num_tasks += self.redis_client.zcount(
|
||||
event_log_set, min=0, max=time.time())
|
||||
if num_tasks is 0:
|
||||
return 0, 0, 0
|
||||
return overall_smallest, overall_largest, num_tasks
|
||||
@@ -966,8 +1051,10 @@ class GlobalState(object):
|
||||
|
||||
for local_scheduler in local_schedulers:
|
||||
for key, value in local_scheduler.items():
|
||||
if key not in ["ClientType", "Deleted", "DBClientID",
|
||||
"AuxAddress", "LocalSchedulerSocketName"]:
|
||||
if key not in [
|
||||
"ClientType", "Deleted", "DBClientID", "AuxAddress",
|
||||
"LocalSchedulerSocketName"
|
||||
]:
|
||||
resources[key] += value
|
||||
|
||||
return dict(resources)
|
||||
|
||||
@@ -27,6 +27,7 @@ class TensorFlowVariables(object):
|
||||
placeholders (Dict[str, tf.placeholders]): Placeholders for weights.
|
||||
assignment_nodes (Dict[str, tf.Tensor]): Nodes that assign weights.
|
||||
"""
|
||||
|
||||
def __init__(self, loss, sess=None, input_variables=None):
|
||||
"""Creates TensorFlowVariables containing extracted variables.
|
||||
|
||||
@@ -74,8 +75,10 @@ class TensorFlowVariables(object):
|
||||
if "Variable" in tf_obj.node_def.op:
|
||||
variable_names.append(tf_obj.node_def.name)
|
||||
self.variables = OrderedDict()
|
||||
variable_list = [v for v in tf.global_variables()
|
||||
if v.op.node_def.name in variable_names]
|
||||
variable_list = [
|
||||
v for v in tf.global_variables()
|
||||
if v.op.node_def.name in variable_names
|
||||
]
|
||||
if input_variables is not None:
|
||||
variable_list += input_variables
|
||||
for v in variable_list:
|
||||
@@ -86,9 +89,10 @@ class TensorFlowVariables(object):
|
||||
|
||||
# Create new placeholders to put in custom weights.
|
||||
for k, var in self.variables.items():
|
||||
self.placeholders[k] = tf.placeholder(var.value().dtype,
|
||||
var.get_shape().as_list(),
|
||||
name="Placeholder_" + k)
|
||||
self.placeholders[k] = tf.placeholder(
|
||||
var.value().dtype,
|
||||
var.get_shape().as_list(),
|
||||
name="Placeholder_" + k)
|
||||
self.assignment_nodes[k] = var.assign(self.placeholders[k])
|
||||
|
||||
def set_session(self, sess):
|
||||
@@ -105,8 +109,9 @@ class TensorFlowVariables(object):
|
||||
Returns:
|
||||
The length of all flattened variables concatenated.
|
||||
"""
|
||||
return sum([np.prod(v.get_shape().as_list())
|
||||
for v in self.variables.values()])
|
||||
return sum([
|
||||
np.prod(v.get_shape().as_list()) for v in self.variables.values()
|
||||
])
|
||||
|
||||
def _check_sess(self):
|
||||
"""Checks if the session is set, and if not throw an error message."""
|
||||
@@ -122,8 +127,10 @@ class TensorFlowVariables(object):
|
||||
1D Array containing the flattened weights.
|
||||
"""
|
||||
self._check_sess()
|
||||
return np.concatenate([v.eval(session=self.sess).flatten()
|
||||
for v in self.variables.values()])
|
||||
return np.concatenate([
|
||||
v.eval(session=self.sess).flatten()
|
||||
for v in self.variables.values()
|
||||
])
|
||||
|
||||
def set_flat(self, new_weights):
|
||||
"""Sets the weights to new_weights, converting from a flat array.
|
||||
@@ -138,10 +145,12 @@ class TensorFlowVariables(object):
|
||||
self._check_sess()
|
||||
shapes = [v.get_shape().as_list() for v in self.variables.values()]
|
||||
arrays = unflatten(new_weights, shapes)
|
||||
placeholders = [self.placeholders[k] for k, v
|
||||
in self.variables.items()]
|
||||
self.sess.run(list(self.assignment_nodes.values()),
|
||||
feed_dict=dict(zip(placeholders, arrays)))
|
||||
placeholders = [
|
||||
self.placeholders[k] for k, v in self.variables.items()
|
||||
]
|
||||
self.sess.run(
|
||||
list(self.assignment_nodes.values()),
|
||||
feed_dict=dict(zip(placeholders, arrays)))
|
||||
|
||||
def get_weights(self):
|
||||
"""Returns a dictionary containing the weights of the network.
|
||||
@@ -150,8 +159,10 @@ class TensorFlowVariables(object):
|
||||
Dictionary mapping variable names to their weights.
|
||||
"""
|
||||
self._check_sess()
|
||||
return {k: v.eval(session=self.sess) for k, v
|
||||
in self.variables.items()}
|
||||
return {
|
||||
k: v.eval(session=self.sess)
|
||||
for k, v in self.variables.items()
|
||||
}
|
||||
|
||||
def set_weights(self, new_weights):
|
||||
"""Sets the weights to new_weights.
|
||||
@@ -165,15 +176,19 @@ class TensorFlowVariables(object):
|
||||
weights.
|
||||
"""
|
||||
self._check_sess()
|
||||
assign_list = [self.assignment_nodes[name]
|
||||
for name in new_weights.keys()
|
||||
if name in self.assignment_nodes]
|
||||
assign_list = [
|
||||
self.assignment_nodes[name] for name in new_weights.keys()
|
||||
if name in self.assignment_nodes
|
||||
]
|
||||
assert assign_list, ("No variables in the input matched those in the "
|
||||
"network. Possible cause: Two networks were "
|
||||
"defined in the same TensorFlow graph. To fix "
|
||||
"this, place each network definition in its own "
|
||||
"tf.Graph.")
|
||||
self.sess.run(assign_list,
|
||||
feed_dict={self.placeholders[name]: value
|
||||
for (name, value) in new_weights.items()
|
||||
if name in self.placeholders})
|
||||
self.sess.run(
|
||||
assign_list,
|
||||
feed_dict={
|
||||
self.placeholders[name]: value
|
||||
for (name, value) in new_weights.items()
|
||||
if name in self.placeholders
|
||||
})
|
||||
|
||||
+200
-215
@@ -29,9 +29,9 @@ class _EventRecursionContextManager(object):
|
||||
total_time_value = "% total time"
|
||||
total_tasks_value = "% total tasks"
|
||||
|
||||
|
||||
# Function that returns instances of sliders and handles associated events.
|
||||
|
||||
|
||||
def get_sliders(update):
|
||||
# Start_box value indicates the desired start point of queried window.
|
||||
start_box = widgets.FloatText(
|
||||
@@ -60,18 +60,14 @@ def get_sliders(update):
|
||||
|
||||
# Indicates the number of tasks that the user wants to be returned. Is
|
||||
# disabled when the breakdown_opt value is set to total_time_value.
|
||||
num_tasks_box = widgets.IntText(
|
||||
description="Num Tasks:",
|
||||
disabled=False
|
||||
)
|
||||
num_tasks_box = widgets.IntText(description="Num Tasks:", disabled=False)
|
||||
|
||||
# Dropdown bar that lets the user choose between modifying % of total
|
||||
# time or total number of tasks.
|
||||
breakdown_opt = widgets.Dropdown(
|
||||
options=[total_time_value, total_tasks_value],
|
||||
value=total_tasks_value,
|
||||
description="Selection Options:"
|
||||
)
|
||||
description="Selection Options:")
|
||||
|
||||
# Display box for layout.
|
||||
total_time_box = widgets.VBox([start_box, end_box])
|
||||
@@ -105,9 +101,9 @@ def get_sliders(update):
|
||||
if event == INIT_EVENT:
|
||||
if breakdown_opt.value == total_tasks_value:
|
||||
num_tasks_box.value = -min(10000, num_tasks)
|
||||
range_slider.value = (int(100 -
|
||||
(100. * -num_tasks_box.value) /
|
||||
num_tasks), 100)
|
||||
range_slider.value = (int(
|
||||
100 - (100. * -num_tasks_box.value) / num_tasks),
|
||||
100)
|
||||
else:
|
||||
low, high = map(lambda x: x / 100., range_slider.value)
|
||||
start_box.value = round(diff * low, 2)
|
||||
@@ -120,8 +116,8 @@ def get_sliders(update):
|
||||
elif start_box.value < 0:
|
||||
start_box.value = 0
|
||||
low, high = range_slider.value
|
||||
range_slider.value = (int((start_box.value * 100.) /
|
||||
diff), high)
|
||||
range_slider.value = (int((start_box.value * 100.) / diff),
|
||||
high)
|
||||
|
||||
# Event was triggered by a change in the end_box value.
|
||||
elif event["owner"] == end_box:
|
||||
@@ -130,8 +126,8 @@ def get_sliders(update):
|
||||
elif end_box.value > diff:
|
||||
end_box.value = diff
|
||||
low, high = range_slider.value
|
||||
range_slider.value = (low, int((end_box.value * 100.) /
|
||||
diff))
|
||||
range_slider.value = (low,
|
||||
int((end_box.value * 100.) / diff))
|
||||
|
||||
# Event was triggered by a change in the breakdown options
|
||||
# toggle.
|
||||
@@ -145,9 +141,9 @@ def get_sliders(update):
|
||||
# Make CSS display go back to the default settings.
|
||||
num_tasks_box.layout.display = None
|
||||
num_tasks_box.value = min(10000, num_tasks)
|
||||
range_slider.value = (int(100 -
|
||||
(100. * num_tasks_box.value) /
|
||||
num_tasks), 100)
|
||||
range_slider.value = (int(
|
||||
100 - (100. * num_tasks_box.value) / num_tasks),
|
||||
100)
|
||||
else:
|
||||
start_box.disabled = False
|
||||
end_box.disabled = False
|
||||
@@ -156,10 +152,9 @@ def get_sliders(update):
|
||||
# Make CSS display go back to the default settings.
|
||||
total_time_box.layout.display = None
|
||||
num_tasks_box.layout.display = 'none'
|
||||
range_slider.value = (int((start_box.value * 100.) /
|
||||
diff),
|
||||
int((end_box.value * 100.) /
|
||||
diff))
|
||||
range_slider.value = (
|
||||
int((start_box.value * 100.) / diff),
|
||||
int((end_box.value * 100.) / diff))
|
||||
|
||||
# Event was triggered by a change in the range_slider
|
||||
# value.
|
||||
@@ -170,8 +165,8 @@ def get_sliders(update):
|
||||
new_low, new_high = event["new"]
|
||||
if old_low != new_low:
|
||||
range_slider.value = (new_low, 100)
|
||||
num_tasks_box.value = (-(100. - new_low) /
|
||||
100. * num_tasks)
|
||||
num_tasks_box.value = (
|
||||
-(100. - new_low) / 100. * num_tasks)
|
||||
else:
|
||||
range_slider.value = (0, new_high)
|
||||
num_tasks_box.value = new_high / 100. * num_tasks
|
||||
@@ -183,14 +178,12 @@ def get_sliders(update):
|
||||
# value.
|
||||
elif event["owner"] == num_tasks_box:
|
||||
if num_tasks_box.value > 0:
|
||||
range_slider.value = (0, int(100 *
|
||||
float(num_tasks_box.value) /
|
||||
num_tasks))
|
||||
range_slider.value = (
|
||||
0, int(
|
||||
100 * float(num_tasks_box.value) / num_tasks))
|
||||
elif num_tasks_box.value < 0:
|
||||
range_slider.value = (100 +
|
||||
int(100 *
|
||||
float(num_tasks_box.value) /
|
||||
num_tasks), 100)
|
||||
range_slider.value = (100 + int(
|
||||
100 * float(num_tasks_box.value) / num_tasks), 100)
|
||||
|
||||
if not update:
|
||||
return
|
||||
@@ -205,23 +198,20 @@ def get_sliders(update):
|
||||
# box values.
|
||||
# (Querying based on the % total amount of time.)
|
||||
if breakdown_opt.value == total_time_value:
|
||||
tasks = _truncated_task_profiles(start=(smallest +
|
||||
diff * low),
|
||||
end=(smallest +
|
||||
diff * high))
|
||||
tasks = _truncated_task_profiles(
|
||||
start=(smallest + diff * low),
|
||||
end=(smallest + diff * high))
|
||||
|
||||
# (Querying based on % of total number of tasks that were
|
||||
# run.)
|
||||
elif breakdown_opt.value == total_tasks_value:
|
||||
if range_slider.value[0] == 0:
|
||||
tasks = _truncated_task_profiles(num_tasks=(int(
|
||||
num_tasks * high)),
|
||||
fwd=True)
|
||||
tasks = _truncated_task_profiles(
|
||||
num_tasks=(int(num_tasks * high)), fwd=True)
|
||||
else:
|
||||
tasks = _truncated_task_profiles(num_tasks=(int(
|
||||
num_tasks *
|
||||
(high - low))),
|
||||
fwd=False)
|
||||
tasks = _truncated_task_profiles(
|
||||
num_tasks=(int(num_tasks * (high - low))),
|
||||
fwd=False)
|
||||
|
||||
update(smallest, largest, num_tasks, tasks)
|
||||
|
||||
@@ -237,8 +227,8 @@ def get_sliders(update):
|
||||
update_wrapper(INIT_EVENT)
|
||||
|
||||
# Display sliders and search boxes
|
||||
display(breakdown_opt, widgets.HBox([range_slider, total_time_box,
|
||||
num_tasks_box]))
|
||||
display(breakdown_opt,
|
||||
widgets.HBox([range_slider, total_time_box, num_tasks_box]))
|
||||
|
||||
# Return the sliders and text boxes
|
||||
return start_box, end_box, range_slider, breakdown_opt
|
||||
@@ -249,8 +239,7 @@ def object_search_bar():
|
||||
value="",
|
||||
placeholder="Object ID",
|
||||
description="Search for an object:",
|
||||
disabled=False
|
||||
)
|
||||
disabled=False)
|
||||
display(object_search)
|
||||
|
||||
def handle_submit(sender):
|
||||
@@ -265,8 +254,7 @@ def task_search_bar():
|
||||
value="",
|
||||
placeholder="Task ID",
|
||||
description="Search for a task:",
|
||||
disabled=False
|
||||
)
|
||||
disabled=False)
|
||||
display(task_search)
|
||||
|
||||
def handle_submit(sender):
|
||||
@@ -284,14 +272,12 @@ MAX_TASKS_TO_VISUALIZE = 10000
|
||||
def _truncated_task_profiles(start=None, end=None, num_tasks=None, fwd=True):
|
||||
if num_tasks is None:
|
||||
num_tasks = MAX_TASKS_TO_VISUALIZE
|
||||
print(
|
||||
"Warning: at most {} tasks will be fetched within this "
|
||||
"time range.".format(MAX_TASKS_TO_VISUALIZE))
|
||||
print("Warning: at most {} tasks will be fetched within this "
|
||||
"time range.".format(MAX_TASKS_TO_VISUALIZE))
|
||||
elif num_tasks > MAX_TASKS_TO_VISUALIZE:
|
||||
print(
|
||||
"Warning: too many tasks to visualize, "
|
||||
"fetching only the first {} of {}.".format(
|
||||
MAX_TASKS_TO_VISUALIZE, num_tasks))
|
||||
print("Warning: too many tasks to visualize, "
|
||||
"fetching only the first {} of {}.".format(
|
||||
MAX_TASKS_TO_VISUALIZE, num_tasks))
|
||||
num_tasks = MAX_TASKS_TO_VISUALIZE
|
||||
return ray.global_state.task_profiles(num_tasks, start, end, fwd)
|
||||
|
||||
@@ -299,9 +285,8 @@ def _truncated_task_profiles(start=None, end=None, num_tasks=None, fwd=True):
|
||||
# Helper function that guarantees unique and writeable temp files.
|
||||
# Prevents clashes in task trace files when multiple notebooks are running.
|
||||
def _get_temp_file_path(**kwargs):
|
||||
temp_file = tempfile.NamedTemporaryFile(delete=False,
|
||||
dir=os.getcwd(),
|
||||
**kwargs)
|
||||
temp_file = tempfile.NamedTemporaryFile(
|
||||
delete=False, dir=os.getcwd(), **kwargs)
|
||||
temp_file_path = temp_file.name
|
||||
temp_file.close()
|
||||
return os.path.relpath(temp_file_path)
|
||||
@@ -319,22 +304,16 @@ def task_timeline():
|
||||
disabled=False,
|
||||
)
|
||||
obj_dep = widgets.Checkbox(
|
||||
value=True,
|
||||
disabled=False,
|
||||
layout=widgets.Layout(width='20px')
|
||||
)
|
||||
value=True, disabled=False, layout=widgets.Layout(width='20px'))
|
||||
task_dep = widgets.Checkbox(
|
||||
value=True,
|
||||
disabled=False,
|
||||
layout=widgets.Layout(width='20px')
|
||||
)
|
||||
value=True, disabled=False, layout=widgets.Layout(width='20px'))
|
||||
# Labels to bypass width limitation for descriptions.
|
||||
label_tasks = widgets.Label(value='Task submissions',
|
||||
layout=widgets.Layout(width='110px'))
|
||||
label_objects = widgets.Label(value='Object dependencies',
|
||||
layout=widgets.Layout(width='130px'))
|
||||
label_options = widgets.Label(value='View options:',
|
||||
layout=widgets.Layout(width='100px'))
|
||||
label_tasks = widgets.Label(
|
||||
value='Task submissions', layout=widgets.Layout(width='110px'))
|
||||
label_objects = widgets.Label(
|
||||
value='Object dependencies', layout=widgets.Layout(width='130px'))
|
||||
label_options = widgets.Label(
|
||||
value='View options:', layout=widgets.Layout(width='100px'))
|
||||
start_box, end_box, range_slider, time_opt = get_sliders(False)
|
||||
display(widgets.HBox([task_dep, label_tasks, obj_dep, label_objects]))
|
||||
display(widgets.HBox([label_options, breakdown_opt]))
|
||||
@@ -344,8 +323,9 @@ def task_timeline():
|
||||
# current working directory if it is not present.
|
||||
if not os.path.exists("trace_viewer_full.html"):
|
||||
shutil.copy(
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
"../core/src/catapult_files/trace_viewer_full.html"),
|
||||
os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"../core/src/catapult_files/trace_viewer_full.html"),
|
||||
"trace_viewer_full.html")
|
||||
|
||||
def handle_submit(sender):
|
||||
@@ -357,8 +337,8 @@ def task_timeline():
|
||||
elif breakdown_opt.value == breakdown_task:
|
||||
breakdown = True
|
||||
else:
|
||||
raise ValueError(
|
||||
"Unexpected breakdown value '{}'".format(breakdown_opt.value))
|
||||
raise ValueError("Unexpected breakdown value '{}'".format(
|
||||
breakdown_opt.value))
|
||||
|
||||
low, high = map(lambda x: x / 100., range_slider.value)
|
||||
|
||||
@@ -366,30 +346,28 @@ def task_timeline():
|
||||
diff = largest - smallest
|
||||
|
||||
if time_opt.value == total_time_value:
|
||||
tasks = _truncated_task_profiles(start=smallest + diff * low,
|
||||
end=smallest + diff * high)
|
||||
tasks = _truncated_task_profiles(
|
||||
start=smallest + diff * low, end=smallest + diff * high)
|
||||
elif time_opt.value == total_tasks_value:
|
||||
if range_slider.value[0] == 0:
|
||||
tasks = _truncated_task_profiles(num_tasks=int(
|
||||
num_tasks * high),
|
||||
fwd=True)
|
||||
tasks = _truncated_task_profiles(
|
||||
num_tasks=int(num_tasks * high), fwd=True)
|
||||
else:
|
||||
tasks = _truncated_task_profiles(num_tasks=int(
|
||||
num_tasks * (high - low)),
|
||||
fwd=False)
|
||||
tasks = _truncated_task_profiles(
|
||||
num_tasks=int(num_tasks * (high - low)), fwd=False)
|
||||
else:
|
||||
raise ValueError("Unexpected time value '{}'".format(
|
||||
time_opt.value))
|
||||
time_opt.value))
|
||||
# Write trace to a JSON file
|
||||
print("Collected profiles for {} tasks.".format(len(tasks)))
|
||||
print(
|
||||
"Dumping task profile data to {}, "
|
||||
"this might take a while...".format(json_tmp))
|
||||
ray.global_state.dump_catapult_trace(json_tmp,
|
||||
tasks,
|
||||
breakdowns=breakdown,
|
||||
obj_dep=obj_dep.value,
|
||||
task_dep=task_dep.value)
|
||||
print("Dumping task profile data to {}, "
|
||||
"this might take a while...".format(json_tmp))
|
||||
ray.global_state.dump_catapult_trace(
|
||||
json_tmp,
|
||||
tasks,
|
||||
breakdowns=breakdown,
|
||||
obj_dep=obj_dep.value,
|
||||
task_dep=task_dep.value)
|
||||
print("Opening html file in browser...")
|
||||
|
||||
trace_viewer_path = os.path.join(
|
||||
@@ -415,9 +393,8 @@ def task_timeline():
|
||||
|
||||
# Display the task trace within the Jupyter notebook
|
||||
clear_output(wait=True)
|
||||
print(
|
||||
"To view fullscreen, open chrome://tracing in Google Chrome "
|
||||
"and load `{}`".format(json_tmp))
|
||||
print("To view fullscreen, open chrome://tracing in Google Chrome "
|
||||
"and load `{}`".format(json_tmp))
|
||||
display(IFrame(html_file_path, 900, 800))
|
||||
|
||||
path_input.on_click(handle_submit)
|
||||
@@ -432,36 +409,41 @@ def task_completion_time_distribution():
|
||||
output_notebook(resources=CDN)
|
||||
|
||||
# Create the Bokeh plot
|
||||
p = figure(title="Task Completion Time Distribution",
|
||||
tools=["save", "hover", "wheel_zoom", "box_zoom", "pan"],
|
||||
background_fill_color="#FFFFFF",
|
||||
x_range=(0, 1),
|
||||
y_range=(0, 1))
|
||||
p = figure(
|
||||
title="Task Completion Time Distribution",
|
||||
tools=["save", "hover", "wheel_zoom", "box_zoom", "pan"],
|
||||
background_fill_color="#FFFFFF",
|
||||
x_range=(0, 1),
|
||||
y_range=(0, 1))
|
||||
|
||||
# Create the data source that the plot pulls from
|
||||
source = ColumnDataSource(data={
|
||||
"top": [],
|
||||
"left": [],
|
||||
"right": []
|
||||
})
|
||||
source = ColumnDataSource(data={"top": [], "left": [], "right": []})
|
||||
|
||||
# Plot the histogram rectangles
|
||||
p.quad(top="top", bottom=0, left="left", right="right", source=source,
|
||||
fill_color="#B3B3B3", line_color="#033649")
|
||||
p.quad(
|
||||
top="top",
|
||||
bottom=0,
|
||||
left="left",
|
||||
right="right",
|
||||
source=source,
|
||||
fill_color="#B3B3B3",
|
||||
line_color="#033649")
|
||||
|
||||
# Label the plot axes
|
||||
p.xaxis.axis_label = "Duration in seconds"
|
||||
p.yaxis.axis_label = "Number of tasks"
|
||||
|
||||
handle = show(gridplot(p, ncols=1,
|
||||
plot_width=500,
|
||||
plot_height=500,
|
||||
toolbar_location="below"), notebook_handle=True)
|
||||
handle = show(
|
||||
gridplot(
|
||||
p,
|
||||
ncols=1,
|
||||
plot_width=500,
|
||||
plot_height=500,
|
||||
toolbar_location="below"),
|
||||
notebook_handle=True)
|
||||
|
||||
# Function to update the plot
|
||||
def task_completion_time_update(abs_earliest,
|
||||
abs_latest,
|
||||
abs_num_tasks,
|
||||
def task_completion_time_update(abs_earliest, abs_latest, abs_num_tasks,
|
||||
tasks):
|
||||
if len(tasks) == 0:
|
||||
return
|
||||
@@ -469,8 +451,8 @@ def task_completion_time_distribution():
|
||||
# Create the distribution to plot
|
||||
distr = []
|
||||
for task_id, data in tasks.items():
|
||||
distr.append(data["store_outputs_end"] -
|
||||
data["get_arguments_start"])
|
||||
distr.append(
|
||||
data["store_outputs_end"] - data["get_arguments_start"])
|
||||
|
||||
# Create a histogram from the distribution
|
||||
top, bin_edges = np.histogram(distr, bins="auto")
|
||||
@@ -480,8 +462,8 @@ def task_completion_time_distribution():
|
||||
source.data = {"top": top, "left": left, "right": right}
|
||||
|
||||
# Set the x and y ranges
|
||||
x_range = (min(left) if len(left) else 0,
|
||||
max(right) if len(right) else 1)
|
||||
x_range = (min(left) if len(left) else 0, max(right)
|
||||
if len(right) else 1)
|
||||
y_range = (0, max(top) + 1 if len(top) else 1)
|
||||
|
||||
x_range = helpers._get_range(x_range)
|
||||
@@ -517,8 +499,7 @@ def compute_utilizations(abs_earliest,
|
||||
latest_time = 0
|
||||
for task_id, data in tasks.items():
|
||||
latest_time = max((latest_time, data["store_outputs_end"]))
|
||||
earliest_time = min((earliest_time,
|
||||
data["get_arguments_start"]))
|
||||
earliest_time = min((earliest_time, data["get_arguments_start"]))
|
||||
|
||||
# Add some epsilon to latest_time to ensure that the end time of the
|
||||
# last task falls __within__ a bucket, and not on the edge
|
||||
@@ -533,37 +514,37 @@ def compute_utilizations(abs_earliest,
|
||||
task_start_time = data["get_arguments_start"]
|
||||
task_end_time = data["store_outputs_end"]
|
||||
|
||||
start_bucket = int((task_start_time - earliest_time) /
|
||||
bucket_time_length)
|
||||
end_bucket = int((task_end_time - earliest_time) /
|
||||
bucket_time_length)
|
||||
start_bucket = int(
|
||||
(task_start_time - earliest_time) / bucket_time_length)
|
||||
end_bucket = int((task_end_time - earliest_time) / bucket_time_length)
|
||||
# Walk over each time bucket that this task intersects, adding the
|
||||
# amount of time that the task intersects within each bucket
|
||||
for bucket_idx in range(start_bucket, end_bucket + 1):
|
||||
bucket_start_time = ((earliest_time + bucket_idx) *
|
||||
bucket_time_length)
|
||||
bucket_end_time = ((earliest_time + (bucket_idx + 1)) *
|
||||
bucket_time_length)
|
||||
bucket_start_time = ((
|
||||
earliest_time + bucket_idx) * bucket_time_length)
|
||||
bucket_end_time = ((earliest_time +
|
||||
(bucket_idx + 1)) * bucket_time_length)
|
||||
|
||||
task_start_time_within_bucket = max(task_start_time,
|
||||
bucket_start_time)
|
||||
task_end_time_within_bucket = min(task_end_time,
|
||||
bucket_end_time)
|
||||
task_cpu_time_within_bucket = (task_end_time_within_bucket -
|
||||
task_start_time_within_bucket)
|
||||
task_end_time_within_bucket = min(task_end_time, bucket_end_time)
|
||||
task_cpu_time_within_bucket = (
|
||||
task_end_time_within_bucket - task_start_time_within_bucket)
|
||||
|
||||
if bucket_idx > -1 and bucket_idx < num_buckets:
|
||||
cpu_time[bucket_idx] += task_cpu_time_within_bucket
|
||||
|
||||
# Cpu_utilization is the average cpu utilization of the bucket, which
|
||||
# is just cpu_time divided by bucket_time_length.
|
||||
cpu_utilization = list(map(lambda x: x / float(bucket_time_length),
|
||||
cpu_time))
|
||||
cpu_utilization = list(
|
||||
map(lambda x: x / float(bucket_time_length), cpu_time))
|
||||
|
||||
# Generate histogram bucket edges. Subtract out abs_earliest to get
|
||||
# relative time.
|
||||
all_edges = [earliest_time - abs_earliest + i * bucket_time_length
|
||||
for i in range(num_buckets + 1)]
|
||||
all_edges = [
|
||||
earliest_time - abs_earliest + i * bucket_time_length
|
||||
for i in range(num_buckets + 1)
|
||||
]
|
||||
# Left edges are all but the rightmost edge, right edges are all but
|
||||
# the leftmost edge.
|
||||
left_edges = all_edges[:-1]
|
||||
@@ -591,54 +572,53 @@ def cpu_usage():
|
||||
# Update the plot based on the sliders
|
||||
def plot_utilization():
|
||||
# Create the Bokeh plot
|
||||
time_series_fig = figure(title="CPU Utilization",
|
||||
tools=["save", "hover", "wheel_zoom",
|
||||
"box_zoom", "pan"],
|
||||
background_fill_color="#FFFFFF",
|
||||
x_range=[0, 1],
|
||||
y_range=[0, 1])
|
||||
time_series_fig = figure(
|
||||
title="CPU Utilization",
|
||||
tools=["save", "hover", "wheel_zoom", "box_zoom", "pan"],
|
||||
background_fill_color="#FFFFFF",
|
||||
x_range=[0, 1],
|
||||
y_range=[0, 1])
|
||||
|
||||
# Create the data source that the plot will pull from
|
||||
time_series_source = ColumnDataSource(data=dict(
|
||||
left=[],
|
||||
right=[],
|
||||
top=[]
|
||||
))
|
||||
time_series_source = ColumnDataSource(
|
||||
data=dict(left=[], right=[], top=[]))
|
||||
|
||||
# Plot the rectangles representing the distribution
|
||||
time_series_fig.quad(left="left",
|
||||
right="right",
|
||||
top="top",
|
||||
bottom=0,
|
||||
source=time_series_source,
|
||||
fill_color="#B3B3B3",
|
||||
line_color="#033649")
|
||||
time_series_fig.quad(
|
||||
left="left",
|
||||
right="right",
|
||||
top="top",
|
||||
bottom=0,
|
||||
source=time_series_source,
|
||||
fill_color="#B3B3B3",
|
||||
line_color="#033649")
|
||||
|
||||
# Label the plot axes
|
||||
time_series_fig.xaxis.axis_label = "Time in seconds"
|
||||
time_series_fig.yaxis.axis_label = "Number of CPUs used"
|
||||
|
||||
handle = show(gridplot(time_series_fig,
|
||||
ncols=1,
|
||||
plot_width=500,
|
||||
plot_height=500,
|
||||
toolbar_location="below"), notebook_handle=True)
|
||||
handle = show(
|
||||
gridplot(
|
||||
time_series_fig,
|
||||
ncols=1,
|
||||
plot_width=500,
|
||||
plot_height=500,
|
||||
toolbar_location="below"),
|
||||
notebook_handle=True)
|
||||
|
||||
def update_plot(abs_earliest, abs_latest, abs_num_tasks, tasks):
|
||||
num_buckets = 100
|
||||
left, right, top = compute_utilizations(abs_earliest,
|
||||
abs_latest,
|
||||
abs_num_tasks,
|
||||
tasks,
|
||||
num_buckets)
|
||||
left, right, top = compute_utilizations(
|
||||
abs_earliest, abs_latest, abs_num_tasks, tasks, num_buckets)
|
||||
|
||||
time_series_source.data = {"left": left,
|
||||
"right": right,
|
||||
"top": top}
|
||||
time_series_source.data = {
|
||||
"left": left,
|
||||
"right": right,
|
||||
"top": top
|
||||
}
|
||||
|
||||
x_range = (max(0, min(left))
|
||||
if len(left) else 0,
|
||||
max(right) if len(right) else 1)
|
||||
x_range = (max(0, min(left)) if len(left) else 0, max(right)
|
||||
if len(right) else 1)
|
||||
y_range = (0, max(top) + 1 if len(top) else 1)
|
||||
|
||||
# Define the axis ranges
|
||||
@@ -654,6 +634,7 @@ def cpu_usage():
|
||||
push_notebook(handle=handle)
|
||||
|
||||
get_sliders(update_plot)
|
||||
|
||||
plot_utilization()
|
||||
|
||||
|
||||
@@ -672,33 +653,32 @@ def cluster_usage():
|
||||
output_notebook(resources=CDN)
|
||||
|
||||
# Initial values
|
||||
source = ColumnDataSource(data={"node_ip_address": ['127.0.0.1'],
|
||||
"time": ['0.5'],
|
||||
"num_tasks": ['1'],
|
||||
"length": [1]})
|
||||
source = ColumnDataSource(
|
||||
data={
|
||||
"node_ip_address": ['127.0.0.1'],
|
||||
"time": ['0.5'],
|
||||
"num_tasks": ['1'],
|
||||
"length": [1]
|
||||
})
|
||||
|
||||
# Define the color schema
|
||||
colors = ["#75968f",
|
||||
"#a5bab7",
|
||||
"#c9d9d3",
|
||||
"#e2e2e2",
|
||||
"#dfccce",
|
||||
"#ddb7b1",
|
||||
"#cc7878",
|
||||
"#933b41",
|
||||
"#550b1d"]
|
||||
colors = [
|
||||
"#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1",
|
||||
"#cc7878", "#933b41", "#550b1d"
|
||||
]
|
||||
mapper = LinearColorMapper(palette=colors, low=0, high=2)
|
||||
|
||||
TOOLS = "hover, save, xpan, box_zoom, reset, xwheel_zoom"
|
||||
|
||||
# Create the plot
|
||||
p = figure(title="Cluster Usage",
|
||||
y_range=list(set(source.data['node_ip_address'])),
|
||||
x_axis_location="above",
|
||||
plot_width=900,
|
||||
plot_height=500,
|
||||
tools=TOOLS,
|
||||
toolbar_location='below')
|
||||
p = figure(
|
||||
title="Cluster Usage",
|
||||
y_range=list(set(source.data['node_ip_address'])),
|
||||
x_axis_location="above",
|
||||
plot_width=900,
|
||||
plot_height=500,
|
||||
tools=TOOLS,
|
||||
toolbar_location='below')
|
||||
|
||||
# Format the plot axes
|
||||
p.grid.grid_line_color = None
|
||||
@@ -709,26 +689,33 @@ def cluster_usage():
|
||||
p.xaxis.major_label_orientation = np.pi / 3
|
||||
|
||||
# Plot rectangles
|
||||
p.rect(x="time", y="node_ip_address", width="length", height=1,
|
||||
source=source,
|
||||
fill_color={"field": "num_tasks", "transform": mapper},
|
||||
line_color=None)
|
||||
p.rect(
|
||||
x="time",
|
||||
y="node_ip_address",
|
||||
width="length",
|
||||
height=1,
|
||||
source=source,
|
||||
fill_color={
|
||||
"field": "num_tasks",
|
||||
"transform": mapper
|
||||
},
|
||||
line_color=None)
|
||||
|
||||
# Add legend to the side of the plot
|
||||
color_bar = ColorBar(color_mapper=mapper,
|
||||
major_label_text_font_size="8pt",
|
||||
ticker=BasicTicker(desired_num_ticks=len(colors)),
|
||||
label_standoff=6,
|
||||
border_line_color=None,
|
||||
location=(0, 0))
|
||||
color_bar = ColorBar(
|
||||
color_mapper=mapper,
|
||||
major_label_text_font_size="8pt",
|
||||
ticker=BasicTicker(desired_num_ticks=len(colors)),
|
||||
label_standoff=6,
|
||||
border_line_color=None,
|
||||
location=(0, 0))
|
||||
p.add_layout(color_bar, "right")
|
||||
|
||||
# Define hover tool
|
||||
p.select_one(HoverTool).tooltips = [
|
||||
("Node IP Address", "@node_ip_address"),
|
||||
("Number of tasks running", "@num_tasks"),
|
||||
("Time", "@time")
|
||||
]
|
||||
p.select_one(HoverTool).tooltips = [("Node IP Address",
|
||||
"@node_ip_address"),
|
||||
("Number of tasks running",
|
||||
"@num_tasks"), ("Time", "@time")]
|
||||
|
||||
# Define the axis labels
|
||||
p.xaxis.axis_label = "Time in seconds"
|
||||
@@ -764,12 +751,8 @@ def cluster_usage():
|
||||
num_tasks = []
|
||||
|
||||
for node_ip, task_dict in node_to_tasks.items():
|
||||
left, right, top = compute_utilizations(earliest,
|
||||
latest,
|
||||
abs_num_tasks,
|
||||
task_dict,
|
||||
100,
|
||||
True)
|
||||
left, right, top = compute_utilizations(
|
||||
earliest, latest, abs_num_tasks, task_dict, 100, True)
|
||||
for (l, r, t) in zip(left, right, top):
|
||||
nodes.append(node_ip)
|
||||
times.append((l + r) / 2)
|
||||
@@ -783,10 +766,12 @@ def cluster_usage():
|
||||
mapper.high = max(max(num_tasks), 1)
|
||||
|
||||
# Update plot with new data based on slider and text box values
|
||||
source.data = {"node_ip_address": nodes,
|
||||
"time": times,
|
||||
"num_tasks": num_tasks,
|
||||
"length": lengths}
|
||||
source.data = {
|
||||
"node_ip_address": nodes,
|
||||
"time": times,
|
||||
"num_tasks": num_tasks,
|
||||
"length": lengths
|
||||
}
|
||||
|
||||
push_notebook(handle=handle)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user