From 5f400f00a92f6c95076544e9bea524971e25afed Mon Sep 17 00:00:00 2001 From: alon Date: Thu, 2 Jun 2022 14:38:48 +0300 Subject: [PATCH 1/6] Set backends default path on module load, so it can be retrieved with ai.config get command. --- src/backends/backends.c | 28 ++++++++++++---------------- src/backends/backends.h | 5 +++++ src/config/config.c | 10 +++++----- tests/flow/includes.py | 1 + tests/flow/tests_commands.py | 2 +- tests/flow/tests_setup/tests.sh | 1 + 6 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/backends/backends.c b/src/backends/backends.c index 59ec5a277..36e346b82 100644 --- a/src/backends/backends.c +++ b/src/backends/backends.c @@ -105,20 +105,18 @@ RedisModuleString *RAI_GetModulePath(RedisModuleCtx *ctx) { return module_path; } -RedisModuleString *RAI_GetBackendsPath(RedisModuleCtx *ctx) { +char *RAI_GetBackendsDefaultPath() { Dl_info info; - RedisModuleString *backends_path = NULL; - if (Config_GetBackendsPath() != NULL) { - backends_path = RedisModule_CreateString(ctx, Config_GetBackendsPath(), - strlen(Config_GetBackendsPath())); - } else { - RedisModuleString *module_path = RAI_GetModulePath(ctx); - backends_path = RedisModule_CreateStringPrintf(ctx, "%s/backends", - RedisModule_StringPtrLen(module_path, NULL)); - RedisModule_FreeString(ctx, module_path); - } + // Retrieve the info about the module's dynamic library, and extract the .so file dir name. + RedisModule_Assert(dladdr(RAI_GetBackendsDefaultPath, &info) != 0); + char *dyn_lib_name = RedisModule_Strdup(info.dli_fname); + const char *dyn_lib_dir_name = dirname(dyn_lib_name); + + // Allocate and populate a string containing the default backends path. + char *backends_default_path = RedisModule_Alloc(strlen(dyn_lib_dir_name)+strlen("/backends")); + RedisModule_Assert(sprintf(backends_default_path, "%s/backends", dyn_lib_dir_name) > 0); - return backends_path; + return backends_default_path; } const char *RAI_GetBackendName(RAI_Backend backend) { @@ -460,10 +458,8 @@ int RAI_LoadBackend(RedisModuleCtx *ctx, int backend, const char *path) { if (path[0] == '/') { fullpath = RedisModule_CreateString(ctx, path, strlen(path)); } else { - RedisModuleString *backends_path = RAI_GetBackendsPath(ctx); - fullpath = RedisModule_CreateStringPrintf( - ctx, "%s/%s", RedisModule_StringPtrLen(backends_path, NULL), path); - RedisModule_FreeString(ctx, backends_path); + const char *backends_path = Config_GetBackendsPath(); + fullpath = RedisModule_CreateStringPrintf(ctx, "%s/%s", backends_path, path); } int ret; diff --git a/src/backends/backends.h b/src/backends/backends.h index 6cb8b2ef3..175716bc4 100644 --- a/src/backends/backends.h +++ b/src/backends/backends.h @@ -110,3 +110,8 @@ int RAI_LoadDefaultBackend(RedisModuleCtx *ctx, int backend); * @brief Returns the backend name as string. */ const char *RAI_GetBackendName(RAI_Backend backend); + +/** + * @brief Returns the default backends as string which is /backends. + */ +char *RAI_GetBackendsDefaultPath(void); diff --git a/src/config/config.c b/src/config/config.c index 0a4e6a4e3..c869ed38f 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -3,9 +3,9 @@ #include "redismodule.h" #include "backends/backends.h" -// Default configs -char *BackendsPath = NULL; // Path to backends dir. - +// Default configs: +char *BackendsPath; // Path to backends dir. Default value is set when + // parsing load_time configs. long long BackendsIntraOpParallelism = 0; // number of threads used within an // individual op for parallelism. long long BackendsInterOpParallelism = 0; // number of threads used for parallelism @@ -186,8 +186,8 @@ int Config_SetLoadTimeParams(RedisModuleCtx *ctx, RedisModuleString *const *argv "provide arguments as KEY VAL pairs"); return REDISMODULE_ERR; } - - // need BACKENDSPATH set up before loading specific backends + // need BACKENDSPATH set up before loading specific backends. + BackendsPath = RAI_GetBackendsDefaultPath(); for (int i = 0; i < argc / 2; i++) { const char *key = RedisModule_StringPtrLen(argv[2 * i], NULL); const char *val = RedisModule_StringPtrLen(argv[2 * i + 1], NULL); diff --git a/tests/flow/includes.py b/tests/flow/includes.py index 1c61c175b..185d11c84 100755 --- a/tests/flow/includes.py +++ b/tests/flow/includes.py @@ -17,6 +17,7 @@ import paella ROOT = os.environ.get("ROOT", None) +MODULE = os.environ.get("MODULE", None) TESTMOD_PATH = os.environ.get("TESTMOD", None) MAX_ITERATIONS = 2 if os.environ.get("MAX_ITERATIONS") == None else os.environ.get("MAX_ITERATIONS") TEST_TF = os.environ.get("TEST_TF") != "0" and os.environ.get("WITH_TF") != "0" diff --git a/tests/flow/tests_commands.py b/tests/flow/tests_commands.py index 2c98ef471..2d70dd736 100644 --- a/tests/flow/tests_commands.py +++ b/tests/flow/tests_commands.py @@ -552,7 +552,7 @@ def test_ai_config(env): for con in conns: # Get the default configs. res = con.execute_command('AI.CONFIG', 'GET', 'BACKENDSPATH') - env.assertEqual(res, None) + env.assertEqual(res.decode(), f'{"/".join(MODULE.split("/")[:-1])}/backends') # /backends res = con.execute_command('AI.CONFIG', 'GET', 'MODEL_CHUNK_SIZE') env.assertEqual(res, 511*1024*1024) diff --git a/tests/flow/tests_setup/tests.sh b/tests/flow/tests_setup/tests.sh index 7a7df22c2..7e90684d0 100755 --- a/tests/flow/tests_setup/tests.sh +++ b/tests/flow/tests_setup/tests.sh @@ -141,6 +141,7 @@ install_git_lfs check_redis_server ./Install_RedisGears.sh +RLTEST_ARGS+="--parallelism 8" [[ ! -z $REDIS ]] && RL_TEST_ARGS+=" --env exiting-env --existing-env-addr $REDIS" run_tests "redis-server: $REDIS" [[ $GEN == 1 ]] && run_tests [[ $CLUSTER == 1 ]] && RLTEST_ARGS+=" --env oss-cluster --shards-count 3" run_tests "--env oss-cluster" From 9d454c2c7c7ac5ea7eb7095918f6cc8bba9450ea Mon Sep 17 00:00:00 2001 From: alon Date: Thu, 2 Jun 2022 20:30:43 +0300 Subject: [PATCH 2/6] Limit the backends' path length + fix in script that rns tests with parallelism + fix in onnx test to adjust parallelism. --- src/backends/backends.c | 32 ++++++------------ src/backends/backends.h | 5 +-- src/config/config.c | 58 +++++++++++++++++---------------- src/config/config.h | 11 ++++--- src/redisai.c | 7 ++-- tests/flow/tests_commands.py | 4 +++ tests/flow/tests_onnx.py | 2 +- tests/flow/tests_setup/tests.sh | 2 +- 8 files changed, 61 insertions(+), 60 deletions(-) diff --git a/src/backends/backends.c b/src/backends/backends.c index 36e346b82..60b388391 100644 --- a/src/backends/backends.c +++ b/src/backends/backends.c @@ -92,31 +92,19 @@ int RAI_ExportFunc(const char *func_name, void **targetFuncPtr) { return REDISMODULE_OK; } -RedisModuleString *RAI_GetModulePath(RedisModuleCtx *ctx) { - Dl_info info; - RedisModuleString *module_path = NULL; - if (dladdr(RAI_GetModulePath, &info)) { - char *dli_fname = RedisModule_Strdup(info.dli_fname); - const char *dli_dirname = dirname(dli_fname); - module_path = RedisModule_CreateString(ctx, dli_dirname, strlen(dli_dirname)); - RedisModule_Free(dli_fname); - } - - return module_path; -} - -char *RAI_GetBackendsDefaultPath() { +int RAI_SetBackendsDefaultPath(char *backends_path) { Dl_info info; // Retrieve the info about the module's dynamic library, and extract the .so file dir name. - RedisModule_Assert(dladdr(RAI_GetBackendsDefaultPath, &info) != 0); - char *dyn_lib_name = RedisModule_Strdup(info.dli_fname); - const char *dyn_lib_dir_name = dirname(dyn_lib_name); + RedisModule_Assert(dladdr(RAI_SetBackendsDefaultPath, &info) != 0); + const char *dyn_lib_dir_name = dirname((char *)info.dli_fname); - // Allocate and populate a string containing the default backends path. - char *backends_default_path = RedisModule_Alloc(strlen(dyn_lib_dir_name)+strlen("/backends")); - RedisModule_Assert(sprintf(backends_default_path, "%s/backends", dyn_lib_dir_name) > 0); - - return backends_default_path; + // Populate backends_path global string with the default path. + size_t backends_default_path_len = strlen(dyn_lib_dir_name) + strlen("/backends"); + if (backends_default_path_len > REDISAI_BACKENDS_PATH_MAX_LEN) { + return REDISMODULE_ERR; + } + RedisModule_Assert(sprintf(backends_path, "%s/backends", dyn_lib_dir_name) > 0); + return REDISMODULE_OK; } const char *RAI_GetBackendName(RAI_Backend backend) { diff --git a/src/backends/backends.h b/src/backends/backends.h index 175716bc4..00b4b3a59 100644 --- a/src/backends/backends.h +++ b/src/backends/backends.h @@ -112,6 +112,7 @@ int RAI_LoadDefaultBackend(RedisModuleCtx *ctx, int backend); const char *RAI_GetBackendName(RAI_Backend backend); /** - * @brief Returns the default backends as string which is /backends. + * @brief Set the default backends path (/backends) in backends_path. + * @return REDISMODULE_OK on success, or REDISMODULE_ERR if path is too long. */ -char *RAI_GetBackendsDefaultPath(void); +int RAI_SetBackendsDefaultPath(char *backends_path); diff --git a/src/config/config.c b/src/config/config.c index c869ed38f..efc7cd6e5 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -3,21 +3,21 @@ #include "redismodule.h" #include "backends/backends.h" -// Default configs: -char *BackendsPath; // Path to backends dir. Default value is set when - // parsing load_time configs. -long long BackendsIntraOpParallelism = 0; // number of threads used within an - // individual op for parallelism. -long long BackendsInterOpParallelism = 0; // number of threads used for parallelism - // between independent operations. -long long ModelChunkSize = 535822336; // size of chunks used to break up model payloads. - // default is 511 * 1024 * 1024 -long long ThreadPoolSizePerQueue = 1; // Number of working threads for device. - -long long ModelExecutionTimeout = 5000; // The maximum time in milliseconds - // before killing onnx run session. -long long BackendMemoryLimit = 0; // The maximum amount of memory in MB - // that backend is allowed to consume. +/* Default configs: */ +// Path to backends dir. Default value is set when parsing load_time configs. +char BackendsPath[REDISAI_BACKENDS_PATH_MAX_LEN]; +// Number of threads used within an individual op for parallelism. +long long BackendsIntraOpParallelism = 0; +// Number of threads used for parallelism between independent operations. +long long BackendsInterOpParallelism = 0; +// Size of chunks used to break up model payloads. Default is 511 * 1024 * 1024 +long long ModelChunkSize = REDISAI_DEFAULT_MODEL_CHUNK_SIZE; +// Number of working threads for device. +long long ThreadPoolSizePerQueue = 1; +// The maximum time in milliseconds before killing onnx run session. +long long ModelExecutionTimeout = 5000; +// The maximum amount of memory in MB that backend is allowed to consume. +long long BackendMemoryLimit = 0; static int _Config_LoadTimeParamParse(RedisModuleCtx *ctx, const char *key, const char *val, RedisModuleString *rsval) { @@ -110,11 +110,12 @@ int Config_LoadBackend(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) return RedisModule_ReplyWithError(ctx, "ERR error loading backend"); } -void Config_SetBackendsPath(const char *path) { - if (BackendsPath != NULL) { - RedisModule_Free(BackendsPath); +int Config_SetBackendsPath(const char *path) { + if (strlen(path) > REDISAI_BACKENDS_PATH_MAX_LEN) { + return REDISMODULE_ERR; } - BackendsPath = RedisModule_Strdup(path); + strcpy(BackendsPath, path); + return REDISMODULE_OK; } int Config_SetQueueThreadsNum(RedisModuleString *num_threads_string) { @@ -150,7 +151,7 @@ int Config_SetIntraOperationParallelism(RedisModuleString *num_threads_string) { int Config_SetModelChunkSize(RedisModuleString *chunk_size_string) { long long val; int result = RedisModule_StringToLongLong(chunk_size_string, &val); - if (result != REDISMODULE_OK || val <= 0) { + if (result != REDISMODULE_OK || val <= 0 || val > REDISAI_DEFAULT_MODEL_CHUNK_SIZE) { return REDISMODULE_ERR; } ModelChunkSize = val; @@ -187,20 +188,18 @@ int Config_SetLoadTimeParams(RedisModuleCtx *ctx, RedisModuleString *const *argv return REDISMODULE_ERR; } // need BACKENDSPATH set up before loading specific backends. - BackendsPath = RAI_GetBackendsDefaultPath(); + int ret = RAI_SetBackendsDefaultPath(BackendsPath); + const char *key; + const char *val; for (int i = 0; i < argc / 2; i++) { - const char *key = RedisModule_StringPtrLen(argv[2 * i], NULL); - const char *val = RedisModule_StringPtrLen(argv[2 * i + 1], NULL); + key = RedisModule_StringPtrLen(argv[2 * i], NULL); + val = RedisModule_StringPtrLen(argv[2 * i + 1], NULL); if (strcasecmp(key, "BACKENDSPATH") == 0) { - Config_SetBackendsPath(val); + ret = Config_SetBackendsPath(val); } } for (int i = 0; i < argc / 2; i++) { - const char *key = RedisModule_StringPtrLen(argv[2 * i], NULL); - const char *val = RedisModule_StringPtrLen(argv[2 * i + 1], NULL); - int ret = _Config_LoadTimeParamParse(ctx, key, val, argv[2 * i + 1]); - if (ret == REDISMODULE_ERR) { char *buffer = RedisModule_Alloc( (4 + strlen(REDISAI_ERRORMSG_PROCESSING_ARG) + strlen(key) + strlen(val)) * @@ -210,6 +209,9 @@ int Config_SetLoadTimeParams(RedisModuleCtx *ctx, RedisModuleString *const *argv RedisModule_Free(buffer); return ret; } + key = RedisModule_StringPtrLen(argv[2 * i], NULL); + val = RedisModule_StringPtrLen(argv[2 * i + 1], NULL); + ret = _Config_LoadTimeParamParse(ctx, key, val, argv[2 * i + 1]); } return REDISMODULE_OK; } diff --git a/src/config/config.h b/src/config/config.h index d6798f2f3..44c687d65 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -28,6 +28,9 @@ typedef enum { RAI_DEVICE_CPU = 0, RAI_DEVICE_GPU = 1 } RAI_Device; #define REDISAI_INFOMSG_MODEL_EXECUTION_TIMEOUT "Setting MODEL_EXECUTION_TIMEOUT parameter to" #define REDISAI_INFOMSG_BACKEND_MEMORY_LIMIT "Setting BACKEND_MEMORY_LIMIT parameter to" +#define REDISAI_BACKENDS_PATH_MAX_LEN 1023 +#define REDISAI_DEFAULT_MODEL_CHUNK_SIZE (511 * 1024 * 1024) + /** * Get number of threads used for parallelism between independent operations, by * backend. @@ -81,11 +84,11 @@ char *Config_GetBackendsPath(void); int Config_LoadBackend(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); /** - * Helper method for AI.CONFIG BACKENDSPATH - * - * @param path string containing backend path + * Helper method for AI.CONFIG BACKENDSPATH + * @param path string containing backend path. + * @return REDISMODULE_OK on success, or REDISMODULE_ERR if path is too long. */ -void Config_SetBackendsPath(const char *path); +int Config_SetBackendsPath(const char *path); /** * Set number of threads used for parallelism between RedisAI independent diff --git a/src/redisai.c b/src/redisai.c index 419619691..8cef728bb 100644 --- a/src/redisai.c +++ b/src/redisai.c @@ -921,8 +921,11 @@ int RedisAI_Config_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, i if (!strcasecmp(subcommand, "BACKENDSPATH")) { if (argc > 2) { - Config_SetBackendsPath(RedisModule_StringPtrLen(argv[2], NULL)); - return RedisModule_ReplyWithSimpleString(ctx, "OK"); + if (Config_SetBackendsPath(RedisModule_StringPtrLen(argv[2], NULL)) == REDISMODULE_OK) { + return RedisModule_ReplyWithSimpleString(ctx, "OK"); + } else { + return RedisModule_ReplyWithError(ctx, "ERR BACKENDSPATH: path exceeds 1023 chars"); + } } else { return RedisModule_ReplyWithError(ctx, "ERR BACKENDSPATH: missing path argument"); } diff --git a/tests/flow/tests_commands.py b/tests/flow/tests_commands.py index 2d70dd736..3679a59d6 100644 --- a/tests/flow/tests_commands.py +++ b/tests/flow/tests_commands.py @@ -608,7 +608,11 @@ def test_ai_config_errors(env): check_error_message(env, con, "wrong number of arguments for 'AI.CONFIG' command", 'AI.CONFIG', 'LOADBACKEND', "TORCH") check_error_message(env, con, 'BACKENDSPATH: missing path argument', 'AI.CONFIG', 'BACKENDSPATH') + long_path = f'{"/".join(["d" for i in range(1024)])}' + check_error_message(env, con, 'BACKENDSPATH: path exceeds 1023 chars', 'AI.CONFIG', 'BACKENDSPATH', long_path) check_error_message(env, con, 'MODEL_CHUNK_SIZE: missing chunk size', 'AI.CONFIG', 'MODEL_CHUNK_SIZE') + check_error_message(env, con, 'MODEL_CHUNK_SIZE: invalid chunk size', 'AI.CONFIG', 'MODEL_CHUNK_SIZE', 'not_number') + check_error_message(env, con, 'MODEL_CHUNK_SIZE: invalid chunk size', 'AI.CONFIG', 'MODEL_CHUNK_SIZE', 512*1024*1024) check_error_message(env, con, "wrong number of arguments for 'AI.CONFIG' command", 'AI.CONFIG', 'GET') env.assertEqual(con.execute_command('AI.CONFIG', 'GET', 'bad_config'), None) diff --git a/tests/flow/tests_onnx.py b/tests/flow/tests_onnx.py index fd16bce48..5755d3901 100644 --- a/tests/flow/tests_onnx.py +++ b/tests/flow/tests_onnx.py @@ -567,7 +567,7 @@ def test_synchronization(self): def launch_redis_and_run_onnx(con, proc_id, pipes): my_pipe = pipes[proc_id] - port = 6380 + proc_id # Let every subprocess run on a fresh port. + port = 6380 + 30*proc_id # Let every subprocess run on a fresh port (safe distance for RLTEST parallelism). redis_server = subprocess.Popen(['redis-server', '--port', str(port), '--loadmodule', f'{ROOT}/install-{DEVICE.lower()}/redisai.so', '--logfile', f'{self.env.logDir}/test_onnx_kill_switch_synchronization-{port}.log', diff --git a/tests/flow/tests_setup/tests.sh b/tests/flow/tests_setup/tests.sh index 7e90684d0..c0d98cea7 100755 --- a/tests/flow/tests_setup/tests.sh +++ b/tests/flow/tests_setup/tests.sh @@ -141,7 +141,7 @@ install_git_lfs check_redis_server ./Install_RedisGears.sh -RLTEST_ARGS+="--parallelism 8" +RLTEST_ARGS+=" --parallelism 8" [[ ! -z $REDIS ]] && RL_TEST_ARGS+=" --env exiting-env --existing-env-addr $REDIS" run_tests "redis-server: $REDIS" [[ $GEN == 1 ]] && run_tests [[ $CLUSTER == 1 ]] && RLTEST_ARGS+=" --env oss-cluster --shards-count 3" run_tests "--env oss-cluster" From a6d5f0377c48b44121824b344dba6fc5d98814a6 Mon Sep 17 00:00:00 2001 From: alon Date: Fri, 3 Jun 2022 11:21:57 +0300 Subject: [PATCH 3/6] Update docs --- docs/commands.md | 2 +- docs/configuration.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index e088e44ee..adbd4f33b 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1149,7 +1149,7 @@ AI.CONFIG > | > | Date: Tue, 7 Jun 2022 14:00:08 +0300 Subject: [PATCH 4/6] Use server shutdown event to clean up global backends path instead of limiting its size --- docs/commands.md | 2 +- docs/configuration.md | 2 +- src/backends/backends.c | 10 ++++------ src/backends/backends.h | 5 ++--- src/config/config.c | 32 +++++++++++++++----------------- src/config/config.h | 4 +--- src/redisai.c | 14 +++++++++----- tests/flow/tests_commands.py | 2 -- 8 files changed, 33 insertions(+), 38 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index adbd4f33b..e088e44ee 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1149,7 +1149,7 @@ AI.CONFIG > | > | REDISAI_BACKENDS_PATH_MAX_LEN) { - return REDISMODULE_ERR; - } - RedisModule_Assert(sprintf(backends_path, "%s/backends", dyn_lib_dir_name) > 0); - return REDISMODULE_OK; + *backends_path = RedisModule_Alloc(backends_default_path_len + 1); + RedisModule_Assert(sprintf(*backends_path, "%s/backends", dyn_lib_dir_name) > 0); } const char *RAI_GetBackendName(RAI_Backend backend) { diff --git a/src/backends/backends.h b/src/backends/backends.h index 00b4b3a59..b883c5bdb 100644 --- a/src/backends/backends.h +++ b/src/backends/backends.h @@ -112,7 +112,6 @@ int RAI_LoadDefaultBackend(RedisModuleCtx *ctx, int backend); const char *RAI_GetBackendName(RAI_Backend backend); /** - * @brief Set the default backends path (/backends) in backends_path. - * @return REDISMODULE_OK on success, or REDISMODULE_ERR if path is too long. + * @brief Set the default backends path (/backends) in backends_path place holder. */ -int RAI_SetBackendsDefaultPath(char *backends_path); +void RAI_SetBackendsDefaultPath(char **backends_path); diff --git a/src/config/config.c b/src/config/config.c index efc7cd6e5..ab9891e8d 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -5,7 +5,7 @@ /* Default configs: */ // Path to backends dir. Default value is set when parsing load_time configs. -char BackendsPath[REDISAI_BACKENDS_PATH_MAX_LEN]; +char *BackendsPath; // Number of threads used within an individual op for parallelism. long long BackendsIntraOpParallelism = 0; // Number of threads used for parallelism between independent operations. @@ -110,12 +110,10 @@ int Config_LoadBackend(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) return RedisModule_ReplyWithError(ctx, "ERR error loading backend"); } -int Config_SetBackendsPath(const char *path) { - if (strlen(path) > REDISAI_BACKENDS_PATH_MAX_LEN) { - return REDISMODULE_ERR; - } - strcpy(BackendsPath, path); - return REDISMODULE_OK; +void Config_SetBackendsPath(const char *path) { + RedisModule_Assert(BackendsPath != NULL && path != NULL); + RedisModule_Free(BackendsPath); + BackendsPath = RedisModule_Strdup(path); } int Config_SetQueueThreadsNum(RedisModuleString *num_threads_string) { @@ -187,19 +185,22 @@ int Config_SetLoadTimeParams(RedisModuleCtx *ctx, RedisModuleString *const *argv "provide arguments as KEY VAL pairs"); return REDISMODULE_ERR; } - // need BACKENDSPATH set up before loading specific backends. - int ret = RAI_SetBackendsDefaultPath(BackendsPath); - const char *key; - const char *val; + + // need BACKENDSPATH set up before loading specific backends + RAI_SetBackendsDefaultPath(&BackendsPath); for (int i = 0; i < argc / 2; i++) { - key = RedisModule_StringPtrLen(argv[2 * i], NULL); - val = RedisModule_StringPtrLen(argv[2 * i + 1], NULL); + const char *key = RedisModule_StringPtrLen(argv[2 * i], NULL); + const char *val = RedisModule_StringPtrLen(argv[2 * i + 1], NULL); if (strcasecmp(key, "BACKENDSPATH") == 0) { - ret = Config_SetBackendsPath(val); + Config_SetBackendsPath(val); } } for (int i = 0; i < argc / 2; i++) { + const char *key = RedisModule_StringPtrLen(argv[2 * i], NULL); + const char *val = RedisModule_StringPtrLen(argv[2 * i + 1], NULL); + int ret = _Config_LoadTimeParamParse(ctx, key, val, argv[2 * i + 1]); + if (ret == REDISMODULE_ERR) { char *buffer = RedisModule_Alloc( (4 + strlen(REDISAI_ERRORMSG_PROCESSING_ARG) + strlen(key) + strlen(val)) * @@ -209,9 +210,6 @@ int Config_SetLoadTimeParams(RedisModuleCtx *ctx, RedisModuleString *const *argv RedisModule_Free(buffer); return ret; } - key = RedisModule_StringPtrLen(argv[2 * i], NULL); - val = RedisModule_StringPtrLen(argv[2 * i + 1], NULL); - ret = _Config_LoadTimeParamParse(ctx, key, val, argv[2 * i + 1]); } return REDISMODULE_OK; } diff --git a/src/config/config.h b/src/config/config.h index 44c687d65..7b7e00ecc 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -28,7 +28,6 @@ typedef enum { RAI_DEVICE_CPU = 0, RAI_DEVICE_GPU = 1 } RAI_Device; #define REDISAI_INFOMSG_MODEL_EXECUTION_TIMEOUT "Setting MODEL_EXECUTION_TIMEOUT parameter to" #define REDISAI_INFOMSG_BACKEND_MEMORY_LIMIT "Setting BACKEND_MEMORY_LIMIT parameter to" -#define REDISAI_BACKENDS_PATH_MAX_LEN 1023 #define REDISAI_DEFAULT_MODEL_CHUNK_SIZE (511 * 1024 * 1024) /** @@ -86,9 +85,8 @@ int Config_LoadBackend(RedisModuleCtx *ctx, RedisModuleString **argv, int argc); /** * Helper method for AI.CONFIG BACKENDSPATH * @param path string containing backend path. - * @return REDISMODULE_OK on success, or REDISMODULE_ERR if path is too long. */ -int Config_SetBackendsPath(const char *path); +void Config_SetBackendsPath(const char *path); /** * Set number of threads used for parallelism between RedisAI independent diff --git a/src/redisai.c b/src/redisai.c index 8cef728bb..dd4d182d0 100644 --- a/src/redisai.c +++ b/src/redisai.c @@ -921,11 +921,8 @@ int RedisAI_Config_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, i if (!strcasecmp(subcommand, "BACKENDSPATH")) { if (argc > 2) { - if (Config_SetBackendsPath(RedisModule_StringPtrLen(argv[2], NULL)) == REDISMODULE_OK) { - return RedisModule_ReplyWithSimpleString(ctx, "OK"); - } else { - return RedisModule_ReplyWithError(ctx, "ERR BACKENDSPATH: path exceeds 1023 chars"); - } + Config_SetBackendsPath(RedisModule_StringPtrLen(argv[2], NULL)); + return RedisModule_ReplyWithSimpleString(ctx, "OK"); } else { return RedisModule_ReplyWithError(ctx, "ERR BACKENDSPATH: missing path argument"); } @@ -1282,6 +1279,11 @@ void RAI_moduleInfoFunc(RedisModuleInfoCtx *ctx, int for_crash_report) { AI_dictReleaseIterator(iter); } +void RAI_CleanupModule(RedisModuleCtx *ctx, RedisModuleEvent eid, uint64_t subevent, void *data) { + RedisModule_Log(ctx, "notice", "%s", "Clearing resources on shutdown"); + RedisModule_Free(Config_GetBackendsPath()); +} + int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { #ifndef REDISAI_LITE @@ -1427,6 +1429,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) RedisModule_SetModuleOptions(ctx, REDISMODULE_OPTIONS_HANDLE_IO_ERRORS); + RedisModule_SubscribeToServerEvent(ctx, RedisModuleEvent_Shutdown, RAI_CleanupModule); + if (Config_SetLoadTimeParams(ctx, argv, argc) != REDISMODULE_OK) { return REDISMODULE_ERR; } diff --git a/tests/flow/tests_commands.py b/tests/flow/tests_commands.py index 3679a59d6..209bcde79 100644 --- a/tests/flow/tests_commands.py +++ b/tests/flow/tests_commands.py @@ -608,8 +608,6 @@ def test_ai_config_errors(env): check_error_message(env, con, "wrong number of arguments for 'AI.CONFIG' command", 'AI.CONFIG', 'LOADBACKEND', "TORCH") check_error_message(env, con, 'BACKENDSPATH: missing path argument', 'AI.CONFIG', 'BACKENDSPATH') - long_path = f'{"/".join(["d" for i in range(1024)])}' - check_error_message(env, con, 'BACKENDSPATH: path exceeds 1023 chars', 'AI.CONFIG', 'BACKENDSPATH', long_path) check_error_message(env, con, 'MODEL_CHUNK_SIZE: missing chunk size', 'AI.CONFIG', 'MODEL_CHUNK_SIZE') check_error_message(env, con, 'MODEL_CHUNK_SIZE: invalid chunk size', 'AI.CONFIG', 'MODEL_CHUNK_SIZE', 'not_number') check_error_message(env, con, 'MODEL_CHUNK_SIZE: invalid chunk size', 'AI.CONFIG', 'MODEL_CHUNK_SIZE', 512*1024*1024) From 7549768f7b038fd4097e7854fcbfd9d3b3c3296a Mon Sep 17 00:00:00 2001 From: alon Date: Tue, 7 Jun 2022 18:43:23 +0300 Subject: [PATCH 5/6] Remove parallelism from tests, since it may cause problem in CI for some configs (COV + slaves) --- tests/flow/tests_setup/tests.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/flow/tests_setup/tests.sh b/tests/flow/tests_setup/tests.sh index c0d98cea7..7a7df22c2 100755 --- a/tests/flow/tests_setup/tests.sh +++ b/tests/flow/tests_setup/tests.sh @@ -141,7 +141,6 @@ install_git_lfs check_redis_server ./Install_RedisGears.sh -RLTEST_ARGS+=" --parallelism 8" [[ ! -z $REDIS ]] && RL_TEST_ARGS+=" --env exiting-env --existing-env-addr $REDIS" run_tests "redis-server: $REDIS" [[ $GEN == 1 ]] && run_tests [[ $CLUSTER == 1 ]] && RLTEST_ARGS+=" --env oss-cluster --shards-count 3" run_tests "--env oss-cluster" From ec1b2fffbc6583b585c6e056bd3e7d558bb19053 Mon Sep 17 00:00:00 2001 From: alon Date: Thu, 9 Jun 2022 12:35:13 +0300 Subject: [PATCH 6/6] Remove chunk_size limitation. --- src/config/config.c | 2 +- tests/flow/tests_commands.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/config/config.c b/src/config/config.c index ab9891e8d..0a97ec1e7 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -149,7 +149,7 @@ int Config_SetIntraOperationParallelism(RedisModuleString *num_threads_string) { int Config_SetModelChunkSize(RedisModuleString *chunk_size_string) { long long val; int result = RedisModule_StringToLongLong(chunk_size_string, &val); - if (result != REDISMODULE_OK || val <= 0 || val > REDISAI_DEFAULT_MODEL_CHUNK_SIZE) { + if (result != REDISMODULE_OK || val <= 0) { return REDISMODULE_ERR; } ModelChunkSize = val; diff --git a/tests/flow/tests_commands.py b/tests/flow/tests_commands.py index 209bcde79..c8b5e7c72 100644 --- a/tests/flow/tests_commands.py +++ b/tests/flow/tests_commands.py @@ -610,7 +610,6 @@ def test_ai_config_errors(env): check_error_message(env, con, 'BACKENDSPATH: missing path argument', 'AI.CONFIG', 'BACKENDSPATH') check_error_message(env, con, 'MODEL_CHUNK_SIZE: missing chunk size', 'AI.CONFIG', 'MODEL_CHUNK_SIZE') check_error_message(env, con, 'MODEL_CHUNK_SIZE: invalid chunk size', 'AI.CONFIG', 'MODEL_CHUNK_SIZE', 'not_number') - check_error_message(env, con, 'MODEL_CHUNK_SIZE: invalid chunk size', 'AI.CONFIG', 'MODEL_CHUNK_SIZE', 512*1024*1024) check_error_message(env, con, "wrong number of arguments for 'AI.CONFIG' command", 'AI.CONFIG', 'GET') env.assertEqual(con.execute_command('AI.CONFIG', 'GET', 'bad_config'), None)