Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/gpu support extended #87

Open
wants to merge 76 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
5b9a16a
adding GPU support, adding test cases, adding NVIDIA runtime support
ksatzke Jul 10, 2020
5628d51
removing local configuration
ksatzke Jul 10, 2020
2d8a7ff
adding description on how to prepare and add a GPU node, and correspo…
ksatzke Jul 23, 2020
9fab0e3
fixing typos
ksatzke Jul 23, 2020
01c5c3d
corrections to description on adding GPU nodes
ksatzke Jul 29, 2020
977ee01
add GPU sandbox type to Makefiles and helm charts
ksatzke Aug 11, 2020
87fd792
add GPU sandbox type to Makefiles and helm charts
ksatzke Aug 11, 2020
32dd904
adding logig to spin up a GPU sandbox on demand
ksatzke Aug 12, 2020
cdd0faf
fixing typos in README
ksatzke Aug 20, 2020
9fba583
configure separate GPU support for management and common workflow kscv's
Aug 21, 2020
0124123
added configuration of sandox_gpu container image for wf pods to run …
Sep 29, 2020
cf047f0
improved configuration for workflows calling for GPUs
ksatzke Sep 29, 2020
89e8d24
first cut on extending Workflow class with GPU properties
ksatzke Oct 2, 2020
dfc7cd7
fixing bug on addWorkflow
ksatzke Oct 2, 2020
4508ea6
adding support for dynamic config of helm deployments on GPU to Manag…
ksatzke Oct 5, 2020
e251bf2
removing bug on java function executions
ksatzke Oct 6, 2020
5508abc
fixing a bug on asl_Map state tests with helm deployment
ksatzke Oct 6, 2020
a9ad920
adding first cut on gpu node selection logic for ansible multi-host d…
ksatzke Oct 7, 2020
ea3b5f6
merge develop branch
ksatzke Oct 8, 2020
ef7ed75
fixing bugs on SDK and GPU test configurations
ksatzke Oct 8, 2020
f7571f2
adding logic to configure gpu hosts, fixing bug on deployWorkflow on …
ksatzke Oct 9, 2020
a250fb3
cleanup tests and values.yaml
ksatzke Oct 12, 2020
f86c970
adjustments to available_hosts script and cleanup
ksatzke Oct 12, 2020
e334db1
final adjustments to values.yaml
ksatzke Oct 12, 2020
297a8e0
addressing comments from PR review, first part
ksatzke Oct 13, 2020
677cacd
adding ansible inventory group for GPU host configuration
ksatzke Oct 20, 2020
6941e7e
Merge branch 'feature/GPU_support_extended' of https://github.com/kni…
ksatzke Oct 20, 2020
6c3efd5
fixing errors in GPU deployment description
Nov 5, 2020
eaae6be
fixing errors in GPU deployment description
Nov 5, 2020
f707010
fixing errors in GPU deployment description
Nov 5, 2020
46577ad
1st cut on API modifications to allow configuration of mfn GPU requir…
Nov 11, 2020
dd3a1c3
adding GUI support for indicating assigned GPU cores in function table
abeckn Nov 11, 2020
4d734fa
adding GUI support for indicating assigned GPU cores in function tabl…
abeckn Nov 11, 2020
95d81ca
merging develop branch, first cut on integrating GUI support, partly …
Nov 16, 2020
232b3c0
fixing bug in deployWorkflow choosing the wrong sandbox image
Nov 16, 2020
d494c86
fixing bugs on GPU configuration in Management functions
Nov 16, 2020
a6f84a8
debug GPU parameter modifucation via GUI
Nov 17, 2020
9055a30
cleanup, tests are passing on gpu machine
ksatzke Nov 18, 2020
ecc1b8f
first cut on logic to deduce sandbox GPU requirements from function d…
ksatzke Nov 18, 2020
3fbcfb1
cleaning asl_Tensorflow_HelloWorld test
ksatzke Nov 18, 2020
99e04b0
adapted values.yaml to lab testbed vagrant conf
ksatzke Nov 30, 2020
1012b31
Merge branch 'develop' into feature/GPU_support_extended
ksatzke Nov 30, 2020
5db4cfb
updated values for kubespray setup
ksatzke Dec 1, 2020
50dc35f
remove hardcoding of imageRepo, adjusting values.yaml for GPU testbed
ksatzke Dec 1, 2020
ff25274
remove blocking of concurrent gpu pods in k8s deployment caused by 'l…
ksatzke Dec 10, 2020
d8c01e9
resolving conflicts with develop branch
ksatzke Dec 10, 2020
5163ede
adding support for configurable GPU core+memory sharing based on gpu-…
ksatzke Jan 12, 2021
47bd2cd
Merge branch 'develop' into feature/GPU_support_extended
ksatzke Jan 12, 2021
defacaf
fixing bug on GPU parameter calculations
ksatzke Jan 15, 2021
730e0f7
WIP: adding logic for node GPU capacity queries to ManagementService
ksatzke Jan 26, 2021
cd779af
use vgpu parameters in kservice setup
ksatzke Jan 27, 2021
09f58e8
adding capability to handle secret token for k8s core API
ksatzke Feb 2, 2021
7311aec
adding GUI and ManagementService changes for GPU parameters
ksatzke Feb 2, 2021
8520d5f
fixing bugs on GPU memory parameter calculations
ksatzke Feb 3, 2021
338fcd3
fixing more bugs on GPU memory parameter calculations
ksatzke Feb 8, 2021
5697446
fixing bugs in deployment script, adjusting values
ksatzke Feb 16, 2021
051b327
fixing bugs in available_hosts scripts
ksatzke Feb 26, 2021
70ce3ec
resolving bugs in host selection logic for deployment
ksatzke Mar 2, 2021
e0e4a86
fixing a bug in workflow GPU resource calculation
ksatzke Mar 25, 2021
d92a604
extending mfn SDK to handle GPU parameters
ksatzke Apr 1, 2021
1de8f8b
Merge branch 'feature/GPU_support_extended' of https://github.com/kni…
ksatzke Apr 1, 2021
48f7546
fixing bugs on ASL tests using GPUs
ksatzke Apr 13, 2021
463cbab
merge develop; update Dockerfile_gpu
iakkus Apr 19, 2021
7a1b157
fix to helm template management.yaml
iakkus Apr 26, 2021
191e0da
Revert "fix to helm template management.yaml"
iakkus Apr 26, 2021
4528bc6
fix to helm template management.yaml after merging with develop
iakkus Apr 26, 2021
ea5e1bd
Merge branch 'develop' into feature/GPU_support_extended
iakkus May 5, 2021
6913fbb
make Dockerfile installation instructions follow the same order
iakkus May 7, 2021
3647851
ansible: fix available hosts script
May 7, 2021
3187c49
management: fix deployWorkflow for bare metal with gpu hosts
iakkus May 7, 2021
700e298
update ansible readme; fixes #117
iakkus May 14, 2021
c46055b
Revert "update ansible readme; fixes #117"
iakkus May 14, 2021
f30f610
function worker: fix addressable function stopping when blocking for …
May 17, 2021
529be65
adding Dockerfile for opencv package
ksatzke Jun 9, 2021
05e6b25
fixing Map state, all tests are running
ksatzke Jun 11, 2021
a198f2b
merging recent develop into GPU feature branch
ksatzke Jan 10, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions FunctionWorker/python/SessionHelperThread.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ def _store_message(self, msg):
self._message_queue.put(msg)

