Skip to content

Commit 6986bde

Browse files
authored
Merge branch 'master' into align_script_get_command
2 parents 0b3e7f8 + d3d4501 commit 6986bde

37 files changed

+656
-197
lines changed

.circleci/config.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ commands:
138138
- artifacts/*.tgz
139139
- artifacts/*.tar
140140
- store_artifacts:
141-
path: tests/logs
141+
path: tests/flow/logs
142142

143143
valgrind-general-steps:
144144
parameters:
@@ -191,11 +191,10 @@ commands:
191191
name: Test
192192
command: |
193193
mkdir -p $HOME/tests
194-
docker run --gpus all -v $HOME/tests:/build/tests/logs -it --rm redisai-gpu:latest-x64-bionic-test
194+
docker run --gpus all -v $HOME/tests:/build/tests/flow/logs -it --rm redisai-gpu:latest-x64-bionic-test
195195
no_output_timeout: 40m
196196
- store_artifacts:
197-
path: tests/logs
198-
197+
path: /home/circleci/tests
199198

200199

201200
jobs:
@@ -254,8 +253,6 @@ jobs:
254253
root: bin/
255254
paths:
256255
- artifacts/*
257-
- store_artifacts:
258-
path: test/logs
259256

260257
coverage:
261258
docker:
@@ -284,6 +281,8 @@ jobs:
284281
make -C opt test SHOW=1 COV=1 CLUSTER=1
285282
make -C opt cov-upload
286283
no_output_timeout: 30m
284+
- store_artifacts:
285+
path: tests/flow/logs
287286

288287
valgrind:
289288
parameters:

Dockerfile.gpu-test

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ SHELL ["/bin/bash", "-c"]
2323

2424
ENV NVIDIA_VISIBLE_DEVICES all
2525
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
26-
26+
ENV LANG=en_US.UTF-8
27+
RUN apt-get update
28+
RUN apt-get install -y locales && \
29+
sed -i -e "s/# $LANG.*/$LANG UTF-8/" /etc/locale.gen && \
30+
dpkg-reconfigure --frontend=noninteractive locales && \
31+
update-locale LANG=$LANG
2732
WORKDIR /build
2833
COPY --from=redis /usr/local/ /usr/local/
2934

