Skip to content

Set default backends path #924

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 9, 2022
42 changes: 12 additions & 30 deletions src/backends/backends.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,33 +92,17 @@ int RAI_ExportFunc(const char *func_name, void **targetFuncPtr) {
return REDISMODULE_OK;
}

RedisModuleString *RAI_GetModulePath(RedisModuleCtx *ctx) {
void RAI_SetBackendsDefaultPath(char **backends_path) {
RedisModule_Assert(*backends_path == NULL);
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;
}

RedisModuleString *RAI_GetBackendsPath(RedisModuleCtx *ctx) {
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);
}

return backends_path;
// Retrieve the info about the module's dynamic library, and extract the .so file dir name.
RedisModule_Assert(dladdr(RAI_SetBackendsDefaultPath, &info) != 0);
const char *dyn_lib_dir_name = dirname((char *)info.dli_fname);

// Populate backends_path global string with the default path.
size_t backends_default_path_len = strlen(dyn_lib_dir_name) + strlen("/backends");
*backends_path = RedisModule_Alloc(backends_default_path_len + 1);
RedisModule_Assert(sprintf(*backends_path, "%s/backends", dyn_lib_dir_name) > 0);
Comment on lines +103 to +105
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RedisModule_CreateStringPrintf?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that better? We don't use HoldString or something here (so I can't see why using RedisModuleString object has an advantage...)

}

const char *RAI_GetBackendName(RAI_Backend backend) {
Expand Down Expand Up @@ -460,10 +444,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;
Expand Down
5 changes: 5 additions & 0 deletions src/backends/backends.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 Set the default backends path (<module_path>/backends) in backends_path place holder.
*/
void RAI_SetBackendsDefaultPath(char **backends_path);
36 changes: 18 additions & 18 deletions src/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@
#include "redismodule.h"
#include "backends/backends.h"

// Default configs
char *BackendsPath = NULL; // Path to backends dir.

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;
// 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) {
Expand Down Expand Up @@ -111,9 +111,8 @@ int Config_LoadBackend(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
}

void Config_SetBackendsPath(const char *path) {
if (BackendsPath != NULL) {
RedisModule_Free(BackendsPath);
}
RedisModule_Assert(BackendsPath != NULL && path != NULL);
RedisModule_Free(BackendsPath);
BackendsPath = RedisModule_Strdup(path);
}

Expand Down Expand Up @@ -188,6 +187,7 @@ int Config_SetLoadTimeParams(RedisModuleCtx *ctx, RedisModuleString *const *argv
}

// need BACKENDSPATH set up before loading specific backends
RAI_SetBackendsDefaultPath(&BackendsPath);
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);
Expand Down
7 changes: 4 additions & 3 deletions src/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ 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_DEFAULT_MODEL_CHUNK_SIZE (511 * 1024 * 1024)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the addition?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use this constant in Config_SetModelChunkSize


/**
* Get number of threads used for parallelism between independent operations, by
* backend.
Expand Down Expand Up @@ -81,9 +83,8 @@ char *Config_GetBackendsPath(void);
int Config_LoadBackend(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);

/**
* Helper method for AI.CONFIG BACKENDSPATH
* <default_location_of_backend_libraries>
* @param path string containing backend path
* Helper method for AI.CONFIG BACKENDSPATH <default_location_of_backend_libraries>
* @param path string containing backend path.
*/
void Config_SetBackendsPath(const char *path);

Expand Down
7 changes: 7 additions & 0 deletions src/redisai.c
Original file line number Diff line number Diff line change
Expand Up @@ -1279,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
Expand Down Expand Up @@ -1424,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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the minimal redis version supporting this event? does it align with our min_redis_version on our ramp files?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this API is supported from version 6.0.0, which is the minimal version for RedisAI anyway....


if (Config_SetLoadTimeParams(ctx, argv, argc) != REDISMODULE_OK) {
return REDISMODULE_ERR;
}
Expand Down
1 change: 1 addition & 0 deletions tests/flow/includes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion tests/flow/tests_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -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') # <path_to_module_dir>/backends
res = con.execute_command('AI.CONFIG', 'GET', 'MODEL_CHUNK_SIZE')
env.assertEqual(res, 511*1024*1024)

Expand Down Expand Up @@ -609,6 +609,7 @@ 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, "wrong number of arguments for 'AI.CONFIG' command", 'AI.CONFIG', 'GET')
env.assertEqual(con.execute_command('AI.CONFIG', 'GET', 'bad_config'), None)
2 changes: 1 addition & 1 deletion tests/flow/tests_onnx.py
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't you remove RLTest parallelism?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes... But I don't think that this addition is bad, as we might wan't to use the parallelism in the future. WDYT?

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',
Expand Down