def _handle_special_message(self, msg):
#self._logger.debug("[SessionHelperThread] Special message: " + str(msg))
action = msg["action"]

if action == "--stop":
Expand Down
80 changes: 69 additions & 11 deletions FunctionWorker/python/StateUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,15 +419,21 @@ def evaluateMapState(self, function_input, key, metadata, sapi):
self._logger.debug("[StateUtils] evaluateMapState, maxConcurrency: " + str(maxConcurrency))
self._logger.debug("[StateUtils] evaluateMapState metadata: " + str(metadata))

self._logger.info("[StateUtils] evaluateMapState, maxConcurrency: " + str(maxConcurrency))
self._logger.info("[StateUtils] evaluateMapState metadata: " + str(metadata))

counter_name_topic = self.functionstatename + "-" + self.sandboxid

total_branch_count = len(function_input) # all branches executed concurrently

#sapi.put(name_prefix + "_" + "mapInputCount", str(len(function_input)))

klist = [total_branch_count]

self.parsedfunctionstateinfo["BranchCount"] = int(total_branch_count) # overwrite parsed BranchCount with new value
self._logger.debug("[StateUtils] evaluateMapState, total_branch_count: " + str(total_branch_count))

self._logger.info("[StateUtils] evaluateMapState, total_branch_count: " + str(total_branch_count))