docs/commands.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ redis> AI.TENSORGET result{tag} VALUES
606606
```
607607

608608
### Redis Commands support.
609-
In RedisAI TorchScript now supports simple (non-blocking) Redis commnands via the `redis.execute` API. The following (usless) script gets a key name (`x{1}`), and an `int` value (3). First, the script `SET`s the value in the key. Next, the script `GET`s the value back from the key, and sets it in a tensor which is eventually stored under the key 'y{1}'. Note that the inputs are `str` and `int`. The script sets and gets the value and set it into a tensor.
609+
RedisAI TorchScript now supports simple (non-blocking) Redis commands via the `redis.execute` API. The following (useless) script gets a key name (`x{1}`), and an `int` value (3). First, the script `SET`s the value in the key. Next, the script `GET`s the value back from the key, and sets it in a tensor which is eventually stored under the key 'y{1}'. Note that the inputs are `str` and `int`. The script sets and gets the value and set it into a tensor.
610610

611611
```
612612
def redis_int_to_tensor(redis_value: int):
@@ -624,6 +624,30 @@ redis> AI.TENSORGET y{1} VALUES
624624
1) (integer) 3
625625
```
626626

627+
### RedisAI model execution support.
628+
RedisAI TorchScript also supports executing models which are stored in RedisAI by calling `redisAI.model_execute` command.
629+
The command receives 3 inputs:
630+
1. model name (string)
631+
2. model inputs (List of torch.Tensor)
632+
3. number of model outputs (int)
633+
Return value - the model execution output tensors (List of torch.Tensor)
634+
The following script creates two tensors, and executes the (tensorflow) model which is stored under the name 'tf_mul{1}' with these two tensors as inputs.
635+
```
636+
def test_model_execute(keys:List[str]):
637+
a = torch.tensor([[2.0, 3.0], [2.0, 3.0]])
638+
b = torch.tensor([[2.0, 3.0], [2.0, 3.0]])
639+
return redisAI.model_execute(keys[0], [a, b], 1) # assume keys[0] is the model name stored in RedisAI.
640+
```
641+
```
642+
redis> AI.SCRIPTEXECUTE redis_scripts{1} test_model_execute KEYS 1 {1} LIST_INPUTS 1 tf_mul{1} OUTPUTS 1 y{1}
643+
OK
644+
redis> AI.TENSORGET y{1} VALUES
645+
1) (float) 4
646+
2) (float) 9
647+
3) (float) 4
648+
4) (float) 9
649+
```
650+
627651
!!! warning "Intermediate memory overhead"
628652
The execution of scripts may generate intermediate tensors that are not allocated by the Redis allocator, but by whatever allocator is used in the backends (which may act on main memory or GPU memory, depending on the device), thus not being limited by `maxmemory` configuration settings of Redis.
629653

get_deps.sh

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,17 @@ else
4747
fi
4848
fi
4949

50-
git submodule update --init --recursive || true
50+
#git submodule update --init --recursive || true
51+
52+
if [ -f ${HERE}/opt/readies/bin/platform ]; then
53+
OS=$(python3 $HERE/opt/readies/bin/platform --os)
54+
ARCH=$(python3 $HERE/opt/readies/bin/platform --arch)
55+
else
56+
OS=`uname -s | tr '[:upper:]' '[:lower:]'`
57+
uname -m|grep aarch64 || ARCH=x64
58+
uname -m|grep x86 || ARCH=arm64v8
59+
fi
5160

52-
OS=$(python3 $HERE/opt/readies/bin/platform --os)
53-
ARCH=$(python3 $HERE/opt/readies/bin/platform --arch)
5461

5562
# avoid wget warnings on macOS
5663
[[ $OS == macos ]] && export LC_ALL=en_US.UTF-8
@@ -235,7 +242,7 @@ if [[ $WITH_PT != 0 ]]; then
235242
LIBTORCH_ARCHIVE=libtorch-${PT_BUILD}-${PT_OS}-${PT_ARCH}-${PT_VERSION}.tar.gz
236243

237244
if [[ $PT_REPACK == 1 ]]; then
238-
PT_VERSION=$PT_VERSION GPU=$GPU $HERE/opt/build/libtorch/repack.sh
245+
PT_VERSION=$PT_VERSION GPU=$GPU OS=${OS} ARCH=${ARCH} $HERE/opt/build/libtorch/repack.sh
239246
else
240247
LIBTORCH_URL=https://s3.amazonaws.com/redismodules/pytorch/$LIBTORCH_ARCHIVE
241248

opt/build/libtorch/repack.sh

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ set -e
66
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
77

88
ROOT=$HERE/../../..
9-
. $ROOT/opt/readies/shibumi/functions
9+
#. $ROOT/opt/readies/shibumi/functions
1010
ROOT=$(realpath $ROOT)
1111

1212
if [[ "$1" == "cpu" || $CPU == 1 ]]; then
@@ -24,8 +24,13 @@ else
2424
fi
2525
fi
2626

27-
OS=$(python3 $ROOT/opt/readies/bin/platform --os)
28-
ARCH=$(python3 $ROOT/opt/readies/bin/platform --arch)
27+
# set them internally or externally
28+
if [ -z ${OS} ]; then
29+
OS=$(python3 $ROOT/opt/readies/bin/platform --os)
30+
fi
31+
if [ -z ${ARCH} ]; then
32+
ARCH=$(python3 $ROOT/opt/readies/bin/platform --arch)
33+
fi
2934

3035
TARGET_DIR=$ROOT/deps/$OS-$ARCH-$DEVICE
3136

src/backends/backedns_api.h

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/backends/backends.c

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "redismodule.h"
1818
#include "config/config.h"
1919
#include "execution/background_workers.h"
20+
#include "execution/execution_contexts/modelRun_ctx.h"
2021

2122
static bool _ValidateFuncExists(RedisModuleCtx *ctx, void *func_ptr, const char *func_name,
2223
const char *backend_name, const char *path) {
@@ -40,6 +41,7 @@ static bool _ValidateFuncExists(RedisModuleCtx *ctx, void *func_ptr, const char
4041
*/
4142
int RAI_ExportFunc(const char *func_name, void **targetFuncPtr) {
4243

44+
// Retrieve info from RedisAI internals.
4345
if (strcmp("GetThreadId", func_name) == 0) {
4446
*targetFuncPtr = BGWorker_GetThreadId;
4547
} else if (strcmp("GetNumThreadsPerQueue", func_name) == 0) {
@@ -48,6 +50,40 @@ int RAI_ExportFunc(const char *func_name, void **targetFuncPtr) {
4850
*targetFuncPtr = Config_GetModelExecutionTimeout;
4951
} else if (strcmp("GetThreadsCount", func_name) == 0) {
5052
*targetFuncPtr = BGWorker_GetThreadsCount;
53+
54+
// Export RedisAI low level API functions.
55+
} else if (strcmp("RedisAI_InitError", func_name) == 0) {
56+
*targetFuncPtr = RAI_InitError;
57+
} else if (strcmp("RedisAI_FreeError", func_name) == 0) {
58+
*targetFuncPtr = RAI_FreeError;
59+
} else if (strcmp("RedisAI_GetError", func_name) == 0) {
60+
*targetFuncPtr = RAI_GetError;
61+
} else if (strcmp("RedisAI_TensorCreateFromDLTensor", func_name) == 0) {
62+
*targetFuncPtr = RAI_TensorCreateFromDLTensor;
63+
} else if (strcmp("RedisAI_TensorGetDLTensor", func_name) == 0) {
64+
*targetFuncPtr = RAI_TensorGetDLTensor;
65+
} else if (strcmp("RedisAI_TensorGetShallowCopy", func_name) == 0) {
66+
*targetFuncPtr = RAI_TensorGetShallowCopy;
67+
} else if (strcmp("RedisAI_TensorFree", func_name) == 0) {
68+
*targetFuncPtr = RAI_TensorFree;
69+
} else if (strcmp("RedisAI_GetModelFromKeyspace", func_name) == 0) {
70+
*targetFuncPtr = RAI_GetModelFromKeyspace;
71+
} else if (strcmp("RedisAI_ModelRunCtxCreate", func_name) == 0) {
72+
*targetFuncPtr = RAI_ModelRunCtxCreate;
73+
} else if (strcmp("RedisAI_ModelRunCtxAddInput", func_name) == 0) {
74+
*targetFuncPtr = RAI_ModelRunCtxAddInput;
75+
} else if (strcmp("RedisAI_ModelRunCtxNumOutputs", func_name) == 0) {
76+
*targetFuncPtr = RAI_ModelRunCtxNumOutputs;
77+
} else if (strcmp("RedisAI_ModelRunCtxAddOutput", func_name) == 0) {
78+
*targetFuncPtr = RAI_ModelRunCtxAddOutput;
79+
} else if (strcmp("RedisAI_ModelRunCtxOutputTensor", func_name) == 0) {
80+
*targetFuncPtr = RAI_ModelRunCtxOutputTensor;
81+
} else if (strcmp("RedisAI_ModelRunCtxFree", func_name) == 0) {
82+
*targetFuncPtr = RAI_ModelRunCtxFree;
83+
} else if (strcmp("RedisAI_ModelRun", func_name) == 0) {
84+
*targetFuncPtr = RAI_ModelRun;
85+
86+
// Export RedisModule API functions.
5187
} else {
5288
return RedisModule_GetApi(func_name, targetFuncPtr);
5389
}
@@ -244,15 +280,15 @@ int RAI_LoadBackend_Torch(RedisModuleCtx *ctx, const char *path) {
244280

245281
RAI_LoadedBackend backend = {0}; // Initialize all the callbacks to NULL.
246282

247-
int (*init_backend)(int (*)(const char *, void *));
248-
init_backend = (int (*)(int (*)(const char *, void *)))(unsigned long)dlsym(
283+
int (*init_backend)(int (*)(const char *, void **));
284+
init_backend = (int (*)(int (*)(const char *, void **)))(unsigned long)dlsym(
249285
handle, "RAI_InitBackendTorch");
250286
if (!_ValidateFuncExists(ctx, init_backend, "RAI_InitBackendTorch", "TORCH", path)) {
251287
goto error;
252288
}
253-
// Here we use the input callback to export functions from Redis to the backend,
254-
// by setting the backend's function pointers to the corresponding functions in Redis.
255-
init_backend(RedisModule_GetApi);
289+
// Here we use the input callback to export functions from Redis and Redis AI to the backend,
290+
// by setting the backend's function pointers to the corresponding functions in Redis/RedisAI.
291+
init_backend(RAI_ExportFunc);
256292

257293
backend.model_create =
258294
(RAI_Model * (*)(RAI_Backend, const char *, RAI_ModelOpts, const char *, size_t,

src/backends/backends_api.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
#include "redismodule.h"
5+
6+
#ifdef BACKENDS_API_EXTERN
7+
#define BACKENDS_API extern
8+
#endif
9+
10+
#ifndef BACKENDS_API
11+
#define BACKENDS_API
12+
#endif
13+
14+
typedef struct RAI_Tensor RAI_Tensor;
15+
typedef struct RAI_Model RAI_Model;
16+
typedef struct RAI_ModelRunCtx RAI_ModelRunCtx;
17+
typedef struct RAI_Error RAI_Error;
18+
19+
/**
20+
* @return The internal id of RedisAI current working thread.
21+
* id range is {0, ..., <threads_count>-1}. If this is called from a non
22+
* RedisAI BG thread, return -1.
23+
*/
24+
BACKENDS_API long (*RedisAI_GetThreadId)(void);
25+
26+
/**
27+
* @return The number of working threads in RedisAI. This number should be
28+
* equal to the number of threads per queue (load time config) * number of devices
29+
* registered in RedisAI (a new device is registered if a model is set to run on
30+
* this device in AI.MODELSTORE command.
31+
*/
32+
BACKENDS_API uintptr_t (*RedisAI_GetThreadsCount)(void);
33+
34+
/**
35+
* @return The number of working threads per device queue (load time config).
36+
*/
37+
BACKENDS_API long long (*RedisAI_GetNumThreadsPerQueue)(void);
38+
39+
/**
40+
* @return The maximal number of milliseconds that a model run session should run
41+
* before it is terminated forcefully (load time config).
42+
* Currently supported only fo onnxruntime backend.
43+
*/
44+
BACKENDS_API long long (*RedisAI_GetModelExecutionTimeout)(void);
45+
46+
/**
47+
* The following functions are part of RedisAI low level API (the full low level
48+
* API is defined in redisai.h). For every function below named "RedisAI_X", its
49+
* implementation can be found under the name "RAI_X" in RedisAI header files.
50+
*/
51+
52+
BACKENDS_API int (*RedisAI_InitError)(RAI_Error **err);
53+
BACKENDS_API void (*RedisAI_FreeError)(RAI_Error *err);
54+
BACKENDS_API const char *(*RedisAI_GetError)(RAI_Error *err);
55+
56+
BACKENDS_API RAI_Tensor *(*RedisAI_TensorCreateFromDLTensor)(DLManagedTensor *dl_tensor);
57+
BACKENDS_API DLTensor *(*RedisAI_TensorGetDLTensor)(RAI_Tensor *tensor);
58+
BACKENDS_API RAI_Tensor *(*RedisAI_TensorGetShallowCopy)(RAI_Tensor *t);
59+
BACKENDS_API void (*RedisAI_TensorFree)(RAI_Tensor *tensor);
60+
61+
BACKENDS_API RAI_ModelRunCtx *(*RedisAI_ModelRunCtxCreate)(RAI_Model *model);
62+
BACKENDS_API int (*RedisAI_GetModelFromKeyspace)(RedisModuleCtx *ctx, RedisModuleString *keyName,
63+
RAI_Model **model, int mode, RAI_Error *err);
64+
BACKENDS_API int (*RedisAI_ModelRunCtxAddInput)(RAI_ModelRunCtx *mctx, const char *inputName,
65+
RAI_Tensor *inputTensor);
66+
BACKENDS_API int (*RedisAI_ModelRunCtxAddOutput)(RAI_ModelRunCtx *mctx, const char *outputName);
67+
BACKENDS_API size_t (*RedisAI_ModelRunCtxNumOutputs)(RAI_ModelRunCtx *mctx);
68+
BACKENDS_API RAI_Tensor *(*RedisAI_ModelRunCtxOutputTensor)(RAI_ModelRunCtx *mctx, size_t index);
69+
BACKENDS_API void (*RedisAI_ModelRunCtxFree)(RAI_ModelRunCtx *mctx);
70+
BACKENDS_API int (*RedisAI_ModelRun)(RAI_ModelRunCtx **mctx, long long n, RAI_Error *err);

0 commit comments

Comments
 (0)