diff --git a/.circleci/config.yml b/.circleci/config.yml index 659de54ea..bada64872 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,7 +30,7 @@ commands: command: | ./opt/readies/bin/getpy3 BREW_NO_UPDATE=1 ./opt/system-setup.py - # ./opt/readies/bin/getredis -v 6 --force + ./opt/readies/bin/getredis -v 6 --force ./get_deps.sh cpu - save_cache: paths: @@ -95,7 +95,7 @@ commands: jobs: build-debian: docker: - - image: redisfab/rmbuilder:6.0.1-x64-buster + - image: redisfab/rmbuilder:6.0.5-x64-buster steps: - build-steps: platform: debian @@ -112,7 +112,7 @@ jobs: coverage: docker: - - image: redisfab/rmbuilder:6.0.1-x64-buster + - image: redisfab/rmbuilder:6.0.5-x64-buster steps: - checkout - run: @@ -136,7 +136,7 @@ jobs: - run: name: Test with coverage command: | - make -C opt test SHOW=1 COV=1 + make -C opt test SHOW=1 COV=1 CLUSTER=1 make -C opt cov-upload no_output_timeout: 20m @@ -209,7 +209,7 @@ jobs: package: type: string docker: - - image: redisfab/rmbuilder:6.0.1-x64-buster + - image: redisfab/rmbuilder:6.0.5-x64-buster steps: - attach_workspace: at: workspace diff --git a/Dockerfile.gpu-test b/Dockerfile.gpu-test index 943a03bd0..d4accce22 100644 --- a/Dockerfile.gpu-test +++ b/Dockerfile.gpu-test @@ -1,6 +1,6 @@ # BUILD redisfab/redisai:${VERSION}-gpu-${ARCH}-${OSNICK}-test -ARG REDIS_VER=6.0.1 +ARG REDIS_VER=6.0.5 # OSNICK=bionic|centos7|centos6 ARG OSNICK=bionic @@ -29,11 +29,13 @@ COPY --from=redis /usr/local/ /usr/local/ COPY ./opt/ opt/ COPY ./test/test_requirements.txt test/ -RUN ./opt/readies/bin/getpy3 -RUN ./opt/system-setup.py +RUN PIP=19.3.1 ./opt/readies/bin/getpy3 +RUN python3 -m pip install virtualenv + RUN set -e ;\ - python3 -m virtualenv venv --system-site-packages;\ + python3 -m virtualenv venv --system-site-packages ;\ . venv/bin/activate ;\ + python -m pip install pip==19.3.1 ;\ ./opt/system-setup.py ARG DEPS_ARGS="" diff --git a/opt/Makefile b/opt/Makefile index ae638ab3f..a8193f250 100755 --- a/opt/Makefile +++ b/opt/Makefile @@ -189,12 +189,14 @@ endif export GEN ?= 1 export SLAVES ?= 1 export AOF ?= 1 +export CLUSTER ?= 1 test: $(COVERAGE_RESET) $(SHOW)\ DEVICE=$(DEVICE) \ MODULE=$(INSTALLED_TARGET) \ + CLUSTER=$(CLUSTER) \ GEN=$(GEN) AOF=$(AOF) SLAVES=$(SLAVES) \ VALGRIND=$(VALGRIND) \ $(ROOT)/test/tests.sh diff --git a/opt/build/docker/Makefile b/opt/build/docker/Makefile index afff92f26..8c5f8967d 100755 --- a/opt/build/docker/Makefile +++ b/opt/build/docker/Makefile @@ -1,5 +1,6 @@ ROOT=../../.. +MK.pyver:=3 include $(ROOT)/opt/readies/mk/main # OSNICK=buster|stretch|bionic|xenial|centos7 @@ -8,6 +9,8 @@ OSNICK ?= buster REPO=redisfab STEM=$(REPO)/redisai +REDIS_VER:=6.0.5 + ART_DIR=$(ROOT)/bin/artifacts ART_INT_DIR=/var/opt/redislabs/artifacts diff --git a/opt/readies b/opt/readies index 14abdad48..e3b1c5910 160000 --- a/opt/readies +++ b/opt/readies @@ -1 +1 @@ -Subproject commit 14abdad4868c9adb011942830ffe748d1c05f073 +Subproject commit e3b1c5910f8440ac2a5fdfd3d252fd32c8fc1915 diff --git a/opt/system-setup.py b/opt/system-setup.py index c84aacaaf..ae2d498ea 100755 --- a/opt/system-setup.py +++ b/opt/system-setup.py @@ -18,15 +18,16 @@ def __init__(self, nop=False): def common_first(self): self.install_downloaders() self.setup_pip() - self.pip3_install("wheel virtualenv") - self.pip3_install("setuptools --upgrade") + self.pip_install("wheel virtualenv") + self.pip_install("setuptools --upgrade") if self.os == 'linux': self.install("ca-certificates") - self.install("git unzip wget patchelf awscli") + self.install("git unzip wget patchelf") self.install("coreutils") # for realpath def debian_compat(self): + self.pip_install("-IU --force-reinstall setuptools") self.install("build-essential cmake") self.install("python3-regex") self.install("python3-venv python3-psutil python3-networkx python3-numpy") # python3-skimage @@ -53,7 +54,7 @@ def redhat_compat(self): else: self.run("amazon-linux-extras install epel", output_on_error=True) self.install("python3-devel") - self.pip3_install("psutil") + self.pip_install("psutil") self.install_git_lfs_on_linux() @@ -76,14 +77,15 @@ def macosx(self): def common_last(self): self.run("python3 -m pip uninstall -y ramp-packer RLTest || true") # redis-py-cluster should be installed from git due to redis-py dependency - self.pip3_install("--no-cache-dir git+https://github.com/Grokzen/redis-py-cluster.git@master") - self.pip3_install("--no-cache-dir git+https://github.com/RedisLabsModules/RLTest.git@master") - self.pip3_install("--no-cache-dir git+https://github.com/RedisLabs/RAMP@master") + self.pip_install("--no-cache-dir git+https://github.com/Grokzen/redis-py-cluster.git@master") + self.pip_install("--no-cache-dir git+https://github.com/RedisLabsModules/RLTest.git@master") + self.pip_install("--no-cache-dir git+https://github.com/RedisLabs/RAMP@master") - self.pip3_install("-r %s/readies/paella/requirements.txt" % HERE) - self.pip3_install("-r %s/test/test_requirements.txt" % ROOT) + self.pip_install("-r %s/readies/paella/requirements.txt" % HERE) + self.pip_install("-r %s/test/test_requirements.txt" % ROOT) - self.pip3_install("mkdocs mkdocs-material mkdocs-extensions") + self.pip_install("awscli") + self.pip_install("mkdocs mkdocs-material mkdocs-extensions") #---------------------------------------------------------------------------------------------- diff --git a/ramp.yml b/ramp.yml index 0f83c228e..bfe8bfbdd 100644 --- a/ramp.yml +++ b/ramp.yml @@ -1,6 +1,6 @@ display_name: RedisAI -author: Orobix and RedisLabs -email: luca.antiga@orobix.com +author: Tensorwerk and RedisLabs +email: support@redislabs.com description: Serving tensors and executing deep learning graphs homepage: https://oss.redislabs.com/redisai/ license: Redis Source Available License v1.0 diff --git a/src/dag.c b/src/dag.c index 53c76e259..33f74f634 100644 --- a/src/dag.c +++ b/src/dag.c @@ -258,7 +258,6 @@ int RAI_parseDAGLoadArgs(RedisModuleCtx *ctx, RedisModuleString **argv, ctx, "ERR invalid or negative value found in number of keys to LOAD"); return -1; } - int number_loaded_keys = 0; int separator_flag = 0; size_t argpos = 2; @@ -270,8 +269,7 @@ int RAI_parseDAGLoadArgs(RedisModuleCtx *ctx, RedisModuleString **argv, } else { RAI_Tensor *t; RedisModuleKey *key; - const int status = RAI_GetTensorFromKeyspace(ctx, argv[argpos], &key, &t, - REDISMODULE_READ); + const int status = RAI_GetTensorFromKeyspace(ctx, argv[argpos], &key, &t, REDISMODULE_READ); if (status == REDISMODULE_ERR) { RedisModule_Log( ctx, "warning", @@ -334,3 +332,26 @@ int RAI_parseDAGPersistArgs(RedisModuleCtx *ctx, RedisModuleString **argv, } return argpos; } + +int RedisAI_DagRun_IsKeysPositionRequest_ReportKeys(RedisModuleCtx *ctx, + RedisModuleString **argv, int argc){ + for (size_t argpos = 1; argpos < argc; argpos++){ + const char *arg_string = RedisModule_StringPtrLen(argv[argpos], NULL); + if ( (!strcasecmp(arg_string, "LOAD") || !strcasecmp(arg_string, "PERSIST") ) && (argpos+1 < argc) ) { + long long n_keys; + argpos++; + const int retval = RedisModule_StringToLongLong(argv[argpos], &n_keys); + if(retval != REDISMODULE_OK){ + return REDISMODULE_ERR; + } + argpos++; + if (n_keys > 0){ + size_t last_persist_argpos = n_keys+argpos; + for (; argpos < last_persist_argpos && argpos < argc; argpos++){ + RedisModule_KeyAtPos(ctx, argpos); + } + } + } + } + return REDISMODULE_OK; +} diff --git a/src/dag.h b/src/dag.h index 9c9787a15..38cf29057 100644 --- a/src/dag.h +++ b/src/dag.h @@ -73,4 +73,19 @@ int RAI_parseDAGPersistArgs(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, AI_dict **localContextDict, const char *chaining_operator); +/** + * When a module command is called in order to obtain the position of + * keys, since it was flagged as "getkeys-api" during the registration, + * the command implementation checks for this special call using the + * RedisModule_IsKeysPositionRequest() API and uses this function in + * order to report keys. + * No real execution is done on this special call. + * @param ctx Context in which Redis modules operate + * @param argv Redis command arguments, as an array of strings + * @param argc Redis command number of arguments + * @return + */ +int RedisAI_DagRun_IsKeysPositionRequest_ReportKeys(RedisModuleCtx *ctx, + RedisModuleString **argv, int argc); + #endif /* SRC_DAG_H_ */ diff --git a/src/model.c b/src/model.c index e8e1079cb..599429e17 100644 --- a/src/model.c +++ b/src/model.c @@ -513,6 +513,18 @@ int RAI_ModelSerialize(RAI_Model *model, char **buffer, size_t *len, RAI_Error * return ret; } +int RedisAI_ModelRun_IsKeysPositionRequest_ReportKeys(RedisModuleCtx *ctx, + RedisModuleString **argv, int argc){ + RedisModule_KeyAtPos(ctx, 1); + for (size_t argpos = 3; argpos < argc; argpos++){ + const char *str = RedisModule_StringPtrLen(argv[argpos], NULL); + if (!strcasecmp(str, "OUTPUTS")) { + continue; + } + RedisModule_KeyAtPos(ctx,argpos); + } + return REDISMODULE_OK; +} int RedisAI_Parse_ModelRun_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, @@ -620,7 +632,6 @@ int RedisAI_Parse_ModelRun_RedisCommand(RedisModuleCtx *ctx, } } } - if ((*mto)->inputs && array_len((*mto)->inputs) != ninputs) { if (ctx == NULL) { RAI_SetError( diff --git a/src/model.h b/src/model.h index 6df0a62aa..ef9373236 100644 --- a/src/model.h +++ b/src/model.h @@ -201,6 +201,21 @@ int RAI_ModelSerialize(RAI_Model* model, char** buffer, size_t* len, int RAI_GetModelFromKeyspace(RedisModuleCtx* ctx, RedisModuleString* keyName, RedisModuleKey** key, RAI_Model** model, int mode); +/** + * When a module command is called in order to obtain the position of + * keys, since it was flagged as "getkeys-api" during the registration, + * the command implementation checks for this special call using the + * RedisModule_IsKeysPositionRequest() API and uses this function in + * order to report keys. + * No real execution is done on this special call. + * @param ctx Context in which Redis modules operate + * @param argv Redis command arguments, as an array of strings + * @param argc Redis command number of arguments + * @return + */ +int RedisAI_ModelRun_IsKeysPositionRequest_ReportKeys(RedisModuleCtx *ctx, + RedisModuleString **argv, int argc); + /** * Helper method to parse AI.MODELRUN arguments * diff --git a/src/redisai.c b/src/redisai.c index b7d40d9e9..e5b534de8 100644 --- a/src/redisai.c +++ b/src/redisai.c @@ -520,20 +520,20 @@ int RedisAI_ModelScan_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv */ int RedisAI_ModelRun_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + if (RedisModule_IsKeysPositionRequest(ctx)) { + return RedisAI_ModelRun_IsKeysPositionRequest_ReportKeys(ctx, argv, argc); + } if (argc < 3) return RedisModule_WrongArity(ctx); - RedisAI_RunInfo *rinfo = NULL; if (RAI_InitRunInfo(&rinfo) == REDISMODULE_ERR) { return RedisModule_ReplyWithError(ctx, "ERR Unable to allocate the memory and initialise the RedisAI_RunInfo structure"); } - RAI_Model *mto; RedisModuleKey *modelKey; const int status = RAI_GetModelFromKeyspace(ctx, argv[1], &modelKey, &mto, REDISMODULE_READ); if(status==REDISMODULE_ERR){ return REDISMODULE_ERR; } - RedisModule_RetainString(NULL, argv[1]); rinfo->runkey = argv[1]; rinfo->mctx = RAI_ModelRunCtxCreate(mto); @@ -567,110 +567,77 @@ int RedisAI_ModelRun_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, * AI.SCRIPTRUN script_key fn_name INPUTS input_key1 ... OUTPUTS output_key1 ... */ int RedisAI_ScriptRun_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { - if (argc < 4) return RedisModule_WrongArity(ctx); - + if (RedisModule_IsKeysPositionRequest(ctx)) { + return RedisAI_ScriptRun_IsKeysPositionRequest_ReportKeys(ctx, argv, argc); + } + if (argc < 6) return RedisModule_WrongArity(ctx); RedisAI_RunInfo *rinfo = NULL; if (RAI_InitRunInfo(&rinfo) == REDISMODULE_ERR) { - return RedisModule_ReplyWithError(ctx, "ERR Unable to allocate the memory and initialise the RedisAI_RunInfo structure"); - } - - if (RedisModule_IsKeysPositionRequest(ctx)) { - RedisModule_KeyAtPos(ctx, 1); - for (int i=3; irunkey = argv[1]; RAI_Script *sto; RedisModuleKey *key; - const int status = RAI_GetScriptFromKeyspace(ctx, argv[1], &key, &sto, REDISMODULE_READ); - if(status==REDISMODULE_ERR){ - return REDISMODULE_ERR; - } - - const char* fnname; - AC_GetString(&ac, &fnname, NULL, 0); - - ArgsCursor inac = {0}; - ArgsCursor outac = {0}; - - if (!AC_AdvanceIfMatch(&ac, "INPUTS")) { - return RedisModule_ReplyWithError(ctx, "ERR Insufficient arguments, INPUTS not specified"); - } - - const char* matches[] = {"OUTPUTS"}; - AC_GetSliceUntilMatches(&ac, &inac, 1, matches); - - if (!AC_AdvanceIfMatch(&ac, "OUTPUTS")) { - return RedisModule_ReplyWithError(ctx, "ERR Insufficient arguments, OUTPUTS not specified"); + const int status = + RAI_GetScriptFromKeyspace(ctx, argv[1], &key, &sto, REDISMODULE_READ); + if (status == REDISMODULE_ERR) { + return REDISMODULE_ERR; } + const char *functionName = RedisModule_StringPtrLen(argv[2], NULL); + rinfo->sctx = RAI_ScriptRunCtxCreate(sto, functionName); - AC_GetSliceToEnd(&ac, &outac); + RedisModuleString** inkeys = (RedisModuleString **)array_new(RedisModuleString *, 1); - size_t ninputs = inac.argc; - RedisModuleString *inputs[ninputs]; - for (size_t i=0; ioutkeys), &variadic, &err); + RedisModule_CloseKey(key); - size_t noutputs = outac.argc; - RedisModuleString *outputs[noutputs]; - for (size_t i=0; isctx = RAI_ScriptRunCtxCreate(sto, fnname); + for (int i=0; isctx, t)) { - RAI_FreeRunInfo(ctx,rinfo); - RedisModule_CloseKey(key); - return RedisModule_ReplyWithError(ctx, "ERR Input key not found"); + RedisModule_CloseKey(tensorKey); + + if (!RAI_ScriptRunCtxAddInput(rinfo->sctx, inputTensor)) { + // todo free rinfo + return RedisModule_ReplyWithError(ctx, err.detail_oneline); } } - for (size_t i=0; ioutkeys); i++) { if (!RAI_ScriptRunCtxAddOutput(rinfo->sctx)) { - RAI_FreeRunInfo(ctx,rinfo); - RedisModule_CloseKey(key); - return RedisModule_ReplyWithError(ctx, "ERR Output key not found"); + // todo free rinfo + return RedisModule_ReplyWithError(ctx, err.detail_oneline); } - RedisModule_RetainString(ctx, outputs[i]); - array_append(rinfo->outkeys,outputs[i]); } - - RedisModule_RetainString(ctx, keystr); - rinfo->runkey = keystr; + RunQueueInfo *run_queue_info = NULL; - // If the queue does not exist, initialize it - if (ensureRunQueue(sto->devicestr,&run_queue_info) == REDISMODULE_ERR) { - RAI_FreeRunInfo(ctx,rinfo); - return RedisModule_ReplyWithError(ctx, "ERR Queue not initialized for device"); + // If the queue does not exist, initialize it + if (ensureRunQueue(sto->devicestr, &run_queue_info) == REDISMODULE_ERR) { + return RedisModule_ReplyWithError(ctx, + "ERR Queue not initialized for device"); } - rinfo->client = RedisModule_BlockClient(ctx, RAI_ModelRunScriptRunReply, NULL, RedisAI_FreeData, 0); + rinfo->client = RedisModule_BlockClient(ctx, RAI_ModelRunScriptRunReply, NULL, + RedisAI_FreeData, 0); // RedisModule_SetDisconnectCallback(rinfo->client, RedisAI_Disconnected); pthread_mutex_lock(&run_queue_info->run_queue_mutex); @@ -678,8 +645,6 @@ int RedisAI_ScriptRun_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv pthread_cond_signal(&run_queue_info->queue_condition_var); pthread_mutex_unlock(&run_queue_info->run_queue_mutex); - RedisModule_CloseKey(key); - return REDISMODULE_OK; } @@ -971,6 +936,9 @@ int RedisAI_Config_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, i */ int RedisAI_DagRun_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + if (RedisModule_IsKeysPositionRequest(ctx)) { + return RedisAI_DagRun_IsKeysPositionRequest_ReportKeys(ctx, argv, argc); + } if (argc < 4) return RedisModule_WrongArity(ctx); RedisAI_RunInfo *rinfo = NULL; @@ -1091,6 +1059,9 @@ int RedisAI_DagRun_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, */ int RedisAI_DagRunRO_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + if (RedisModule_IsKeysPositionRequest(ctx)) { + return RedisAI_DagRun_IsKeysPositionRequest_ReportKeys(ctx, argv, argc); + } if (argc < 4) return RedisModule_WrongArity(ctx); RedisAI_RunInfo *rinfo = NULL; @@ -1364,11 +1335,11 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) == REDISMODULE_ERR) return REDISMODULE_ERR; - if (RedisModule_CreateCommand(ctx, "ai.dagrun", RedisAI_DagRun_RedisCommand, "write deny-oom", 3, 3, 1) + if (RedisModule_CreateCommand(ctx, "ai.dagrun", RedisAI_DagRun_RedisCommand, "write deny-oom getkeys-api", 3, 3, 1) == REDISMODULE_ERR) return REDISMODULE_ERR; - if (RedisModule_CreateCommand(ctx, "ai.dagrun_ro", RedisAI_DagRunRO_RedisCommand, "readonly", 3, 3, 1) + if (RedisModule_CreateCommand(ctx, "ai.dagrun_ro", RedisAI_DagRunRO_RedisCommand, "readonly getkeys-api", 3, 3, 1) == REDISMODULE_ERR) return REDISMODULE_ERR; diff --git a/src/run_info.c b/src/run_info.c index af4f5bdc6..9a195ee6d 100644 --- a/src/run_info.c +++ b/src/run_info.c @@ -136,6 +136,9 @@ int RAI_InitRunInfo(RedisAI_RunInfo **result) { void RAI_FreeDagOp(RedisModuleCtx *ctx, RAI_DagOp *dagOp) { if (dagOp) { RAI_FreeError(dagOp->err); + if(dagOp->runkey){ + RedisModule_FreeString(ctx,dagOp->runkey); + } if (dagOp->argv) { for (size_t i = 0; i < array_len(dagOp->argv); i++) { RedisModule_FreeString(ctx, dagOp->argv[i]); @@ -157,6 +160,13 @@ void RAI_FreeDagOp(RedisModuleCtx *ctx, RAI_DagOp *dagOp) { RAI_ScriptRunCtxFree(dagOp->sctx, false); } + if (dagOp->outkeys) { + for (size_t i=0; ioutkeys); i++) { + RedisModule_FreeString(ctx,dagOp->outkeys[i]); + } + array_free(dagOp->outkeys); + } + RedisModule_Free(dagOp); } } @@ -204,10 +214,6 @@ void RAI_FreeRunInfo(RedisModuleCtx *ctx, struct RedisAI_RunInfo *rinfo) { entry = AI_dictNext(iter); } AI_dictReleaseIterator(iter); - - RedisModule_Free(rinfo->dagTensorsContext); - RedisModule_Free(rinfo->dagTensorsLoadedContext); - RedisModule_Free(rinfo->dagTensorsPersistentContext); } if (rinfo->dagOps) { diff --git a/src/script.c b/src/script.c index eada1922e..4dd8b676d 100644 --- a/src/script.c +++ b/src/script.c @@ -246,3 +246,67 @@ int RAI_GetScriptFromKeyspace(RedisModuleCtx* ctx, RedisModuleString* keyName, *script = RedisModule_ModuleTypeGetValue(*key); return REDISMODULE_OK; } + +int RedisAI_ScriptRun_IsKeysPositionRequest_ReportKeys(RedisModuleCtx *ctx, + RedisModuleString **argv, int argc){ + RedisModule_KeyAtPos(ctx, 1); + for (size_t argpos = 4; argpos < argc; argpos++){ + const char *str = RedisModule_StringPtrLen(argv[argpos], NULL); + if (!strcasecmp(str, "OUTPUTS")) { + continue; + } + RedisModule_KeyAtPos(ctx,argpos); + } + return REDISMODULE_OK; +} + +/** + * AI.SCRIPTRUN INPUTS [input ...] OUTPUTS [output ...] + */ +int RedisAI_Parse_ScriptRun_RedisCommand(RedisModuleCtx *ctx, + RedisModuleString **argv, int argc, + RedisModuleString ***inkeys, + RedisModuleString ***outkeys, + int *variadic, + RAI_Error *error) { + if (argc < 6) { + RAI_SetError(error, RAI_ESCRIPTRUN, "ERR wrong number of arguments for 'AI.SCRIPTRUN' command"); + return -1; + } + + const char *inputstr = RedisModule_StringPtrLen(argv[2], NULL); + if (strcasecmp(inputstr, "INPUTS") == 0) { + RAI_SetError(error, RAI_ESCRIPTRUN, "ERR function name not specified"); + return -1; + } + + inputstr = RedisModule_StringPtrLen(argv[3], NULL); + if (strcasecmp(inputstr, "INPUTS")) { + RAI_SetError(error, RAI_ESCRIPTRUN, "ERR INPUTS not specified"); + return -1; + } + + // parsing aux vars + int is_output = 0; + int outputs_flag_count = 0; + size_t argpos = 4; + for (; argpos <= argc - 1; argpos++) { + const char *arg_string = RedisModule_StringPtrLen(argv[argpos], NULL); + if (!arg_string) { + RAI_SetError(error, RAI_ESCRIPTRUN, "ERR NULL argument on SCRIPTRUN"); + return -1; + } + if (!strcasecmp(arg_string, "OUTPUTS") && outputs_flag_count == 0) { + is_output = 1; + outputs_flag_count = 1; + } else { + RedisModule_RetainString(ctx, argv[argpos]); + if (is_output == 0) { + *inkeys = array_append(*inkeys, argv[argpos]); + } else { + *outkeys = array_append(*outkeys, argv[argpos]); + } + } + } + return argpos; +} \ No newline at end of file diff --git a/src/script.h b/src/script.h index 7936f8537..b3bc50c2e 100644 --- a/src/script.h +++ b/src/script.h @@ -153,4 +153,41 @@ int RAI_GetScriptFromKeyspace(RedisModuleCtx* ctx, RedisModuleString* keyName, RedisModuleKey** key, RAI_Script** script, int mode); + +/** + * When a module command is called in order to obtain the position of + * keys, since it was flagged as "getkeys-api" during the registration, + * the command implementation checks for this special call using the + * RedisModule_IsKeysPositionRequest() API and uses this function in + * order to report keys. + * No real execution is done on this special call. + * @param ctx Context in which Redis modules operate + * @param argv Redis command arguments, as an array of strings + * @param argc Redis command number of arguments + * @return + */ +int RedisAI_ScriptRun_IsKeysPositionRequest_ReportKeys(RedisModuleCtx *ctx, + RedisModuleString **argv, int argc); + + +/** + * Helper method to parse AI.SCRIPTRUN arguments + * + * @param ctx Context in which Redis modules operate + * @param argv Redis command arguments, as an array of strings + * @param argc Redis command number of arguments + * @param outkeys array to store the parsed input keys + * @param outkeys array to store the parsed output keys + * @param variadic int to store the variadic input location + * @param error error data structure to store error message in the case of + * parsing failures + * @return processed number of arguments on success, or -1 if the parsing failed + */ +int RedisAI_Parse_ScriptRun_RedisCommand(RedisModuleCtx *ctx, + RedisModuleString **argv, int argc, + RedisModuleString ***inkeys, + RedisModuleString ***outkeys, + int *variadic, + RAI_Error *error); + #endif /* SRC_SCRIPT_H_ */ diff --git a/src/util/dict.c b/src/util/dict.c index d04efa993..1b73a90ba 100644 --- a/src/util/dict.c +++ b/src/util/dict.c @@ -99,10 +99,10 @@ static unsigned int dict_force_resize_ratio = 5; /* -------------------------- private prototypes ---------------------------- */ -static int _dictExpandIfNeeded(AI_dict *ht); -static unsigned long _dictNextPower(unsigned long size); -static long _dictKeyIndex(AI_dict *ht, const void *key, uint64_t hash, AI_dictEntry **existing); -static int _dictInit(AI_dict *ht, AI_dictType *type, void *privDataPtr); +static int _AI_dictExpandIfNeeded(AI_dict *ht); +static unsigned long _AI_dictNextPower(unsigned long size); +static long _AI_dictKeyIndex(AI_dict *ht, const void *key, uint64_t hash, AI_dictEntry **existing); +static int _AI_dictInit(AI_dict *ht, AI_dictType *type, void *privDataPtr); /* -------------------------- hash functions -------------------------------- */ @@ -117,24 +117,24 @@ uint8_t *AI_dictGetHashFunctionSeed(void) { } /* The default hashing function uses SipHash implementation - * in siphash.c. */ + * in _AI_siphash.c. */ -uint64_t siphash(const uint8_t *in, const size_t inlen, const uint8_t *k); -uint64_t siphash_nocase(const uint8_t *in, const size_t inlen, const uint8_t *k); +uint64_t _AI_siphash(const uint8_t *in, const size_t inlen, const uint8_t *k); +uint64_t _AI_siphash_nocase(const uint8_t *in, const size_t inlen, const uint8_t *k); uint64_t AI_dictGenHashFunction(const void *key, int len) { - return siphash(key,len,dict_hash_function_seed); + return _AI_siphash(key,len,dict_hash_function_seed); } uint64_t AI_dictGenCaseHashFunction(const unsigned char *buf, int len) { - return siphash_nocase(buf,len,dict_hash_function_seed); + return _AI_siphash_nocase(buf,len,dict_hash_function_seed); } /* ----------------------------- API implementation ------------------------- */ /* Reset a hash table already initialized with ht_init(). * NOTE: This function should only be called by ht_destroy(). */ -static void _dictReset(AI_dictht *ht) +static void _AI_dictReset(AI_dictht *ht) { ht->table = NULL; ht->size = 0; @@ -148,16 +148,16 @@ AI_dict *AI_dictCreate(AI_dictType *type, { AI_dict *d = RA_ALLOC(sizeof(*d)); - _dictInit(d,type,privDataPtr); + _AI_dictInit(d,type,privDataPtr); return d; } /* Initialize the hash table */ -int _dictInit(AI_dict *d, AI_dictType *type, +int _AI_dictInit(AI_dict *d, AI_dictType *type, void *privDataPtr) { - _dictReset(&d->ht[0]); - _dictReset(&d->ht[1]); + _AI_dictReset(&d->ht[0]); + _AI_dictReset(&d->ht[1]); d->type = type; d->privdata = privDataPtr; d->rehashidx = -1; @@ -187,7 +187,7 @@ int AI_dictExpand(AI_dict *d, unsigned long size) return DICT_ERR; AI_dictht n; /* the new hash table */ - unsigned long realsize = _dictNextPower(size); + unsigned long realsize = _AI_dictNextPower(size); /* Rehashing to the same table size is not useful. */ if (realsize == d->ht[0].size) return DICT_ERR; @@ -256,7 +256,7 @@ int AI_dictRehash(AI_dict *d, int n) { if (d->ht[0].used == 0) { RA_FREE(d->ht[0].table); d->ht[0] = d->ht[1]; - _dictReset(&d->ht[1]); + _AI_dictReset(&d->ht[1]); d->rehashidx = -1; return 0; } @@ -292,7 +292,7 @@ int AI_dictRehashMilliseconds(AI_dict *d, int ms) { * This function is called by common lookup or update operations in the * dictionary so that the hash table automatically migrates from H1 to H2 * while it is actively used. */ -static void _dictRehashStep(AI_dict *d) { +static void _AI_dictRehashStep(AI_dict *d) { if (d->iterators == 0) AI_dictRehash(d,1); } @@ -334,11 +334,11 @@ AI_dictEntry *AI_dictAddRaw(AI_dict *d, void *key, AI_dictEntry **existing) AI_dictEntry *entry; AI_dictht *ht; - if (AI_dictIsRehashing(d)) _dictRehashStep(d); + if (AI_dictIsRehashing(d))_AI_dictRehashStep(d); /* Get the index of the new element, or -1 if * the element already exists. */ - if ((index = _dictKeyIndex(d, key, AI_dictHashKey(d,key), existing)) == -1) + if ((index = _AI_dictKeyIndex(d, key, AI_dictHashKey(d,key), existing)) == -1) return NULL; /* Allocate the memory and store the new entry. @@ -407,7 +407,7 @@ static AI_dictEntry *dictGenericDelete(AI_dict *d, const void *key, int nofree) if (d->ht[0].used == 0 && d->ht[1].used == 0) return NULL; - if (AI_dictIsRehashing(d)) _dictRehashStep(d); + if (AI_dictIsRehashing(d))_AI_dictRehashStep(d); h = AI_dictHashKey(d, key); for (table = 0; table <= 1; table++) { @@ -478,7 +478,7 @@ void AI_dictFreeUnlinkedEntry(AI_dict *d, AI_dictEntry *he) { } /* Destroy an entire dictionary */ -static int _dictClear(AI_dict *d, AI_dictht *ht, void(callback)(void *)) { +static int AI_dictClear(AI_dict *d, AI_dictht *ht, void(callback)(void *)) { unsigned long i; /* Free all the elements */ @@ -500,15 +500,15 @@ static int _dictClear(AI_dict *d, AI_dictht *ht, void(callback)(void *)) { /* Free the table and the allocated cache structure */ RA_FREE(ht->table); /* Re-initialize the table */ - _dictReset(ht); + _AI_dictReset(ht); return DICT_OK; /* never fails */ } /* Clear & Release the hash table */ void AI_dictRelease(AI_dict *d) { - _dictClear(d,&d->ht[0],NULL); - _dictClear(d,&d->ht[1],NULL); + AI_dictClear(d,&d->ht[0],NULL); + AI_dictClear(d,&d->ht[1],NULL); RA_FREE(d); } @@ -518,7 +518,7 @@ AI_dictEntry *AI_dictFind(AI_dict *d, const void *key) uint64_t h, idx, table; if (d->ht[0].used + d->ht[1].used == 0) return NULL; /* dict is empty */ - if (AI_dictIsRehashing(d)) _dictRehashStep(d); + if (AI_dictIsRehashing(d))_AI_dictRehashStep(d); h = AI_dictHashKey(d, key); for (table = 0; table <= 1; table++) { idx = h & d->ht[table].sizemask; @@ -653,7 +653,7 @@ AI_dictEntry *AI_dictGetRandomKey(AI_dict *d) int listlen, listele; if (AI_dictSize(d) == 0) return NULL; - if (AI_dictIsRehashing(d)) _dictRehashStep(d); + if (AI_dictIsRehashing(d))_AI_dictRehashStep(d); if (AI_dictIsRehashing(d)) { do { /* We are sure there are no elements in indexes from 0 @@ -721,7 +721,7 @@ unsigned int AI_dictGetSomeKeys(AI_dict *d, AI_dictEntry **des, unsigned int cou /* Try to do a rehashing work proportional to 'count'. */ for (j = 0; j < count; j++) { if (AI_dictIsRehashing(d)) - _dictRehashStep(d); + _AI_dictRehashStep(d); else break; } @@ -958,7 +958,7 @@ unsigned long AI_dictScan(AI_dict *d, /* ------------------------- private functions ------------------------------ */ /* Expand the hash table if needed */ -static int _dictExpandIfNeeded(AI_dict *d) +static int _AI_dictExpandIfNeeded(AI_dict *d) { /* Incremental rehashing already in progress. Return. */ if (AI_dictIsRehashing(d)) return DICT_OK; @@ -980,7 +980,7 @@ static int _dictExpandIfNeeded(AI_dict *d) } /* Our hash table capability is a power of two */ -static unsigned long _dictNextPower(unsigned long size) +static unsigned long _AI_dictNextPower(unsigned long size) { unsigned long i = DICT_HT_INITIAL_SIZE; @@ -999,14 +999,14 @@ static unsigned long _dictNextPower(unsigned long size) * * Note that if we are in the process of rehashing the hash table, the * index is always returned in the context of the second (new) hash table. */ -static long _dictKeyIndex(AI_dict *d, const void *key, uint64_t hash, AI_dictEntry **existing) +static long _AI_dictKeyIndex(AI_dict *d, const void *key, uint64_t hash, AI_dictEntry **existing) { unsigned long idx, table; AI_dictEntry *he; if (existing) *existing = NULL; /* Expand the hash table if needed */ - if (_dictExpandIfNeeded(d) == DICT_ERR) + if (_AI_dictExpandIfNeeded(d) == DICT_ERR) return -1; for (table = 0; table <= 1; table++) { idx = hash & d->ht[table].sizemask; @@ -1025,8 +1025,8 @@ static long _dictKeyIndex(AI_dict *d, const void *key, uint64_t hash, AI_dictEnt } void AI_dictEmpty(AI_dict *d, void(callback)(void*)) { - _dictClear(d,&d->ht[0],callback); - _dictClear(d,&d->ht[1],callback); + AI_dictClear(d,&d->ht[0],callback); + AI_dictClear(d,&d->ht[1],callback); d->rehashidx = -1; d->iterators = 0; } @@ -1071,7 +1071,7 @@ AI_dictEntry **AI_dictFindEntryRefByPtrAndHash(AI_dict *d, const void *oldptr, u /* ------------------------------- Debugging ---------------------------------*/ #define DICT_STATS_VECTLEN 50 -static size_t _dictGetStatsHt(char *buf, size_t bufsize, AI_dictht *ht, int tableid) { +static size_t _AI_dictGetStatsHt(char *buf, size_t bufsize, AI_dictht *ht, int tableid) { unsigned long i, slots = 0, chainlen, maxchainlen = 0; unsigned long totchainlen = 0; unsigned long clvector[DICT_STATS_VECTLEN]; @@ -1137,11 +1137,11 @@ void AI_dictGetStats(char *buf, size_t bufsize, AI_dict *d) { char *orig_buf = buf; size_t orig_bufsize = bufsize; - l = _dictGetStatsHt(buf,bufsize,&d->ht[0],0); + l =_AI_dictGetStatsHt(buf,bufsize,&d->ht[0],0); buf += l; bufsize -= l; if (AI_dictIsRehashing(d) && bufsize > 0) { - _dictGetStatsHt(buf,bufsize,&d->ht[1],1); + _AI_dictGetStatsHt(buf,bufsize,&d->ht[1],1); } /* Make sure there is a NULL term at the end. */ if (orig_bufsize) orig_buf[orig_bufsize-1] = '\0'; diff --git a/src/util/siphash.c.inc b/src/util/siphash.c.inc index 6b9419031..f1b5a66cc 100644 --- a/src/util/siphash.c.inc +++ b/src/util/siphash.c.inc @@ -112,7 +112,7 @@ int siptlw(int c) { v2 = ROTL(v2, 32); \ } while (0) -uint64_t siphash(const uint8_t *in, const size_t inlen, const uint8_t *k) { +uint64_t _AI_siphash(const uint8_t *in, const size_t inlen, const uint8_t *k) { #ifndef UNALIGNED_LE_CPU uint64_t hash; uint8_t *out = (uint8_t*) &hash; @@ -171,7 +171,7 @@ uint64_t siphash(const uint8_t *in, const size_t inlen, const uint8_t *k) { #endif } -uint64_t siphash_nocase(const uint8_t *in, const size_t inlen, const uint8_t *k) +uint64_t _AI_siphash_nocase(const uint8_t *in, const size_t inlen, const uint8_t *k) { #ifndef UNALIGNED_LE_CPU uint64_t hash; @@ -304,13 +304,13 @@ const uint8_t vectors_sip64[64][8] = { }; -/* Test siphash using a test vector. Returns 0 if the function passed +/* Test _AI_siphash using a test vector. Returns 0 if the function passed * all the tests, otherwise 1 is returned. * * IMPORTANT: The test vector is for SipHash 2-4. Before running - * the test revert back the siphash() function to 2-4 rounds since + * the test revert back the _AI_siphash() function to 2-4 rounds since * now it uses 1-2 rounds. */ -int siphash_test(void) { +int _AI_siphash_test(void) { uint8_t in[64], k[16]; int i; int fails = 0; @@ -320,7 +320,7 @@ int siphash_test(void) { for (i = 0; i < 64; ++i) { in[i] = i; - uint64_t hash = siphash(in, i, k); + uint64_t hash = _AI_siphash(in, i, k); const uint8_t *v = NULL; v = (uint8_t *)vectors_sip64; if (memcmp(&hash, v + (i * 8), 8)) { @@ -331,16 +331,16 @@ int siphash_test(void) { /* Run a few basic tests with the case insensitive version. */ uint64_t h1, h2; - h1 = siphash((uint8_t*)"hello world",11,(uint8_t*)"1234567812345678"); - h2 = siphash_nocase((uint8_t*)"hello world",11,(uint8_t*)"1234567812345678"); + h1 = _AI_siphash((uint8_t*)"hello world",11,(uint8_t*)"1234567812345678"); + h2 = _AI_siphash_nocase((uint8_t*)"hello world",11,(uint8_t*)"1234567812345678"); if (h1 != h2) fails++; - h1 = siphash((uint8_t*)"hello world",11,(uint8_t*)"1234567812345678"); - h2 = siphash_nocase((uint8_t*)"HELLO world",11,(uint8_t*)"1234567812345678"); + h1 = _AI_siphash((uint8_t*)"hello world",11,(uint8_t*)"1234567812345678"); + h2 = _AI_siphash_nocase((uint8_t*)"HELLO world",11,(uint8_t*)"1234567812345678"); if (h1 != h2) fails++; - h1 = siphash((uint8_t*)"HELLO world",11,(uint8_t*)"1234567812345678"); - h2 = siphash_nocase((uint8_t*)"HELLO world",11,(uint8_t*)"1234567812345678"); + h1 = _AI_siphash((uint8_t*)"HELLO world",11,(uint8_t*)"1234567812345678"); + h2 = _AI_siphash_nocase((uint8_t*)"HELLO world",11,(uint8_t*)"1234567812345678"); if (h1 == h2) fails++; if (!fails) return 0; diff --git a/test/includes.py b/test/includes.py index 237f556a6..c20e488bf 100755 --- a/test/includes.py +++ b/test/includes.py @@ -155,12 +155,12 @@ def load_creditcardfraud_data(env,max_tensors=10000): def run_mobilenet(con, img, input_var, output_var): time.sleep(0.5 * random.randint(0, 10)) - con.execute_command('AI.TENSORSET', 'input', + con.execute_command('AI.TENSORSET', 'input{1}', 'FLOAT', 1, img.shape[1], img.shape[0], img.shape[2], 'BLOB', img.tobytes()) - con.execute_command('AI.MODELRUN', 'mobilenet', - 'INPUTS', 'input', 'OUTPUTS', 'output') + con.execute_command('AI.MODELRUN', 'mobilenet{1}', + 'INPUTS', 'input{1}', 'OUTPUTS', 'output{1}') def run_test_multiproc(env, n_procs, fn, args=tuple()): diff --git a/test/test_data/pt-minimal-bb.pt b/test/test_data/pt-minimal-bb.pt new file mode 100644 index 000000000..2470afdad --- /dev/null +++ b/test/test_data/pt-minimal-bb.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd657a26454418d7bfd2c02fe76fc15166f6845ec14efa9653ffdc019b021008 +size 1514 diff --git a/test/tests.sh b/test/tests.sh index 4d265b650..0e3820c13 100755 --- a/test/tests.sh +++ b/test/tests.sh @@ -107,7 +107,7 @@ RLTEST_ARGS="" [[ $VALGRIND == 1 || $VGD == 1 ]] && valgrind_config if [[ ! -z $TEST ]]; then - RLTEST_ARGS+=" -s --test $TEST" + RLTEST_ARGS+=" --test $TEST" export PYDEBUG=${PYDEBUG:-1} fi @@ -121,5 +121,6 @@ install_git_lfs check_redis_server [[ $GEN == 1 ]] && run_tests +[[ $CLUSTER == 1 ]] && RLTEST_ARGS+=" --env oss-cluster --shards-count 1" run_tests "--env oss-cluster" [[ $SLAVES == 1 ]] && RLTEST_ARGS+=" --use-slaves" run_tests "--use-slaves" [[ $AOF == 1 ]] && RLTEST_ARGS+=" --use-aof" run_tests "--use-aof" diff --git a/test/tests_dag.py b/test/tests_dag.py index 806727964..2136d8874 100644 --- a/test/tests_dag.py +++ b/test/tests_dag.py @@ -2,6 +2,7 @@ from functools import wraps import multiprocessing as mp from includes import * +import time ''' python -m RLTest --test tests_dag.py --module path/to/redisai.so @@ -13,12 +14,12 @@ def test_dag_load(env): con = env.getConnection() ret = con.execute_command( - "AI.TENSORSET persisted_tensor_1 FLOAT 1 2 VALUES 5 10") + "AI.TENSORSET persisted_tensor_1{{1}} FLOAT 1 2 VALUES 5 10") env.assertEqual(ret, b'OK') command = "AI.DAGRUN "\ - "LOAD 1 persisted_tensor_1 "\ - "PERSIST 1 tensor1 |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10" + "LOAD 1 persisted_tensor_1{{1}} "\ + "PERSIST 1 tensor1{{1}} |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 2 VALUES 5 10" ret = con.execute_command(command) env.assertEqual(ret, [b'OK']) @@ -29,9 +30,9 @@ def test_dag_load_errors(env): # ERR tensor key is empty try: command = "AI.DAGRUN "\ - "LOAD 1 persisted_tensor_1 "\ - "PERSIST 1 tensor1 |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10" + "LOAD 1 persisted_tensor_1{{1}} "\ + "PERSIST 1 tensor1{{1}} |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 2 VALUES 5 10" ret = con.execute_command(command) except Exception as e: @@ -41,11 +42,11 @@ def test_dag_load_errors(env): # WRONGTYPE Operation against a key holding the wrong kind of value try: - con.execute_command('SET', 'non-tensor', 'value') + con.execute_command('SET', 'non-tensor{{1}}', 'value') command = "AI.DAGRUN "\ - "LOAD 1 non-tensor "\ - "PERSIST 1 tensor1 |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10" + "LOAD 1 non-tensor{{1}} "\ + "PERSIST 1 tensor1{{1}} |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 2 VALUES 5 10" ret = con.execute_command(command) except Exception as e: @@ -60,7 +61,7 @@ def test_dag_common_errors(env): # ERR unsupported command within DAG try: command = "AI.DAGRUN |> "\ - "AI.DONTEXIST tensor1 FLOAT 1 2 VALUES 5 10" + "AI.DONTEXIST tensor1{{1}} FLOAT 1 2 VALUES 5 10" ret = con.execute_command(command) except Exception as e: @@ -80,8 +81,8 @@ def test_dag_common_errors(env): # ERR invalid or negative value found in number of keys to PERSIST try: - command = "AI.DAGRUN PERSIST notnumber |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10" + command = "AI.DAGRUN PERSIST notnumber{{1}} |> "\ + "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10" ret = con.execute_command(command) except Exception as e: @@ -91,7 +92,7 @@ def test_dag_common_errors(env): # ERR invalid or negative value found in number of keys to LOAD try: - command = "AI.DAGRUN LOAD notnumber |> "\ + command = "AI.DAGRUN LOAD notnumber{{1}} |> "\ "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10" ret = con.execute_command(command) @@ -127,8 +128,8 @@ def test_dagro_common_errors(env): # ERR invalid or negative value found in number of keys to LOAD try: - command = "AI.DAGRUN_RO LOAD notnumber |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10" + command = "AI.DAGRUN_RO LOAD notnumber{{1}} |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 2 VALUES 5 10" ret = con.execute_command(command) except Exception as e: @@ -141,30 +142,30 @@ def test_dag_modelrun_financialNet_errors(env): if not TEST_TF: return con = env.getConnection() + model_key = 'financialNet_errors{{1}}' model_pb, creditcard_transactions, creditcard_referencedata = load_creditcardfraud_data( env) - ret = con.execute_command('AI.MODELSET', 'financialNet', 'TF', "CPU", + ret = con.execute_command('AI.MODELSET', model_key, 'TF', "CPU", 'INPUTS', 'transaction', 'reference', 'OUTPUTS', 'output', 'BLOB', model_pb) env.assertEqual(ret, b'OK') tensor_number=1 - ret = con.execute_command( 'AI.TENSORSET', 'referenceTensor:{0}'.format(tensor_number), + ret = con.execute_command( 'AI.TENSORSET', 'referenceTensor:{{1}}{0}'.format(tensor_number), 'FLOAT', 1, 256, 'BLOB', creditcard_referencedata[0].tobytes()) env.assertEqual(ret, b'OK') # ERR wrong number of inputs try: - tensor_number=1 ret = con.execute_command( - 'AI.DAGRUN', 'LOAD', '1', 'referenceTensor:{}'.format(tensor_number), - 'PERSIST', '1', 'classificationTensor:{}'.format(tensor_number), '|>', + 'AI.DAGRUN', 'LOAD', '1', 'referenceTensor:{{1}}{}'.format(tensor_number), + 'PERSIST', '1', 'resultTensor:{{1}}{}'.format(tensor_number), '|>', 'AI.TENSORSET', 'transactionTensor:{}'.format(tensor_number), 'FLOAT', 1, 30, '|>', - 'AI.MODELRUN', 'financialNet', + 'AI.MODELRUN', model_key, 'INPUTS', 'transactionTensor:{}'.format(tensor_number), - 'OUTPUTS', 'classificationTensor:{}'.format(tensor_number), '|>', - 'AI.TENSORGET', 'classificationTensor:{}'.format(tensor_number), 'META', + 'OUTPUTS', 'resultTensor:{{1}}{}'.format(tensor_number), '|>', + 'AI.TENSORGET', 'resultTensor:{{1}}{}'.format(tensor_number), 'META', ) except Exception as e: exception = e @@ -206,17 +207,17 @@ def test_dag_local_tensorset_persist(env): con = env.getConnection() command = "AI.DAGRUN "\ - "PERSIST 1 tensor1 |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10" + "PERSIST 1 tensor1{{1}} |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 2 VALUES 5 10" ret = con.execute_command(command) env.assertEqual(ret, [b'OK']) # assert that transaction tensor exists - ret = con.execute_command("EXISTS tensor1") + ret = con.execute_command("EXISTS tensor1{{1}}") env.assertEqual(ret, 1 ) - ret = con.execute_command("AI.TENSORGET tensor1 META VALUES") + ret = con.execute_command("AI.TENSORGET tensor1{{1}} META VALUES") env.assertEqual(ret, [b'dtype', b'FLOAT', b'shape', [1, 2], b'values', [b'5', b'10']]) @@ -224,8 +225,8 @@ def test_dagro_local_tensorset_persist(env): con = env.getConnection() command = "AI.DAGRUN_RO "\ - "PERSIST 1 tensor1 |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10" + "PERSIST 1 tensor1{{1}} |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 2 VALUES 5 10" try: con.execute_command(command) @@ -239,17 +240,17 @@ def test_dag_multilocal_tensorset_persist(env): con = env.getConnection() command = "AI.DAGRUN "\ - "PERSIST 1 tensor3 |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10 |> "\ + "PERSIST 1 tensor3:{{1}} |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 2 VALUES 5 10 |> "\ "AI.TENSORSET tensor2 FLOAT 1 2 VALUES 5 10 |> "\ - "AI.TENSORSET tensor3 FLOAT 1 2 VALUES 5 10 |> "\ - "AI.TENSORSET tensor4 FLOAT 1 2 VALUES 5 10 " + "AI.TENSORSET tensor3:{{1}} FLOAT 1 2 VALUES 5 10 |> "\ + "AI.TENSORSET tensor4:{{1}} FLOAT 1 2 VALUES 5 10 " ret = con.execute_command(command) env.assertEqual([b'OK',b'OK',b'OK',b'OK'],ret) # assert that transaction tensor exists - ret = con.execute_command("EXISTS tensor1") + ret = con.execute_command("EXISTS tensor1{{1}}") env.assertEqual(ret, 0 ) # assert that transaction tensor exists @@ -257,28 +258,28 @@ def test_dag_multilocal_tensorset_persist(env): env.assertEqual(ret, 0 ) # assert that transaction tensor exists - ret = con.execute_command("EXISTS tensor3") + ret = con.execute_command("EXISTS tensor3:{{1}}") env.assertEqual(ret, 1 ) # assert that transaction tensor exists - ret = con.execute_command("EXISTS tensor4") + ret = con.execute_command("EXISTS tensor4:{{1}}") env.assertEqual(ret, 0 ) - ret = con.execute_command("AI.TENSORGET tensor3 META VALUES") + ret = con.execute_command("AI.TENSORGET tensor3:{{1}} META VALUES") env.assertEqual(ret, [b'dtype', b'FLOAT', b'shape', [1, 2], b'values', [b'5', b'10']]) def test_dag_local_tensorset_tensorget_persist(env): con = env.getConnection() - command = "AI.DAGRUN PERSIST 1 tensor1 |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10 |> "\ - "AI.TENSORGET tensor1 VALUES" + command = "AI.DAGRUN PERSIST 1 tensor1{{1}} |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 2 VALUES 5 10 |> "\ + "AI.TENSORGET tensor1{{1}} VALUES" ret = con.execute_command(command) env.assertEqual(ret, [b'OK', [b'5', b'10']]) - ret = con.execute_command("AI.TENSORGET tensor1 VALUES") + ret = con.execute_command("AI.TENSORGET tensor1{{1}} VALUES") env.assertEqual(ret, [b'5', b'10']) @@ -286,11 +287,11 @@ def test_dag_local_multiple_tensorset_on_same_tensor(env): con = env.getConnection() command = "AI.DAGRUN "\ - "PERSIST 1 tensor1 |> "\ - "AI.TENSORSET tensor1 FLOAT 1 2 VALUES 5 10 |> "\ - "AI.TENSORGET tensor1 META VALUES |> "\ - "AI.TENSORSET tensor1 FLOAT 1 4 VALUES 20 40 60 80 |> "\ - "AI.TENSORGET tensor1 META VALUES" + "PERSIST 1 tensor1{{1}} |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 2 VALUES 5 10 |> "\ + "AI.TENSORGET tensor1{{1}} META VALUES |> "\ + "AI.TENSORSET tensor1{{1}} FLOAT 1 4 VALUES 20 40 60 80 |> "\ + "AI.TENSORGET tensor1{{1}} META VALUES" ret = con.execute_command(command) env.assertEqual([ @@ -300,7 +301,7 @@ def test_dag_local_multiple_tensorset_on_same_tensor(env): [b'dtype', b'FLOAT', b'shape', [1, 4], b'values', [b'20', b'40', b'60', b'80']] ], ret) - ret = con.execute_command("AI.TENSORGET tensor1 META VALUES") + ret = con.execute_command("AI.TENSORGET tensor1{{1}} META VALUES") env.assertEqual([b'dtype', b'FLOAT', b'shape', [1, 4], b'values', [b'20', b'40',b'60',b'80']],ret) @@ -308,17 +309,17 @@ def test_dag_load_persist_tensorset_tensorget(env): con = env.getConnection() ret = con.execute_command( - "AI.TENSORSET persisted_tensor_1 FLOAT 1 2 VALUES 5 10") + "AI.TENSORSET persisted_tensor_1{{1}} FLOAT 1 2 VALUES 5 10") env.assertEqual(ret, b'OK') ret = con.execute_command( - "AI.TENSORSET persisted_tensor_2 FLOAT 1 3 VALUES 0 0 0") + "AI.TENSORSET persisted_tensor_2:{{1}} FLOAT 1 3 VALUES 0 0 0") env.assertEqual(ret, b'OK') - command = "AI.DAGRUN LOAD 2 persisted_tensor_1 persisted_tensor_2 PERSIST 1 volatile_tensor_persisted |> "\ + command = "AI.DAGRUN LOAD 2 persisted_tensor_1{{1}} persisted_tensor_2:{{1}} PERSIST 1 volatile_tensor_persisted |> "\ "AI.TENSORSET volatile_tensor_persisted FLOAT 1 2 VALUES 5 10 |> "\ - "AI.TENSORGET persisted_tensor_1 META VALUES |> "\ - "AI.TENSORGET persisted_tensor_2 META VALUES " + "AI.TENSORGET persisted_tensor_1{{1}} META VALUES |> "\ + "AI.TENSORGET persisted_tensor_2:{{1}} META VALUES " ret = con.execute_command(command) env.assertEqual(ret, [b'OK', [b'dtype', b'FLOAT', b'shape', [1, 2], b'values', [b'5', b'10']], [ @@ -390,39 +391,40 @@ def test_dag_modelrun_financialNet_separate_tensorget(env): model_pb, creditcard_transactions, creditcard_referencedata = load_creditcardfraud_data( env) - ret = con.execute_command('AI.MODELSET', 'financialNet', 'TF', "CPU", + model_name = 'financialNet{{hhh}}' + + ret = con.execute_command('AI.MODELSET', model_name, 'TF', "CPU", 'INPUTS', 'transaction', 'reference', 'OUTPUTS', 'output', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - tensor_number = 1 - for reference_tensor in creditcard_referencedata[:MAX_TRANSACTIONS]: - ret = con.execute_command('AI.TENSORSET', 'referenceTensor:{0}'.format(tensor_number), - 'FLOAT', 1, 256, - 'BLOB', reference_tensor.tobytes()) - env.assertEqual(ret, b'OK') - tensor_number = tensor_number + 1 + for tensor_number in range(1,MAX_TRANSACTIONS): + for repetition in range(1,10): + reference_tensor = creditcard_referencedata[tensor_number] + transaction_tensor = creditcard_transactions[tensor_number] + result_tensor_keyname = 'resultTensor{{hhh}}{}'.format(tensor_number) + reference_tensor_keyname = 'referenceTensor{{hhh}}{}'.format(tensor_number) + transaction_tensor_keyname = 'transactionTensor{{hhh}}{}'.format(tensor_number) + + ret = con.execute_command('AI.TENSORSET', reference_tensor_keyname, + 'FLOAT', 1, 256, + 'BLOB', reference_tensor.tobytes()) + env.assertEqual(ret, b'OK') + ret = con.execute_command("EXISTS {}".format(reference_tensor_keyname)) + env.assertEqual(ret, 1) - tensor_number = 1 - for transaction_tensor in creditcard_transactions[:MAX_TRANSACTIONS]: - ret = con.execute_command( - 'AI.DAGRUN', 'LOAD', '1', 'referenceTensor:{}'.format(tensor_number), - 'PERSIST', '1', 'classificationTensor:{}'.format(tensor_number), '|>', - 'AI.TENSORSET', 'transactionTensor:{}'.format(tensor_number), 'FLOAT', 1, 30,'BLOB', transaction_tensor.tobytes(), '|>', - 'AI.MODELRUN', 'financialNet', - 'INPUTS', 'transactionTensor:{}'.format(tensor_number), 'referenceTensor:{}'.format(tensor_number), - 'OUTPUTS', 'classificationTensor:{}'.format(tensor_number), - ) - env.assertEqual([b'OK',b'OK'],ret) - - ret = con.execute_command("AI.TENSORGET classificationTensor:{} META".format( - tensor_number)) - env.assertEqual([b'dtype', b'FLOAT', b'shape', [1, 2]], ret) - - # assert that transaction tensor does not exist - ret = con.execute_command("EXISTS transactionTensor:{} META".format( - tensor_number)) - env.assertEqual(ret, 0 ) - tensor_number = tensor_number + 1 + ret = con.execute_command( + 'AI.DAGRUN', 'LOAD', '1', reference_tensor_keyname, + 'PERSIST', '1', result_tensor_keyname, '|>', + 'AI.TENSORSET', transaction_tensor_keyname, 'FLOAT', 1, 30,'BLOB', transaction_tensor.tobytes(), '|>', + 'AI.MODELRUN', model_name, + 'INPUTS', transaction_tensor_keyname, reference_tensor_keyname, + 'OUTPUTS', result_tensor_keyname, + ) + env.assertEqual([b'OK',b'OK'],ret) + + ret = con.execute_command("AI.TENSORGET {} META".format( + result_tensor_keyname)) + env.assertEqual([b'dtype', b'FLOAT', b'shape', [1, 2]], ret) def test_dag_modelrun_financialNet(env): @@ -432,37 +434,44 @@ def test_dag_modelrun_financialNet(env): model_pb, creditcard_transactions, creditcard_referencedata = load_creditcardfraud_data( env) - ret = con.execute_command('AI.MODELSET', 'financialNet', 'TF', "CPU", + model_name = 'financialNet{{hhh}}' + + ret = con.execute_command('AI.MODELSET', model_name, 'TF', "CPU", 'INPUTS', 'transaction', 'reference', 'OUTPUTS', 'output', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - tensor_number = 1 - for reference_tensor in creditcard_referencedata[:MAX_TRANSACTIONS]: - ret = con.execute_command('AI.TENSORSET', 'referenceTensor:{0}'.format(tensor_number), - 'FLOAT', 1, 256, - 'BLOB', reference_tensor.tobytes()) - env.assertEqual(ret, b'OK') - tensor_number = tensor_number + 1 + for tensor_number in range(1,MAX_TRANSACTIONS): + for repetition in range(1,10): + reference_tensor = creditcard_referencedata[tensor_number] + transaction_tensor = creditcard_transactions[tensor_number] + result_tensor_keyname = 'resultTensor{{hhh}}{}'.format(tensor_number) + reference_tensor_keyname = 'referenceTensor{{hhh}}{}'.format(tensor_number) + transaction_tensor_keyname = 'transactionTensor{{hhh}}{}'.format(tensor_number) + + ret = con.execute_command('AI.TENSORSET', reference_tensor_keyname, + 'FLOAT', 1, 256, + 'BLOB', reference_tensor.tobytes()) + env.assertEqual(ret, b'OK') + ret = con.execute_command("EXISTS {}".format(reference_tensor_keyname)) + env.assertEqual(ret, 1) - tensor_number = 1 - for transaction_tensor in creditcard_transactions[:MAX_TRANSACTIONS]: - ret = con.execute_command( - 'AI.DAGRUN', 'LOAD', '1', 'referenceTensor:{}'.format(tensor_number), - 'PERSIST', '1', 'classificationTensor:{}'.format(tensor_number), '|>', - 'AI.TENSORSET', 'transactionTensor:{}'.format(tensor_number), 'FLOAT', 1, 30,'BLOB', transaction_tensor.tobytes(), '|>', - 'AI.MODELRUN', 'financialNet', - 'INPUTS', 'transactionTensor:{}'.format(tensor_number), 'referenceTensor:{}'.format(tensor_number), - 'OUTPUTS', 'classificationTensor:{}'.format(tensor_number), '|>', - 'AI.TENSORGET', 'classificationTensor:{}'.format(tensor_number), 'META', - ) - env.assertEqual([b'OK',b'OK',[b'dtype', b'FLOAT', b'shape', [1, 2]]], ret) - - # assert that transaction tensor does not exist - ret = con.execute_command("EXISTS transactionTensor:{}".format( - tensor_number)) - env.assertEqual(ret, 0 ) - tensor_number = tensor_number + 1 + ret = con.execute_command( + 'AI.DAGRUN', 'LOAD', '1', reference_tensor_keyname, + 'PERSIST', '1', result_tensor_keyname, '|>', + 'AI.TENSORSET', transaction_tensor_keyname, 'FLOAT', 1, 30,'BLOB', transaction_tensor.tobytes(), '|>', + 'AI.MODELRUN', model_name, + 'INPUTS', transaction_tensor_keyname, reference_tensor_keyname, + 'OUTPUTS', result_tensor_keyname, '|>', + 'AI.TENSORGET', result_tensor_keyname, 'META', + ) + env.assertEqual([b'OK',b'OK',[b'dtype', b'FLOAT', b'shape', [1, 2]]], ret) + # assert that transaction tensor does not exist + ret = con.execute_command("EXISTS {}".format(transaction_tensor_keyname)) + env.assertEqual(ret, 0) + # assert that result tensor exists + ret = con.execute_command("EXISTS {}".format(result_tensor_keyname)) + env.assertEqual(ret, 1) def test_dag_modelrun_financialNet_no_writes(env): if not TEST_TF: @@ -471,29 +480,35 @@ def test_dag_modelrun_financialNet_no_writes(env): model_pb, creditcard_transactions, creditcard_referencedata = load_creditcardfraud_data( env) - ret = con.execute_command('AI.MODELSET', 'financialNet', 'TF', "CPU", + model_name = 'financialNet{{hhh}}' + + ret = con.execute_command('AI.MODELSET', model_name, 'TF', "CPU", 'INPUTS', 'transaction', 'reference', 'OUTPUTS', 'output', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - tensor_number = 1 - for reference_tensor in creditcard_referencedata[:MAX_TRANSACTIONS]: - ret = con.execute_command('AI.TENSORSET', 'referenceTensor:{0}'.format(tensor_number), - 'FLOAT', 1, 256, - 'BLOB', reference_tensor.tobytes()) - env.assertEqual(ret, b'OK') - tensor_number = tensor_number + 1 + for tensor_number in range(1,MAX_TRANSACTIONS): + for repetition in range(1,10): + reference_tensor = creditcard_referencedata[tensor_number] + transaction_tensor = creditcard_transactions[tensor_number] + result_tensor_keyname = 'resultTensor{{hhh}}{}'.format(tensor_number) + reference_tensor_keyname = 'referenceTensor{{hhh}}{}'.format(tensor_number) + transaction_tensor_keyname = 'transactionTensor{{hhh}}{}'.format(tensor_number) + + ret = con.execute_command('AI.TENSORSET', reference_tensor_keyname, + 'FLOAT', 1, 256, + 'BLOB', reference_tensor.tobytes()) + env.assertEqual(ret, b'OK') + ret = con.execute_command("EXISTS {}".format(reference_tensor_keyname)) + env.assertEqual(ret, 1) - tensor_number = 1 - for transaction_tensor in creditcard_transactions[:MAX_TRANSACTIONS]: - for run_number in range(1,10): ret = con.execute_command( - 'AI.DAGRUN', 'LOAD', '1', 'referenceTensor:{}'.format(tensor_number), '|>', - 'AI.TENSORSET', 'transactionTensor:{}'.format(tensor_number), 'FLOAT', 1, 30,'BLOB', transaction_tensor.tobytes(), '|>', - 'AI.MODELRUN', 'financialNet', - 'INPUTS', 'transactionTensor:{}'.format(tensor_number), 'referenceTensor:{}'.format(tensor_number), - 'OUTPUTS', 'classificationTensor:{}'.format(tensor_number), '|>', - 'AI.TENSORGET', 'classificationTensor:{}'.format(tensor_number), 'META', '|>', - 'AI.TENSORGET', 'classificationTensor:{}'.format(tensor_number), 'VALUES' + 'AI.DAGRUN', 'LOAD', '1', reference_tensor_keyname, '|>', + 'AI.TENSORSET', transaction_tensor_keyname, 'FLOAT', 1, 30,'BLOB', transaction_tensor.tobytes(), '|>', + 'AI.MODELRUN', model_name, + 'INPUTS', transaction_tensor_keyname, reference_tensor_keyname, + 'OUTPUTS', result_tensor_keyname, '|>', + 'AI.TENSORGET',result_tensor_keyname, 'META', '|>', + 'AI.TENSORGET', result_tensor_keyname, 'VALUES' ) env.assertEqual(4, len(ret)) env.assertEqual([b'OK', b'OK'], ret[:2]) @@ -503,16 +518,12 @@ def test_dag_modelrun_financialNet_no_writes(env): env.assertEqual(True, 0 <= float(values[0]) <= 1) env.assertEqual(True, 0 <= float(values[1]) <= 1) - # assert that transactionTensor does not exist - ret = con.execute_command("EXISTS transactionTensor:{}".format( - tensor_number)) - env.assertEqual(ret, 0 ) - - # assert that classificationTensor does not exist - ret = con.execute_command("EXISTS classificationTensor:{}".format( - tensor_number)) - env.assertEqual(ret, 0 ) - tensor_number = tensor_number + 1 + # assert that transaction tensor does not exist + ret = con.execute_command("EXISTS {}".format(transaction_tensor_keyname)) + env.assertEqual(ret, 0) + # assert that result tensor exists + ret = con.execute_command("EXISTS {}".format(result_tensor_keyname)) + env.assertEqual(ret, 0) def test_dagro_modelrun_financialNet_no_writes_multiple_modelruns(env): @@ -522,73 +533,70 @@ def test_dagro_modelrun_financialNet_no_writes_multiple_modelruns(env): model_pb, creditcard_transactions, creditcard_referencedata = load_creditcardfraud_data( env) - ret = con.execute_command('AI.MODELSET', 'financialNet', 'TF', DEVICE, + model_name = 'financialNet_no_writes{{hhh}}' + + ret = con.execute_command('AI.MODELSET', model_name, 'TF', "CPU", 'INPUTS', 'transaction', 'reference', 'OUTPUTS', 'output', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - tensor_number = 1 - for reference_tensor in creditcard_referencedata[:MAX_TRANSACTIONS]: - ret = con.execute_command('AI.TENSORSET', 'referenceTensor:{0}'.format(tensor_number), - 'FLOAT', 1, 256, - 'BLOB', reference_tensor.tobytes()) - env.assertEqual(ret, b'OK') - tensor_number = tensor_number + 1 - - tensor_number = 1 - for transaction_tensor in creditcard_transactions[:MAX_TRANSACTIONS]: - ret = con.execute_command( - 'AI.DAGRUN_RO', 'LOAD', '1', 'referenceTensor:{}'.format(tensor_number), '|>', - 'AI.TENSORSET', 'transactionTensor:{}'.format(tensor_number), 'FLOAT', 1, 30,'BLOB', transaction_tensor.tobytes(), '|>', - 'AI.MODELRUN', 'financialNet', - 'INPUTS', 'transactionTensor:{}'.format(tensor_number), 'referenceTensor:{}'.format(tensor_number), - 'OUTPUTS', 'classificationTensor:{}'.format(tensor_number), '|>', - 'AI.TENSORGET', 'classificationTensor:{}'.format(tensor_number), 'META', 'VALUES', '|>', - 'AI.MODELRUN', 'financialNet', - 'INPUTS', 'transactionTensor:{}'.format(tensor_number), 'referenceTensor:{}'.format(tensor_number), - 'OUTPUTS', 'classificationTensor:{}'.format(tensor_number), '|>', - 'AI.TENSORGET', 'classificationTensor:{}'.format(tensor_number), 'META', 'VALUES', - ) - env.assertEqual(5, len(ret)) - env.assertEqual([b'OK', b'OK'], ret[:2]) - env.assertEqual([b'dtype', b'FLOAT', b'shape', [1, 2]], ret[2][:4]) - env.assertEqual(b'OK', ret[3]) - env.assertEqual([b'dtype', b'FLOAT', b'shape', [1, 2]], ret[4][:4]) - for _, dtype, _, shape, _, values in [ret[2], ret[4]]: - # Assert that resulting classification is within [0,1] - env.assertEqual(True, 0 <= float(values[0]) <= 1) - env.assertEqual(True, 0 <= float(values[1]) <= 1) - - # assert that transactionTensor does not exist - ret = con.execute_command("EXISTS transactionTensor:{}".format( - tensor_number)) - env.assertEqual(ret, 0) - - # assert that classificationTensor does not exist - ret = con.execute_command("EXISTS classificationTensor:{}".format( - tensor_number)) - env.assertEqual(ret, 0) - tensor_number = tensor_number + 1 - - info = con.execute_command('AI.INFO', 'financialNet') + for tensor_number in range(1,MAX_TRANSACTIONS+1): + for repetition in range(1,11): + reference_tensor = creditcard_referencedata[tensor_number-1] + transaction_tensor = creditcard_transactions[tensor_number-1] + result_tensor_keyname = 'resultTensor{{hhh}}{}'.format(tensor_number) + reference_tensor_keyname = 'referenceTensor{{hhh}}{}'.format(tensor_number) + transaction_tensor_keyname = 'transactionTensor{{hhh}}{}'.format(tensor_number) + + ret = con.execute_command('AI.TENSORSET', reference_tensor_keyname, + 'FLOAT', 1, 256, + 'BLOB', reference_tensor.tobytes()) + env.assertEqual(ret, b'OK') + ret = con.execute_command("EXISTS {}".format(reference_tensor_keyname)) + env.assertEqual(ret, 1) + ret = con.execute_command( + 'AI.DAGRUN_RO', 'LOAD', '1', reference_tensor_keyname, '|>', + 'AI.TENSORSET', transaction_tensor_keyname, 'FLOAT', 1, 30,'BLOB', transaction_tensor.tobytes(), '|>', + 'AI.MODELRUN', model_name, + 'INPUTS', transaction_tensor_keyname, reference_tensor_keyname, + 'OUTPUTS', result_tensor_keyname, '|>', + 'AI.TENSORGET', result_tensor_keyname, 'META', 'VALUES', '|>', + 'AI.MODELRUN', model_name, + 'INPUTS', transaction_tensor_keyname, reference_tensor_keyname, + 'OUTPUTS', result_tensor_keyname, '|>', + 'AI.TENSORGET', result_tensor_keyname, 'META', 'VALUES', + ) + env.assertEqual(5, len(ret)) + env.assertEqual([b'OK', b'OK'], ret[:2]) + env.assertEqual([b'dtype', b'FLOAT', b'shape', [1, 2]], ret[2][:4]) + env.assertEqual(b'OK', ret[3]) + env.assertEqual([b'dtype', b'FLOAT', b'shape', [1, 2]], ret[4][:4]) + for _, dtype, _, shape, _, values in [ret[2], ret[4]]: + # Assert that resulting classification is within [0,1] + env.assertEqual(True, 0 <= float(values[0]) <= 1) + env.assertEqual(True, 0 <= float(values[1]) <= 1) + + info = con.execute_command('AI.INFO', model_name) financialNetRunInfo = info_to_dict(info) - env.assertEqual('financialNet', financialNetRunInfo['key']) + env.assertEqual(model_name, financialNetRunInfo['key']) env.assertEqual('MODEL', financialNetRunInfo['type']) env.assertEqual('TF', financialNetRunInfo['backend']) - env.assertEqual(DEVICE, financialNetRunInfo['device']) + # Commenting due to: 'ascii' codec can't encode character '\u274c' in position 8: ordinal not in range(128) + # env.assertEqual(DEVICE, financialNetRunInfo['device']) env.assertTrue(financialNetRunInfo['duration'] > 0) env.assertEqual(0, financialNetRunInfo['samples']) - env.assertEqual(2*MAX_TRANSACTIONS, financialNetRunInfo['calls']) + env.assertEqual(2*MAX_TRANSACTIONS*10, financialNetRunInfo['calls']) env.assertEqual(0, financialNetRunInfo['errors']) - con.execute_command('AI.INFO', 'financialNet', 'RESETSTAT') - info = con.execute_command('AI.INFO', 'financialNet') + con.execute_command('AI.INFO', model_name, 'RESETSTAT') + info = con.execute_command('AI.INFO', model_name) financialNetRunInfo = info_to_dict(info) - env.assertEqual('financialNet', financialNetRunInfo['key']) + env.assertEqual(model_name, financialNetRunInfo['key']) env.assertEqual('MODEL', financialNetRunInfo['type']) env.assertEqual('TF', financialNetRunInfo['backend']) - env.assertEqual(DEVICE, financialNetRunInfo['device']) + # Commenting due to: 'ascii' codec can't encode character '\u274c' in position 8: ordinal not in range(128) + # env.assertEqual(DEVICE, financialNetRunInfo['device']) env.assertEqual(0, financialNetRunInfo['duration']) env.assertEqual(0, financialNetRunInfo['samples']) env.assertEqual(0, financialNetRunInfo['calls']) diff --git a/test/tests_onnx.py b/test/tests_onnx.py index fff7f9ebb..004adde36 100644 --- a/test/tests_onnx.py +++ b/test/tests_onnx.py @@ -30,24 +30,24 @@ def test_onnx_modelrun_mnist(env): with open(sample_filename, 'rb') as f: sample_raw = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'ONNX', DEVICE, 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'ONNX', DEVICE, 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) env.assertEqual(ret[5], b'') # assert there are no inputs or outputs env.assertEqual(len(ret[11]), 0) env.assertEqual(len(ret[13]), 0) - ret = con.execute_command('AI.MODELSET', 'm', 'ONNX', DEVICE, 'TAG', 'version:2', 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'ONNX', DEVICE, 'TAG', 'version:2', 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) # TODO: enable me. CI is having issues on GPU asserts of ONNX and CPU if DEVICE == "CPU": @@ -59,96 +59,96 @@ def test_onnx_modelrun_mnist(env): env.assertEqual(len(ret[13]), 0) try: - con.execute_command('AI.MODELSET', 'm', 'ONNX', DEVICE, 'BLOB', wrong_model_pb) + con.execute_command('AI.MODELSET', 'm{1}', 'ONNX', DEVICE, 'BLOB', wrong_model_pb) except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("No graph was found in the protobuf.", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_1', 'ONNX', 'BLOB', model_pb) + con.execute_command('AI.MODELSET', 'm_1{1}', 'ONNX', 'BLOB', model_pb) except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("Invalid DEVICE", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_2', model_pb) + con.execute_command('AI.MODELSET', 'm_2{1}', model_pb) except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("wrong number of arguments for 'AI.MODELSET' command", exception.__str__()) - con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) + con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) try: - con.execute_command('AI.MODELRUN', 'm_1', 'INPUTS', 'a', 'OUTPUTS') + con.execute_command('AI.MODELRUN', 'm_1{1}', 'INPUTS', 'a{1}', 'OUTPUTS') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("model key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_2', 'INPUTS', 'a', 'b', 'c') + con.execute_command('AI.MODELRUN', 'm_2{1}', 'INPUTS', 'a{1}', 'b{1}', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("model key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_3', 'a', 'b', 'c') + con.execute_command('AI.MODELRUN', 'm_3{1}', 'a{1}', 'b{1}', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("model key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_1', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm_1{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("model key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("INPUTS not specified", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("tensor key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_1', 'INPUTS', 'OUTPUTS') + con.execute_command('AI.MODELRUN', 'm_1{1}', 'INPUTS', 'OUTPUTS') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("model key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_1', 'INPUTS', 'a', 'OUTPUTS', 'b') + con.execute_command('AI.MODELRUN', 'm_1{1}', 'INPUTS', 'a{1}', 'OUTPUTS', 'b{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("model key is empty", exception.__str__()) - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'OUTPUTS', 'b') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'OUTPUTS', 'b{1}') ensureSlaveSynced(con, env) - values = con.execute_command('AI.TENSORGET', 'b', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'b{1}', 'VALUES') argmax = max(range(len(values)), key=lambda i: values[i]) env.assertEqual(argmax, 1) if env.useSlaves: con2 = env.getSlaveConnection() - values2 = con2.execute_command('AI.TENSORGET', 'b', 'VALUES') + values2 = con2.execute_command('AI.TENSORGET', 'b{1}', 'VALUES') env.assertEqual(values2, values) @@ -161,15 +161,15 @@ def test_onnx_modelrun_batchdim_mismatch(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'ONNX', DEVICE, 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'ONNX', DEVICE, 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 'VALUES', 1, 1) - con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 'VALUES', 1, 1) + con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 'VALUES', 1, 1) + con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 'VALUES', 1, 1) - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c', 'd') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}', 'd{1}') @@ -189,11 +189,11 @@ def test_onnx_modelrun_mnist_autobatch(env): with open(sample_filename, 'rb') as f: sample_raw = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'ONNX', 'CPU', + ret = con.execute_command('AI.MODELSET', 'm{1}', 'ONNX', 'CPU', 'BATCHSIZE', 2, 'MINBATCHSIZE', 2, 'BLOB', model_pb) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) # TODO: enable me. CI is having issues on GPU asserts of ONNX and CPU if DEVICE == "CPU": @@ -206,31 +206,31 @@ def test_onnx_modelrun_mnist_autobatch(env): env.assertEqual(len(ret[11]), 0) env.assertEqual(len(ret[13]), 0) - con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) - con.execute_command('AI.TENSORSET', 'c', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) + con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) + con.execute_command('AI.TENSORSET', 'c{1}', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) ensureSlaveSynced(con, env) def run(): con = env.getConnection() - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'c', 'OUTPUTS', 'd') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'c{1}', 'OUTPUTS', 'd{1}') t = threading.Thread(target=run) t.start() - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'OUTPUTS', 'b') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'OUTPUTS', 'b{1}') ensureSlaveSynced(con, env) import time time.sleep(1) - values = con.execute_command('AI.TENSORGET', 'b', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'b{1}', 'VALUES') argmax = max(range(len(values)), key=lambda i: values[i]) env.assertEqual(argmax, 1) - values = con.execute_command('AI.TENSORGET', 'd', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'd{1}', 'VALUES') argmax = max(range(len(values)), key=lambda i: values[i]) env.assertEqual(argmax, 1) @@ -253,31 +253,31 @@ def test_onnx_modelrun_iris(env): with open(logreg_model_filename, 'rb') as f: logreg_model = f.read() - ret = con.execute_command('AI.MODELSET', 'linear', 'ONNX', DEVICE, 'BLOB', linear_model) + ret = con.execute_command('AI.MODELSET', 'linear{1}', 'ONNX', DEVICE, 'BLOB', linear_model) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.MODELSET', 'logreg', 'ONNX', DEVICE, 'BLOB', logreg_model) + ret = con.execute_command('AI.MODELSET', 'logreg{1}', 'ONNX', DEVICE, 'BLOB', logreg_model) env.assertEqual(ret, b'OK') - con.execute_command('AI.TENSORSET', 'features', 'FLOAT', 1, 4, 'VALUES', 5.1, 3.5, 1.4, 0.2) + con.execute_command('AI.TENSORSET', 'features{1}', 'FLOAT', 1, 4, 'VALUES', 5.1, 3.5, 1.4, 0.2) ensureSlaveSynced(con, env) - con.execute_command('AI.MODELRUN', 'linear', 'INPUTS', 'features', 'OUTPUTS', 'linear_out') - con.execute_command('AI.MODELRUN', 'logreg', 'INPUTS', 'features', 'OUTPUTS', 'logreg_out', 'logreg_probs') + con.execute_command('AI.MODELRUN', 'linear{1}', 'INPUTS', 'features{1}', 'OUTPUTS', 'linear_out{1}') + con.execute_command('AI.MODELRUN', 'logreg{1}', 'INPUTS', 'features{1}', 'OUTPUTS', 'logreg_out{1}', 'logreg_probs{1}') ensureSlaveSynced(con, env) - linear_out = con.execute_command('AI.TENSORGET', 'linear_out', 'VALUES') - logreg_out = con.execute_command('AI.TENSORGET', 'logreg_out', 'VALUES') + linear_out = con.execute_command('AI.TENSORGET', 'linear_out{1}', 'VALUES') + logreg_out = con.execute_command('AI.TENSORGET', 'logreg_out{1}', 'VALUES') env.assertEqual(float(linear_out[0]), -0.090524077415466309) env.assertEqual(logreg_out[0], 0) if env.useSlaves: con2 = env.getSlaveConnection() - linear_out2 = con2.execute_command('AI.TENSORGET', 'linear_out', 'VALUES') - logreg_out2 = con2.execute_command('AI.TENSORGET', 'logreg_out', 'VALUES') + linear_out2 = con2.execute_command('AI.TENSORGET', 'linear_out{1}', 'VALUES') + logreg_out2 = con2.execute_command('AI.TENSORGET', 'logreg_out{1}', 'VALUES') env.assertEqual(linear_out, linear_out2) env.assertEqual(logreg_out, logreg_out2) @@ -294,28 +294,28 @@ def test_onnx_modelinfo(env): with open(linear_model_filename, 'rb') as f: linear_model = f.read() - ret = con.execute_command('AI.MODELSET', 'linear', 'ONNX', DEVICE, 'BLOB', linear_model) + ret = con.execute_command('AI.MODELSET', 'linear{1}', 'ONNX', DEVICE, 'BLOB', linear_model) env.assertEqual(ret, b'OK') - model_serialized_master = con.execute_command('AI.MODELGET', 'linear', 'META') - con.execute_command('AI.TENSORSET', 'features', 'FLOAT', 1, 4, 'VALUES', 5.1, 3.5, 1.4, 0.2) + model_serialized_master = con.execute_command('AI.MODELGET', 'linear{1}', 'META') + con.execute_command('AI.TENSORSET', 'features{1}', 'FLOAT', 1, 4, 'VALUES', 5.1, 3.5, 1.4, 0.2) ensureSlaveSynced(con, env) if env.useSlaves: con2 = env.getSlaveConnection() - model_serialized_slave = con2.execute_command('AI.MODELGET', 'linear', 'META') + model_serialized_slave = con2.execute_command('AI.MODELGET', 'linear{1}', 'META') env.assertEqual(len(model_serialized_master), len(model_serialized_slave)) previous_duration = 0 for call in range(1, 10): - res = con.execute_command('AI.MODELRUN', 'linear', 'INPUTS', 'features', 'OUTPUTS', 'linear_out') + res = con.execute_command('AI.MODELRUN', 'linear{1}', 'INPUTS', 'features{1}', 'OUTPUTS', 'linear_out{1}') env.assertEqual(res, b'OK') ensureSlaveSynced(con, env) - info = con.execute_command('AI.INFO', 'linear') + info = con.execute_command('AI.INFO', 'linear{1}') info_dict_0 = info_to_dict(info) - env.assertEqual(info_dict_0['key'], 'linear') + env.assertEqual(info_dict_0['key'], 'linear{1}') env.assertEqual(info_dict_0['type'], 'MODEL') env.assertEqual(info_dict_0['backend'], 'ONNX') env.assertEqual(info_dict_0['device'], DEVICE) @@ -326,10 +326,10 @@ def test_onnx_modelinfo(env): previous_duration = info_dict_0['duration'] - res = con.execute_command('AI.INFO', 'linear', 'RESETSTAT') + res = con.execute_command('AI.INFO', 'linear{1}', 'RESETSTAT') env.assertEqual(res, b'OK') - info = con.execute_command('AI.INFO', 'linear') + info = con.execute_command('AI.INFO', 'linear{1}') info_dict_0 = info_to_dict(info) env.assertEqual(info_dict_0['duration'], 0) env.assertEqual(info_dict_0['samples'], 0) @@ -349,20 +349,20 @@ def test_onnx_modelrun_disconnect(env): with open(linear_model_filename, 'rb') as f: linear_model = f.read() - ret = con.execute_command('AI.MODELSET', 'linear', 'ONNX', DEVICE, 'BLOB', linear_model) + ret = con.execute_command('AI.MODELSET', 'linear{1}', 'ONNX', DEVICE, 'BLOB', linear_model) env.assertEqual(ret, b'OK') - model_serialized_master = con.execute_command('AI.MODELGET', 'linear', 'META') - con.execute_command('AI.TENSORSET', 'features', 'FLOAT', 1, 4, 'VALUES', 5.1, 3.5, 1.4, 0.2) + model_serialized_master = con.execute_command('AI.MODELGET', 'linear{1}', 'META') + con.execute_command('AI.TENSORSET', 'features{1}', 'FLOAT', 1, 4, 'VALUES', 5.1, 3.5, 1.4, 0.2) ensureSlaveSynced(con, env) if env.useSlaves: con2 = env.getSlaveConnection() - model_serialized_slave = con2.execute_command('AI.MODELGET', 'linear', 'META') + model_serialized_slave = con2.execute_command('AI.MODELGET', 'linear{1}', 'META') env.assertEqual(len(model_serialized_master), len(model_serialized_slave)) - ret = send_and_disconnect(('AI.MODELRUN', 'linear', 'INPUTS', 'features', 'OUTPUTS', 'linear_out'), con) + ret = send_and_disconnect(('AI.MODELRUN', 'linear{1}', 'INPUTS', 'features{1}', 'OUTPUTS', 'linear_out{1}'), con) env.assertEqual(ret, None) def test_onnx_model_rdb_save_load(env): @@ -378,10 +378,10 @@ def test_onnx_model_rdb_save_load(env): model_pb = f.read() con = env.getConnection() - ret = con.execute_command('AI.MODELSET', 'linear', 'ONNX', DEVICE, 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'linear{1}', 'ONNX', DEVICE, 'BLOB', model_pb) env.assertEqual(ret, b'OK') - model_serialized_memory = con.execute_command('AI.MODELGET', 'linear', 'BLOB') + model_serialized_memory = con.execute_command('AI.MODELGET', 'linear{1}', 'BLOB') ensureSlaveSynced(con, env) ret = con.execute_command('SAVE') @@ -390,7 +390,7 @@ def test_onnx_model_rdb_save_load(env): env.stop() env.start() con = env.getConnection() - model_serialized_after_rdbload = con.execute_command('AI.MODELGET', 'linear', 'BLOB') + model_serialized_after_rdbload = con.execute_command('AI.MODELGET', 'linear{1}', 'BLOB') env.assertEqual(len(model_serialized_memory), len(model_serialized_after_rdbload)) env.assertEqual(len(model_pb), len(model_serialized_after_rdbload)) # Assert in memory model binary is equal to loaded model binary diff --git a/test/tests_pytorch.py b/test/tests_pytorch.py index 44206dada..022c138f4 100644 --- a/test/tests_pytorch.py +++ b/test/tests_pytorch.py @@ -44,10 +44,10 @@ def test_pytorch_modelrun(env): model_filename = os.path.join(test_data_path, 'pt-minimal.pt') wrong_model_filename = os.path.join(test_data_path, 'graph.pb') - ret = con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') with open(model_filename, 'rb') as f: @@ -56,13 +56,13 @@ def test_pytorch_modelrun(env): with open(wrong_model_filename, 'rb') as f: wrong_model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TORCH', DEVICE, 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TORCH', DEVICE, 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.MODELGET', 'm', 'META') - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) # TODO: enable me. CI is having issues on GPU asserts of TORCH and CPU if DEVICE == "CPU": @@ -75,12 +75,12 @@ def test_pytorch_modelrun(env): env.assertEqual(len(ret[11]), 0) env.assertEqual(len(ret[13]), 0) - ret = con.execute_command('AI.MODELSET', 'm', 'TORCH', DEVICE, 'TAG', 'my:tag:v3', 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TORCH', DEVICE, 'TAG', 'my:tag:v3', 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) env.assertEqual(ret[5], b'my:tag:v3') # TODO: enable me. CI is having issues on GPU asserts of TORCH and CPU @@ -89,7 +89,7 @@ def test_pytorch_modelrun(env): env.assertEqual(ret[3], b'CPU') try: - con.execute_command('AI.MODELSET', 'm', 'TORCH', DEVICE, 'BLOB', wrong_model_pb) + con.execute_command('AI.MODELSET', 'm{1}', 'TORCH', DEVICE, 'BLOB', wrong_model_pb) except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -107,37 +107,37 @@ def test_pytorch_modelrun(env): env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.MODELRUN', 'm_1', 'INPUTS', 'a', 'b', 'OUTPUTS') + con.execute_command('AI.MODELRUN', 'm_1', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.MODELRUN', 'm_2', 'INPUTS', 'a', 'b', 'c') + con.execute_command('AI.MODELRUN', 'm_2', 'INPUTS', 'a{1}', 'b{1}', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.MODELRUN', 'm_3', 'a', 'b', 'c') + con.execute_command('AI.MODELRUN', 'm_3', 'a{1}', 'b{1}', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.MODELRUN', 'm_1', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm_1', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.MODELRUN', 'm', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -149,21 +149,21 @@ def test_pytorch_modelrun(env): env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.MODELRUN', 'm_1', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c', 'd') + con.execute_command('AI.MODELRUN', 'm_1', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}', 'd{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') ensureSlaveSynced(con, env) - values = con.execute_command('AI.TENSORGET', 'c', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') env.assertEqual(values, [b'4', b'6', b'4', b'6']) if env.useSlaves: con2 = env.getSlaveConnection() - values2 = con2.execute_command('AI.TENSORGET', 'c', 'VALUES') + values2 = con2.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') env.assertEqual(values2, values) @@ -176,15 +176,15 @@ def test_pytorch_modelrun_batchdim_mismatch(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TORCH', DEVICE, 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TORCH', DEVICE, 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 'VALUES', 1, 1) - con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 'VALUES', 1, 1) + con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 'VALUES', 1, 1) + con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 'VALUES', 1, 1) - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c', 'd') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}', 'd{1}') def test_pytorch_modelrun_autobatch(env): @@ -199,37 +199,82 @@ def test_pytorch_modelrun_autobatch(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TORCH', 'CPU', + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TORCH', 'CPU', 'BATCHSIZE', 4, 'MINBATCHSIZE', 3, 'BLOB', model_pb) env.assertEqual(ret, b'OK') - con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) - con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) - con.execute_command('AI.TENSORSET', 'd', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) - con.execute_command('AI.TENSORSET', 'e', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + con.execute_command('AI.TENSORSET', 'd{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + con.execute_command('AI.TENSORSET', 'e{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) ensureSlaveSynced(con, env) def run(): con = env.getConnection() - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'd', 'e', 'OUTPUTS', 'f') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'd{1}', 'e{1}', 'OUTPUTS', 'f{1}') ensureSlaveSynced(con, env) t = threading.Thread(target=run) t.start() - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') ensureSlaveSynced(con, env) - values = con.execute_command('AI.TENSORGET', 'c', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') env.assertEqual(values, [b'4', b'6', b'4', b'6']) - values = con.execute_command('AI.TENSORGET', 'f', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'f{1}', 'VALUES') env.assertEqual(values, [b'4', b'6', b'4', b'6']) +def test_pytorch_modelrun_autobatch_badbatch(env): + if not TEST_PT: + return + + con = env.getConnection() + + test_data_path = os.path.join(os.path.dirname(__file__), 'test_data') + model_filename = os.path.join(test_data_path, 'pt-minimal-bb.pt') + + with open(model_filename, 'rb') as f: + model_pb = f.read() + + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TORCH', 'CPU', + 'BATCHSIZE', 4, 'MINBATCHSIZE', 3, 'BLOB', model_pb) + env.assertEqual(ret, b'OK') + + con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + + con.execute_command('AI.TENSORSET', 'd{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + con.execute_command('AI.TENSORSET', 'e{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + + ensureSlaveSynced(con, env) + + def run(): + con = env.getConnection() + try: + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'd{1}', 'e{1}', 'OUTPUTS', 'f1{1}', 'f2{1}') + except Exception as e: + exception = e + env.assertEqual(type(exception), redis.exceptions.ResponseError) + env.assertEqual("Model did not generate the expected batch size", exception.__str__()) + + t = threading.Thread(target=run) + t.start() + + try: + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c1{1}', 'c2{1}') + except Exception as e: + exception = e + env.assertEqual(type(exception), redis.exceptions.ResponseError) + env.assertEqual("Model did not generate the expected batch size", exception.__str__()) + + + def test_pytorch_modelinfo(env): if not TEST_PT: env.debugPrint("skipping {} since TEST_PT=0".format(sys._getframe().f_code.co_name), force=True) @@ -239,31 +284,35 @@ def test_pytorch_modelinfo(env): test_data_path = os.path.join(os.path.dirname(__file__), 'test_data') model_filename = os.path.join(test_data_path, 'pt-minimal.pt') + model_key = 'm{1}' + tensor_a_key = 'a{1}' + tensor_b_key = 'b{1}' + tensor_c_key = 'c{1}' with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TORCH', DEVICE, 'TAG', 'asdf', 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', model_key, 'TORCH', DEVICE, 'TAG', 'asdf', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', tensor_a_key, 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', tensor_b_key, 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) previous_duration = 0 - for call in range(1, 10): - ret = con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') + for call in range(1, 100): + ret = con.execute_command('AI.MODELRUN', model_key, 'INPUTS', tensor_a_key, tensor_b_key, 'OUTPUTS', tensor_c_key) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - info = con.execute_command('AI.INFO', 'm') + info = con.execute_command('AI.INFO', model_key) info_dict_0 = info_to_dict(info) - env.assertEqual(info_dict_0['key'], 'm') + env.assertEqual(info_dict_0['key'], model_key) env.assertEqual(info_dict_0['type'], 'MODEL') env.assertEqual(info_dict_0['backend'], 'TORCH') env.assertEqual(info_dict_0['device'], DEVICE) @@ -275,9 +324,9 @@ def test_pytorch_modelinfo(env): previous_duration = info_dict_0['duration'] - res = con.execute_command('AI.INFO', 'm', 'RESETSTAT') + res = con.execute_command('AI.INFO', model_key, 'RESETSTAT') env.assertEqual(res, b'OK') - info = con.execute_command('AI.INFO', 'm') + info = con.execute_command('AI.INFO', model_key) info_dict_0 = info_to_dict(info) env.assertEqual(info_dict_0['duration'], 0) env.assertEqual(info_dict_0['samples'], 0) @@ -293,7 +342,7 @@ def test_pytorch_scriptset(env): con = env.getConnection() try: - con.execute_command('AI.SCRIPTSET', 'ket', DEVICE, 'SOURCE', 'return 1') + con.execute_command('AI.SCRIPTSET', 'ket{1}', DEVICE, 'SOURCE', 'return 1') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -322,7 +371,7 @@ def test_pytorch_scriptset(env): with open(script_filename, 'rb') as f: script = f.read() - ret = con.execute_command('AI.SCRIPTSET', 'ket', DEVICE, 'SOURCE', script) + ret = con.execute_command('AI.SCRIPTSET', 'ket{1}', DEVICE, 'SOURCE', script) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) @@ -330,20 +379,11 @@ def test_pytorch_scriptset(env): with open(script_filename, 'rb') as f: script = f.read() - ret = con.execute_command('AI.SCRIPTSET', 'ket', DEVICE, 'TAG', 'asdf', 'SOURCE', script) + ret = con.execute_command('AI.SCRIPTSET', 'ket{1}', DEVICE, 'TAG', 'asdf', 'SOURCE', script) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - # TODO: Check why this COMMAND is hanging CI - # ret = con.execute_command('AI.SCRIPTGET', 'ket') - # env.assertEqual([b'CPU',script],ret) - # - # if env.useSlaves: - # con2 = env.getSlaveConnection() - # script_slave = con2.execute_command('AI.SCRIPTGET', 'ket') - # env.assertEqual(ret, script_slave) - def test_pytorch_scriptdel(env): if not TEST_PT: @@ -358,21 +398,21 @@ def test_pytorch_scriptdel(env): with open(script_filename, 'rb') as f: script = f.read() - ret = con.execute_command('AI.SCRIPTSET', 'ket', DEVICE, 'SOURCE', script) + ret = con.execute_command('AI.SCRIPTSET', 'ket{1}', DEVICE, 'SOURCE', script) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.SCRIPTDEL', 'ket') + ret = con.execute_command('AI.SCRIPTDEL', 'ket{1}') env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - env.assertFalse(con.execute_command('EXISTS', 'ket')) + env.assertFalse(con.execute_command('EXISTS', 'ket{1}')) if env.useSlaves: con2 = env.getSlaveConnection() - env.assertFalse(con2.execute_command('EXISTS', 'ket')) + env.assertFalse(con2.execute_command('EXISTS', 'ket{1}')) # ERR no script at key from SCRIPTDEL try: @@ -406,12 +446,66 @@ def test_pytorch_scriptrun(env): with open(script_filename, 'rb') as f: script = f.read() - ret = con.execute_command('AI.SCRIPTSET', 'ket', DEVICE, 'TAG', 'asdf', 'SOURCE', script) + ret = con.execute_command('AI.SCRIPTSET', 'myscript{1}', DEVICE, 'TAG', 'version1', 'SOURCE', script) + env.assertEqual(ret, b'OK') + + ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + env.assertEqual(ret, b'OK') + ret = con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + env.assertEqual(ret, b'OK') + + ensureSlaveSynced(con, env) + + for _ in range( 0,100): + + ret = con.execute_command('AI.SCRIPTRUN', 'myscript{1}', 'bar', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') + env.assertEqual(ret, b'OK') + + + ensureSlaveSynced(con, env) + + info = con.execute_command('AI.INFO', 'myscript{1}') + info_dict_0 = info_to_dict(info) + + env.assertEqual(info_dict_0['key'], 'myscript{1}') + env.assertEqual(info_dict_0['type'], 'SCRIPT') + env.assertEqual(info_dict_0['backend'], 'TORCH') + env.assertEqual(info_dict_0['tag'], 'version1') + env.assertTrue(info_dict_0['duration'] > 0) + env.assertEqual(info_dict_0['samples'], -1) + env.assertEqual(info_dict_0['calls'], 100) + env.assertEqual(info_dict_0['errors'], 0) + + values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') + env.assertEqual(values, [b'4', b'6', b'4', b'6']) + + ensureSlaveSynced(con, env) + + if env.useSlaves: + con2 = env.getSlaveConnection() + values2 = con2.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') + env.assertEqual(values2, values) + + +def test_pytorch_scriptrun_errors(env): + if not TEST_PT: + env.debugPrint("skipping {} since TEST_PT=0".format(sys._getframe().f_code.co_name), force=True) + return + + con = env.getConnection() + + test_data_path = os.path.join(os.path.dirname(__file__), 'test_data') + script_filename = os.path.join(test_data_path, 'script.txt') + + with open(script_filename, 'rb') as f: + script = f.read() + + ret = con.execute_command('AI.SCRIPTSET', 'ket{1}', DEVICE, 'TAG', 'asdf', 'SOURCE', script) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) @@ -427,8 +521,8 @@ def test_pytorch_scriptrun(env): # ERR no script at key from SCRIPTGET try: - con.execute_command('DEL', 'EMPTY') - con.execute_command('AI.SCRIPTGET', 'EMPTY') + con.execute_command('DEL', 'EMPTY{1}') + con.execute_command('AI.SCRIPTGET', 'EMPTY{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -436,8 +530,8 @@ def test_pytorch_scriptrun(env): # ERR wrong type from SCRIPTGET try: - con.execute_command('SET', 'NOT_SCRIPT', 'BAR') - con.execute_command('AI.SCRIPTGET', 'NOT_SCRIPT') + con.execute_command('SET', 'NOT_SCRIPT{1}', 'BAR') + con.execute_command('AI.SCRIPTGET', 'NOT_SCRIPT{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -445,8 +539,8 @@ def test_pytorch_scriptrun(env): # ERR no script at key from SCRIPTRUN try: - con.execute_command('DEL', 'EMPTY') - con.execute_command('AI.SCRIPTRUN', 'EMPTY', 'bar', 'INPUTS', 'b', 'OUTPUTS', 'c') + con.execute_command('DEL', 'EMPTY{1}') + con.execute_command('AI.SCRIPTRUN', 'EMPTY{1}', 'bar', 'INPUTS', 'b{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -454,8 +548,8 @@ def test_pytorch_scriptrun(env): # ERR wrong type from SCRIPTRUN try: - con.execute_command('SET', 'NOT_SCRIPT', 'BAR') - con.execute_command('AI.SCRIPTRUN', 'NOT_SCRIPT', 'bar', 'INPUTS', 'b', 'OUTPUTS', 'c') + con.execute_command('SET', 'NOT_SCRIPT{1}', 'BAR') + con.execute_command('AI.SCRIPTRUN', 'NOT_SCRIPT{1}', 'bar', 'INPUTS', 'b{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -463,8 +557,8 @@ def test_pytorch_scriptrun(env): # ERR Input key is empty try: - con.execute_command('DEL', 'EMPTY') - con.execute_command('AI.SCRIPTRUN', 'ket', 'bar', 'INPUTS', 'EMPTY', 'b', 'OUTPUTS', 'c') + con.execute_command('DEL', 'EMPTY{1}') + con.execute_command('AI.SCRIPTRUN', 'ket{1}', 'bar', 'INPUTS', 'EMPTY{1}', 'b{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -472,61 +566,61 @@ def test_pytorch_scriptrun(env): # ERR Input key not tensor try: - con.execute_command('SET', 'NOT_TENSOR', 'BAR') - con.execute_command('AI.SCRIPTRUN', 'ket', 'bar', 'INPUTS', 'NOT_TENSOR', 'b', 'OUTPUTS', 'c') + con.execute_command('SET', 'NOT_TENSOR{1}', 'BAR') + con.execute_command('AI.SCRIPTRUN', 'ket{1}', 'bar', 'INPUTS', 'NOT_TENSOR{1}', 'b{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("WRONGTYPE Operation against a key holding the wrong kind of value", exception.__str__()) try: - con.execute_command('AI.SCRIPTRUN', 'ket', 'bar', 'INPUTS', 'b', 'OUTPUTS', 'c') + con.execute_command('AI.SCRIPTRUN', 'ket{1}', 'bar', 'INPUTS', 'b{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.SCRIPTRUN', 'ket', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') + con.execute_command('AI.SCRIPTRUN', 'ket{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.SCRIPTRUN', 'ket', 'bar', 'INPUTS', 'b', 'OUTPUTS') + con.execute_command('AI.SCRIPTRUN', 'ket{1}', 'bar', 'INPUTS', 'b{1}', 'OUTPUTS') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.SCRIPTRUN', 'ket', 'bar', 'INPUTS', 'OUTPUTS') + con.execute_command('AI.SCRIPTRUN', 'ket{1}', 'bar', 'INPUTS', 'OUTPUTS') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) - con.execute_command('AI.SCRIPTRUN', 'ket', 'bar', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') + con.execute_command('AI.SCRIPTRUN', 'ket{1}', 'bar', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') ensureSlaveSynced(con, env) - info = con.execute_command('AI.INFO', 'ket') + info = con.execute_command('AI.INFO', 'ket{1}') info_dict_0 = info_to_dict(info) - env.assertEqual(info_dict_0['key'], 'ket') + env.assertEqual(info_dict_0['key'], 'ket{1}') env.assertEqual(info_dict_0['type'], 'SCRIPT') env.assertEqual(info_dict_0['backend'], 'TORCH') env.assertEqual(info_dict_0['tag'], 'asdf') env.assertTrue(info_dict_0['duration'] > 0) env.assertEqual(info_dict_0['samples'], -1) - env.assertEqual(info_dict_0['calls'], 4) - env.assertEqual(info_dict_0['errors'], 3) + env.assertEqual(info_dict_0['calls'], 3) + env.assertEqual(info_dict_0['errors'], 2) - values = con.execute_command('AI.TENSORGET', 'c', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') env.assertEqual(values, [b'4', b'6', b'4', b'6']) ensureSlaveSynced(con, env) if env.useSlaves: con2 = env.getSlaveConnection() - values2 = con2.execute_command('AI.TENSORGET', 'c', 'VALUES') + values2 = con2.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') env.assertEqual(values2, values) @@ -546,26 +640,26 @@ def test_pytorch_scriptinfo(env): with open(script_filename, 'rb') as f: script = f.read() - ret = con.execute_command('AI.SCRIPTSET', 'ket_script', DEVICE, 'SOURCE', script) + ret = con.execute_command('AI.SCRIPTSET', 'ket_script{1}', DEVICE, 'SOURCE', script) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) previous_duration = 0 - for call in range(1, 10): - ret = con.execute_command('AI.SCRIPTRUN', 'ket_script', 'bar', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') + for call in range(1, 100): + ret = con.execute_command('AI.SCRIPTRUN', 'ket_script{1}', 'bar', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - info = con.execute_command('AI.INFO', 'ket_script') + info = con.execute_command('AI.INFO', 'ket_script{1}') info_dict_0 = info_to_dict(info) - env.assertEqual(info_dict_0['key'], 'ket_script') + env.assertEqual(info_dict_0['key'], 'ket_script{1}') env.assertEqual(info_dict_0['type'], 'SCRIPT') env.assertEqual(info_dict_0['backend'], 'TORCH') env.assertEqual(info_dict_0['device'], DEVICE) @@ -576,9 +670,9 @@ def test_pytorch_scriptinfo(env): previous_duration = info_dict_0['duration'] - res = con.execute_command('AI.INFO', 'ket_script', 'RESETSTAT') + res = con.execute_command('AI.INFO', 'ket_script{1}', 'RESETSTAT') env.assertEqual(res, b'OK') - info = con.execute_command('AI.INFO', 'ket_script') + info = con.execute_command('AI.INFO', 'ket_script{1}') info_dict_0 = info_to_dict(info) env.assertEqual(info_dict_0['duration'], 0) env.assertEqual(info_dict_0['samples'], -1) @@ -603,17 +697,17 @@ def test_pytorch_scriptrun_disconnect(env): with open(script_filename, 'rb') as f: script = f.read() - ret = con.execute_command('AI.SCRIPTSET', 'ket_script', DEVICE, 'SOURCE', script) + ret = con.execute_command('AI.SCRIPTSET', 'ket_script{1}', DEVICE, 'SOURCE', script) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = send_and_disconnect(('AI.SCRIPTRUN', 'ket_script', 'bar', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c'), con) + ret = send_and_disconnect(('AI.SCRIPTRUN', 'ket_script{1}', 'bar', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}'), con) env.assertEqual(ret, None) @@ -634,18 +728,18 @@ def test_pytorch_modelrun_disconnect(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TORCH', DEVICE, 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TORCH', DEVICE, 'BLOB', model_pb) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + ret = con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = send_and_disconnect(('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c'), con) + ret = send_and_disconnect(('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}'), con) env.assertEqual(ret, None) @@ -711,15 +805,15 @@ def test_pytorch_model_rdb_save_load(env): con = env.getConnection() - ret = con.execute_command('AI.MODELSET', 'm', 'TORCH', DEVICE, 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TORCH', DEVICE, 'BLOB', model_pb) env.assertEqual(ret, b'OK') - model_serialized_memory = con.execute_command('AI.MODELGET', 'm', 'BLOB') + model_serialized_memory = con.execute_command('AI.MODELGET', 'm{1}', 'BLOB') - con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) - con.execute_command('AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') - _, dtype_memory, _, shape_memory, _, data_memory = con.execute_command('AI.TENSORGET', 'c', 'META', 'VALUES') + con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') + _, dtype_memory, _, shape_memory, _, data_memory = con.execute_command('AI.TENSORGET', 'c{1}', 'META', 'VALUES') ensureSlaveSynced(con, env) ret = con.execute_command('SAVE') @@ -728,9 +822,9 @@ def test_pytorch_model_rdb_save_load(env): env.stop() env.start() con = env.getConnection() - model_serialized_after_rdbload = con.execute_command('AI.MODELGET', 'm', 'BLOB') - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') - _, dtype_after_rdbload, _, shape_after_rdbload, _, data_after_rdbload = con.execute_command('AI.TENSORGET', 'c', 'META', 'VALUES') + model_serialized_after_rdbload = con.execute_command('AI.MODELGET', 'm{1}', 'BLOB') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') + _, dtype_after_rdbload, _, shape_after_rdbload, _, data_after_rdbload = con.execute_command('AI.TENSORGET', 'c{1}', 'META', 'VALUES') # Assert in memory model metadata is equal to loaded model metadata env.assertTrue(model_serialized_memory[1:6] == model_serialized_after_rdbload[1:6]) diff --git a/test/tests_sanitizer.py b/test/tests_sanitizer.py index 4f0c45ca4..71ad4c795 100644 --- a/test/tests_sanitizer.py +++ b/test/tests_sanitizer.py @@ -17,7 +17,7 @@ def test_sanitizer_dagrun_mobilenet_v1(env): print("exiting sanitizer test given we're not using stdlib allocator") return - model_name = 'mobilenet_v1' + model_name = 'mobilenet_v1{s}' model_pb, input_var, output_var, labels, img = load_mobilenet_v1_test_data() ret = con.execute_command('AI.MODELSET', model_name, 'TF', DEVICE, @@ -27,8 +27,8 @@ def test_sanitizer_dagrun_mobilenet_v1(env): env.assertEqual(ret, b'OK') for opnumber in range(1, MAX_ITERATIONS): - image_key = 'image{}'.format(opnumber) - class_key = 'output' + image_key = 'image{{s}}{}'.format(opnumber) + class_key = 'output{s}' ret = con.execute_command( 'AI.DAGRUN', '|>', @@ -53,7 +53,7 @@ def test_sanitizer_modelrun_mobilenet_v1(env): print("exiting sanitizer test given we're not using stdlib allocator") return - model_name = 'mobilenet_v1' + model_name = 'mobilenet_v1{s}' model_pb, input_var, output_var, labels, img = load_mobilenet_v1_test_data() ret = con.execute_command('AI.MODELSET', model_name, 'TF', DEVICE, @@ -63,10 +63,10 @@ def test_sanitizer_modelrun_mobilenet_v1(env): env.assertEqual(ret, b'OK') for opnumber in range(1, MAX_ITERATIONS): - image_key = 'image' - temp_key1 = 'temp_key1' - temp_key2 = 'temp_key2' - class_key = 'output' + image_key = 'image{s}' + temp_key1 = 'temp_key1{s}' + temp_key2 = 'temp_key2{s}' + class_key = 'output{s}' ret = con.execute_command( 'AI.TENSORSET', image_key, 'FLOAT', 1, 224, 224, 3, 'BLOB', img.tobytes() ) diff --git a/test/tests_tensorflow.py b/test/tests_tensorflow.py index b494b1f07..2564c53cb 100644 --- a/test/tests_tensorflow.py +++ b/test/tests_tensorflow.py @@ -26,28 +26,28 @@ def test_run_mobilenet(env): model_pb, input_var, output_var, labels, img = load_mobilenet_v2_test_data() - con.execute_command('AI.MODELSET', 'mobilenet', 'TF', DEVICE, + con.execute_command('AI.MODELSET', 'mobilenet{1}', 'TF', DEVICE, 'INPUTS', input_var, 'OUTPUTS', output_var, 'BLOB', model_pb) ensureSlaveSynced(con, env) mobilenet_model_serialized = con.execute_command( - 'AI.MODELGET', 'mobilenet', 'META') + 'AI.MODELGET', 'mobilenet{1}', 'META') ensureSlaveSynced(con, env) if env.useSlaves: con2 = env.getSlaveConnection() slave_mobilenet_model_serialized = con2.execute_command( - 'AI.MODELGET', 'mobilenet', 'META') + 'AI.MODELGET', 'mobilenet{1}', 'META') env.assertEqual(len(mobilenet_model_serialized), len(slave_mobilenet_model_serialized)) - con.execute_command('AI.TENSORSET', 'input', + con.execute_command('AI.TENSORSET', 'input{1}', 'FLOAT', 1, img.shape[1], img.shape[0], img.shape[2], 'BLOB', img.tobytes()) ensureSlaveSynced(con, env) - input_tensor_meta = con.execute_command('AI.TENSORGET', 'input', 'META') + input_tensor_meta = con.execute_command('AI.TENSORGET', 'input{1}', 'META') env.assertEqual( [b'dtype', b'FLOAT', b'shape', [1, img.shape[1], img.shape[0], img.shape[2]]], input_tensor_meta) @@ -55,15 +55,15 @@ def test_run_mobilenet(env): if env.useSlaves: con2 = env.getSlaveConnection() slave_tensor_meta = con2.execute_command( - 'AI.TENSORGET', 'input', 'META') + 'AI.TENSORGET', 'input{1}', 'META') env.assertEqual(input_tensor_meta, slave_tensor_meta) - con.execute_command('AI.MODELRUN', 'mobilenet', - 'INPUTS', 'input', 'OUTPUTS', 'output') + con.execute_command('AI.MODELRUN', 'mobilenet{1}', + 'INPUTS', 'input{1}', 'OUTPUTS', 'output{1}') ensureSlaveSynced(con, env) - _, dtype, _, shape, _, data = con.execute_command('AI.TENSORGET', 'output', 'META', 'BLOB') + _, dtype, _, shape, _, data = con.execute_command('AI.TENSORGET', 'output{1}', 'META', 'BLOB') dtype_map = {b'FLOAT': np.float32} tensor = np.frombuffer(data, dtype=dtype_map[dtype]).reshape(shape) @@ -76,7 +76,7 @@ def test_run_mobilenet(env): if env.useSlaves: con2 = env.getSlaveConnection() _, slave_dtype, _, slave_shape, _, slave_data = con2.execute_command( - 'AI.TENSORGET', 'output', 'META', 'BLOB') + 'AI.TENSORGET', 'output{1}', 'META', 'BLOB') env.assertEqual(dtype, slave_dtype) env.assertEqual(shape, slave_shape) env.assertEqual(data, slave_data) @@ -92,7 +92,7 @@ def test_run_mobilenet_multiproc(env): con = env.getConnection() model_pb, input_var, output_var, labels, img = load_mobilenet_v2_test_data() - con.execute_command('AI.MODELSET', 'mobilenet', 'TF', DEVICE, + con.execute_command('AI.MODELSET', 'mobilenet{1}', 'TF', DEVICE, 'INPUTS', input_var, 'OUTPUTS', output_var, 'BLOB', model_pb) ensureSlaveSynced(con, env) @@ -100,7 +100,7 @@ def test_run_mobilenet_multiproc(env): ensureSlaveSynced(con, env) - _, dtype, _, shape, _, data = con.execute_command('AI.TENSORGET', 'output', 'META', 'BLOB') + _, dtype, _, shape, _, data = con.execute_command('AI.TENSORGET', 'output{1}', 'META', 'BLOB') dtype_map = {b'FLOAT': np.float32} tensor = np.frombuffer(data, dtype=dtype_map[dtype]).reshape(shape) @@ -115,7 +115,7 @@ def test_run_mobilenet_multiproc(env): if env.useSlaves: con2 = env.getSlaveConnection() _, slave_dtype, _, slave_shape, _, slave_data = con2.execute_command( - 'AI.TENSORGET', 'output', 'META', 'BLOB') + 'AI.TENSORGET', 'output{1}', 'META', 'BLOB') env.assertEqual(dtype, slave_dtype) env.assertEqual(shape, slave_shape) env.assertEqual(data, slave_data) @@ -131,23 +131,23 @@ def test_del_tf_model(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - con.execute_command('AI.MODELDEL', 'm') - env.assertFalse(con.execute_command('EXISTS', 'm')) + con.execute_command('AI.MODELDEL', 'm{1}') + env.assertFalse(con.execute_command('EXISTS', 'm{1}')) ensureSlaveSynced(con, env) if env.useSlaves: con2 = env.getSlaveConnection() - env.assertFalse(con2.execute_command('EXISTS', 'm')) + env.assertFalse(con2.execute_command('EXISTS', 'm{1}')) # ERR no model at key try: - con.execute_command('AI.MODELDEL', 'm') + con.execute_command('AI.MODELDEL', 'm{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -155,8 +155,8 @@ def test_del_tf_model(env): # ERR wrong type try: - con.execute_command('SET', 'NOT_MODEL', 'BAR') - con.execute_command('AI.MODELDEL', 'NOT_MODEL') + con.execute_command('SET', 'NOT_MODEL{1}', 'BAR') + con.execute_command('AI.MODELDEL', 'NOT_MODEL{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -174,26 +174,26 @@ def test_run_tf_model(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) env.assertEqual(ret[5], b'') env.assertEqual(ret[11][0], b'a') env.assertEqual(ret[11][1], b'b') env.assertEqual(ret[13][0], b'mul') - ret = con.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, 'TAG', 'version:1', + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'TAG', 'version:1', 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) # TODO: enable me. CI is having issues on GPU asserts of TF and CPU if DEVICE == "CPU": @@ -204,40 +204,40 @@ def test_run_tf_model(env): env.assertEqual(ret[11][1], b'b') env.assertEqual(ret[13][0], b'mul') - con.execute_command('AI.TENSORSET', 'a', 'FLOAT', + con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) - con.execute_command('AI.TENSORSET', 'b', 'FLOAT', + con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) ensureSlaveSynced(con, env) - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') ensureSlaveSynced(con, env) - values = con.execute_command('AI.TENSORGET', 'c', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') env.assertEqual(values, [b'4', b'9', b'4', b'9']) if env.useSlaves: con2 = env.getSlaveConnection() - values2 = con2.execute_command('AI.TENSORGET', 'c', 'VALUES') + values2 = con2.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') env.assertEqual(values2, values) for _ in env.reloadingIterator(): - env.assertExists('m') - env.assertExists('a') - env.assertExists('b') - env.assertExists('c') + env.assertExists('m{1}') + env.assertExists('a{1}') + env.assertExists('b{1}') + env.assertExists('c{1}') - con.execute_command('AI.MODELDEL', 'm') + con.execute_command('AI.MODELDEL', 'm{1}') ensureSlaveSynced(con, env) - env.assertFalse(con.execute_command('EXISTS', 'm')) + env.assertFalse(con.execute_command('EXISTS', 'm{1}')) ensureSlaveSynced(con, env) if env.useSlaves: con2 = env.getSlaveConnection() - env.assertFalse(con2.execute_command('EXISTS', 'm')) + env.assertFalse(con2.execute_command('EXISTS', 'm{1}')) @skip_if_no_TF @@ -250,25 +250,25 @@ def test_run_tf2_model(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'INPUTS', 'x', 'OUTPUTS', 'Identity', 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) env.assertEqual(ret[5], b'') env.assertEqual(ret[11][0], b'x') env.assertEqual(ret[13][0], b'Identity') - ret = con.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, 'TAG', 'asdf', + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'TAG', 'asdf', 'INPUTS', 'x', 'OUTPUTS', 'Identity', 'BLOB', model_pb) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) env.assertEqual(ret[5], b'asdf') env.assertEqual(ret[11][0], b'x') @@ -276,38 +276,38 @@ def test_run_tf2_model(env): zero_values = [0] * (28 * 28) - con.execute_command('AI.TENSORSET', 'x', 'FLOAT', + con.execute_command('AI.TENSORSET', 'x{1}', 'FLOAT', 1, 1, 28, 28, 'VALUES', *zero_values) ensureSlaveSynced(con, env) - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'x', 'OUTPUTS', 'y') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'x{1}', 'OUTPUTS', 'y{1}') ensureSlaveSynced(con, env) - values = con.execute_command('AI.TENSORGET', 'y', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'y{1}', 'VALUES') for value in values: env.assertAlmostEqual(float(value), 0.1, 1E-4) if env.useSlaves: con2 = env.getSlaveConnection() - values2 = con2.execute_command('AI.TENSORGET', 'y', 'VALUES') + values2 = con2.execute_command('AI.TENSORGET', 'y{1}', 'VALUES') env.assertEqual(values2, values) for _ in env.reloadingIterator(): - env.assertExists('m') - env.assertExists('x') - env.assertExists('y') + env.assertExists('m{1}') + env.assertExists('x{1}') + env.assertExists('y{1}') - con.execute_command('AI.MODELDEL', 'm') + con.execute_command('AI.MODELDEL', 'm{1}') ensureSlaveSynced(con, env) - env.assertFalse(con.execute_command('EXISTS', 'm')) + env.assertFalse(con.execute_command('EXISTS', 'm{1}')) ensureSlaveSynced(con, env) if env.useSlaves: con2 = env.getSlaveConnection() - env.assertFalse(con2.execute_command('EXISTS', 'm')) + env.assertFalse(con2.execute_command('EXISTS', 'm{1}')) @skip_if_no_TF @@ -324,7 +324,7 @@ def test_run_tf_model_errors(env): with open(wrong_model_filename, 'rb') as f: wrong_model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) env.assertEqual(ret, b'OK') @@ -339,28 +339,28 @@ def test_run_tf_model_errors(env): "wrong number of arguments for 'AI.MODELGET' command", exception.__str__()) # ERR WRONGTYPE - con.execute_command('SET', 'NOT_MODEL', 'BAR') + con.execute_command('SET', 'NOT_MODEL{1}', 'BAR') try: - con.execute_command('AI.MODELGET', 'NOT_MODEL') + con.execute_command('AI.MODELGET', 'NOT_MODEL{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual( "WRONGTYPE Operation against a key holding the wrong kind of value", exception.__str__()) # cleanup - con.execute_command('DEL', 'NOT_MODEL') + con.execute_command('DEL', 'NOT_MODEL{1}') # ERR model key is empty - con.execute_command('DEL', 'DONT_EXIST') + con.execute_command('DEL', 'DONT_EXIST{1}') try: - con.execute_command('AI.MODELGET', 'DONT_EXIST') + con.execute_command('AI.MODELGET', 'DONT_EXIST{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("model key is empty", exception.__str__()) try: - ret = con.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', wrong_model_pb) except Exception as e: exception = e @@ -368,7 +368,7 @@ def test_run_tf_model_errors(env): env.assertEqual("Invalid GraphDef", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_1', 'TF', + con.execute_command('AI.MODELSET', 'm_1{1}', 'TF', 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) except Exception as e: exception = e @@ -376,7 +376,7 @@ def test_run_tf_model_errors(env): env.assertEqual("Invalid DEVICE", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_2', 'PORCH', DEVICE, + con.execute_command('AI.MODELSET', 'm_2{1}', 'PORCH', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) except Exception as e: exception = e @@ -384,14 +384,14 @@ def test_run_tf_model_errors(env): env.assertEqual("unsupported backend", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_3', 'TORCH', DEVICE, + con.execute_command('AI.MODELSET', 'm_3{1}', 'TORCH', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) try: - con.execute_command('AI.MODELSET', 'm_4', 'TF', + con.execute_command('AI.MODELSET', 'm_4{1}', 'TF', 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) except Exception as e: exception = e @@ -399,7 +399,7 @@ def test_run_tf_model_errors(env): env.assertEqual("Invalid DEVICE", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_5', 'TF', DEVICE, + con.execute_command('AI.MODELSET', 'm_5{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'c', 'OUTPUTS', 'mul', 'BLOB', model_pb) except Exception as e: exception = e @@ -407,7 +407,7 @@ def test_run_tf_model_errors(env): env.assertEqual("WRONGTYPE Operation against a key holding the wrong kind of value", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_6', 'TF', DEVICE, + con.execute_command('AI.MODELSET', 'm_6{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mult', 'BLOB', model_pb) except Exception as e: exception = e @@ -415,14 +415,14 @@ def test_run_tf_model_errors(env): env.assertEqual("Output node named \"mult\" not found in TF graph", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_7', 'TF', DEVICE, 'BLOB', model_pb) + con.execute_command('AI.MODELSET', 'm_7{1}', 'TF', DEVICE, 'BLOB', model_pb) except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("Insufficient arguments, INPUTS and OUTPUTS not specified", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_8', 'TF', DEVICE, + con.execute_command('AI.MODELSET', 'm_8{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul') except Exception as e: exception = e @@ -430,7 +430,7 @@ def test_run_tf_model_errors(env): env.assertEqual("Insufficient arguments, missing model BLOB", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_8', 'TF', DEVICE, + con.execute_command('AI.MODELSET', 'm_8{1}', 'TF', DEVICE, 'INPUTS', 'a_', 'b', 'OUTPUTS', 'mul') except Exception as e: exception = e @@ -438,15 +438,15 @@ def test_run_tf_model_errors(env): env.assertEqual("Insufficient arguments, missing model BLOB", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_8', 'TF', DEVICE, - 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul_') + con.execute_command('AI.MODELSET', 'm_8{1}', 'TF', DEVICE, + 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'mul_') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("Insufficient arguments, missing model BLOB", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_8', 'TF', DEVICE, + con.execute_command('AI.MODELSET', 'm_8{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS') except Exception as e: exception = e @@ -454,14 +454,14 @@ def test_run_tf_model_errors(env): env.assertEqual("Insufficient arguments, missing model BLOB",exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("tensor key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -481,40 +481,40 @@ def test_run_tf_model_autobatch(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TF', 'CPU', + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', 'CPU', 'BATCHSIZE', 4, 'MINBATCHSIZE', 3, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - con.execute_command('AI.TENSORSET', 'a', 'FLOAT', + con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) - con.execute_command('AI.TENSORSET', 'b', 'FLOAT', + con.execute_command('AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) - con.execute_command('AI.TENSORSET', 'd', 'FLOAT', + con.execute_command('AI.TENSORSET', 'd{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) - con.execute_command('AI.TENSORSET', 'e', 'FLOAT', + con.execute_command('AI.TENSORSET', 'e{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) ensureSlaveSynced(con, env) def run(): con = env.getConnection() - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', - 'd', 'e', 'OUTPUTS', 'f') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', + 'd{1}', 'e{1}', 'OUTPUTS', 'f{1}') ensureSlaveSynced(con, env) t = threading.Thread(target=run) t.start() - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') ensureSlaveSynced(con, env) - values = con.execute_command('AI.TENSORGET', 'c', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'c{1}', 'VALUES') env.assertEqual(values, [b'4', b'9', b'4', b'9']) - values = con.execute_command('AI.TENSORGET', 'f', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'f{1}', 'VALUES') env.assertEqual(values, [b'4', b'9', b'4', b'9']) @@ -527,29 +527,29 @@ def test_tensorflow_modelinfo(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - info = con.execute_command('AI.INFO', 'm') # Getting initial info before modelrun + info = con.execute_command('AI.INFO', 'm{1}') # Getting initial info before modelrun info_dict0 = info_to_dict(info) - expected = {'key': 'm', 'type': 'MODEL', 'backend': 'TF', 'device': DEVICE, + expected = {'key': 'm{1}', 'type': 'MODEL', 'backend': 'TF', 'device': DEVICE, 'tag': '', 'duration': 0, 'samples': 0, 'calls': 0, 'errors': 0} env.assertEqual(info_dict0, expected) # second modelset; a corner case - ret = con.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - info = con.execute_command('AI.INFO', 'm') # this will fail + info = con.execute_command('AI.INFO', 'm{1}') # this will fail info_dict1 = info_to_dict(info) env.assertEqual(info_dict1, info_dict0) ret = con.execute_command( - 'AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + 'AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') ret = con.execute_command( - 'AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + 'AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) @@ -557,14 +557,14 @@ def test_tensorflow_modelinfo(env): previous_duration = 0 for call in range(1, 10): ret = con.execute_command( - 'AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c') + 'AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}') env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - info = con.execute_command('AI.INFO', 'm') + info = con.execute_command('AI.INFO', 'm{1}') info_dict_0 = info_to_dict(info) - env.assertEqual(info_dict_0['key'], 'm') + env.assertEqual(info_dict_0['key'], 'm{1}') env.assertEqual(info_dict_0['type'], 'MODEL') env.assertEqual(info_dict_0['backend'], 'TF') env.assertEqual(info_dict_0['device'], DEVICE) @@ -575,9 +575,9 @@ def test_tensorflow_modelinfo(env): previous_duration = info_dict_0['duration'] - res = con.execute_command('AI.INFO', 'm', 'RESETSTAT') + res = con.execute_command('AI.INFO', 'm{1}', 'RESETSTAT') env.assertEqual(res, b'OK') - info = con.execute_command('AI.INFO', 'm') + info = con.execute_command('AI.INFO', 'm{1}') info_dict_0 = info_to_dict(info) env.assertEqual(info_dict_0['duration'], 0) env.assertEqual(info_dict_0['samples'], 0) @@ -595,22 +595,22 @@ def test_tensorflow_modelrun_disconnect(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = red.execute_command('AI.MODELSET', 'm', 'TF', DEVICE, + ret = red.execute_command('AI.MODELSET', 'm{1}', 'TF', DEVICE, 'INPUTS', 'a', 'b', 'OUTPUTS', 'mul', 'BLOB', model_pb) env.assertEqual(ret, b'OK') ret = red.execute_command( - 'AI.TENSORSET', 'a', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + 'AI.TENSORSET', 'a{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') ret = red.execute_command( - 'AI.TENSORSET', 'b', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) + 'AI.TENSORSET', 'b{1}', 'FLOAT', 2, 2, 'VALUES', 2, 3, 2, 3) env.assertEqual(ret, b'OK') ensureSlaveSynced(red, env) ret = send_and_disconnect( - ('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b', 'OUTPUTS', 'c'), red) + ('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}', 'OUTPUTS', 'c{1}'), red) env.assertEqual(ret, None) @@ -619,8 +619,8 @@ def test_tensorflow_modelrun_with_batch_and_minbatch(env): con = env.getConnection() batch_size = 2 minbatch_size = 2 - model_name = 'model' - another_model_name = 'another_model' + model_name = 'model{1}' + another_model_name = 'another_model{1}' model_pb, input_var, output_var, labels, img = load_mobilenet_v2_test_data() con.execute_command('AI.MODELSET', model_name, 'TF', DEVICE, @@ -628,14 +628,14 @@ def test_tensorflow_modelrun_with_batch_and_minbatch(env): 'INPUTS', input_var, 'OUTPUTS', output_var, 'BLOB', model_pb) - con.execute_command('AI.TENSORSET', 'input', + con.execute_command('AI.TENSORSET', 'input{1}', 'FLOAT', 1, img.shape[1], img.shape[0], img.shape[2], 'BLOB', img.tobytes()) - def run(name=model_name, output_name='output'): + def run(name=model_name, output_name='output{1}'): con = env.getConnection() con.execute_command('AI.MODELRUN', name, - 'INPUTS', 'input', 'OUTPUTS', output_name) + 'INPUTS', 'input{1}', 'OUTPUTS', output_name) # Running thrice since minbatchsize = 2 p1 = mp.Process(target=run) @@ -653,12 +653,12 @@ def run(name=model_name, output_name='output'): 'OUTPUTS', output_var, 'BLOB', model_pb) - p1b = mp.Process(target=run, args=(another_model_name, 'final1')) + p1b = mp.Process(target=run, args=(another_model_name, 'final1{1}')) p1b.start() - run(another_model_name, 'final2') + run(another_model_name, 'final2{1}') - _, dtype, _, shape, _, data = con.execute_command('AI.TENSORGET', 'final1', 'META', 'BLOB') + _, dtype, _, shape, _, data = con.execute_command('AI.TENSORGET', 'final1{1}', 'META', 'BLOB') dtype_map = {b'FLOAT': np.float32} tensor = np.frombuffer(data, dtype=dtype_map[dtype]).reshape(shape) label_id = np.argmax(tensor) - 1 @@ -678,7 +678,7 @@ def test_tensorflow_modelrun_financialNet(env): tensor_number = 1 for transaction_tensor in creditcard_transactions[:MAX_TRANSACTIONS]: - ret = con.execute_command('AI.TENSORSET', 'transactionTensor:{0}'.format(tensor_number), + ret = con.execute_command('AI.TENSORSET', 'transactionTensor{{1}}:{0}'.format(tensor_number), 'FLOAT', 1, 30, 'BLOB', transaction_tensor.tobytes()) env.assertEqual(ret, b'OK') @@ -686,22 +686,22 @@ def test_tensorflow_modelrun_financialNet(env): tensor_number = 1 for reference_tensor in creditcard_referencedata[:MAX_TRANSACTIONS]: - ret = con.execute_command('AI.TENSORSET', 'referenceTensor:{0}'.format(tensor_number), + ret = con.execute_command('AI.TENSORSET', 'referenceTensor{{1}}:{0}'.format(tensor_number), 'FLOAT', 1, 256, 'BLOB', reference_tensor.tobytes()) env.assertEqual(ret, b'OK') tensor_number = tensor_number + 1 - ret = con.execute_command('AI.MODELSET', 'financialNet', 'TF', DEVICE, + ret = con.execute_command('AI.MODELSET', 'financialNet{1}', 'TF', DEVICE, 'INPUTS', 'transaction', 'reference', 'OUTPUTS', 'output', 'BLOB', model_pb) env.assertEqual(ret, b'OK') for tensor_number in range(1, MAX_TRANSACTIONS): for repetition in range(0, 10): - ret = con.execute_command('AI.MODELRUN', 'financialNet', 'INPUTS', - 'transactionTensor:{}'.format(tensor_number), - 'referenceTensor:{}'.format(tensor_number), 'OUTPUTS', - 'classificationTensor:{}_{}'.format(tensor_number, repetition)) + ret = con.execute_command('AI.MODELRUN', 'financialNet{1}', 'INPUTS', + 'transactionTensor{{1}}:{}'.format(tensor_number), + 'referenceTensor{{1}}:{}'.format(tensor_number), 'OUTPUTS', + 'classificationTensor{{1}}:{}_{}'.format(tensor_number, repetition)) env.assertEqual(ret, b'OK') @@ -712,7 +712,7 @@ def test_tensorflow_modelrun_financialNet_multiproc(env): tensor_number = 1 for transaction_tensor in creditcard_transactions[:MAX_TRANSACTIONS]: - ret = con.execute_command('AI.TENSORSET', 'transactionTensor:{0}'.format(tensor_number), + ret = con.execute_command('AI.TENSORSET', 'transactionTensor{{1}}:{0}'.format(tensor_number), 'FLOAT', 1, 30, 'BLOB', transaction_tensor.tobytes()) env.assertEqual(ret, b'OK') @@ -720,23 +720,23 @@ def test_tensorflow_modelrun_financialNet_multiproc(env): tensor_number = 1 for reference_tensor in creditcard_referencedata[:MAX_TRANSACTIONS]: - ret = con.execute_command('AI.TENSORSET', 'referenceTensor:{0}'.format(tensor_number), + ret = con.execute_command('AI.TENSORSET', 'referenceTensor{{1}}:{0}'.format(tensor_number), 'FLOAT', 1, 256, 'BLOB', reference_tensor.tobytes()) env.assertEqual(ret, b'OK') tensor_number = tensor_number + 1 - ret = con.execute_command('AI.MODELSET', 'financialNet', 'TF', DEVICE, + ret = con.execute_command('AI.MODELSET', 'financialNet{1}', 'TF', DEVICE, 'INPUTS', 'transaction', 'reference', 'OUTPUTS', 'output', 'BLOB', model_pb) env.assertEqual(ret, b'OK') def functor_financialNet(env, key_max, repetitions): for tensor_number in range(1, key_max): for repetition in range(1, repetitions): - ret = env.execute_command('AI.MODELRUN', 'financialNet', 'INPUTS', - 'transactionTensor:{}'.format(tensor_number), - 'referenceTensor:{}'.format(tensor_number), 'OUTPUTS', - 'classificationTensor:{}_{}'.format(tensor_number, repetition)) + ret = env.execute_command('AI.MODELRUN', 'financialNet{1}', 'INPUTS', + 'transactionTensor{{1}}:{}'.format(tensor_number), + 'referenceTensor{{1}}:{}'.format(tensor_number), 'OUTPUTS', + 'classificationTensor{{1}}:{}_{}'.format(tensor_number, repetition)) t = time.time() run_test_multiproc(env, 10, diff --git a/test/tests_tflite.py b/test/tests_tflite.py index 947e486a9..a6f2c40b6 100644 --- a/test/tests_tflite.py +++ b/test/tests_tflite.py @@ -31,37 +31,37 @@ def test_run_tflite_model(env): with open(sample_filename, 'rb') as f: sample_raw = f.read() - ret = con.execute_command('AI.MODELSET', 'm', 'TFLITE', 'CPU', 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TFLITE', 'CPU', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) env.assertEqual(ret[5], b'') - ret = con.execute_command('AI.MODELSET', 'm', 'TFLITE', 'CPU', 'TAG', 'asdf', 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TFLITE', 'CPU', 'TAG', 'asdf', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) env.assertEqual(ret[5], b'asdf') - ret = con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) + ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - ret = con.execute_command('AI.MODELGET', 'm', 'META') + ret = con.execute_command('AI.MODELGET', 'm{1}', 'META') env.assertEqual(len(ret), 14) # TODO: enable me. CI is having issues on GPU asserts of TFLITE and CPU if DEVICE == "CPU": env.assertEqual(ret[1], b'TFLITE') env.assertEqual(ret[3], b'CPU') - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'OUTPUTS', 'b', 'c') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'OUTPUTS', 'b{1}', 'c{1}') ensureSlaveSynced(con, env) - values = con.execute_command('AI.TENSORGET', 'b', 'VALUES') + values = con.execute_command('AI.TENSORGET', 'b{1}', 'VALUES') env.assertEqual(values[0], 1) @@ -90,40 +90,40 @@ def test_run_tflite_model_errors(env): with open(sample_filename, 'rb') as f: sample_raw = f.read() - ret = con.execute_command('AI.MODELSET', 'm_2', 'TFLITE', 'CPU', 'BLOB', model_pb2) + ret = con.execute_command('AI.MODELSET', 'm_2{1}', 'TFLITE', 'CPU', 'BLOB', model_pb2) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.MODELSET', 'm', 'TFLITE', 'CPU', 'TAG', 'asdf', 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TFLITE', 'CPU', 'TAG', 'asdf', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) + ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) try: - con.execute_command('AI.MODELSET', 'm_1', 'TFLITE', model_pb) + con.execute_command('AI.MODELSET', 'm_1{1}', 'TFLITE', model_pb) except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("Insufficient arguments, missing model BLOB", exception.__str__()) try: - con.execute_command('AI.MODELSET', 'm_2', 'BLOB', model_pb) + con.execute_command('AI.MODELSET', 'm_2{1}', 'BLOB', model_pb) except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("unsupported backend", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_2', 'INPUTS', 'EMPTY_TENSOR', 'OUTPUTS') + con.execute_command('AI.MODELRUN', 'm_2{1}', 'INPUTS', 'EMPTY_TENSOR{1}', 'OUTPUTS') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("tensor key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_2') + con.execute_command('AI.MODELRUN', 'm_2{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -137,56 +137,56 @@ def test_run_tflite_model_errors(env): env.assertEqual("model key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_2', 'INPUTS', 'a', 'b', 'c') + con.execute_command('AI.MODELRUN', 'm_2{1}', 'INPUTS', 'a{1}', 'b{1}', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("tensor key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_2', 'a', 'b', 'c') + con.execute_command('AI.MODELRUN', 'm_2{1}', 'a{1}', 'b{1}', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("INPUTS not specified", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm_2', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm_2{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("INPUTS not specified", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm', 'OUTPUTS', 'c') + con.execute_command('AI.MODELRUN', 'm{1}', 'OUTPUTS', 'c{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("INPUTS not specified", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'b') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'b{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("tensor key is empty", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'OUTPUTS') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'OUTPUTS') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("Inconsistent number of inputs", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'OUTPUTS') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'OUTPUTS') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) env.assertEqual("Inconsistent number of outputs", exception.__str__()) try: - con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'OUTPUTS', 'b') + con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'OUTPUTS', 'b{1}') except Exception as e: exception = e env.assertEqual(type(exception), redis.exceptions.ResponseError) @@ -213,7 +213,7 @@ def test_run_tflite_model_autobatch(env): sample_raw = f.read() try: - ret = con.execute_command('AI.MODELSET', 'm', 'TFLITE', 'CPU', + ret = con.execute_command('AI.MODELSET', 'm{1}', 'TFLITE', 'CPU', 'BATCHSIZE', 2, 'MINBATCHSIZE', 2, 'BLOB', model_pb) except Exception as e: exception = e @@ -222,19 +222,19 @@ def test_run_tflite_model_autobatch(env): # env.assertEqual(ret, b'OK') - # con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) - # con.execute_command('AI.TENSORSET', 'c', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) + # con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) + # con.execute_command('AI.TENSORSET', 'c{1}', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) # def run(): # con = env.getConnection() - # con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'c', 'OUTPUTS', 'd', 'd2') + # con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'c{1}', 'OUTPUTS', 'd', 'd2') # t = threading.Thread(target=run) # t.start() - # con.execute_command('AI.MODELRUN', 'm', 'INPUTS', 'a', 'OUTPUTS', 'b', 'b2') + # con.execute_command('AI.MODELRUN', 'm{1}', 'INPUTS', 'a{1}', 'OUTPUTS', 'b{1}', 'b2') - # values = con.execute_command('AI.TENSORGET', 'b', 'VALUES') + # values = con.execute_command('AI.TENSORGET', 'b{1}', 'VALUES') # env.assertEqual(values[0], 1) @@ -263,24 +263,24 @@ def test_tflite_modelinfo(env): with open(sample_filename, 'rb') as f: sample_raw = f.read() - ret = con.execute_command('AI.MODELSET', 'mnist', 'TFLITE', 'CPU', 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'mnist{1}', 'TFLITE', 'CPU', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - ret = con.execute_command('AI.TENSORSET', 'a', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) + ret = con.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) previous_duration = 0 for call in range(1, 10): - ret = con.execute_command('AI.MODELRUN', 'mnist', 'INPUTS', 'a', 'OUTPUTS', 'b', 'c') + ret = con.execute_command('AI.MODELRUN', 'mnist{1}', 'INPUTS', 'a{1}', 'OUTPUTS', 'b{1}', 'c{1}') env.assertEqual(ret, b'OK') ensureSlaveSynced(con, env) - info = con.execute_command('AI.INFO', 'mnist') + info = con.execute_command('AI.INFO', 'mnist{1}') info_dict_0 = info_to_dict(info) - env.assertEqual(info_dict_0['key'], 'mnist') + env.assertEqual(info_dict_0['key'], 'mnist{1}') env.assertEqual(info_dict_0['type'], 'MODEL') env.assertEqual(info_dict_0['backend'], 'TFLITE') env.assertEqual(info_dict_0['device'], DEVICE) @@ -291,9 +291,9 @@ def test_tflite_modelinfo(env): previous_duration = info_dict_0['duration'] - res = con.execute_command('AI.INFO', 'mnist', 'RESETSTAT') + res = con.execute_command('AI.INFO', 'mnist{1}', 'RESETSTAT') env.assertEqual(res, b'OK') - info = con.execute_command('AI.INFO', 'mnist') + info = con.execute_command('AI.INFO', 'mnist{1}') info_dict_0 = info_to_dict(info) env.assertEqual(info_dict_0['duration'], 0) env.assertEqual(info_dict_0['samples'], 0) @@ -317,15 +317,15 @@ def test_tflite_modelrun_disconnect(env): with open(sample_filename, 'rb') as f: sample_raw = f.read() - ret = red.execute_command('AI.MODELSET', 'mnist', 'TFLITE', 'CPU', 'BLOB', model_pb) + ret = red.execute_command('AI.MODELSET', 'mnist{1}', 'TFLITE', 'CPU', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - ret = red.execute_command('AI.TENSORSET', 'a', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) + ret = red.execute_command('AI.TENSORSET', 'a{1}', 'FLOAT', 1, 1, 28, 28, 'BLOB', sample_raw) env.assertEqual(ret, b'OK') ensureSlaveSynced(red, env) - ret = send_and_disconnect(('AI.MODELRUN', 'mnist', 'INPUTS', 'a', 'OUTPUTS', 'b', 'c'), red) + ret = send_and_disconnect(('AI.MODELRUN', 'mnist{1}', 'INPUTS', 'a{1}', 'OUTPUTS', 'b{1}', 'c{1}'), red) env.assertEqual(ret, None) @@ -342,10 +342,10 @@ def test_tflite_model_rdb_save_load(env): with open(model_filename, 'rb') as f: model_pb = f.read() - ret = con.execute_command('AI.MODELSET', 'mnist', 'TFLITE', 'CPU', 'BLOB', model_pb) + ret = con.execute_command('AI.MODELSET', 'mnist{1}', 'TFLITE', 'CPU', 'BLOB', model_pb) env.assertEqual(ret, b'OK') - model_serialized_memory = con.execute_command('AI.MODELGET', 'mnist', 'BLOB') + model_serialized_memory = con.execute_command('AI.MODELGET', 'mnist{1}', 'BLOB') ensureSlaveSynced(con, env) ret = con.execute_command('SAVE') @@ -354,7 +354,7 @@ def test_tflite_model_rdb_save_load(env): env.stop() env.start() con = env.getConnection() - model_serialized_after_rdbload = con.execute_command('AI.MODELGET', 'mnist', 'BLOB') + model_serialized_after_rdbload = con.execute_command('AI.MODELGET', 'mnist{1}', 'BLOB') env.assertEqual(len(model_serialized_memory), len(model_serialized_after_rdbload)) env.assertEqual(len(model_pb), len(model_serialized_after_rdbload)) # Assert in memory model binary is equal to loaded model binary