# prepare counter metadata
counter_metadata = {}
counter_metadata["__state_action"] = "post_map_processing"
Expand Down Expand Up @@ -459,6 +465,7 @@ def evaluateMapState(self, function_input, key, metadata, sapi):
counter_name_value_metadata["__state_action"] = "post_map_processing"
counter_name_value_metadata["state_counter"] = metadata["state_counter"]
self._logger.debug("[StateUtils] evaluateMapState, metadata[state_counter]: " + str(metadata["state_counter"]))
self._logger.info("[StateUtils] evaluateMapState, metadata[state_counter]: " + str(metadata["state_counter"]))
self.mapStateCounter = int(metadata["state_counter"])

counter_name_value = {"__mfnmetadata": counter_name_value_metadata, "__mfnuserdata": '{}'}
Expand Down Expand Up @@ -506,6 +513,8 @@ def evaluateMapState(self, function_input, key, metadata, sapi):
assert py3utils.is_string(workflow_instance_metadata_storage_key)
self._logger.debug("[StateUtils] full_metadata_encoded put key: " + str(workflow_instance_metadata_storage_key))

self._logger.info("[StateUtils] full_metadata_encoded put key: " + str(workflow_instance_metadata_storage_key))

sapi.put(workflow_instance_metadata_storage_key, json.dumps(metadata))

# Now provide each branch with its own input
Expand All @@ -523,9 +532,14 @@ def evaluateMapState(self, function_input, key, metadata, sapi):
self._logger.debug("\t Map State StartAt:" + startat)
self._logger.debug("\t Map State input:" + str(function_input[i]))

self._logger.info("\t Map State StartAt:" + startat)
self._logger.info("\t Map State input:" + str(function_input[i]))

return function_input, metadata

def evaluatePostMap(self, function_input, key, metadata, sapi):
self._logger.info("\t inside evaluatePostMap: " + str(function_input)+ " " + str(metadata) + " " + str(sapi))


name_prefix = self.functiontopic + "_" + key

Expand All @@ -542,11 +556,15 @@ def evaluatePostMap(self, function_input, key, metadata, sapi):

self._logger.debug("\t metadata:" + json.dumps(metadata))

self._logger.info("\t metadata:" + json.dumps(metadata))

workflow_instance_metadata_storage_key = str(function_input["WorkflowInstanceMetadataStorageKey"])
assert py3utils.is_string(workflow_instance_metadata_storage_key)
full_metadata_encoded = sapi.get(workflow_instance_metadata_storage_key)
self._logger.debug("[StateUtils] full_metadata_encoded get: " + str(full_metadata_encoded))

self._logger.info("[StateUtils] full_metadata_encoded get: " + str(full_metadata_encoded))

full_metadata = json.loads(full_metadata_encoded)
full_metadata["state_counter"] = state_counter

Expand All @@ -557,6 +575,8 @@ def evaluatePostMap(self, function_input, key, metadata, sapi):
branchOutputKeysSet = sapi.retrieveSet(branchOutputKeysSetKey)
self._logger.debug("\t branchOutputKeysSet: " + str(branchOutputKeysSet))

self._logger.info("\t branchOutputKeysSet: " + str(branchOutputKeysSet))

if not branchOutputKeysSet:
self._logger.error("[StateUtils] branchOutputKeysSet is empty")
raise Exception("[StateUtils] branchOutputKeysSet is empty")
Expand All @@ -576,13 +596,17 @@ def evaluatePostMap(self, function_input, key, metadata, sapi):
NumBranchesFinished = abs(counterValue)
self._logger.debug("\t NumBranchesFinished:" + str(NumBranchesFinished))

self._logger.info("\t NumBranchesFinished:" + str(NumBranchesFinished))

do_cleanup = False

if klist[-1] == NumBranchesFinished:
do_cleanup = True

self._logger.debug("\t do_cleanup:" + str(do_cleanup))

self._logger.info("\t do_cleanup:" + str(do_cleanup))

counterName = str(mapInfo["CounterName"])
counter_metadata_key_name = counterName + "_metadata"
assert py3utils.is_string(counterName)
Expand Down Expand Up @@ -610,6 +634,10 @@ def evaluatePostMap(self, function_input, key, metadata, sapi):

self._logger.debug("\t mapInfo_BranchOutputKeys length: " + str(len(mapInfo["BranchOutputKeys"])))

self._logger.info("\t mapInfo_BranchOutputKeys:" + str(mapInfo["BranchOutputKeys"]))

self._logger.info("\t mapInfo_BranchOutputKeys length: " + str(len(mapInfo["BranchOutputKeys"])))

for outputkey in mapInfo["BranchOutputKeys"]:
outputkey = str(outputkey)
if outputkey in branchOutputKeysSet: # mapInfo["BranchOutputKeys"]:
Expand All @@ -623,15 +651,23 @@ def evaluatePostMap(self, function_input, key, metadata, sapi):
self._logger.debug("\t branchOutput:" + branchOutput)
self._logger.debug("\t branchOutput_decoded(type):" + str(type(branchOutput_decoded)))
self._logger.debug("\t branchOutput_decoded:" + str(branchOutput_decoded))
self._logger.info("\t branchOutput(type):" + str(type(branchOutput)))
self._logger.info("\t branchOutput:" + branchOutput)
self._logger.info("\t branchOutput_decoded(type):" + str(type(branchOutput_decoded)))
self._logger.info("\t branchOutput_decoded:" + str(branchOutput_decoded))
post_map_output_values = post_map_output_values + [branchOutput_decoded]
if do_cleanup:
sapi.delete(outputkey) # cleanup the key from data layer
self._logger.debug("\t cleaned output key:" + outputkey)
self._logger.info("\t cleaned output key:" + outputkey)
else:
post_map_output_values = post_map_output_values + [None]
self._logger.debug("\t this_BranchOutputKeys is not contained: " + str(outputkey))

self._logger.info("\t this_BranchOutputKeys is not contained: " + str(outputkey))

self._logger.debug("\t post_map_output_values:" + str(post_map_output_values))
self._logger.info("\t post_map_output_values:" + str(post_map_output_values))
while (sapi.get(name_prefix + "_" + "mapStatePartialResult")) == "":
time.sleep(0.1) # wait until value is available

Expand All @@ -640,18 +676,25 @@ def evaluatePostMap(self, function_input, key, metadata, sapi):
mapStatePartialResult += post_map_output_values
sapi.put(name_prefix + "_" + "mapStatePartialResult", str(mapStatePartialResult))

time.sleep(5.0)

# now apply ResultPath and OutputPath
if do_cleanup:

sapi.deleteSet(branchOutputKeysSetKey)

while sapi.get(name_prefix + "_" + "mapStatePartialResult") != str(mapStatePartialResult):
time.sleep(0.1)
while (sapi.get(name_prefix + "_" + "mapInputCount") == ""):
time.sleep(0.1) # wait until value is available

if ast.literal_eval(sapi.get(name_prefix + "_" + "mapInputCount")) == len(mapStatePartialResult):
#time.sleep(0.5)

# we are ready to publish but need to honour ResultPath and OutputPath
while (sapi.get(name_prefix + "_" +"mapStatePartialResult") == ""):
time.sleep(0.1)
res_raw = ast.literal_eval(sapi.get(name_prefix + "_" +"mapStatePartialResult"))
self._logger.info("[StateUtils] evaluatePostMap: res_raw" + str(res_raw) + " vs. " + sapi.get(name_prefix + "_" + "mapInputCount"))


# remove unwanted keys from input before publishing
function_input = {}
Expand All @@ -671,6 +714,9 @@ def evaluatePostMap(self, function_input, key, metadata, sapi):
sapi.delete(name_prefix + "_" + "mapStatePartialResult")
sapi.delete(name_prefix + "_" + "tobeProcessedlater")
post_map_output_values = function_input_post_output
else:
#raise Exception("mapInputCount" + str(sapi.get(name_prefix + "_" + "mapInputCount")) + " does not match mapStatePartialResult: " + str(mapStatePartialResult))
print("mapInputCount" + str(sapi.get(name_prefix + "_" + "mapInputCount")) + " does not match mapStatePartialResult: " + str(mapStatePartialResult))
return post_map_output_values, full_metadata

def evaluateParallelState(self, function_input, key, metadata, sapi):
Expand Down Expand Up @@ -967,7 +1013,7 @@ def evaluatePostParallel(self, function_input, key, metadata, sapi):

def evaluateNonTaskState(self, function_input, key, metadata, sapi):
# 3. Evaluate Non Task states
#self._logger.debug("[StateUtils] NonTask state type: " + str(self.functionstatetype))
self._logger.info("[StateUtils] NonTask state type: " + str(self.functionstatetype))
#self._logger.debug("[StateUtils] Welcome to evaluateNonTaskState! Current key:" + str(key))
function_output = None
if self.functionstatetype == StateUtils.choiceStateType:
Expand Down Expand Up @@ -1094,6 +1140,9 @@ def evaluateNonTaskState(self, function_input, key, metadata, sapi):
self._logger.debug("[StateUtils] Map state maxConcurrency: " + str(maxConcurrency))
self._logger.debug("[StateUtils] Map state handling")

self._logger.info("[StateUtils] Map state maxConcurrency: " + str(maxConcurrency))
self._logger.info("[StateUtils] Map state handling metadata: " + str(metadata) )

if "__state_action" not in metadata or metadata["__state_action"] != "post_map_processing":
# here we start the iteration process on a first batch
if maxConcurrency != 0:
Expand All @@ -1103,32 +1152,41 @@ def evaluateNonTaskState(self, function_input, key, metadata, sapi):
tobeProcessednow = function_input
tobeProcessedlater = []
self._logger.debug("[StateUtils] Map state function_input split:" + str(tobeProcessednow) + " " + str(tobeProcessedlater))
self._logger.info("[StateUtils] Map state function_input split:" + str(tobeProcessednow) + " " + str(tobeProcessedlater))
sapi.put(name_prefix + "_" + "tobeProcessedlater", str(tobeProcessedlater)) # store elements to be processed on DL
sapi.put(name_prefix + "_" + "mapStatePartialResult", "[]") # initialise the collector variable
sapi.put(name_prefix + "_" + "mapInputCount", str(len(function_input)))
#if "__client_origin_frontend" in metadata and metadata["__client_origin_frontend"] != "":
# sapi.put(name_prefix + "_" + "mapInputOriginFE", str(metadata["__client_origin_frontend"]))
#metadata["__state_action"] = ""

function_output, metadata = self.evaluateMapState(tobeProcessednow, key, metadata, sapi)
#metadata["__state_action"] = ""


elif metadata["__state_action"] == "post_map_processing":
tobeProcessedlater = ast.literal_eval(sapi.get(name_prefix + "_" + "tobeProcessedlater")) # get all elements that have not yet been processed
self._logger.debug("[StateUtils] Map state post_map processing input:" + str(tobeProcessedlater))
self._logger.info("[StateUtils] Map state post_map processing input:" + str(tobeProcessedlater))
# we need to decide at this point if there is a need for more batches. if so:

if len(tobeProcessedlater) > 0: # we need to start another batch
function_output, metadata = self.evaluatePostMap(function_input, key, metadata, sapi) # take care not to overwrite metadata
metadata["__client_origin_frontend"] = self._internal_endpoint
time.sleep(5.0) # allow cleanup of previous execution before launching new
#metadata["__client_origin_frontend"] = sapi.get(name_prefix + "_" + "mapInputOriginFE")
self._logger.debug("[StateUtils] Map state metadata between calls: " + str(metadata))
self._logger.info("[StateUtils] tobeProcessedlater: " + str(tobeProcessedlater)+ ", function_input: " +str(function_input))
function_output, metadata2 = self.evaluatePostMap(function_input, key, metadata, sapi) # take care not to overwrite metadata
self._logger.info("[StateUtils] after evaluatPostMap: " + str(function_output))
function_output, metadata = self.evaluateMapState(tobeProcessedlater[:maxConcurrency], key, metadata, sapi) # start a new batch
self._logger.info("[StateUtils] after evaluateMapState:" + str(function_output))
self._logger.info("[StateUtils] after evaluateMapState, metadata: " + str(metadata))
sapi.put(name_prefix + "_" + "tobeProcessedlater", str(tobeProcessedlater[maxConcurrency:])) # store remaining elements to be processed on DL
self._logger.info("[StateUtils] after sapi.put: " + str(tobeProcessedlater[maxConcurrency:]))


else:# no more batches required. we are at the iteration end, publish the final result
self._logger.debug("[StateUtils] Map state input final stage: " + str(function_input))
self._logger.info("[StateUtils] Map state input final stage: " + str(function_input))
function_output, metadata = self.evaluatePostMap(function_input, key, metadata, sapi)

elif metadata["__state_action"] == '':
raise Exception("Unkown state action in map state")

else:
raise Exception("Unknow action type in map state")

Expand Down
9 changes: 5 additions & 4 deletions GUI/app/pages/functions/FunctionTableCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@
return selected.length ? mFunction.runtime : 'Not set';
};


function createTemporaryWorkflow(functionIndex) {
var req = {
method: 'POST',
Expand Down Expand Up @@ -636,7 +635,7 @@

},

data: JSON.stringify({ "action" : "addFunction", "data" : { "user" : { "token" : token } , "function" : { "name" : mFunction.name, "runtime" : mFunction.runtime } } })
data: JSON.stringify({ "action" : "addFunction", "data" : { "user" : { "token" : token } , "function" : { "name" : mFunction.name, "runtime" : mFunction.runtime, "gpu_usage": mFunction.gpu_usage, "gpu_mem_usage": mFunction.gpu_mem_usage } } })

}
$http(req).then(function successCallback(response) {
Expand All @@ -646,7 +645,7 @@
console.log('new function id:' + response.data.data.function.id);
toastr.success('Your function has been created successfully!');
$scope.reloadFunctions();
$scope.open('app/pages/functions/modals/codeEditorModal.html', 'lg', mFunction.id, mFunction.name, mFunction.status, mFunction.runtime);
$scope.open('app/pages/functions/modals/codeEditorModal.html', 'lg', mFunction.id, mFunction.name, mFunction.status, mFunction.runtime, mFunction.gpu_usage, mFunction.gpu_mem_usage);

} else {
console.log("Failure status returned by addFunction");
Expand Down Expand Up @@ -692,7 +691,7 @@

},

data: JSON.stringify({ "action" : "modifyFunction", "data" : { "user" : { "token" : token } , "function" : { "id": mFunction.id, "name" : mFunction.name, "runtime" : mFunction.runtime } } })
data: JSON.stringify({ "action" : "modifyFunction", "data" : { "user" : { "token" : token } , "function" : { "id": mFunction.id, "name" : mFunction.name, "runtime" : mFunction.runtime, "gpu_usage" : mFunction.gpu_usage, "gpu_mem_usage": mFunction.gpu_mem_usage } } })

}
$http(req).then(function successCallback(response) {
Expand Down Expand Up @@ -738,6 +737,8 @@
name: '',
status: 'undeployed',
runtime: 'Python 3.6',
gpu_usage: '0',
gpu_mem_usage: '0',
modified: '0'
};
$scope.functions.push($scope.inserted);
Expand Down
14 changes: 13 additions & 1 deletion GUI/app/pages/functions/widgets/editableRowTable.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

<th st-sort="name" style="text-align:left;border:0;"><b>Name</b></th>
<th st-sort="runtime" style="border:0;"><b>Runtime</b></th>
<th st-sort="gpu_cores" style="border:0;"><b>GPU Cores (%)</b></th>
<th st-sort="gpu_memory" style="border:0;"><b>GPU Memory (GB)</b></th>
<th id="sortHeader" style="border:0;" st-sort="modified" st-sort-default="reverse"><b>Last Modified</b></th>
<th style="border:0;"><b>Actions</b></th>
</tr>
Expand All @@ -45,6 +47,16 @@
{{ showRuntime(mFunction) }}
</span>
</td>
<td style="text-align:left;">
<span editable-text="mFunction.gpu_usage" e-name="gpu_usage" e-form="rowform">
{{ mFunction.gpu_usage || 'Not set' }}
</span>
</td>
<td style="text-align:left;">
<span editable-text="mFunction.gpu_mem_usage" e-name="gpu_mem_usage" e-form="rowform">
{{ mFunction.gpu_mem_usage || 'Not set' }}
</span>
</td>
<td>
<span e-name="modified" e-form="rowform">
{{ showLastModified(mFunction) }}
Expand All @@ -66,7 +78,7 @@
</button>
</form>
<div class="buttons" ng-show="!rowform.$visible">
<button class="btn btn-primary editable-table-button btn-xs" ng-click="rowform.$show()">Rename</button>
<button class="btn btn-primary editable-table-button btn-xs" ng-click="rowform.$show()">Edit</button>


<button type="button" ng-disabled="rowform.$waiting" class="btn btn-primary editable-table-button btn-xs" style="width:85px; background-color: #757a74; border-color: #757a74;" data-toggle="modal" ng-click="open('app/pages/functions/modals/codeEditorModal.html', 'lg', functions[getIndex(mFunction)].id, functions[getIndex(mFunction)].name, functions[getIndex(mFunction)].status, functions[getIndex(mFunction)].runtime)">Code Editor</button>
Expand Down
2 changes: 1 addition & 1 deletion GUI/app/pages/workflows/WorkflowImportCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@

},

data: JSON.stringify({ "action" : "addFunction", "data" : { "user" : { "token" : token } , "function" : { "name" : functionName, "runtime" : functionRuntime } } })
data: JSON.stringify({ "action" : "addFunction", "data" : { "user" : { "token" : token } , "function" : { "name" : functionName, "runtime" : functionRuntime, "gpu_usage": functionGpuusage, "gpu_mem_usage": functionGpuMemusage } } })

}
$http(req).then(function successCallback(response) {
Expand Down
2 changes: 1 addition & 1 deletion ManagementService/management_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ def printUsage():
sys.path.append(workflowdir)
if os.getenv("KUBERNETES_PORT", None) != None:
import deployWorkflow
url, endpoint_key = deployWorkflow.create_k8s_deployment(email, workflow_info, "Python", management=True)
url, endpoint_key = deployWorkflow.create_k8s_deployment(email, workflow_info, "Python", 0, 0, management=True)
DLCLIENT_MANAGEMENT.putMapEntry("Management_workflow_endpoint_map", endpoint_key, url)
# Kubernetes mode only has one url
endpoint_list = [url]
Expand Down
Loading