├── .circleci
└── config.yml
├── .clang-format
├── .dockerignore
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── release-drafter-config.yml
└── workflows
│ ├── deploy-docs.yaml
│ ├── release-drafter.yml
│ ├── trigger-build-and-test-gpu.yaml
│ └── trigger-valgrind.yaml
├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── LICENSE.txt
├── README.md
├── commands.json
├── docs
├── Doxyfile
├── clients.md
├── commands.md
├── configuration.md
├── contrib.md
├── developer-backends.md
├── developer.md
├── examples.md
├── generate_llapi_reference.py
├── gtm.js
├── images
│ ├── RedisAI_data_structures_and_backends.png
│ ├── cat_classified.jpg
│ ├── favicon.png
│ ├── flask_modelserver.png
│ ├── graph.pb.png
│ ├── logo.svg
│ ├── logo_small.png
│ ├── redisai_modelserver.png
│ └── tfs_modelserver.png
├── index.md
├── intro.md
├── performance.md
├── quickstart.md
├── requirements-llapi.txt
├── requirements.txt
└── snippets
│ └── notebooks
│ ├── data
│ └── cat.jpg
│ └── models
│ └── tensorflow
│ ├── imagenet
│ └── resnet50.pb
│ ├── mobilenet
│ └── mobilenet_224.pb
│ └── tinyyolo
│ └── tinyyolo.pb
├── get_deps.sh
├── hooks
└── post_checkout
├── license
├── RSALv2.txt
└── SSPLv1.txt
├── mkdocs.yml
├── opt
├── Makefile
├── build
│ ├── backends.rules
│ ├── docker
│ │ ├── Makefile
│ │ ├── dockerfile-gpu-test.tmpl
│ │ ├── dockerfile.tmpl
│ │ └── templates
│ │ │ └── gpu.yml
│ ├── dockerparts
│ │ ├── apt.yml
│ │ └── cmake.yml
│ └── onnxruntime
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ ├── dockerfile.tmpl
│ │ └── pack.sh
├── clang-check-all.sh
├── clang-format-all.sh
├── getver
├── pack.sh
├── redis_valgrind.sup
└── system-setup.py
├── ramp-light.yml
├── ramp-rce.yml
├── ramp.yml
├── src
├── CMakeLists.txt
├── backends
│ ├── backends.c
│ ├── backends.h
│ ├── backends_api.h
│ ├── libtflite_c
│ │ ├── CMakeLists.txt
│ │ ├── tflite_c.cpp
│ │ └── tflite_c.h
│ ├── libtorch_c
│ │ ├── CMakeLists.txt
│ │ ├── torch_c.cpp
│ │ ├── torch_c.h
│ │ └── torch_extensions
│ │ │ ├── torch_redis.cpp
│ │ │ └── torch_redis.h
│ ├── onnx_allocator
│ │ ├── CMakeLists.txt
│ │ ├── onnx_allocator.cpp
│ │ └── onnx_allocator.h
│ ├── onnx_timeout.c
│ ├── onnx_timeout.h
│ ├── onnxruntime.c
│ ├── onnxruntime.h
│ ├── tensorflow.c
│ ├── tensorflow.h
│ ├── tflite.c
│ ├── tflite.h
│ ├── torch.c
│ ├── torch.h
│ ├── util.c
│ └── util.h
├── config
│ ├── config.c
│ ├── config.h
│ └── gdb_config.h
├── execution
│ ├── DAG
│ │ ├── dag.c
│ │ ├── dag.h
│ │ ├── dag_builder.c
│ │ ├── dag_builder.h
│ │ ├── dag_execute.c
│ │ ├── dag_execute.h
│ │ ├── dag_op.c
│ │ └── dag_op.h
│ ├── background_workers.c
│ ├── background_workers.h
│ ├── command_parser.c
│ ├── command_parser.h
│ ├── execution_contexts
│ │ ├── execution_ctx.c
│ │ ├── execution_ctx.h
│ │ ├── modelRun_ctx.c
│ │ ├── modelRun_ctx.h
│ │ ├── scriptRun_ctx.c
│ │ └── scriptRun_ctx.h
│ ├── parsing
│ │ ├── dag_parser.c
│ │ ├── dag_parser.h
│ │ ├── deprecated.c
│ │ ├── deprecated.h
│ │ ├── model_commands_parser.c
│ │ ├── model_commands_parser.h
│ │ ├── parse_utils.c
│ │ ├── parse_utils.h
│ │ ├── script_commands_parser.c
│ │ ├── script_commands_parser.h
│ │ ├── tensor_commands_parsing.c
│ │ └── tensor_commands_parsing.h
│ ├── run_info.c
│ ├── run_info.h
│ ├── run_queue_info.c
│ ├── run_queue_info.h
│ ├── utils.c
│ └── utils.h
├── redis_ai_objects
│ ├── err.c
│ ├── err.h
│ ├── model.c
│ ├── model.h
│ ├── model_struct.h
│ ├── script.c
│ ├── script.h
│ ├── script_struct.h
│ ├── stats.c
│ ├── stats.h
│ ├── tensor.c
│ ├── tensor.h
│ └── tensor_struct.h
├── redis_ai_types
│ ├── model_type.c
│ ├── model_type.h
│ ├── script_type.c
│ ├── script_type.h
│ ├── tensor_type.c
│ └── tensor_type.h
├── redisai.c
├── redisai.h
├── redismodule.h
├── rmutil
│ ├── alloc.c
│ ├── alloc.h
│ ├── args.c
│ ├── args.h
│ ├── sds.c
│ ├── sds.h
│ └── sdsalloc.h
├── serialization
│ ├── AOF
│ │ ├── rai_aof_rewrite.c
│ │ └── rai_aof_rewrite.h
│ ├── RDB
│ │ ├── decoder
│ │ │ ├── current
│ │ │ │ └── v4
│ │ │ │ │ ├── decode_v4.c
│ │ │ │ │ └── decode_v4.h
│ │ │ ├── decode_previous.c
│ │ │ ├── decode_previous.h
│ │ │ ├── previous
│ │ │ │ ├── v0
│ │ │ │ │ ├── decode_v0.c
│ │ │ │ │ └── decode_v0.h
│ │ │ │ ├── v1
│ │ │ │ │ ├── decode_v1.c
│ │ │ │ │ └── decode_v1.h
│ │ │ │ ├── v2
│ │ │ │ │ ├── decode_v2.c
│ │ │ │ │ └── decode_v2.h
│ │ │ │ └── v3
│ │ │ │ │ ├── decode_v3.c
│ │ │ │ │ └── decode_v3.h
│ │ │ ├── rai_rdb_decoder.c
│ │ │ └── rai_rdb_decoder.h
│ │ └── encoder
│ │ │ ├── rai_rdb_encode.c
│ │ │ ├── rai_rdb_encode.h
│ │ │ └── v4
│ │ │ ├── encode_v4.c
│ │ │ └── encode_v4.h
│ ├── ai_datatypes.c
│ └── serialization_include.h
├── util
│ ├── arr.h
│ ├── dict.c
│ ├── dict.h
│ ├── dictionaries.c
│ ├── dictionaries.h
│ ├── queue.c
│ ├── queue.h
│ ├── redisai_memory.h
│ ├── siphash.c.inc
│ ├── string_utils.c
│ └── string_utils.h
└── version.h
└── tests
├── __init__.py
├── flow
├── __init__.py
├── includes.py
├── onnx_benchmark.py
├── test_data_files.txt
├── test_serializations.py
├── test_torchscript_extensions.py
├── tests_commands.py
├── tests_common.py
├── tests_dag.py
├── tests_dag_basic.py
├── tests_dag_errors.py
├── tests_deprecated_commands.py
├── tests_gears_llapi.py
├── tests_llapi.py
├── tests_onnx.py
├── tests_pytorch.py
├── tests_sanitizer.py
├── tests_setup
│ ├── Install_RedisGears.sh
│ ├── test_requirements.txt
│ ├── tests.sh
│ └── valgrind.sh
├── tests_tensorflow.py
└── tests_tflite.py
├── module
├── CMakeLists.txt
├── DAG_utils.c
├── DAG_utils.h
└── LLAPI.c
└── qa
├── RS_VERSIONS
├── RS_VERSIONS-lite
├── nightly.json
├── release.json
└── run
/.clang-format:
--------------------------------------------------------------------------------
1 | IndentWidth: 4
2 | ColumnLimit: 100
3 | SortIncludes: false
4 | AlignEscapedNewlinesLeft: false
5 | AlignConsecutiveMacros: true
6 | SpacesBeforeTrailingComments: 1
7 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /deps/
3 | /docs/
4 | /install*
5 | /build/
6 | .venv/
7 | venv*/
8 | /[0-9]*/
9 | *.zip
10 | *.tgz
11 | *.tar.gz
12 | /VARAINT
13 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pb filter=lfs diff=lfs merge=lfs -text
2 | *.pt filter=lfs diff=lfs merge=lfs -text
3 | *.onnx filter=lfs diff=lfs merge=lfs -text
4 | *.tflite filter=lfs diff=lfs merge=lfs -text
5 | *.jpg filter=lfs diff=lfs merge=lfs -text
6 | *.raw filter=lfs diff=lfs merge=lfs -text
7 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve RedisAI
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. ...
16 | 2. ....
17 |
18 | **Expected behavior**
19 | A clear and concise description of what you expected to happen.
20 |
21 | **Screenshots**
22 | If applicable, add screenshots to help explain your problem.
23 |
24 | **Environment (please complete the following information):**
25 | - OS: [e.g. ubuntu 20.04]
26 | - Version [e.g. 1.2.2]
27 | - Platfrom [e.g. x86, Jetson, ARM]
28 | - Runtime [e.g. CPU, CUDA]
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for pushing RedisAI further
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/release-drafter-config.yml:
--------------------------------------------------------------------------------
1 | name-template: '$NEXT_MAJOR_VERSION'
2 | tag-template: 'v$NEXT_MAJOR_VERSION'
3 | autolabeler:
4 | - label: 'maintenance'
5 | files:
6 | - '*.md'
7 | - '.github/*'
8 | - label: 'bug'
9 | branch:
10 | - '/bug-.+'
11 | - label: 'maintenance'
12 | branch:
13 | - '/maintenance-.+'
14 | - label: 'feature'
15 | branch:
16 | - '/feature-.+'
17 | categories:
18 | - title: 'Breaking Changes'
19 | labels:
20 | - 'breakingchange'
21 |
22 | - title: '🧪 Experimental Features'
23 | labels:
24 | - 'experimental'
25 | - title: '🚀 New Features'
26 | labels:
27 | - 'feature'
28 | - 'enhancement'
29 | - title: '🐛 Bug Fixes'
30 | labels:
31 | - 'fix'
32 | - 'bugfix'
33 | - 'bug'
34 | - 'BUG'
35 | - title: '🧰 Maintenance'
36 | label: 'maintenance'
37 | change-template: '- $TITLE (#$NUMBER)'
38 | exclude-labels:
39 | - 'skip-changelog'
40 | template: |
41 | ## Changes
42 |
43 | $CHANGES
44 |
45 | ## Contributors
46 | We'd like to thank all the contributors who worked on this release!
47 |
48 | $CONTRIBUTORS
49 |
50 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-docs.yaml:
--------------------------------------------------------------------------------
1 | name: Deploy docs to website
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - master
8 | - '[0-9]+.[0-9]+'
9 | paths:
10 | - 'mkdocs.yml'
11 | - 'docs/**'
12 |
13 | jobs:
14 | deploy:
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v2.1.1
19 | - name: Set up Python 3.x
20 | uses: actions/setup-python@v2
21 | with:
22 | python-version: '3.9'
23 | - name: Display Python version
24 | run: python -c "import sys; print(sys.version)"
25 | - name: Install docs dependencies
26 | run: pip install -r docs/requirements.txt
27 | - name: Get entire project
28 | run: git fetch -t
29 | - name: Build docs
30 | run: mkdocs build
31 | - uses: jakejarvis/s3-sync-action@v0.5.1
32 | with:
33 | args: --acl public-read --follow-symlinks
34 | env:
35 | AWS_S3_BUCKET: ${{ secrets.DOCS_AWS_S3_BUCKET }}
36 | AWS_ACCESS_KEY_ID: ${{ secrets.DOCS_AWS_ACCESS_KEY_ID }}
37 | AWS_SECRET_ACCESS_KEY: ${{ secrets.DOCS_AWS_SECRET_ACCESS_KEY }}
38 | DEST_DIR: ${{ secrets.DOCS_AWS_S3_DIR }}
39 | SOURCE_DIR: 'site'
40 |
--------------------------------------------------------------------------------
/.github/workflows/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name: Release Drafter
2 |
3 | on:
4 | push:
5 | # branches to consider in the event; optional, defaults to all
6 | branches:
7 | - master
8 |
9 | jobs:
10 | update_release_draft:
11 | runs-on: ubuntu-latest
12 | steps:
13 | # Drafts your next Release notes as Pull Requests are merged into "master"
14 | - uses: release-drafter/release-drafter@v5
15 | with:
16 | # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml
17 | config-name: release-drafter-config.yml
18 | env:
19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20 |
--------------------------------------------------------------------------------
/.github/workflows/trigger-build-and-test-gpu.yaml:
--------------------------------------------------------------------------------
1 | # https://github.com/marketplace/actions/run-circle-ci-on-label
2 | name: build-and-test-gpu
3 |
4 | on:
5 | pull_request:
6 | types:
7 | - labeled
8 | - synchronize
9 | - assigned
10 |
11 | jobs:
12 | valgrind_general:
13 | if: github.event.label.name == 'ci-test'
14 | runs-on: ubuntu-latest
15 | name: Run build and test gpu
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: circle-ci job runner
20 | id: curl-circle-ci
21 | uses: Open-Source-Contrib/circle-ci-trigger-action@latest
22 | with:
23 | circle_ci_token: ${{ secrets.CIRCLE_CI_SECRET}}
24 | circle_ci_job: build-and-test-gpu
25 | circle_ci_project_url: ${{ github.event.pull_request.head.ref }}
26 |
--------------------------------------------------------------------------------
/.github/workflows/trigger-valgrind.yaml:
--------------------------------------------------------------------------------
1 | # https://github.com/marketplace/actions/run-circle-ci-on-label
2 | name: valgrind-general-run
3 |
4 | on:
5 | pull_request:
6 | types:
7 | - labeled
8 | - synchronize
9 | - assigned
10 |
11 | jobs:
12 | valgrind_general:
13 | if: github.event.label.name == 'ci-test'
14 | runs-on: ubuntu-latest
15 | name: Run valgrind general
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: circle-ci job runner
20 | id: curl-circle-ci
21 | uses: Open-Source-Contrib/circle-ci-trigger-action@latest
22 | with:
23 | circle_ci_token: ${{ secrets.CIRCLE_CI_SECRET}}
24 | circle_ci_job: valgrind-general
25 | circle_ci_project_url: ${{ github.event.pull_request.head.ref }}
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | /deps/
3 | /build/
4 | /install*
5 | /tests/venv/
6 | logs/
7 | /tests/logs/
8 | .env/
9 | env*/
10 | .venv/
11 | venv*/
12 | /install
13 | /[0-9]*/
14 | *.zip
15 | *.tgz
16 | *.tar.gz
17 | /VARIANT
18 |
19 | # Docs API reference
20 | docs/api_reference.md
21 |
22 | ### Cmake auto tools
23 | cmake-build-debug
24 |
25 | # Misc
26 | .DS_Store
27 | *.swp
28 |
29 | # Python
30 | __pycache__
31 | *.pyc
32 |
33 | # Eclipse (if that's your jam...)
34 | .project
35 | .cproject
36 | .settings/
37 |
38 | # VSCode
39 | *.vscode
40 |
41 | # Prerequisites
42 | *.d
43 |
44 | # Object files
45 | *.o
46 | *.ko
47 | *.obj
48 | *.elf
49 |
50 | # Linker output
51 | *.ilk
52 | *.map
53 | *.exp
54 |
55 | # Precompiled Headers
56 | *.gch
57 | *.pch
58 |
59 | # Libraries
60 | *.lib
61 | *.a
62 | *.la
63 | *.lo
64 |
65 | # Shared objects (inc. Windows DLLs)
66 | *.dll
67 | *.so
68 | *.so.*
69 | *.dylib
70 |
71 | # Executables
72 | *.exe
73 | *.out
74 | *.app
75 | *.i*86
76 | *.x86_64
77 | *.hex
78 |
79 | # Debug files
80 | *.dSYM/
81 | *.su
82 | *.idb
83 | *.pdb
84 |
85 | # Debug/Profile files
86 | # ignore perf html reports
87 | *.html
88 |
89 | # Kernel Module Compile Results
90 | *.mod*
91 | *.cmd
92 | .tmp_versions/
93 | modules.order
94 | Module.symvers
95 | Mkfile.old
96 | dkms.conf
97 |
98 | ### from JetBrains template
99 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
100 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
101 |
102 | .idea
103 | .idea/
104 | .idea/*
105 |
106 | # User-specific stuff:
107 | .idea/workspace.xml
108 | .idea/tasks.xml
109 | .idea/dictionaries
110 | .idea/vcs.xml
111 | .idea/jsLibraryMappings.xml
112 |
113 | # Sensitive or high-churn files:
114 | .idea/dataSources.ids
115 | .idea/dataSources.xml
116 | .idea/dataSources.local.xml
117 | .idea/sqlDataSources.xml
118 | .idea/dynamic.xml
119 | .idea/uiDesigner.xml
120 |
121 | # Gradle:
122 | .idea/gradle.xml
123 | .idea/libraries
124 |
125 | # Mongo Explorer plugin:
126 | .idea/mongoSettings.xml
127 |
128 | ## File-based project format:
129 | *.iws
130 |
131 | ## Plugin-specific files:
132 |
133 | # IntelliJ
134 | /out/
135 |
136 | # mpeltonen/sbt-idea plugin
137 | .idea_modules/
138 |
139 | # docs site
140 | site/
141 |
142 | # test data
143 | tests/flow/test_data
144 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "opt/readies"]
2 | path = opt/readies
3 | url = https://github.com/RedisLabsModules/readies.git
4 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Except as otherwise specified in the source code headers for specific files, the source code in this repository is made available to you under your choice of
2 | (i) Redis Source Available License 2.0 (RSALv2) or (ii) the Server Side Public License v1 (SSPLv1)
3 |
--------------------------------------------------------------------------------
/docs/clients.md:
--------------------------------------------------------------------------------
1 | # RedisAI Clients
2 |
3 | Some languages already have client libraries that provide support for RedisAI's commands. The following table lists the known ones:
4 |
5 | | Project | Language | License | Author | URL |
6 | | ------- | -------- | ------- | ------ | --- |
7 | | JRedisAI | Java | BSD-3 | [RedisLabs](https://redislabs.com/) | [Github](https://github.com/RedisAI/JRedisAI) |
8 | | redisai-py | Python | BSD-3 | [RedisLabs](https://redislabs.com/) | [Github](https://github.com/RedisAI/redisai-py) |
9 | | redisai-go | Go | BSD-3 | [RedisLabs](https://redislabs.com/) | [Github](https://github.com/RedisAI/redisai-go) |
10 | | redisai-js | Typescript/Javascript | BSD-3 | [RedisLabs](https://redislabs.com/) | [Github](https://github.com/RedisAI/redisai-js) |
11 | | redis-modules-sdk | TypeScript | BSD-3-Clause | [Dani Tseitlin](https://github.com/danitseitlin) | [Github](https://github.com/danitseitlin/redis-modules-sdk) |
12 | | redis-modules-java | Java | Apache-2.0 | [dengliming](https://github.com/dengliming) | [Github](https://github.com/dengliming/redis-modules-java) |
13 | | smartredis | C++ | BSD-2-Clause | [Cray Labs](https://github.com/CrayLabs) | [Github](https://github.com/CrayLabs/SmartRedis) |
14 | | smartredis | C | BSD-2-Clause | [Cray Labs](https://github.com/CrayLabs) | [Github](https://github.com/CrayLabs/SmartRedis) |
15 | | smartredis | Fortran | BSD-2-Clause | [Cray Labs](https://github.com/CrayLabs) | [Github](https://github.com/CrayLabs/SmartRedis) |
16 | | smartredis | Python | BSD-2-Clause | [Cray Labs](https://github.com/CrayLabs) | [Github](https://github.com/CrayLabs/SmartRedis) |
17 |
18 |
19 |
20 | The full documentation for RedisAI's API can be found at the [Commands page](commands.md).
21 |
--------------------------------------------------------------------------------
/docs/contrib.md:
--------------------------------------------------------------------------------
1 | # Contributor Agreement
2 | Please refer to the following page for the agreement: [Redis Labs Software Grant and Contributor License Agreement](https://cla-assistant.io/RedisAI/RedisAI)
3 |
--------------------------------------------------------------------------------
/docs/developer-backends.md:
--------------------------------------------------------------------------------
1 | # RedisAI Development Backends
2 |
3 | This document describes how ONNXRuntime backend can be built from this repository.
4 | We build the ONNXRuntime library with the DISABLE_EXTERNAL_INITIALIZERS=ON build flag. As a result, loading ONNX models that use external files to store the initial (usually very large) values of the model's operations, is invalid. Hence, initialization values must be part of the serialized model, which is also the standard use case.
5 |
6 | It is compiled in a docker, which is responsible for the configuration and installation of all tools required the build process.
7 |
8 | To follow these instructions, this repository must be cloned with all of its submodules (i.e *git clone --recursive https://github.com/redisai/redisai*)
9 |
10 | GNU Make is used as a runner for the dockerfile generator. Python is the language used for the generator script, and jinja is the templating library used to create the docker file from the template *dockerfile.tmpl*, located in the `/opt/build/onnxruntime` directory.
11 |
12 | ### Tools
13 |
14 | Building the backend requires installation of the following tools:
15 |
16 | 1. gnu make
17 | 1. python (3.0 or higher)
18 | 1. docker
19 | 1. jinja2
20 |
21 | On ubuntu bionic these can be installed by running the following steps, to install python3, create a virtual environment, and install the jinja templating dependency. Replace */path/to/venv* with your desired virtualenv location.
22 |
23 | ```
24 | sudo apt install python3 python3-dev make docker
25 | python3 -m venv /path/to/venv
26 | source /path/to/venv/bin/activate
27 | pip install jinja2
28 | ```
29 |
30 | -------
31 |
32 | **Compilation target devices:**
33 |
34 | 1. x86\_64 bit linux systems
35 |
36 | 1. x86\_64 bit linux systems with a GPU
37 |
38 | **Directory:** opt/build/onnxruntime
39 |
40 | **Build options:**
41 |
42 | 1. To build run *make*
43 |
44 | 1. To build with GPU support on x86\_64 run *make GPU=1*
45 |
--------------------------------------------------------------------------------
/docs/examples.md:
--------------------------------------------------------------------------------
1 | # RedisAI Examples
2 | The following sections consist of various sample projects and python notebook examples showing the uses for RedisAI.
3 |
4 | To contribute your example (and get the credit for it), click the "Edit this page" button at the top to submit a Pull Request.
5 |
6 | ## Sample projects
7 | This is a list of RedisAI sample projects that can be used as-is or as an inspiration source.
8 |
9 | | Example | Description | Author | License | URL |
10 | | --- | --- | --- | --- | --- |
11 | | RedisAI showcase | Demonstrates using RedisAI functionality, backends and clients | [RedisLabs](https://redislabs.com/) | MIT | [git](https://github.com/RedisAI/redisai-examples) |
12 | | ChatBotDemo | An example of using RedisAI and a Web App for Conversational AI (i.e. chatbot) | [RedisLabs](https://redislabs.com/) | Apache-2.0 | [git](https://github.com/RedisAI/ChatBotDemo) |
13 | | AnimalRecognitionDemo | An example of using Redis Streams, RedisGears and RedisAI for Realtime Video Analytics (i.e. filtering cats) | [RedisLabs](https://redislabs.com/) | BSD-3-Clause | [git](https://github.com/RedisGears/AnimalRecognitionDemo) |
14 | | EdgeRealtimeVideoAnalytics | An example of using Redis Streams, RedisGears, RedisAI and RedisTimeSeries for Realtime Video Analytics (i.e. counting people) | [RedisLabs](https://redislabs.com/) | Apache-2.0 | [git](https://github.com/RedisGears/EdgeRealtimeVideoAnalytics) |
15 | | demo-market-basket-analysis | An exmaple of prediciting shopping baskets on passed purchases | [RedisLabs](https://redislabs.com/) | | [git](https://github.com/RedisLabs-Field-Engineering/demo-market-basket-analysis) |
16 |
--------------------------------------------------------------------------------
/docs/gtm.js:
--------------------------------------------------------------------------------
1 | (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
2 | new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
3 | j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
4 | 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
5 | })(window,document,'script','dataLayer','GTM-MDHLQC4');
6 |
--------------------------------------------------------------------------------
/docs/images/RedisAI_data_structures_and_backends.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedisAI/redis-inference-optimization/c458c5f83e93ee07963af7123e9ad17b52389bcd/docs/images/RedisAI_data_structures_and_backends.png
--------------------------------------------------------------------------------
/docs/images/cat_classified.jpg:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:736790963619339be55eea9ae4986751e744d8e9670a14b3aaf5d95d41fcc056
3 | size 26775
4 |
--------------------------------------------------------------------------------
/docs/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedisAI/redis-inference-optimization/c458c5f83e93ee07963af7123e9ad17b52389bcd/docs/images/favicon.png
--------------------------------------------------------------------------------
/docs/images/flask_modelserver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedisAI/redis-inference-optimization/c458c5f83e93ee07963af7123e9ad17b52389bcd/docs/images/flask_modelserver.png
--------------------------------------------------------------------------------
/docs/images/graph.pb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedisAI/redis-inference-optimization/c458c5f83e93ee07963af7123e9ad17b52389bcd/docs/images/graph.pb.png
--------------------------------------------------------------------------------
/docs/images/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
--------------------------------------------------------------------------------
/docs/images/logo_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedisAI/redis-inference-optimization/c458c5f83e93ee07963af7123e9ad17b52389bcd/docs/images/logo_small.png
--------------------------------------------------------------------------------
/docs/images/redisai_modelserver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedisAI/redis-inference-optimization/c458c5f83e93ee07963af7123e9ad17b52389bcd/docs/images/redisai_modelserver.png
--------------------------------------------------------------------------------
/docs/images/tfs_modelserver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedisAI/redis-inference-optimization/c458c5f83e93ee07963af7123e9ad17b52389bcd/docs/images/tfs_modelserver.png
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | #
RedisAI
2 | [](https://forum.redislabs.com/c/modules/redisai)
3 | [](https://discord.gg/rTQm7UZ)
4 |
5 | RedisAI is a Redis module for executing Deep Learning/Machine Learning models and managing their data. Its purpose is being a "workhorse" for model serving, by providing out-of-the-box support for popular DL/ML frameworks and unparalleled performance. **RedisAI both maximizes computation throughput and reduces latency by adhering to the principle of data locality**, as well as simplifies the deployment and serving of graphs by leveraging on Redis' production-proven infrastructure.
6 |
7 | ## Where Next?
8 | * The [Introduction](intro.md) is the recommended starting point
9 | * The [Quickstart](quickstart.md) page provides information about building, installing and running RedisAI
10 | * The [Commands](commands.md) page is a reference of the RedisAI API
11 | * The [RedisGears integration](https://oss.redis.com/redisgears/master/redisai.html) page is a reference of the built-in integration of [RedisGears](https://oss.redis.com/redisgears/) with RedisAI via a Python plugin.
12 | * The [Clients](clients.md) page lists RedisAI clients by programming language
13 | * The [Configuration](configuration.md) page explains how to configure RedisAI
14 | * The [Performance](performance.md) page provides instructions for running benchmarks with RedisAI
15 | * The [Developer](developer.md) page has more information about the design and implementation of the RedisAI module
16 |
17 | ## Quick Links
18 | * [Source code repository](https://github.com/RedisAI/RedisAI)
19 | * [Releases](https://github.com/RedisAI/RedisAI/releases)
20 | * [Docker image](https://hub.docker.com/r/redislabs/redisai/)
21 |
22 | ## Contact Us
23 | If you have questions, want to provide feedback or perhaps report an issue or [contribute some code](contrib.md), here's where we're listening to you:
24 |
25 | * [Forum](https://forum.redis.com/c/modules/redisai)
26 | * [Repository](https://github.com/RedisAI/RedisAI/issues)
27 |
28 | ## License
29 | RedisAI is licensed under the [Redis Source Available License Agreement](https://github.com/RedisAI/RedisAI/blob/master/LICENSE).
30 |
--------------------------------------------------------------------------------
/docs/quickstart.md:
--------------------------------------------------------------------------------
1 | # RedisAI Quickstart
2 | RedisAI is a Redis module. To run it you'll need a Redis server (v6.0.0 or greater), the module's shared library, and its dependencies.
3 |
4 | The following sections describe how to get started with RedisAI.
5 |
6 | ## Docker
7 | The quickest way to try RedisAI is by launching its official Docker container images.
8 |
9 | ### On a CPU only machine
10 | ```
11 | docker run -p 6379:6379 redislabs/redisai:1.2.7-cpu-bionic
12 | ```
13 |
14 | ### On a GPU machine
15 | For GPU support you will need a machine you'll need a machine that has Nvidia driver (CUDA 11.2 and cuDNN 8.1), nvidia-container-toolkit and Docker 19.03+ installed. For detailed information, checkout [nvidia-docker documentation](https://github.com/NVIDIA/nvidia-docker)
16 | ```
17 | docker run -p 6379:6379 --gpus all -it --rm redislabs/redisai:1.2.7-gpu-bionic
18 | ```
19 |
20 |
21 | ## Building
22 | You can compile and build the module from its source code. The [Developer](developer.md) page has more information about the design and implementation of the RedisAI module and how to contribute.
23 |
24 | ### Prerequisites
25 | * Packages: git, python3, make, wget, g++/clang, & unzip
26 | * CMake 3.0 or higher needs to be installed.
27 | * CUDA 11.2 and cuDNN 8.1 or higher needs to be installed if GPU support is required.
28 | * Redis v6.0.0 or greater.
29 |
30 | ### Get the Source Code
31 | You can obtain the module's source code by cloning the project's repository using git like so:
32 |
33 | ```sh
34 | git clone --recursive https://github.com/RedisAI/RedisAI
35 | ```
36 |
37 | Switch to the project's directory with:
38 |
39 | ```sh
40 | cd RedisAI
41 | ```
42 |
43 | ### Building the Dependencies
44 | Use the following script to download and build the libraries of the various RedisAI backends (TensorFlow, PyTorch, ONNXRuntime) for CPU only:
45 |
46 | ```sh
47 | bash get_deps.sh
48 | ```
49 |
50 | Alternatively, you can run the following to fetch the backends with GPU support.
51 |
52 | ```sh
53 | bash get_deps.sh gpu
54 | ```
55 |
56 | ### Building the Module
57 | Once the dependencies have been built, you can build the RedisAI module with:
58 |
59 | ```sh
60 | make -C opt clean ALL=1
61 | make -C opt
62 | ```
63 |
64 | Alternatively, run the following to build RedisAI with GPU support:
65 |
66 | ```sh
67 | make -C opt clean ALL=1
68 | make -C opt GPU=1
69 | ```
70 |
71 | ## Loading the Module
72 | To load the module upon starting the Redis server, simply use the `--loadmodule` command line switch, the `loadmodule` configuration directive or the [Redis `MODULE LOAD` command](https://redis.io/commands/module-load) with the path to module's library.
73 |
74 | For example, to load the module from the project's path with a server command line switch use the following:
75 |
76 | ```sh
77 | redis-server --loadmodule ./install-cpu/redisai.so
78 | ```
79 |
--------------------------------------------------------------------------------
/docs/requirements-llapi.txt:
--------------------------------------------------------------------------------
1 | -e git+https://github.com/matusnovak/doxybook.git#egg=doxybook
2 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | mkdocs==1.3.0
2 | mkdocs-material==6.2.2
3 | -e git+https://github.com/RedisLabs/mkdocs-versions-menu.git#egg=mkdocs-versions-menu
4 | -e git+https://github.com/RedisLabs/mkdocs-include.git#egg=mkdocs-include
5 | -e git+https://github.com/RedisLabs/mkdocs-modules-template.git#egg=mkdocs-modules-template
6 | # uncomment requirement to build LL API
7 | # -e git+https://github.com/matusnovak/doxybook.git#egg=doxybook
8 |
--------------------------------------------------------------------------------
/docs/snippets/notebooks/data/cat.jpg:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:6705f3b1bada344ec2ab7bc33d626ba64eb7f50e1b6bab7e09240e493e91875d
3 | size 52647
4 |
--------------------------------------------------------------------------------
/docs/snippets/notebooks/models/tensorflow/imagenet/resnet50.pb:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:7018654e139bbbc15518e204af9c08e84a520247f42e2d81fe547538ab865742
3 | size 102621616
4 |
--------------------------------------------------------------------------------
/docs/snippets/notebooks/models/tensorflow/mobilenet/mobilenet_224.pb:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:111479258f3841c93d0a7a377c976c24e8281077818991931429d2277dd88590
3 | size 24508794
4 |
--------------------------------------------------------------------------------
/docs/snippets/notebooks/models/tensorflow/tinyyolo/tinyyolo.pb:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:5a48ca053cf228a10023f11f92274efdaac7a0f991d7f15066add62523612137
3 | size 63481382
4 |
--------------------------------------------------------------------------------
/hooks/post_checkout:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Docker hub does a recursive clone, then checks the branch out,
3 | # so when a PR adds a submodule (or updates it), it fails.
4 | git submodule update --init --recursive
5 |
6 |
--------------------------------------------------------------------------------
/license/RSALv2.txt:
--------------------------------------------------------------------------------
1 | Redis Source Available License 2.0 dated November 15, 2022
2 |
3 | ## Acceptance
4 |
5 | By using the software, you agree to all of the terms and conditions below.
6 |
7 | ## Copyright License
8 |
9 | The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations and conditions below.
10 |
11 | ## Limitations
12 |
13 | You may not make the functionality of the software or a modified version available to third parties as a service, or distribute the software or a modified version in a manner that makes the functionality of the software available to third parties.
14 | Making the functionality of the software or modified version available to third parties includes, without limitation, enabling third parties to interact with the functionality of the software or modified version in distributed form or remotely through a computer network, offering a product or service the value of which entirely or primarily derives from the value of the software or modified version, or offering a product or service that accomplishes for users the primary purpose of the software or modified version.
15 |
16 | You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor’s trademarks is subject to applicable law.
17 |
18 | ## Patents
19 |
20 | The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
21 |
22 | ## Notices
23 |
24 | You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms.
25 | If you modify the software, you must include in any modified copies of the software prominent notices stating that you have modified the software.
26 |
27 | ## No Other Rights
28 |
29 | These terms do not imply any licenses other than those expressly granted in these terms.
30 | Termination
31 |
32 | If you use the software in violation of these terms, such use is not licensed, and your licenses will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violations of this license no later than 30 days after you receive that notice, your licenses will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your licenses to terminate automatically and permanently.
33 |
34 | ## No Liability
35 |
36 | As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
37 |
38 | ## Definitions
39 |
40 | The licensor is the entity offering these terms, and the software is the software the licensor makes available under these terms, including any portion of it.
41 |
42 | To modify a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission other than making an exact copy. The resulting work is called a modified version of the earlier work.
43 |
44 | you refers to the individual or entity agreeing to these terms.
45 |
46 | your company is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
47 |
48 | your licenses are all the licenses granted to you for the software under these terms.
49 |
50 | use means anything you do with the software requiring one of your licenses.
51 |
52 | trademark means trademarks, service marks, and similar rights.
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: RedisAI - A Server for Machine and Deep Learning Models
2 | site_url: http://redisai.io
3 | repo_url: https://github.com/RedisAI/RedisAI
4 | repo_name: RedisAI/RedisAI
5 |
6 | google_analytics:
7 | - 'UA-92003007-1'
8 | - 'auto'
9 |
10 | use_directory_urls: true
11 |
12 | theme:
13 | name: 'material'
14 | language: 'en'
15 | logo: 'images/logo_small.png'
16 | favicon: 'images/favicon.png'
17 | palette:
18 | primary: 'indigo'
19 | accent: 'red'
20 | font:
21 | text: 'Roboto'
22 | code: 'Roboto Mono'
23 | feature:
24 | tabs: false
25 |
26 | extra_javascript:
27 | - 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML'
28 | - gtm.js
29 |
30 | nav:
31 | - 'Home': index.md
32 | - 'Introduction': intro.md
33 | - 'Quickstart': quickstart.md
34 | - 'Commands': commands.md
35 | - 'Clients': clients.md
36 | - 'Configuration': configuration.md
37 | - 'Developer': developer.md
38 | - 'Performance': performance.md
39 | - 'Examples': examples.md
40 | - 'Contributing': contrib.md
41 |
42 | markdown_extensions:
43 | - admonition
44 | - pymdownx.arithmatex
45 | - pymdownx.details
46 | - pymdownx.superfences
47 | - codehilite:
48 | guess_lang: False
49 | - toc:
50 | permalink: True
51 |
52 | plugins:
53 | - search
54 | - include:
55 | src_path: docs/snippets
56 | - modules-template:
57 | try-for-free: false
58 | modules:
59 | - name: 'Search'
60 | link: '/redisearch'
61 |
62 | - name: 'Time Series'
63 | link: '/redistimeseries'
64 |
65 | - name: 'Bloom'
66 | link: '/redisbloom'
67 |
68 | - name: 'Graph'
69 | link: '/redisgraph'
70 |
71 | - name: 'JSON'
72 | link: '/redisjson'
73 |
74 | - name: 'Gears'
75 | link: '/redisgears'
76 | - versions-menu:
77 |
--------------------------------------------------------------------------------
/opt/build/backends.rules:
--------------------------------------------------------------------------------
1 | # PRODUCT var is the backend name, without any other configuration (set in each backend's corresponding makefile)
2 |
3 | # default is x64
4 | ARCH=$(shell ${READIES}/bin/platform --arch)
5 | OS=$(shell ${READIES}/bin/platform --os)
6 | REDIS_CMAKE_ARCH=x86_64
7 | DOCKER_ORG=redislabs
8 |
9 | # jetson
10 | ifeq ($(shell test -e /usr/share/doc/nvidia-l4t-jetson-io && echo -n yes),yes)
11 | ARCH=jetson
12 | REDIS_CMAKE_ARCH=aarch64
13 | GPU=1
14 | endif
15 | export REDIS_CMAKE_ARCH
16 |
17 | # override if necessary in top-level make files
18 | DEFAULT_DOCKER_TAG=${DOCKER_ORG}/${PRODUCT}:build
19 | CIDFILE=${PRODUCT}.${ARCH}.cid
20 |
21 | ifeq ($(GPU),1)
22 | REDIS_GPU=1
23 | VARIANT=gpu
24 | CIDFILE=${PRODUCT}.${ARCH}.gpu.cid # this way we can build from the same tree across platforms
25 | export REDIS_GPU
26 | endif
27 |
28 | ifeq ($(VARIANT),)
29 | BACKEND_NAME=${PRODUCT}-${OS}-${ARCH}-${VERSION}.tgz
30 | else
31 | BACKEND_NAME=${PRODUCT}-${OS}-${ARCH}-${VARIANT}-${VERSION}.tgz
32 | endif
33 |
34 | S3_URL=redismodules/${PRODUCT}
35 |
36 | build:
37 | @rm -f ${BACKEND_NAME} *.cid
38 | REDIS_ARCH=${ARCH} \
39 | REDIS_OSNICK=${OSNICK} \
40 | ${READIES}/bin/dockerwrapper \
41 | -d ${CURDIR}/Dockerfile${DOCKER_SUFFIX} \
42 | -t ${DEFAULT_DOCKER_TAG} \
43 | -S ../dockerparts \
44 | -e REDIS \
45 | -D "${DOCKER_OPTS}" \
46 | ${DOCKER_ARGS}
47 | docker create --cidfile ${CIDFILE} ${DEFAULT_DOCKER_TAG}
48 | docker cp `cat ${CIDFILE}`:/build/${BACKEND_NAME} .
49 |
50 | publish:
51 | @aws s3 cp ${BACKEND_NAME} s3://$(S3_URL)/ --acl public-read
52 |
53 | # ---------------------------------------------------------------------------------------------------
54 | define HELP
55 | make build> # build the backend, tagging the docker image so that the files can be copied out of it
56 | OSNICK=<> # optional base operating system (xenial, bionic, etc)
57 | REDIS_CUDA_VERSION=<> # optional cuda version to override
58 | DOCKER_SUFFIX=<> # optional suffix for the generated dockerfile
59 | GPU=1 # if set, build the GPU
60 | make publish > # upload the generated artifacts to s3 same
61 | GPU=1 # if set, upload the GPU artifact (defaults to cpu)
62 | endef
63 | # ---------------------------------------------------------------------------------------------------
64 | include ${READIES}/mk/help.defs
65 | include ${READIES}/mk/help.rules
66 |
--------------------------------------------------------------------------------
/opt/build/docker/Makefile:
--------------------------------------------------------------------------------
1 | # Feel free to change these
2 | PRODUCT=redisai
3 | DOCKER_ORG=redislabs
4 | REDIS_VERSION=6.2.7
5 | REDIS_CUDA_VERSION=11.3.1-cudnn8
6 | REDISAI_LITE=0
7 |
8 | PACK=1 # to fetch the artifacts
9 |
10 | DOCKER_OPTS= # set, to pass custom options to docker, but remember to quote them
11 | OSNICK ?= bionic
12 |
13 | # set to pass multiple directories as docker sources to include in templates
14 | DOCKER_SOURCES=""
15 |
16 | # set, to generate a file named Dockerfile, i.e useful when you want to run things in parallel
17 | DOCKER_SUFFIX=
18 |
19 | # Add space delimited docker tags, and they'll all be applied
20 | DOCKER_TAGS=
21 |
22 | DEFAULT_TAG=${DOCKER_ORG}/${PRODUCT}:${VERSION}-cpu-${OSNICK}
23 |
24 | # set gpu arguments
25 | ifeq ($(GPU),1)
26 | DOCKER_ARGS = gpu_build=1
27 | DOCKER_SUFFIX=gpu
28 | DEFAULT_TAG=${DOCKER_ORG}/${PRODUCT}:${VERSION}-gpu-${OSNICK}
29 | endif
30 |
31 | # remap ubuntu versions because of nvidia cuda
32 | ifeq ($(OSNICK),xenial)
33 | REDIS_CUDA_MAPVERSION=ubuntu16.04
34 | endif
35 | ifeq ($(OSNICK),bionic)
36 | REDIS_CUDA_MAPVERSION=ubuntu18.04
37 | endif
38 | ifeq ($(OSNICK),centos8)
39 | REDIS_CUDA_MAPVERSION=centos8
40 | endif
41 |
42 | DOCKERWRAPPER_EXTRA_VARS=\
43 | REDISAI_LITE=${REDISAI_LITE} \
44 | REDIS_CUDA_VERSION=${REDIS_CUDA_VERSION} \
45 | REDIS_CUDA_MAPVERSION=${REDIS_CUDA_MAPVERSION}
46 |
47 | ### Defaults ###
48 | ROOT=../../..
49 | READIES=${ROOT}/opt/readies
50 |
51 | #------------------------------------------------------------------------------
52 | define HELP
53 | make build # build and optionally publish the docker, from a template file
54 | OSNICK=<> # base operating system
55 | REDISAI_LITE=1 # enable RedisAI lite builds
56 | DOCKER_SUFFIX=<> # optional suffix for the generated dockerfile
57 | DOCKER_ARGS=FOO=BAR # key-value pairs of variables to pass into the docker build
58 | PACK=1 # fetch generated artifacts
59 | DOCKER_TAGS=a,b,c # tags to append and push to dockerhub
60 | DEFAULT_TAG=redislabs/redisai # default docker tag to build, and push
61 | TEST=1 # run tests, if specified
62 | VERSION=x.y.z # set the docker version
63 | NOP=1 # set to echo files in docker generation, and not run
64 | DOCKER_SOURCES=/a/path # append paths to the template generator
65 | PUBLISH=1 # if set, push to dockerhub (requires docker login)
66 | DOCKER_OPTS=XXX # Options to pass to the docker build command
67 | GPU=1 # if set, build the GPU docker
68 | endef
69 | #------------------------------------------------------------------------------
70 |
71 | # rules, for building
72 | include ${READIES}/mk/docker.rules
73 |
--------------------------------------------------------------------------------
/opt/build/docker/dockerfile-gpu-test.tmpl:
--------------------------------------------------------------------------------
1 | # BUILD redisfab/redisai:{{VERSION}}-gpu-{{REDIS_ARCH}}-{{REDIS_OSNICK}}-test
2 |
3 | ARG PACK={{REDIS_PACK}}
4 |
5 | # OSNICK=bionic|centos7|centos6
6 | ARG OSNICK=bionic
7 |
8 | # ARCH=x64|arm64v8|arm32v7
9 | ARG ARCH=x64
10 |
11 | # OS=ubuntu18.04|ubuntu16.04|centos7
12 | ARG OS=ubuntu18.04
13 |
14 | #----------------------------------------------------------------------------------------------
15 | FROM redisfab/redis:{{REDIS_VERSION}}-{{REDIS_ARCH}}-{{REDIS_OSNICK}} AS redis
16 | FROM nvidia/cuda:{{REDIS_CUDA_VERSION}}-devel-ubuntu18.04 AS builder
17 |
18 | ARG PACK
19 |
20 | SHELL ["/bin/bash", "-c"]
21 |
22 | {% include "templates/gpu.yml" %}
23 |
24 | ENV LANG=en_US.UTF-8
25 | RUN apt-get update
26 | RUN apt-get install -y locales && \
27 | sed -i -e "s/# $LANG.*/$LANG UTF-8/" /etc/locale.gen && \
28 | dpkg-reconfigure --frontend=noninteractive locales && \
29 | update-locale LANG=$LANG
30 |
31 | WORKDIR /build
32 | ADD ./ /build
33 | COPY --from=redis /usr/local/ /usr/local/
34 | COPY ./opt/ opt/
35 | COPY ./tests/flow/tests_setup/test_requirements.txt tests/flow/tests_setup/
36 | COPY ./tests/flow/tests_setup/Install_RedisGears.sh tests/flow/tests_setup/
37 | COPY ./get_deps.sh .
38 |
39 | RUN apt-get -q install -y git
40 |
41 | RUN VENV=venv FORCE=1 ./opt/readies/bin/getpy3
42 |
43 | RUN set -e ;\
44 | . venv/bin/activate ;\
45 | ./opt/system-setup.py
46 |
47 | ARG DEPS_ARGS=""
48 | RUN set -e ;\
49 | . venv/bin/activate ;\
50 | if [[ -z $DEPS_ARGS ]]; then \
51 | VERBOSE=1 ./get_deps.sh gpu ;\
52 | else \
53 | env $DEPS_ARGS ./get_deps.sh gpu ;\
54 | fi
55 |
56 | ARG BUILD_ARGS=""
57 | RUN set -e ;\
58 | . venv/bin/activate ;\
59 | bash -l -c "make -C opt build GPU=1 $BUILD_ARGS SHOW=1"
60 |
61 | RUN set -e ;\
62 | if [[ $PACK == 1 ]]; then \
63 | . venv/bin/activate ;\
64 | bash -l -c "make -C opt pack GPU=1 VERBOSE=1" ;\
65 | fi
66 |
67 | RUN git remote set-url origin https://github.com/RedisAI/RedisAI
68 |
69 | CMD ["bash", "-c", ". ./venv/bin/activate; make -C opt test GPU=1 SHOW=1"]
70 |
--------------------------------------------------------------------------------
/opt/build/docker/dockerfile.tmpl:
--------------------------------------------------------------------------------
1 | # BUILD redisfab/redisai:{{VERSION}}-cpu-{{REDIS_ARCH}}-{{REDIS_OSNICK}}
2 |
3 |
4 | ARG PACK={{REDIS_PACK}}
5 | ARG REDISAI_LITE={{REDISAI_LITE}}
6 | ARG TEST={{REDIS_TEST}}
7 |
8 |
9 | #----------------------------------------------------------------------------------------------
10 | FROM redisfab/redis:{{REDIS_VERSION}}-{{REDIS_ARCH}}-{{REDIS_OSNICK}} AS redis
11 | {% if gpu_build is defined %}
12 | FROM nvidia/cuda:{{REDIS_CUDA_VERSION}}-devel-{{REDIS_CUDA_MAPVERSION}} AS builder
13 | {% else %}
14 | FROM {{REDIS_OS}} AS builder
15 | {% endif %}
16 |
17 | ARG REDISAI_LITE
18 | ARG PACK
19 | ARG TEST
20 |
21 | RUN echo "Building for {{REDIS_OSNICK}} ({{REDIS_OS}}) for {{REDIS_ARCH}} [with Redis {{REDIS_VERSION}}]"
22 |
23 | {% if gpu_build is defined %}
24 | {% include "templates/gpu.yml" %}
25 | {% endif %}
26 |
27 | # centos8 specific integration until a move to rocky or similar
28 | {% if REDIS_OSNICK == "centos8" %}
29 | RUN cd /etc/yum.repos.d/
30 | RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
31 | RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
32 | {% endif %}
33 |
34 | WORKDIR /build
35 | COPY --from=redis /usr/local/ /usr/local/
36 |
37 | COPY ./opt/ opt/
38 | ADD ./tests/flow/ tests/flow/
39 |
40 | RUN if [ ! -z $(command -v apt-get) ]; then apt-get -qq update; apt-get -q install -y git; fi
41 | RUN if [ ! -z $(command -v yum) ]; then yum install -y git; fi
42 | RUN FORCE=1 ./opt/readies/bin/getpy3
43 | RUN ./opt/system-setup.py
44 |
45 | ARG DEPS_ARGS=""
46 | COPY ./get_deps.sh .
47 | RUN if [ "$DEPS_ARGS" = "" ]; then ./get_deps.sh {% if gpu_build is defined %}gpu {% else %} cpu {% endif %}; else env $DEPS_ARGS ./get_deps.sh {% if gpu_build is defined %} gpu {% else %} cpu {% endif %}; fi
48 |
49 | ARG BUILD_ARGS=""
50 | ADD ./ /build
51 | RUN bash -l -c "make -C opt build {% if gpu_build is defined %} GPU=1 {% else %} REDISAI_LITE={{REDISAI_LITE}} {% endif %}$BUILD_ARGS SHOW=1"
52 |
53 |
54 | RUN mkdir -p bin/artifacts
55 | RUN set -e ;\
56 | if [ "$PACK" = "1" ]; then bash -l -c "make -C opt pack {% if gpu_build is defined %} GPU=1 {% endif %} REDISAI_LITE={{REDISAI_LITE}}"; fi
57 |
58 | RUN set -e ;\
59 | if [ "$TEST" = "1" ]; then \
60 | bash -l -c "TEST= make -C opt test {% if gpu_build is defined %}GPU=1{% endif %} REDISAI_LITE={{REDISAI_LITE}} $BUILD_ARGS NO_LFS=1" ;\
61 | if [[ -d test/logs ]]; then \
62 | {% if gpu_build is defined %}
63 | tar -C test/logs -czf bin/artifacts/test-logs-gpu.tgz . ;\
64 | {% else %}
65 | tar -C test/logs -czf bin/artifacts/test-logs-cpu.tgz . ;\
66 | {% endif %}
67 | fi ;\
68 | fi
69 |
70 | #----------------------------------------------------------------------------------------------
71 | {% if gpu_build is defined %}
72 | FROM nvidia/cuda:{{REDIS_CUDA_VERSION}}-runtime-{{REDIS_CUDA_MAPVERSION}}
73 | {% else %}
74 | FROM redisfab/redis:{{REDIS_VERSION}}-{{REDIS_ARCH}}-{{REDIS_OSNICK}}
75 | {% endif %}
76 |
77 | ARG PACK
78 | # centos8 specific integration until a move to rocky or similar
79 | {% if REDIS_OSNICK == "centos8" %}
80 | RUN cd /etc/yum.repos.d/
81 | RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
82 | RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
83 | {% endif %}
84 |
85 | RUN if [ ! -z $(command -v apt-get) ]; then apt-get -qq update; apt-get -q install -y libgomp1; fi
86 | RUN if [ ! -z $(command -v yum) ]; then yum install -y libgomp; fi
87 |
88 | ENV REDIS_MODULES /usr/lib/redis/modules
89 | ENV LD_LIBRARY_PATH $REDIS_MODULES
90 |
91 | RUN mkdir -p $REDIS_MODULES/
92 |
93 | {% if gpu_build is defined %}
94 | COPY --from=builder /build/install-gpu/ $REDIS_MODULES/
95 | {% else %}
96 | COPY --from=builder /build/install-cpu/ $REDIS_MODULES/
97 | {% endif %}
98 |
99 | COPY --from=builder /build/bin/artifacts/ /var/opt/redislabs/artifacts
100 | {% if gpu_build is defined %}
101 | COPY --from=redis /usr/local/bin/redis* /usr/local/bin/
102 | {% endif %}
103 |
104 | WORKDIR /data
105 | EXPOSE 6379
106 | CMD ["/usr/local/bin/redis-server", "--loadmodule", "/usr/lib/redis/modules/redisai.so"]
107 |
--------------------------------------------------------------------------------
/opt/build/docker/templates/gpu.yml:
--------------------------------------------------------------------------------
1 | # given the cuda version, generate the paths so that we don't manually maintain them
2 | {% set cuda_list = REDIS_CUDA_VERSION.split("-") %}
3 | {% set cuda_parts = cuda_list[0].split(".") %}
4 | {% set cuda_version = cuda_parts[0] + "." + cuda_parts[1] %}
5 | ENV NVIDIA_VISIBLE_DEVICES all
6 | ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
7 | RUN echo export LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/local/cuda-{{cuda_version}}/lib64:/usr/local/cuda-{{cuda_version}}/compat/:$LD_LIBRARY_PATH > /etc/profile.d/cuda.sh
8 |
9 |
--------------------------------------------------------------------------------
/opt/build/dockerparts/apt.yml:
--------------------------------------------------------------------------------
1 | RUN apt-get update -qq
2 | RUN DEBIAN_NONINTERACTIVE=y1 apt-get install -y software-properties-common
3 |
4 | {% if REDIS_OSNICK == 'xenial' %}
5 | RUN add-apt-repository ppa:deadsnakes/ppa
6 | RUN add-apt-repository ppa:ubuntu-toolchain-r/test
7 | {% endif %}
8 |
9 | RUN apt-get update -qq
10 | RUN DEBIAN_NONINTERACTIVE=1 apt-get install -y curl wget tar git patch \
11 | build-essential libcurl4-openssl-dev libssl-dev libatlas-base-dev zlib1g-dev \
12 | python3.7 python3-pip python3-dev \
13 | gcc-7 g++-7
14 |
15 | RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 60
16 | RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 --slave /usr/bin/g++ g++ /usr/bin/g++-7
17 |
18 | RUN python3 -m pip install --upgrade pip setuptools wheel
19 |
20 | ENV LANG=en_US.UTF-8
21 | RUN apt-get install -y locales && \
22 | sed -i -e "s/# $LANG.*/$LANG UTF-8/" /etc/locale.gen && \
23 | dpkg-reconfigure --frontend=noninteractive locales && \
24 | update-locale LANG=$LANG
25 |
26 |
27 |
--------------------------------------------------------------------------------
/opt/build/dockerparts/cmake.yml:
--------------------------------------------------------------------------------
1 | {% set cmake_version = "3.19.7" %}
2 | RUN wget -q https://github.com/Kitware/CMake/releases/download/v{{cmake_version}}/cmake-{{cmake_version}}-Linux-{{REDIS_CMAKE_ARCH}}.tar.gz -O /tmp/cmake.tgz
3 |
4 | WORKDIR /tmp
5 | RUN tar -zxpf /tmp/cmake.tgz
6 | RUN mv /tmp/cmake*/bin/* /usr/bin
7 | RUN mv /tmp/cmake-*/share/cmake* /usr/share/
8 |
9 |
10 |
--------------------------------------------------------------------------------
/opt/build/onnxruntime/.gitignore:
--------------------------------------------------------------------------------
1 | Dockerfile
2 | *.cid
3 |
--------------------------------------------------------------------------------
/opt/build/onnxruntime/Makefile:
--------------------------------------------------------------------------------
1 | REDIS_ONNX_VERSION?=1.11.1
2 | REDIS_ONNX_REPO?=https://github.com/microsoft/onnxruntime
3 |
4 | PRODUCT=onnxruntime
5 | VERSION=${REDIS_ONNX_VERSION}
6 | REDIS_CUDA_VERSION=11.3.1-cudnn8
7 |
8 | # anything prefixed with REDIS, and exported is available in the docker build
9 | export REDIS_ONNX_VERSION
10 | export REDIS_ONNX_REPO
11 | export REDIS_CUDA_VERSION
12 |
13 | OSNICK=bionic
14 |
15 | ROOT=.
16 | READIES=${ROOT}/../../readies
17 |
18 | include ../backends.rules
19 |
--------------------------------------------------------------------------------
/opt/build/onnxruntime/dockerfile.tmpl:
--------------------------------------------------------------------------------
1 | {% if REDIS_OSNICK == "bionic" %}
2 | {% set cuda_suffix_os = "ubuntu18.04" %}
3 | {% endif %}
4 |
5 | {% if REDIS_ARCH == 'jetson' %}
6 | FROM nvcr.io/nvidia/deepstream-l4t:5.1-21.02-base
7 | {% endif %}
8 |
9 | {% if REDIS_ARCH == 'x64' %}
10 | {% if REDIS_GPU is defined %}
11 | FROM nvidia/cuda:{{REDIS_CUDA_VERSION}}-devel-{{cuda_suffix_os}}
12 | {% else %}
13 | {% if REDIS_OSNICK == "bionic" %}
14 | FROM ubuntu:bionic
15 | {% endif %}
16 | {% endif %}
17 | {% endif %}
18 |
19 | ARG ONNXRUNTIME_REPO={{REDIS_ONNX_REPO}}
20 | ARG ONNXRUNTIME_VER={{REDIS_ONNX_VERSION}}
21 |
22 | {% include 'apt.yml' %}
23 |
24 | {% include 'cmake.yml' %}
25 |
26 | # build
27 | WORKDIR /build
28 | {% if REDIS_GPU is defined %}
29 | {% set BUILDTYPE="Release" %}
30 | {% set BUILDARGS="--use_cuda --cudnn_home /usr/local/cuda --cuda_home /usr/local/cuda --cmake_extra_defines onnxruntime_DISABLE_EXTERNAL_INITIALIZERS=ON"%}
31 | {% else %}
32 | {% set BUILDTYPE="Release" %}
33 | {% set BUILDARGS="--cmake_extra_defines onnxruntime_DISABLE_EXTERNAL_INITIALIZERS=ON" %}
34 | {% endif %}
35 |
36 | ARG BUILDARGS="--config {{BUILDTYPE}} --parallel"
37 | RUN git clone --single-branch --branch v{{REDIS_ONNX_VERSION}} {{REDIS_ONNX_REPO}} onnxruntime
38 | WORKDIR /build/onnxruntime
39 | RUN ./build.sh --config {{BUILDTYPE}} {{BUILDARGS}} --update --build --build_shared_lib --parallel
40 |
41 | # package
42 | ADD ./pack.sh /build
43 | WORKDIR /build
44 | RUN ./pack.sh {{REDIS_ONNX_VERSION}} {{REDIS_ARCH}} {{BUILDTYPE}} linux {% if REDIS_GPU is defined %} gpu {% endif %}
45 |
--------------------------------------------------------------------------------
/opt/build/onnxruntime/pack.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 | VER="$1" # 1.9.0
5 | PLATFORM="$2" # x64|jetson
6 | BUILDTYPE="$3" # Release
7 | BASEOS="$4" # linux (mac future?)
8 | VARIANT="$5" # if set (gpu)
9 |
10 | target=onnxruntime-${BASEOS}-${PLATFORM}-${VER}
11 | if [ ! -z "${VARIANT}" ]; then
12 | target=onnxruntime-${BASEOS}-${PLATFORM}-${VARIANT}-${VER}
13 | fi
14 |
15 | mkdir -p pack/include pack/lib
16 | cp onnxruntime/build/Linux/$BUILDTYPE/libonnxruntime.so.${VER} pack/lib/
17 | cp onnxruntime/docs/C_API_Guidelines.md pack/
18 | cp onnxruntime/LICENSE pack/
19 | cp onnxruntime/README.md pack/
20 | cp onnxruntime/ThirdPartyNotices.txt pack/
21 | cp onnxruntime/VERSION_NUMBER pack/
22 | cd onnxruntime/
23 | git rev-parse HEAD > ../pack/GIT_COMMIT_ID
24 | cd ..
25 | cp onnxruntime/include/onnxruntime/core/session/onnxruntime_c_api.h pack/include/
26 | cp onnxruntime/include/onnxruntime/core/session/onnxruntime_cxx_api.h pack/include/
27 | cp onnxruntime/include/onnxruntime/core/session/onnxruntime_cxx_inline.h pack/include/
28 | cp onnxruntime/include/onnxruntime/core/framework/provider_options.h pack/include/
29 | cp onnxruntime/include/onnxruntime/core/providers/cpu/cpu_provider_factory.h pack/include/
30 | cd pack/lib/
31 | ln -s libonnxruntime.so.${VER} libonnxruntime.so
32 | cd ../..
33 | mv pack ${target}
34 | tar czf ${target}.tgz ${target}/
35 |
--------------------------------------------------------------------------------
/opt/clang-check-all.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # exit immediatly on error ( no need to keep checking )
4 | set -e
5 |
6 | CLANG_FMT_SRCS=$(find ../src/ \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hh' -o -name '*.hpp' \))
7 | CLANG_FMT_TESTS=$(find ../tests/ \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hh' -o -name '*.hpp' \))
8 |
9 | for filename in $CLANG_FMT_SRCS; do
10 | echo "Checking $filename"
11 | clang-format -style=file -Werror --dry-run $filename
12 | done
13 |
14 | for filename in $CLANG_FMT_TESTS; do
15 | echo "Checking $filename"
16 | clang-format -style=file -Werror --dry-run $filename
17 | done
18 |
--------------------------------------------------------------------------------
/opt/clang-format-all.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # exit immediatly on error ( no need to keep checking )
4 | set -e
5 |
6 | CLANG_FMT_SRCS=$(find ../src/ \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hh' -o -name '*.hpp' \))
7 | CLANG_FMT_TESTS=$(find ../tests/ \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hh' -o -name '*.hpp' \))
8 |
9 | for filename in $CLANG_FMT_SRCS; do
10 | clang-format --verbose -style=file -i $filename
11 | done
12 |
13 | for filename in $CLANG_FMT_TESTS; do
14 | clang-format --verbose -style=file -i $filename
15 | done
16 |
--------------------------------------------------------------------------------
/opt/getver:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
4 | ROOT=$(cd $HERE/..; pwd)
5 |
6 | getver_c=$(mktemp "${TMPDIR:-/tmp}/getver-XXXXXXX.c")
7 | if [[ $NUMERIC != 1 ]]; then
8 | cat <<- EOF > $getver_c
9 | #include
10 |
11 | #include "src/version.h"
12 |
13 | int main(int argc, char *argv[]) {
14 | printf("%d.%d.%d\n", REDISAI_VERSION_MAJOR, REDISAI_VERSION_MINOR, REDISAI_VERSION_PATCH);
15 | return 0;
16 | }
17 | EOF
18 | else
19 | cat <<- EOF > $getver_c
20 | #include
21 |
22 | #include "src/version.h"
23 |
24 | int main(int argc, char *argv[]) {
25 | printf("%d\n", REDISAI_MODULE_VERSION);
26 | return 0;
27 | }
28 | EOF
29 | fi
30 | prog=$(mktemp "${TMPDIR:-/tmp}/getver.XXXXXXX")
31 | gcc -I$ROOT -o $prog $getver_c
32 | ver=`$prog`
33 | rm -f $prog $getver_c
34 | echo $ver
35 | exit 0
36 |
--------------------------------------------------------------------------------
/opt/redis_valgrind.sup:
--------------------------------------------------------------------------------
1 | {
2 | ignore_unversioned_libs
3 | Memcheck:Leak
4 | ...
5 | obj:*/libtensorflow.so.*
6 | }
7 |
8 | {
9 | ignore_unversioned_libs
10 | Memcheck:Leak
11 | ...
12 | obj:*/libtensorflow_framework.so.*
13 | }
14 |
15 | {
16 | ignore_unversioned_libs
17 | Memcheck:Leak
18 | ...
19 | obj:*/libtorch.so.*
20 | }
21 |
22 | {
23 | ignore_unversioned_libs
24 | Memcheck:Overlap
25 | ...
26 | obj:*/libtorch_cpu.so*
27 | }
28 |
29 | {
30 | ignore_unversioned_libs
31 | Memcheck:Overlap
32 | ...
33 | obj:*/libonnxruntime.so*
34 | }
35 |
36 | {
37 | ignore_unversioned_libs
38 | Memcheck:Leak
39 | ...
40 | obj:*/libtorch.so*
41 | }
42 |
43 | {
44 |
45 | Memcheck:Cond
46 | fun:lzf_compress
47 | }
48 |
49 | {
50 |
51 | Memcheck:Value4
52 | fun:lzf_compress
53 | }
54 |
55 | {
56 |
57 | Memcheck:Value8
58 | fun:lzf_compress
59 | }
60 |
61 | {
62 |
63 | Memcheck:Leak
64 | fun:malloc
65 | ...
66 | fun:dlopen@@GLIBC_2.2.5
67 | ...
68 | fun:RAI_LoadBackend
69 | }
70 |
71 | {
72 |
73 | Memcheck:Cond
74 | fun:lzf_compress
75 | }
76 | {
77 |
78 | Memcheck:Cond
79 | ...
80 | fun:Py_InitializeEx
81 | ...
82 | }
83 | {
84 |
85 | Memcheck:Cond
86 | ...
87 | fun:_PyEval_EvalFrameDefault
88 | ...
89 | }
90 | {
91 |
92 | Memcheck:Leak
93 | ...
94 | fun:_imp_exec_builtin
95 | ...
96 | }
97 | {
98 |
99 | Memcheck:Cond
100 | ...
101 | fun:PySys_SetArgvEx
102 | ...
103 | }
104 | {
105 |
106 | Memcheck:Cond
107 | ...
108 | fun:_PyMethodDef_RawFastCallKeywords
109 | ...
110 | }
111 | {
112 |
113 | Memcheck:Value8
114 | fun:lzf_compress
115 | }
116 | {
117 |
118 | Memcheck:Addr4
119 | obj:*libpython2.7*
120 | }
121 | {
122 |
123 | Memcheck:Addr8
124 | obj:*libpython2.7*
125 | }
126 | {
127 |
128 | Memcheck:Value8
129 | obj:*libpython2.7*
130 | }
131 | {
132 |
133 | Memcheck:Cond
134 | obj:*libpython2.7*
135 | }
136 | {
137 |
138 | Memcheck:Leak
139 | ...
140 | obj:*libpython2.7*
141 | ...
142 | }
143 | {
144 |
145 | Memcheck:Leak
146 | ...
147 | fun:redisLibeventAttach
148 | ...
149 | }
150 | {
151 |
152 | Memcheck:Leak
153 | ...
154 | fun:compiler_visit_expr
155 | ...
156 | }
157 | {
158 |
159 | Memcheck:Leak
160 | ...
161 | fun:redisConnectNonBlock
162 | ...
163 | }
164 | {
165 |
166 | Memcheck:Leak
167 | ...
168 | fun:_redisContextConnectTcp
169 | ...
170 | }
171 | {
172 | Libuv_epoll_ctl
173 | Memcheck:Param
174 | epoll_ctl(event)
175 | fun:epoll_ctl
176 | ...
177 | }
178 |
179 |
180 | {
181 | <_dl_catch_exception>
182 | Memcheck:Addr8
183 | fun:strncmp
184 | ...
185 | fun:_dl_catch_exception
186 | ...
187 | }
188 |
189 | {
190 |
191 | Memcheck:Cond
192 | ...
193 | obj:*/libtorch_cpu.so*
194 | }
195 |
--------------------------------------------------------------------------------
/opt/system-setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import sys
4 | import os
5 | import argparse
6 |
7 | HERE = os.path.abspath(os.path.dirname(__file__))
8 | ROOT = os.path.abspath(os.path.join(HERE, ".."))
9 | READIES = os.path.join(ROOT, "opt/readies")
10 | sys.path.insert(0, READIES)
11 | import paella
12 |
13 | #----------------------------------------------------------------------------------------------
14 |
15 | class RedisAISetup(paella.Setup):
16 | def __init__(self, nop=False):
17 | paella.Setup.__init__(self, nop)
18 |
19 | def common_first(self):
20 | self.install_downloaders()
21 | self.pip_install("wheel")
22 |
23 | self.install("git unzip")
24 | if self.osnick != 'centos8':
25 | self.install("coreutils") # for realpath
26 |
27 | def debian_compat(self):
28 | self.run("%s/bin/enable-utf8" % READIES)
29 | self.run("%s/bin/getgcc" % READIES)
30 | self.install("gawk libssl-dev python3-regex python3-networkx libmpich-dev libopenblas-dev")
31 | if self.platform.is_arm():
32 | self.install("python3-dev") # python3-skimage
33 | self.install_git_lfs_on_linux()
34 |
35 | def redhat_compat(self):
36 | self.run("%s/bin/enable-utf8" % READIES)
37 | self.install("epel-release")
38 | if self.osnick == "centos8":
39 | self.run("dnf install -qy dnf-plugins-core")
40 | self.run("dnf config-manager -qy --set-enabled powertools")
41 | self.install("redhat-lsb-core")
42 |
43 | self.run("%s/bin/getgcc --modern" % READIES)
44 |
45 | if self.arch == 'x64':
46 | self.install_linux_gnu_tar()
47 |
48 | if not self.dist == "amzn":
49 | self.install("epel-release")
50 | self.install("python3-devel libaec-devel")
51 | else:
52 | self.run("amazon-linux-extras install epel", output_on_error=True)
53 | self.install("python3-devel")
54 |
55 | self.install_git_lfs_on_linux()
56 |
57 | def fedora(self):
58 | self.run("%s/bin/getepel" % READIES)
59 | self.install("python3-networkx")
60 | self.install_git_lfs_on_linux()
61 |
62 | def linux_last(self):
63 | self.install("valgrind")
64 |
65 | def macos(self):
66 | self.install_gnu_utils()
67 | self.install("git-lfs")
68 | self.install("redis")
69 |
70 | def common_last(self):
71 | self.run("%s/bin/getclang --format" % READIES)
72 | if self.platform == "arm":
73 | self.run("%s/bin/getcmake --from-repo" % READIES)
74 | else:
75 | self.run("%s/bin/getcmake" % READIES)
76 |
77 | self.pip_install("--ignore-installed PyYAML -r %s/tests/flow/tests_setup/test_requirements.txt" % ROOT)
78 |
79 | self.pip_install("awscli")
80 | self.pip_install("mkdocs mkdocs-material mkdocs-extensions")
81 |
82 | #----------------------------------------------------------------------------------------------
83 |
84 | parser = argparse.ArgumentParser(description='Set up system for build.')
85 | parser.add_argument('-n', '--nop', action="store_true", help='no operation')
86 | args = parser.parse_args()
87 |
88 | RedisAISetup(nop=args.nop).setup()
89 |
--------------------------------------------------------------------------------
/ramp-light.yml:
--------------------------------------------------------------------------------
1 | display_name: RedisAI Light
2 | author: Tensorwerk and RedisLabs
3 | email: support@redislabs.com
4 | description: Serving tensors and executing deep learning graphs
5 | homepage: https://oss.redislabs.com/redisai/
6 | license: Redis Source Available License 2.0 (RSALv2) or the Server Side Public License v1 (SSPLv1)
7 | command_line_args: "BACKENDSPATH /var/opt/redislabs/modules/ai-light/{{NUMVER}}/deps"
8 | # command_line_args: "BACKENDSPATH /var/opt/redislabs/modules/ai/{{NUMVER}}/deps/backends"
9 | min_redis_version: "6.0.0"
10 | min_redis_pack_version: "6.0.12"
11 | capabilities:
12 | - types
13 | - hash_policy
14 | - eviction_expiry
15 | - failover_migrate
16 | - persistence_rdb
17 | - persistence_aof
18 | - clustering
19 | - backup_restore
20 | - replica_of
21 | - flash
22 | - reshard_rebalance
23 | dependencies:
24 | {{NAME_tensorflow}}:
25 | url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_tensorflow}}
26 | sha256: {{SHA256_tensorflow}}
27 | {{NAME_torch}}:
28 | url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_torch}}
29 | sha256: {{SHA256_torch}}
30 | {{NAME_onnxruntime}}:
31 | url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_onnxruntime}}
32 | sha256: {{SHA256_onnxruntime}}
33 | {{NAME_tflite}}:
34 | url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_tflite}}
35 | sha256: {{SHA256_tflite}}
36 | # {{NAME_all}}:
37 | # url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_all}}
38 | # sha256: {{SHA256_all}}
39 |
--------------------------------------------------------------------------------
/ramp-rce.yml:
--------------------------------------------------------------------------------
1 | display_name: RedisAI-RCE
2 | author: Tensorwerk and RedisLabs
3 | email: support@redislabs.com
4 | description: Serving tensors and executing deep learning graphs
5 | homepage: https://oss.redislabs.com/redisai/
6 | license: Redis Source Available License 2.0 (RSALv2) or the Server Side Public License v1 (SSPLv1)
7 | command_line_args: "BACKENDSPATH /var/opt/redislabs/modules/ai-light/{{NUMVER}}/deps"
8 | # command_line_args: "BACKENDSPATH /var/opt/redislabs/modules/ai/{{NUMVER}}/deps/backends"
9 | min_redis_version: "6.0.0"
10 | min_redis_pack_version: "6.0.12"
11 | capabilities:
12 | - types
13 | - hash_policy
14 | - eviction_expiry
15 | - failover_migrate
16 | - persistence_rdb
17 | - persistence_aof
18 | - clustering
19 | - backup_restore
20 | - replica_of
21 | - flash
22 | - resharding
23 | dependencies:
24 | {{NAME_onnxruntime}}:
25 | url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_onnxruntime}}
26 | sha256: {{SHA256_onnxruntime}}
27 |
28 |
--------------------------------------------------------------------------------
/ramp.yml:
--------------------------------------------------------------------------------
1 | display_name: RedisAI
2 | author: Tensorwerk and RedisLabs
3 | email: support@redislabs.com
4 | description: Serving tensors and executing deep learning graphs
5 | homepage: https://oss.redislabs.com/redisai/
6 | license: Redis Source Available License 2.0 (RSALv2) or the Server Side Public License v1 (SSPLv1)
7 | command_line_args: "BACKENDSPATH /var/opt/redislabs/modules/ai/{{NUMVER}}/deps"
8 | # command_line_args: "BACKENDSPATH /var/opt/redislabs/modules/ai/{{NUMVER}}/deps/backends"
9 | min_redis_version: "6.0.0"
10 | min_redis_pack_version: "6.2.2"
11 | capabilities:
12 | - types
13 | - hash_policy
14 | - eviction_expiry
15 | - failover_migrate
16 | - persistence_rdb
17 | - persistence_aof
18 | - clustering
19 | - backup_restore
20 | - intershard_tls
21 | - intershard_tls_pass
22 | exclude_commands:
23 | - ai.modelstore
24 | - ai.modelset
25 | - ai.modeldel
26 | - ai.scriptstore
27 | - ai.scriptset
28 | - ai.scriptdel
29 | dependencies:
30 | {{NAME_tensorflow}}:
31 | url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_tensorflow}}
32 | sha256: {{SHA256_tensorflow}}
33 | {{NAME_torch}}:
34 | url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_torch}}
35 | sha256: {{SHA256_torch}}
36 | {{NAME_onnxruntime}}:
37 | url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_onnxruntime}}
38 | sha256: {{SHA256_onnxruntime}}
39 | {{NAME_tflite}}:
40 | url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_tflite}}
41 | sha256: {{SHA256_tflite}}
42 | # {{NAME_all}}:
43 | # url: http://redismodules.s3.amazonaws.com/redisai/{{PATH_all}}
44 | # sha256: {{SHA256_all}}
45 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | if (CMAKE_BUILD_TYPE STREQUAL Debug)
2 | SET(DEBUG_SRC "${CMAKE_CURRENT_SOURCE_DIR}/../opt/readies/cetara/diag/gdb.c")
3 | endif()
4 |
5 | file (GLOB_RECURSE SERIALIZATION_SRC
6 | redis_ai_objects/tensor.c
7 | redis_ai_objects/model.c
8 | redis_ai_objects/script.c
9 | backends/backends.c
10 | stats.c
11 | config.c
12 | serialization/*.c)
13 |
14 | file (GLOB BACKEND_COMMON_SRC
15 | backends/util.c
16 | redis_ai_objects/err.c
17 | util/dict.c
18 | util/dictionaries.c
19 | redis_ai_objects/tensor.c
20 | redis_ai_objects/model.c
21 | redis_ai_objects/stats.c
22 | redis_ai_objects/script.c
23 | util/string_utils.c
24 | execution/utils.c
25 | execution/execution_contexts/execution_ctx.c
26 | serialization/ai_datatypes.c)
27 |
28 | ADD_LIBRARY(redisai_obj OBJECT
29 | util/dict.c
30 | util/dictionaries.c
31 | util/queue.c
32 | util/string_utils.c
33 | redisai.c
34 | execution/command_parser.c
35 | execution/parsing/deprecated.c
36 | execution/parsing/dag_parser.c
37 | execution/parsing/tensor_commands_parsing.c
38 | execution/parsing/model_commands_parser.c
39 | execution/parsing/script_commands_parser.c
40 | execution/parsing/parse_utils.c
41 | execution/run_info.c
42 | execution/background_workers.c
43 | execution/run_queue_info.c
44 | execution/utils.c
45 | config/config.c
46 | execution/DAG/dag.c
47 | execution/DAG/dag_builder.c
48 | execution/DAG/dag_execute.c
49 | execution/DAG/dag_op.c
50 | execution/execution_contexts/execution_ctx.c
51 | execution/execution_contexts/modelRun_ctx.c
52 | execution/execution_contexts/scriptRun_ctx.c
53 | backends/backends.c
54 | backends/util.c
55 | redis_ai_objects/model.c
56 | redis_ai_objects/err.c
57 | redis_ai_objects/script.c
58 | redis_ai_objects/stats.c
59 | redis_ai_objects/tensor.c
60 | rmutil/alloc.c
61 | rmutil/sds.c
62 | rmutil/args.c
63 | redis_ai_types/model_type.c
64 | redis_ai_types/tensor_type.c
65 | redis_ai_types/script_type.c
66 | ${SERIALIZATION_SRC}
67 | ${DEBUG_SRC})
68 |
69 | IF(BUILD_TF)
70 | ADD_LIBRARY(redisai_tensorflow_obj OBJECT
71 | backends/tensorflow.c
72 | ${BACKEND_COMMON_SRC}
73 | )
74 | ENDIF()
75 |
76 | IF(BUILD_TFLITE)
77 | ADD_LIBRARY(redisai_tflite_obj OBJECT
78 | backends/tflite.c
79 | ${BACKEND_COMMON_SRC}
80 | )
81 | ENDIF()
82 |
83 | IF(BUILD_TORCH)
84 | ADD_LIBRARY(redisai_torch_obj OBJECT
85 | backends/torch.c
86 | ${BACKEND_COMMON_SRC}
87 | )
88 | ENDIF()
89 |
90 | IF(BUILD_ORT)
91 | ADD_LIBRARY(redisai_onnxruntime_obj OBJECT
92 | backends/onnxruntime.c
93 | backends/onnx_timeout.c
94 | ${BACKEND_COMMON_SRC}
95 | )
96 | ENDIF()
97 |
98 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
99 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/rmutil)
100 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/util)
101 |
--------------------------------------------------------------------------------
/src/backends/backends.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | /**
8 | * backends.h
9 | *
10 | * Contains the structure and method signatures required to register a new
11 | * backend to be loaded by the module.
12 | *
13 | */
14 |
15 | #pragma once
16 |
17 | #include "config/config.h"
18 | #include "redis_ai_objects/err.h"
19 | #include "redis_ai_objects/tensor.h"
20 | #include "redis_ai_objects/model.h"
21 | #include "redis_ai_objects/script.h"
22 | #include "execution/execution_contexts/execution_ctx.h"
23 |
24 | /*
25 | * To register a new backend to be loaded by the module, the backend needs to
26 | * implement the following:
27 | *
28 | * * ** model_create_with_nodes **: A callback function pointer that creates a
29 | * model given the RAI_ModelOpts and input and output nodes.
30 | *
31 | * * ** model_create **: A callback function pointer that creates a model given
32 | * the RAI_ModelOpts.
33 | *
34 | * * ** model_run **: A callback function pointer that runs a model given the
35 | * RAI_Model pointer and an array of RAI_ExecutionCtx pointers.
36 | *
37 | * * ** model_serialize **: A callback function pointer that serializes a model
38 | * given the RAI_Model pointer.
39 | *
40 | * * ** script_create **: A callback function pointer that creates a script.
41 | *
42 | * * ** script_free **: A callback function pointer that frees a script given
43 | * the RAI_Script pointer.
44 | *
45 | * * ** script_run **: A callback function pointer that runs a model given the
46 | * RAI_Script pointer and .
47 | */
48 | typedef struct RAI_LoadedBackend {
49 | // ** model_create_with_nodes **: A callback function pointer that creates a
50 | // model given the RAI_ModelOpts and input and output nodes
51 | RAI_Model *(*model_create_with_nodes)(RAI_Backend, const char *, RAI_ModelOpts, size_t,
52 | const char **, size_t, const char **, const char *,
53 | size_t, RAI_Error *);
54 |
55 | // ** model_create **: A callback function pointer that creates a model given
56 | // the RAI_ModelOpts
57 | RAI_Model *(*model_create)(RAI_Backend, const char *, RAI_ModelOpts, const char *, size_t,
58 | RAI_Error *);
59 |
60 | // ** model_free **: A callback function pointer that frees a model given the
61 | // RAI_Model pointer
62 | void (*model_free)(RAI_Model *, RAI_Error *);
63 |
64 | // ** model_run **: A callback function pointer that runs a model given the
65 | // RAI_Model pointer and an array of RAI_ExecutionCtx pointers
66 | int (*model_run)(RAI_Model *, RAI_ExecutionCtx **, RAI_Error *);
67 |
68 | // ** model_serialize **: A callback function pointer that serializes a model
69 | // given the RAI_Model pointer
70 | int (*model_serialize)(RAI_Model *, char **, size_t *, RAI_Error *);
71 |
72 | // ** script_create **: A callback function pointer that creates a script
73 | RAI_Script *(*script_create)(const char *, const char *, const char **, size_t, RAI_Error *);
74 |
75 | // ** script_free **: A callback function pointer that frees a script given
76 | // the RAI_Script pointer
77 | void (*script_free)(RAI_Script *, RAI_Error *);
78 |
79 | // ** script_run **: A callback function pointer that runs a model given the
80 | // RAI_ScriptRunCtx pointer
81 | int (*script_run)(RAI_Script *, const char *function, RAI_ExecutionCtx *, RAI_Error *);
82 |
83 | // Returns the backend version.
84 | const char *(*get_version)(void);
85 |
86 | // Returns the backend's memory usage for INFO report
87 | unsigned long long (*get_memory_info)(void);
88 |
89 | // Returns the number of times that Redis accessed backend allocator.
90 | unsigned long long (*get_memory_access_num)(void);
91 |
92 | // A callback for to use whenever a new device is introduced.
93 | int (*add_new_device_cb)(const char *);
94 |
95 | // Kill run session callback (for stopping long runs).
96 | void (*stop_long_running_sessions_cb)(RedisModuleCtx *, RedisModuleEvent, uint64_t, void *);
97 |
98 | // Get the number of maximum run sessions that can run.
99 | size_t (*get_max_run_sessions)(void);
100 | } RAI_LoadedBackend;
101 |
102 | typedef struct RAI_LoadedBackends {
103 | RAI_LoadedBackend tf;
104 | RAI_LoadedBackend tflite;
105 | RAI_LoadedBackend torch;
106 | RAI_LoadedBackend onnx;
107 | } RAI_LoadedBackends;
108 |
109 | RAI_LoadedBackends RAI_backends;
110 |
111 | int RAI_LoadBackend(RedisModuleCtx *ctx, int backend, const char *path);
112 |
113 | int RAI_LoadDefaultBackend(RedisModuleCtx *ctx, int backend);
114 |
115 | /**
116 | * @brief Returns the backend name as string.
117 | */
118 | const char *RAI_GetBackendName(RAI_Backend backend);
119 |
120 | /**
121 | * @brief Set the default backends path (/backends) in backends_path place holder.
122 | */
123 | void RAI_SetBackendsDefaultPath(char **backends_path);
124 |
--------------------------------------------------------------------------------
/src/backends/backends_api.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include
10 | #include "redismodule.h"
11 |
12 | #ifdef BACKENDS_API_EXTERN
13 | #define BACKENDS_API extern
14 | #endif
15 |
16 | #ifndef BACKENDS_API
17 | #define BACKENDS_API
18 | #endif
19 |
20 | typedef struct RAI_Tensor RAI_Tensor;
21 | typedef struct RAI_Model RAI_Model;
22 | typedef struct RAI_ModelRunCtx RAI_ModelRunCtx;
23 | typedef struct RAI_Error RAI_Error;
24 |
25 | /**
26 | * @return The internal id of RedisAI current working thread.
27 | * id range is {0, ..., -1}. If this is called from a non
28 | * RedisAI BG thread, return -1.
29 | */
30 | BACKENDS_API long (*RedisAI_GetThreadId)(void);
31 |
32 | /**
33 | * @return The number of working threads in RedisAI. This number should be
34 | * equal to the number of threads per queue (load time config) * number of devices
35 | * registered in RedisAI (a new device is registered if a model is set to run on
36 | * this device in AI.MODELSTORE command.
37 | */
38 | BACKENDS_API uintptr_t (*RedisAI_GetThreadsCount)(void);
39 |
40 | /**
41 | * @return The number of working threads per device queue (load time config).
42 | */
43 | BACKENDS_API long long (*RedisAI_GetNumThreadsPerQueue)(void);
44 |
45 | /**
46 | * @return The maximum number of milliseconds that a model run session should run
47 | * before it is terminated forcefully (load time config).
48 | * Currently supported only for onnxruntime backend.
49 | */
50 | BACKENDS_API long long (*RedisAI_GetModelExecutionTimeout)(void);
51 |
52 | /**
53 | * @return The maximum number of memory (in MB) that a backend can consume
54 | * for creating and running inference sessions. When memory limit is exceeded, operation
55 | * is not permitted and an error is returned.
56 | * Currently supported only for onnxruntime backend.
57 | */
58 | BACKENDS_API long long (*RedisAI_GetMemoryLimit)(void);
59 |
60 | /**
61 | * The following functions are part of RedisAI low level API (the full low level
62 | * API is defined in redisai.h). For every function below named "RedisAI_X", its
63 | * implementation can be found under the name "RAI_X" in RedisAI header files.
64 | */
65 |
66 | BACKENDS_API int (*RedisAI_InitError)(RAI_Error **err);
67 | BACKENDS_API void (*RedisAI_FreeError)(RAI_Error *err);
68 | BACKENDS_API const char *(*RedisAI_GetError)(RAI_Error *err);
69 |
70 | BACKENDS_API RAI_Tensor *(*RedisAI_TensorCreateFromDLTensor)(DLManagedTensor *dl_tensor);
71 | BACKENDS_API DLTensor *(*RedisAI_TensorGetDLTensor)(RAI_Tensor *tensor);
72 | BACKENDS_API RAI_Tensor *(*RedisAI_TensorGetShallowCopy)(RAI_Tensor *t);
73 | BACKENDS_API void (*RedisAI_TensorFree)(RAI_Tensor *tensor);
74 |
75 | BACKENDS_API RAI_ModelRunCtx *(*RedisAI_ModelRunCtxCreate)(RAI_Model *model);
76 | BACKENDS_API int (*RedisAI_GetModelFromKeyspace)(RedisModuleCtx *ctx, RedisModuleString *keyName,
77 | RAI_Model **model, int mode, RAI_Error *err);
78 | BACKENDS_API int (*RedisAI_ModelRunCtxAddInput)(RAI_ModelRunCtx *mctx, const char *inputName,
79 | RAI_Tensor *inputTensor);
80 | BACKENDS_API int (*RedisAI_ModelRunCtxAddOutput)(RAI_ModelRunCtx *mctx, const char *outputName);
81 | BACKENDS_API size_t (*RedisAI_ModelRunCtxNumOutputs)(RAI_ModelRunCtx *mctx);
82 | BACKENDS_API RAI_Tensor *(*RedisAI_ModelRunCtxOutputTensor)(RAI_ModelRunCtx *mctx, size_t index);
83 | BACKENDS_API void (*RedisAI_ModelRunCtxFree)(RAI_ModelRunCtx *mctx);
84 | BACKENDS_API int (*RedisAI_ModelRun)(RAI_ModelRunCtx **mctx, long long n, RAI_Error *err);
85 |
--------------------------------------------------------------------------------
/src/backends/libtflite_c/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(tflite_c STATIC tflite_c.cpp)
2 | message(${TFLITE_LIBRARIES})
3 | target_link_libraries(tflite_c "${TFLITE_LIBRARIES}")
4 | set_property(TARGET tflite_c PROPERTY CXX_STANDARD 11)
5 |
--------------------------------------------------------------------------------
/src/backends/libtflite_c/tflite_c.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "dlpack/dlpack.h"
10 |
11 | #ifdef __cplusplus
12 | extern "C" {
13 | #endif
14 |
15 | // void tfliteBasicTest();
16 |
17 | void *tfliteLoadModel(const char *model, size_t modellen, DLDeviceType device, int64_t device_id,
18 | char **error);
19 |
20 | void tfliteRunModel(void *ctx, long nInputs, DLManagedTensor **inputs, long nOutputs,
21 | DLManagedTensor **outputs, char **error);
22 |
23 | void tfliteSerializeModel(void *ctx, char **buffer, size_t *len, char **error);
24 |
25 | void tfliteDeallocContext(void *ctx);
26 |
27 | size_t tfliteModelNumInputs(void *ctx, char **error);
28 |
29 | const char *tfliteModelInputNameAtIndex(void *modelCtx, size_t index, char **error);
30 |
31 | size_t tfliteModelNumOutputs(void *ctx, char **error);
32 |
33 | const char *tfliteModelOutputNameAtIndex(void *modelCtx, size_t index, char **error);
34 |
35 | #ifdef __cplusplus
36 | }
37 | #endif
38 |
--------------------------------------------------------------------------------
/src/backends/libtorch_c/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(torch_c STATIC torch_c.cpp torch_extensions/torch_redis.cpp)
2 | target_link_libraries(torch_c "${TORCH_LIBRARIES}")
3 | set_property(TARGET torch_c PROPERTY CXX_STANDARD 14)
4 |
--------------------------------------------------------------------------------
/src/backends/libtorch_c/torch_extensions/torch_redis.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "torch/jit.h"
8 | #include "torch/script.h"
9 | #include "torch/csrc/jit/frontend/resolver.h"
10 |
11 | namespace torch {
12 | namespace jit {
13 | namespace script {
14 | struct RedisResolver : public Resolver {
15 |
16 | std::shared_ptr resolveValue(const std::string &name, GraphFunction &m,
17 | const SourceRange &loc) override {
18 | if (strcasecmp(name.c_str(), "torch") == 0) {
19 | return std::make_shared("aten");
20 | } else if (strcasecmp(name.c_str(), "redis") == 0) {
21 | return std::make_shared("redis");
22 | } else if (strcasecmp(name.c_str(), "redisAI") == 0) {
23 | return std::make_shared("redisAI");
24 | }
25 | return nullptr;
26 | }
27 |
28 | TypePtr resolveType(const std::string &name, const SourceRange &loc) override {
29 | return nullptr;
30 | }
31 | };
32 | inline std::shared_ptr redisResolver() { return std::make_shared(); }
33 | } // namespace script
34 | } // namespace jit
35 | } // namespace torch
36 |
37 | torch::IValue redisExecute(const std::string &fn_name, const std::vector &args);
38 | torch::List asList(const torch::IValue &v);
39 | std::vector modelExecute(const std::string &model_key,
40 | const std::vector &inputs,
41 | int64_t num_outputs);
42 |
43 | // Register Redis and RedisAI costume ops in torch
44 | void registerRedisOps(void);
45 |
--------------------------------------------------------------------------------
/src/backends/onnx_allocator/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(onnx_allocator STATIC onnx_allocator.cpp)
2 | target_link_libraries(onnx_allocator "${ONNX_LIBRARIES}")
3 | set_property(TARGET onnx_allocator PROPERTY CXX_STANDARD 14)
--------------------------------------------------------------------------------
/src/backends/onnx_allocator/onnx_allocator.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "onnxruntime_c_api.h"
10 |
11 | #ifdef __cplusplus
12 | extern "C" {
13 | #endif
14 |
15 | OrtAllocator *CreateCustomAllocator(unsigned long long max_memory);
16 |
17 | unsigned long long RAI_GetMemoryInfoORT();
18 |
19 | unsigned long long RAI_GetMemoryAccessORT();
20 |
21 | #ifdef __cplusplus
22 | }
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/backends/onnx_timeout.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "backends/onnxruntime.h"
10 | #include "onnxruntime_c_api.h"
11 |
12 | /**
13 | * The possible states for every run session entry in the array (entry per BG thread):
14 | * Every is initialized as AVAILABLE, which means that it is ready to get a new run session.
15 | * BG thread can perform a transition from AVAILABLE to ACTIVE upon starting a new run session.
16 | * In the cron callback, Redis main thread can perform a transition from ACTIVE to
17 | * INVALID if a timeout has reached, set the run session as terminated, and then make
18 | * another transition to TERMINATED.
19 | * At the end of a run session, the state is ACTIVE/TERMINATED, and then the BG thread
20 | * reset the entry and make a transition back to AVAILABLE.
21 | * Transition are done atomically to ensure right synchronization (BG thread cannot reset
22 | * run session while main thread is setting it as terminated).
23 | */
24 | typedef enum {
25 | RUN_SESSION_AVAILABLE,
26 | RUN_SESSION_ACTIVE,
27 | RUN_SESSION_TERMINATED,
28 | RUN_SESSION_INVALID
29 | } RunSessionState;
30 |
31 | typedef struct OnnxRunSessionCtx {
32 | long long queuingTime;
33 | OrtRunOptions *runOptions;
34 | RunSessionState *runState;
35 | } OnnxRunSessionCtx;
36 |
37 | // This is a global array of OnnxRunSessionCtx. Contains an entry for every thread
38 | // (on every device) that onnx models may run on.
39 | typedef struct OnnxGlobalRunSessions {
40 | OnnxRunSessionCtx **OnnxRunSessions;
41 | pthread_rwlock_t rwlock;
42 | } OnnxGlobalRunSessions;
43 |
44 | OnnxGlobalRunSessions *onnx_global_run_sessions;
45 |
46 | /**
47 | * @brief This is called whenever Onnx backend is loaded. It creates the global
48 | * OnnxGlobalRunSessions structure with entry-per-thread (for CPU threads at first),
49 | * so that every thread will have a designated entry to update with the onnx session
50 | * that it's going to run.
51 | */
52 | int RAI_InitGlobalRunSessionsORT(void);
53 |
54 | /**
55 | * @return The length of the global array (should be the number of current working threads)
56 | */
57 | size_t RAI_GetGlobalRunSessionsLenORT(void);
58 |
59 | /**
60 | * @brief This is called whenever RedisAI gets a request to store a model that run
61 | * on a new device, and creates some more working thread, as configured in
62 | * ThreadPerQueue. Thus, the global array of onnx sessions that has an
63 | * entry-per-thread is extended accordingly.
64 | */
65 | int RAI_AddNewDeviceORT(const char *device_str);
66 |
67 | /**
68 | * @brief A callback that is registered to RedisCron event, that is, it is called
69 | * periodically and go over all the (possibly running) onnx sessions, and kill
70 | * those that exceeds the timeout.
71 | */
72 | void RAI_EnforceTimeoutORT(RedisModuleCtx *ctx, RedisModuleEvent eid, uint64_t subevent,
73 | void *data);
74 |
75 | /**
76 | * @brief Set a new OrtRunOptions in the global structure, to allow us to
77 | * "terminate" the run session from the cron callback.
78 | * @param new_run_options - The newly created OrtRunOptions to store.
79 | * @param run_session_index - placeholder for the index of the running thread
80 | * in the global array, to have a quick access later to clean this entry.
81 | */
82 | void RAI_ActivateRunSessionCtxORT(OrtRunOptions *new_run_options, long *run_session_index);
83 |
84 | /**
85 | * @brief Release the OrtRunOptions of a session that finished its run and
86 | * reset the corresponding entry in the global structure.
87 | * @param run_session_index - The entry index where OrtRunOptions was stored.
88 | */
89 | void RAI_ResetRunSessionCtxORT(long run_session_index);
90 |
--------------------------------------------------------------------------------
/src/backends/onnxruntime.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "config/config.h"
10 | #include "redis_ai_objects/err.h"
11 | #include "redis_ai_objects/model.h"
12 | #include "execution/execution_contexts/execution_ctx.h"
13 |
14 | int RAI_InitBackendORT(int (*get_api_fn)(const char *, void **));
15 |
16 | RAI_Model *RAI_ModelCreateORT(RAI_Backend backend, const char *devicestr, RAI_ModelOpts opts,
17 | const char *modeldef, size_t modellen, RAI_Error *err);
18 |
19 | void RAI_ModelFreeORT(RAI_Model *model, RAI_Error *error);
20 |
21 | int RAI_ModelRunORT(RAI_Model *model, RAI_ExecutionCtx **ectxs, RAI_Error *error);
22 |
23 | int RAI_ModelSerializeORT(RAI_Model *model, char **buffer, size_t *len, RAI_Error *error);
24 |
25 | const char *RAI_GetBackendVersionORT(void);
26 |
--------------------------------------------------------------------------------
/src/backends/tensorflow.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "config/config.h"
10 | #include "redis_ai_objects/err.h"
11 | #include "redis_ai_objects/model.h"
12 | #include "execution/execution_contexts/execution_ctx.h"
13 |
14 | int RAI_InitBackendTF(int (*get_api_fn)(const char *, void *));
15 |
16 | RAI_Model *RAI_ModelCreateTF(RAI_Backend backend, const char *devicestr, RAI_ModelOpts opts,
17 | size_t ninputs, const char **inputs, size_t noutputs,
18 | const char **outputs, const char *modeldef, size_t modellen,
19 | RAI_Error *error);
20 |
21 | void RAI_ModelFreeTF(RAI_Model *model, RAI_Error *error);
22 |
23 | int RAI_ModelRunTF(RAI_Model *model, RAI_ExecutionCtx **ectxs, RAI_Error *error);
24 |
25 | int RAI_ModelSerializeTF(RAI_Model *model, char **buffer, size_t *len, RAI_Error *error);
26 |
27 | const char *RAI_GetBackendVersionTF(void);
28 |
--------------------------------------------------------------------------------
/src/backends/tflite.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "config/config.h"
10 | #include "redis_ai_objects/err.h"
11 | #include "redis_ai_objects/model.h"
12 | #include "execution/execution_contexts/execution_ctx.h"
13 |
14 | int RAI_InitBackendTFLite(int (*get_api_fn)(const char *, void *));
15 |
16 | RAI_Model *RAI_ModelCreateTFLite(RAI_Backend backend, const char *devicestr, RAI_ModelOpts opts,
17 | const char *modeldef, size_t modellen, RAI_Error *err);
18 |
19 | void RAI_ModelFreeTFLite(RAI_Model *model, RAI_Error *error);
20 |
21 | int RAI_ModelRunTFLite(RAI_Model *model, RAI_ExecutionCtx **ectxs, RAI_Error *error);
22 |
23 | int RAI_ModelSerializeTFLite(RAI_Model *model, char **buffer, size_t *len, RAI_Error *error);
24 |
25 | const char *RAI_GetBackendVersionTFLite(void);
26 |
--------------------------------------------------------------------------------
/src/backends/torch.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "config/config.h"
10 | #include "redis_ai_objects/err.h"
11 | #include "redis_ai_objects/model.h"
12 | #include "redis_ai_objects/script.h"
13 | #include "execution/execution_contexts/execution_ctx.h"
14 |
15 | int RAI_InitBackendTorch(int (*get_api_fn)(const char *, void *));
16 |
17 | RAI_Model *RAI_ModelCreateTorch(RAI_Backend backend, const char *devicestr, RAI_ModelOpts opts,
18 | const char *modeldef, size_t modellen, RAI_Error *err);
19 |
20 | void RAI_ModelFreeTorch(RAI_Model *model, RAI_Error *error);
21 |
22 | int RAI_ModelRunTorch(RAI_Model *model, RAI_ExecutionCtx **ectxs, RAI_Error *error);
23 |
24 | int RAI_ModelSerializeTorch(RAI_Model *model, char **buffer, size_t *len, RAI_Error *error);
25 |
26 | RAI_Script *RAI_ScriptCreateTorch(const char *devicestr, const char *scriptdef,
27 | const char **entry_points, size_t n_entry_points,
28 | RAI_Error *error);
29 |
30 | void RAI_ScriptFreeTorch(RAI_Script *script, RAI_Error *error);
31 |
32 | int RAI_ScriptRunTorch(RAI_Script *script, const char *function, RAI_ExecutionCtx *ectx,
33 | RAI_Error *error);
34 |
35 | const char *RAI_GetBackendVersionTorch(void);
36 |
--------------------------------------------------------------------------------
/src/backends/util.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include
8 | #include
9 | #include "backends/util.h"
10 |
11 | int parseDeviceStr(const char *device_str, RAI_Device *device, int64_t *device_id) {
12 | if (strncasecmp(device_str, "CPU", 3) == 0) {
13 | *device = RAI_DEVICE_CPU;
14 | *device_id = -1;
15 | } else if (strcasecmp(device_str, "GPU") == 0) {
16 | *device = RAI_DEVICE_GPU;
17 | *device_id = -1;
18 | } else if (strncasecmp(device_str, "GPU:", 4) == 0) {
19 | *device = RAI_DEVICE_GPU;
20 | // Convert the id string into a number, returns zero if no valid conversion could be
21 | // preformed, and sets errno in case of overflow.
22 | long long id = strtoll(device_str + 4, NULL, 0);
23 | if (errno == ERANGE)
24 | return 0;
25 | *device_id = id;
26 | } else {
27 | return 0;
28 | }
29 | return 1;
30 | }
31 |
--------------------------------------------------------------------------------
/src/backends/util.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | #include "config/config.h"
14 |
15 | int parseDeviceStr(const char *device_str, RAI_Device *device, int64_t *device_id);
16 |
--------------------------------------------------------------------------------
/src/config/gdb_config.h:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | *Copyright Redis Ltd. 2018 - present
4 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
5 | *the Server Side Public License v1 (SSPLv1).
6 | */
7 |
8 | #if defined(DEBUG) || defined(_DEBUG)
9 | #include "readies/cetara/diag/gdb.h"
10 | #endif
11 |
--------------------------------------------------------------------------------
/src/execution/DAG/dag_builder.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "redisai.h"
10 |
11 | /**
12 | * @brief Create a new empty DAG runInfo object.
13 | */
14 | RAI_DAGRunCtx *RAI_DAGRunCtxCreate(void);
15 |
16 | /**
17 | * @brief Create a new MODELRUN op for a DAG.
18 | * @param model The model to run.
19 | */
20 | RAI_DAGRunOp *RAI_DAGCreateModelRunOp(RAI_Model *model);
21 |
22 | /**
23 | * @brief Create a new SCRIPTRUN op for a DAG.
24 | * @param script The script to run.
25 | * @param func_name The specific function to run in the given script.
26 | */
27 | RAI_DAGRunOp *RAI_DAGCreateScriptRunOp(RAI_Script *script, const char *func_name);
28 |
29 | /**
30 | * @brief Add an input key to a DAG run op (before inserting it to the DAG).
31 | * @param DAGop The DAG run op (MODELRUN / SCRIPTRUN).
32 | * @param input The tensor input name (this name should appear in a previous op of the DAG).
33 | */
34 | int RAI_DAGRunOpAddInput(RAI_DAGRunOp *DAGOp, const char *input);
35 |
36 | /**
37 | * @brief Add an output key to a DAG run op (before inserting it to the DAG).
38 | * @param DAGop The DAG run op (MODELRUN / SCRIPTRUN).
39 | * @param output The tensor output name (this name may appear in one of the following ops of the
40 | * DAG).
41 | */
42 | int RAI_DAGRunOpAddOutput(RAI_DAGRunOp *DAGOp, const char *output);
43 |
44 | /**
45 | * @brief Add a run op (MODELRUN/SCRIPTRUN) to a DAG.
46 | * @param runInfo The DAG to insert the op to.
47 | * @param DAGop The DAG run op (MODELRUN / SCRIPTRUN).
48 | * @param err Error is returned in case of a MODELRUN op if the number of inputs and outputs
49 | * given to the op does not match to the number of inputs and outputs in the model definition.
50 | */
51 | int RAI_DAGAddRunOp(RAI_DAGRunCtx *run_info, RAI_DAGRunOp *DAGop, RAI_Error *err);
52 |
53 | /**
54 | * @brief Load a given tensor to the DAG local context.
55 | * @param runInfo The DAG to load the tensor into.
56 | * @param tname The tensor key.
57 | * @param tensor The tensor to load to the DAG (we load a shallow copy).
58 | */
59 | int RAI_DAGLoadTensor(RAI_DAGRunCtx *run_info, const char *t_name, RAI_Tensor *tensor);
60 |
61 | /**
62 | * @brief Append a TENSORSET op to a DAG (can use to load an intermediate tensors)
63 | * @param runInfo The DAG to append this op into.
64 | * @param tensor The tensor to set.
65 | */
66 | int RAI_DAGAddTensorSet(RAI_DAGRunCtx *run_info, const char *t_name, RAI_Tensor *tensor);
67 |
68 | /**
69 | * @brief Append a TENSORGET op to a DAG (can use to output intermediate and final tensors)
70 | * @param runInfo The DAG to append this op into.
71 | * @param tensor The tensor to set.
72 | */
73 | int RAI_DAGAddTensorGet(RAI_DAGRunCtx *run_info, const char *t_name);
74 |
75 | /**
76 | * @brief Add ops to a DAG from string (according to the command syntax). In case of a valid
77 | * string, the ops are added to the DAG run info, and otherwise all the ops are discarded.
78 | * @param runInfo The DAG to insert the ops into.
79 | * @param dag The string representing the DAG ops to add.
80 | * @param err Error is returned in case of a MODELRUN op if the number of inputs and outputs
81 | * given to the op does not match to the number of inputs and outputs in the model definition.
82 | */
83 | int RAI_DAGAddOpsFromString(RAI_DAGRunCtx *run_info, const char *dag, RAI_Error *err);
84 |
85 | /**
86 | * @brief Returns the number of ops in a DAG.
87 | */
88 | size_t RAI_DAGNumOps(RAI_DAGRunCtx *run_info);
89 |
90 | /**
91 | * @brief Free DAG's runInfo and all its internal ops.
92 | */
93 | void RAI_DAGFree(RAI_DAGRunCtx *run_info);
94 |
95 | /**
96 | * @brief Free a specific DAG run op (MODELRUN/SCRIPTRUN).
97 | */
98 | void RAI_DAGRunOpFree(RAI_DAGRunOp *dagOp);
99 |
--------------------------------------------------------------------------------
/src/execution/DAG/dag_execute.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "redismodule.h"
10 | #include "execution/run_info.h"
11 |
12 | /**
13 | @brief We are given a DAG runInfo of a sequence of operations, each with its own
14 | input and output keys. The names of the keys will be used to look whether the
15 | inputs to a DAG operation have all been realized by previous operations (or if
16 | they are available as part of LOADed keys from keyspace).
17 | This strategy is fine if keys are not aliased, that is, if a command's output
18 | overwrites the key of a previous command. This would trick DAG operations into
19 | thinking that their input is ready when it's not.
20 | To overcome this, we map the input and output tensors for every operation to indices,
21 | in the following way. For every input of an operation having the key "x", we map the index
22 | for which "x" was last mapped to when, it was an output of a previous operation.
23 | For every output of an operation "y", we map the next available index in the array.
24 | Every entry in the DAG array contains NULL (except for tensors that where loaded
25 | before the DAG run starts).
26 | @param rinfo The DAG runInfo.
27 | @param tensorsNamesToInd A dict mapping every key name of a tensor that appeared
28 | in DAG operation, to the maximal index of the DAG shared array for which they were mapped to.
29 | @returns REDISMODULE_ERR if there exists an operation for which one of the input
30 | tensors didn't appear as an output of a previous operation, REDISMODULE_OK otherwise
31 | */
32 | int MapTensorsKeysToIndices(RedisAI_RunInfo *rinfo, AI_dict *tensorsNamesToInd);
33 |
34 | /**
35 | * @brief Validates that tensors key names to persist appeared in the DAG operations.
36 | * @param rinfo The DAG runInfo.
37 | * @param tensorsNamesToInd A dict mapping every key name of a tensor that appeared
38 | * in DAG operation, to the maximal index of the DAG shared array for which they were mapped to.
39 | * @param persistTensorsNames A hash table the contains the names of the tensors
40 | * to persist when the DAG run is finished.
41 | * @return REDISMODULE_ERR if there exists a tensor key to persist that didn't
42 | * appear in DAG operation, REDISMODULE_OK otherwise
43 | */
44 | int ValidatePersistKeys(RedisAI_RunInfo *rinfo, AI_dict *tensorsNamesToInd,
45 | AI_dict *persistTensorsNames);
46 |
47 | /**
48 | * @brief Run asynchronously a DAG. This will validate that the sequence of DAG ops
49 | * is valid and generate a unique key to the tensor that flow in the DAG (mangleTensorsNames)
50 | * Then, DAG is sent to the devices' run queues and will be execute by a workung thread.
51 | * @param DAGAsyncFinish This is a callback that will be called after the whole DAG finish its run.
52 | * @param private_data This is an input to the DAGAsyncFinish callback. Can be used to save the
53 | * results and errors
54 | * @param err Error is returned in case that the validation failed, and the DAG wasn't inserted to
55 | * the queues.
56 | */
57 | int RAI_DAGRun(RAI_DAGRunCtx *run_info, RAI_OnFinishCB DAGAsyncFinish, void *private_data,
58 | RAI_Error *err);
59 |
60 | /**
61 | * @brief This can be called in the finish CB, returns the number of outputs (TENSORGET ops).
62 | * @param finish_ctx This represents the DAG runInfo at the end of the run.
63 | */
64 | size_t RAI_DAGNumOutputs(RAI_OnFinishCtx *finish_ctx);
65 |
66 | /**
67 | * @brief This can be called in the finish CB, returns a specific output tensor (result of a
68 | * TENSORGET op).
69 | * @param finish_ctx This represents the DAG runInfo at the end of the run.
70 | * @param index The index of the TENSORGET op in the DAG.
71 | * @retval returns the tensor that the i'th TENSORGET op outputs.
72 | */
73 | const RAI_Tensor *RAI_DAGOutputTensor(RAI_OnFinishCtx *finish_ctx, size_t index);
74 |
75 | /**
76 | * @brief Returns true if (at least) one of the DAG ops encountered an error.
77 | */
78 | bool RAI_DAGRunError(RAI_OnFinishCtx *finish_ctx);
79 |
80 | /**
81 | * @brief This can be called in the finish CB, to get DAG error details.
82 | * @param finish_ctx This represents the DAG runInfo at the end of the run.
83 | * @retval returns an object that represents the DAG status, from which a user can
84 | * obtain the error code (error code is "OK" if no error has occurred) and error details.
85 | */
86 | const RAI_Error *RAI_DAGGetError(RAI_OnFinishCtx *finish_ctx);
87 |
--------------------------------------------------------------------------------
/src/execution/DAG/dag_op.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "dag_op.h"
8 | #include "util/arr.h"
9 | #include "execution/execution_contexts/modelRun_ctx.h"
10 | #include "execution/execution_contexts/scriptRun_ctx.h"
11 | /**
12 | * Allocate the memory and initialise the RAI_DagOp.
13 | * @param result Output parameter to capture allocated RAI_DagOp.
14 | * @return REDISMODULE_OK on success, or REDISMODULE_ERR if the allocation
15 | * failed.
16 | */
17 | int RAI_InitDagOp(RAI_DagOp **result) {
18 | RAI_DagOp *dagOp;
19 | dagOp = (RAI_DagOp *)RedisModule_Calloc(1, sizeof(RAI_DagOp));
20 |
21 | dagOp->commandType = REDISAI_DAG_CMD_NONE;
22 | dagOp->inkeys = (RedisModuleString **)array_new(RedisModuleString *, 1);
23 | dagOp->outkeys = (RedisModuleString **)array_new(RedisModuleString *, 1);
24 | dagOp->inkeys_indices = array_new(size_t, 1);
25 | dagOp->outkeys_indices = array_new(size_t, 1);
26 | dagOp->outTensor = NULL;
27 | dagOp->ectx = NULL;
28 | dagOp->devicestr = NULL;
29 | dagOp->duration_us = 0;
30 | dagOp->result = -1;
31 | RAI_InitError(&dagOp->err);
32 | dagOp->argv = NULL;
33 | dagOp->argc = 0;
34 |
35 | *result = dagOp;
36 | return REDISMODULE_OK;
37 | }
38 |
39 | void RAI_FreeDagOp(RAI_DagOp *dagOp) {
40 |
41 | RAI_FreeError(dagOp->err);
42 |
43 | if (dagOp->outTensor)
44 | RAI_TensorFree(dagOp->outTensor);
45 |
46 | if (dagOp->ectx) {
47 | dagOp->ectx->freeFn(dagOp->ectx);
48 | }
49 |
50 | if (dagOp->inkeys) {
51 | for (size_t i = 0; i < array_len(dagOp->inkeys); i++) {
52 | RedisModule_FreeString(NULL, dagOp->inkeys[i]);
53 | }
54 | array_free(dagOp->inkeys);
55 | }
56 | array_free(dagOp->inkeys_indices);
57 |
58 | if (dagOp->outkeys) {
59 | for (size_t i = 0; i < array_len(dagOp->outkeys); i++) {
60 | RedisModule_FreeString(NULL, dagOp->outkeys[i]);
61 | }
62 | array_free(dagOp->outkeys);
63 | }
64 | array_free(dagOp->outkeys_indices);
65 | RedisModule_Free(dagOp);
66 | }
67 |
--------------------------------------------------------------------------------
/src/execution/DAG/dag_op.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "redismodule.h"
9 | #include "redis_ai_objects/err.h"
10 | #include "redis_ai_objects/script.h"
11 | #include "redis_ai_objects/model_struct.h"
12 | #include "execution/execution_contexts/execution_ctx.h"
13 |
14 | typedef enum DAGCommand {
15 | REDISAI_DAG_CMD_NONE = 0,
16 | REDISAI_DAG_CMD_TENSORSET,
17 | REDISAI_DAG_CMD_TENSORGET,
18 | REDISAI_DAG_CMD_MODELRUN,
19 | REDISAI_DAG_CMD_SCRIPTRUN
20 | } DAGCommand;
21 |
22 | #define VALIDATE_DAG_COMMAND(cmd) \
23 | RedisModule_Assert(cmd >= REDISAI_DAG_CMD_TENSORSET && cmd <= REDISAI_DAG_CMD_SCRIPTRUN);
24 |
25 | typedef struct RAI_DagOp {
26 | DAGCommand commandType;
27 | RedisModuleString **inkeys;
28 | RedisModuleString **outkeys;
29 | size_t *inkeys_indices;
30 | size_t *outkeys_indices;
31 | RAI_Tensor *outTensor; // The tensor to upload in TENSORSET op.
32 | RAI_ExecutionCtx *ectx;
33 | uint fmt; // This is relevant for TENSORGET op.
34 | char *devicestr;
35 | int result; // REDISMODULE_OK or REDISMODULE_ERR
36 | long long duration_us;
37 | RAI_Error *err;
38 | RedisModuleString **argv;
39 | int argc;
40 | } RAI_DagOp;
41 |
42 | /**
43 | * Allocate the memory and initialise the RAI_DagOp.
44 | * @param result Output parameter to capture allocated RAI_DagOp.
45 | * @return REDISMODULE_OK on success, or REDISMODULE_ERR if the allocation
46 | * failed.
47 | */
48 | int RAI_InitDagOp(RAI_DagOp **result);
49 |
50 | /**
51 | * Frees the memory allocated of RAI_DagOp
52 | * @param ctx Context in which Redis modules operate
53 | * @param RAI_DagOp context in which RedisAI command operates.
54 | */
55 | void RAI_FreeDagOp(RAI_DagOp *dagOp);
56 |
--------------------------------------------------------------------------------
/src/execution/background_workers.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | /**
8 | * background_workers.h
9 | *
10 | * Contains the structure and method signatures required to manage the
11 | * per-device queues, used for decoupling the work from the main thread to the
12 | * background worker threads. For each of the incoming ModelRun, ScriptRun, and
13 | * DagRun commands, the request is queued and evaded asynchronously to one the
14 | * device queues.
15 | *
16 | */
17 |
18 | #pragma once
19 |
20 | #if defined(__linux__) && !defined(_GNU_SOURCE)
21 | #define _GNU_SOURCE
22 | #endif
23 |
24 | #include
25 |
26 | #include "config/config.h"
27 | #include "DAG/dag.h"
28 | #include "redis_ai_objects/model.h"
29 | #include "redisai.h"
30 | #include "rmutil/alloc.h"
31 | #include "rmutil/args.h"
32 | #include "redis_ai_objects/script.h"
33 | #include "redis_ai_objects/stats.h"
34 | #include "redis_ai_objects/tensor.h"
35 | #include "util/arr.h"
36 | #include "util/queue.h"
37 |
38 | /**
39 | * @brief RedisAI main loop for every background working thread
40 | * @param arg - This is the run queue info of the device on which this thread is
41 | * running the AI model/script
42 | */
43 | void *BGWorker_ThreadMain(void *arg);
44 |
45 | /**
46 | * @brief Returns the thread id (among RedisAI working threads). If this is called
47 | * form a non RedisAI working thread, return -1
48 | */
49 | long BGWorker_GetThreadId(void);
50 |
51 | /**
52 | * @brief Returns the total number of RedisAI working threads (for all devices).
53 | */
54 | uintptr_t BGWorker_GetThreadsCount(void);
--------------------------------------------------------------------------------
/src/execution/command_parser.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "command_parser.h"
8 | #include "redismodule.h"
9 | #include "execution/utils.h"
10 | #include "execution/run_info.h"
11 | #include "execution/DAG/dag.h"
12 | #include "execution/parsing/dag_parser.h"
13 | #include "execution/parsing/deprecated.h"
14 | #include "execution/parsing/model_commands_parser.h"
15 | #include "execution/parsing/script_commands_parser.h"
16 |
17 | int RedisAI_ExecuteCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc,
18 | RunCommand command, bool ro_dag) {
19 |
20 | int flags = RedisModule_GetContextFlags(ctx);
21 | bool blocking_not_allowed = (flags & (REDISMODULE_CTX_FLAGS_MULTI | REDISMODULE_CTX_FLAGS_LUA));
22 | if (blocking_not_allowed)
23 | return RedisModule_ReplyWithError(
24 | ctx, "ERR Cannot run RedisAI command within a transaction or a LUA script");
25 |
26 | RedisAI_RunInfo *rinfo;
27 | RAI_InitRunInfo(&rinfo);
28 | int status = REDISMODULE_ERR;
29 |
30 | switch (command) {
31 | case CMD_MODELRUN:
32 | rinfo->single_op_dag = 1;
33 | RAI_DagOp *modelRunOp;
34 | RAI_InitDagOp(&modelRunOp);
35 | rinfo->dagOps = array_append(rinfo->dagOps, modelRunOp);
36 | status = ParseModelRunCommand(rinfo, modelRunOp, argv, argc);
37 | break;
38 | case CMD_SCRIPTRUN:
39 | rinfo->single_op_dag = 1;
40 | RAI_DagOp *scriptRunOp;
41 | RAI_InitDagOp(&scriptRunOp);
42 | rinfo->dagOps = array_append(rinfo->dagOps, scriptRunOp);
43 | status = ParseScriptRunCommand(rinfo, scriptRunOp, argv, argc);
44 | break;
45 | case CMD_DAGRUN:
46 | status = ParseDAGRunCommand(rinfo, ctx, argv, argc, ro_dag);
47 | break;
48 | case CMD_MODELEXECUTE:
49 | rinfo->single_op_dag = 1;
50 | RAI_DagOp *modelExecuteOp;
51 | RAI_InitDagOp(&modelExecuteOp);
52 | rinfo->dagOps = array_append(rinfo->dagOps, modelExecuteOp);
53 | status = ParseModelExecuteCommand(rinfo, modelExecuteOp, argv, argc);
54 | break;
55 | case CMD_SCRIPTEXECUTE:
56 | rinfo->single_op_dag = 1;
57 | RAI_DagOp *scriptExecOp;
58 | RAI_InitDagOp(&scriptExecOp);
59 | rinfo->dagOps = array_append(rinfo->dagOps, scriptExecOp);
60 | status = ParseScriptExecuteCommand(rinfo, scriptExecOp, argv, argc);
61 | break;
62 | case CMD_DAGEXECUTE:
63 | status = ParseDAGExecuteCommand(rinfo, ctx, argv, argc, ro_dag);
64 | break;
65 | default:
66 | break;
67 | }
68 | if (status == REDISMODULE_ERR) {
69 | RedisModule_ReplyWithError(ctx, RAI_GetErrorOneLine(rinfo->err));
70 | RAI_FreeRunInfo(rinfo);
71 | return REDISMODULE_OK;
72 | }
73 | rinfo->dagOpCount = array_len(rinfo->dagOps);
74 |
75 | rinfo->OnFinish = DAG_ReplyAndUnblock;
76 | rinfo->client = RedisModule_BlockClient(ctx, RedisAI_DagRun_Reply, NULL, RunInfo_FreeData, 0);
77 | if (DAG_InsertDAGToQueue(rinfo) != REDISMODULE_OK) {
78 | RedisModule_UnblockClient(rinfo->client, rinfo);
79 | return REDISMODULE_ERR;
80 | }
81 | int major, minor, patch;
82 | RedisAI_GetRedisVersion(&major, &minor, &patch);
83 | // The following command is supported only from redis 6.2
84 | if (major > 6 || (major == 6 && minor >= 2)) {
85 | RedisModule_BlockedClientMeasureTimeStart(rinfo->client);
86 | }
87 | return REDISMODULE_OK;
88 | }
89 |
--------------------------------------------------------------------------------
/src/execution/command_parser.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "redismodule.h"
10 | #include "run_info.h"
11 |
12 | typedef enum RunCommand {
13 | CMD_MODELRUN = 0,
14 | CMD_SCRIPTRUN,
15 | CMD_DAGRUN,
16 | CMD_MODELEXECUTE,
17 | CMD_SCRIPTEXECUTE,
18 | CMD_DAGEXECUTE
19 | } RunCommand;
20 |
21 | /**
22 | * @brief Parse and execute RedisAI run command. After parsing and validation, the resulted
23 | * runInfo (DAG) is queued and the client is blocked until the execution is complete (async
24 | * execution).
25 | * @return Returns REDISMODULE_OK if the command is valid, REDISMODULE_ERR otherwise.
26 | */
27 | int RedisAI_ExecuteCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc,
28 | RunCommand command, bool ro_dag);
29 |
--------------------------------------------------------------------------------
/src/execution/execution_contexts/execution_ctx.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "execution_ctx.h"
8 | #include "redismodule.h"
9 | #include "util/arr.h"
10 |
11 | void RAI_ExecutionCtx_Init(RAI_ExecutionCtx *ctx, RAI_RunStats *run_stats,
12 | RAI_ExecutionCtx_Free_fn freeFn) {
13 | ctx->inputs = array_new(RAI_Tensor *, 10);
14 | ctx->outputs = array_new(RAI_Tensor *, 10);
15 | ctx->runStats = run_stats;
16 | ctx->freeFn = freeFn;
17 | }
18 | void RAI_ExecutionCtx_Free(RAI_ExecutionCtx *ctx) {
19 | size_t inputsLen = array_len(ctx->inputs);
20 | for (size_t i = 0; i < inputsLen; i++) {
21 | RAI_TensorFree(ctx->inputs[i]);
22 | }
23 | size_t outputsLen = array_len(ctx->outputs);
24 | for (size_t i = 0; i < outputsLen; i++) {
25 | RAI_TensorFree(ctx->outputs[i]);
26 | }
27 | array_free(ctx->inputs);
28 | array_free(ctx->outputs);
29 | }
30 |
31 | inline size_t RAI_ExecutionCtx_NumInputs(RAI_ExecutionCtx *ctx) { return array_len(ctx->inputs); }
32 |
33 | inline void RAI_ExecutionCtx_AddInput(RAI_ExecutionCtx *ctx, RAI_Tensor *t) {
34 | if (t != NULL) {
35 | t = RAI_TensorGetShallowCopy(t);
36 | }
37 | ctx->inputs = array_append(ctx->inputs, t);
38 | }
39 |
40 | inline RAI_Tensor *RAI_ExecutionCtx_GetInput(RAI_ExecutionCtx *ctx, size_t index) {
41 | RedisModule_Assert(index < array_len(ctx->inputs));
42 | return ctx->inputs[index];
43 | }
44 |
45 | inline size_t RAI_ExecutionCtx_NumOutputs(RAI_ExecutionCtx *ctx) { return array_len(ctx->outputs); }
46 |
47 | inline void RAI_ExecutionCtx_AddOutputPlaceholder(RAI_ExecutionCtx *ctx) {
48 | ctx->outputs = array_append(ctx->outputs, NULL);
49 | }
50 |
51 | void RAI_ExecutionCtx_SetOutput(RAI_ExecutionCtx *ctx, RAI_Tensor *t, size_t index) {
52 | RedisModule_Assert(index < array_len(ctx->outputs));
53 | ctx->outputs[index] = t;
54 | }
55 |
56 | inline RAI_Tensor *RAI_ExecutionCtx_GetOutput(RAI_ExecutionCtx *ctx, size_t index) {
57 | RedisModule_Assert(index < array_len(ctx->outputs));
58 | return ctx->outputs[index];
59 | }
60 |
61 | inline RAI_RunStats *RAI_ExecutionCtx_GetStats(RAI_ExecutionCtx *ctx) { return ctx->runStats; }
62 |
--------------------------------------------------------------------------------
/src/execution/execution_contexts/execution_ctx.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include
10 | #include "redis_ai_objects/tensor.h"
11 |
12 | // Pre decleration
13 | typedef struct RAI_ExecutionCtx RAI_ExecutionCtx;
14 |
15 | typedef void (*RAI_ExecutionCtx_Free_fn)(RAI_ExecutionCtx *ctx);
16 |
17 | /**
18 | * @brief Generic struct to hold execution contexts for DAG ops. This struct holds the input and
19 | * output tensors of the op, as well as inheriting classes specific functionality.
20 | *
21 | */
22 | typedef struct RAI_ExecutionCtx {
23 | RAI_Tensor **inputs; // DAG op input tensors.
24 | RAI_Tensor **outputs; // DAG op output tensors.
25 | RAI_RunStats *runStats; // The underline op's (Model/Script) stats entry.
26 | RAI_ExecutionCtx_Free_fn freeFn; // Inheriting execution context free function.
27 | } RAI_ExecutionCtx;
28 |
29 | /**
30 | * @brief Initializes an allocated RAI_ExecutionCtx.
31 | *
32 | * @param ctx - Execution context to initialize.
33 | * @param freeFn - Specific free function for inheriting execution contexts (script or model)
34 | */
35 | void RAI_ExecutionCtx_Init(RAI_ExecutionCtx *ctx, RAI_RunStats *run_stats,
36 | RAI_ExecutionCtx_Free_fn freeFn);
37 |
38 | /**
39 | * @brief Frees the execution context internal structures. To be used from an inhereting execution
40 | * contxt.
41 | *
42 | * @param ctx - Execution context to Free.
43 | */
44 | void RAI_ExecutionCtx_Free(RAI_ExecutionCtx *ctx);
45 |
46 | /**
47 | * @brief Returns the number of input tensors of the execution context.
48 | *
49 | * @param ctx - Execution context.
50 | * @return size_t - Number of input tensors.
51 | */
52 | size_t RAI_ExecutionCtx_NumInputs(RAI_ExecutionCtx *ctx);
53 |
54 | /**
55 | * @brief Adds an input tensor to the execution context.
56 | *
57 | * @param ctx - Execution context.
58 | * @param t - Input tensor.
59 | */
60 | void RAI_ExecutionCtx_AddInput(RAI_ExecutionCtx *ctx, RAI_Tensor *t);
61 |
62 | /**
63 | * @brief Returns an input tensor from the execution context, for a given index.
64 | *
65 | * @param ctx - Execution context.
66 | * @param index
67 | * @return RAI_Tensor* - Input tensor.
68 | */
69 | RAI_Tensor *RAI_ExecutionCtx_GetInput(RAI_ExecutionCtx *ctx, size_t index);
70 |
71 | /**
72 | * @brief Returns the number of output tensors/placeholders of the execution context.
73 | *
74 | * @param ctx - Execution context.
75 | * @return size_t - Number of output tensors/placeholders.
76 | */
77 | size_t RAI_ExecutionCtx_NumOutputs(RAI_ExecutionCtx *ctx);
78 |
79 | /**
80 | * @brief Sets (appends) an output tensor placeholder to the execution context.
81 | *
82 | * @param ctx - Execution context.
83 | */
84 | void RAI_ExecutionCtx_AddOutputPlaceholder(RAI_ExecutionCtx *ctx);
85 |
86 | /**
87 | * @brief Sets an output tensor in a specfic index, populated before by a placeholder.
88 | *
89 | * @param ctx - Execution context.
90 | * @param t - Output tensor.
91 | * @param index
92 | */
93 | void RAI_ExecutionCtx_SetOutput(RAI_ExecutionCtx *ctx, RAI_Tensor *t, size_t index);
94 |
95 | /**
96 | * @brief Returns an output tensor from the execution context, for a given index.
97 | *
98 | * @param ctx - Execution context.
99 | * @param index
100 | * @return RAI_Tensor* - Output tensor.
101 | */
102 | RAI_Tensor *RAI_ExecutionCtx_GetOutput(RAI_ExecutionCtx *ctx, size_t index);
103 |
104 | /**
105 | * @brief Returns the RunStats object for underline object.
106 | * @param ctx - Execution context.
107 | * @return RAI_RunStats
108 | */
109 | RAI_RunStats *RAI_ExecutionCtx_GetStats(RAI_ExecutionCtx *ctx);
110 |
--------------------------------------------------------------------------------
/src/execution/parsing/dag_parser.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "execution/run_info.h"
10 |
11 | /**
12 | * @brief Parse and validate DAGEXECUTE command (Populate the rinfo object):
13 | * - parse KEYS, LOAD, PERSIST, and TIMEOUT args. Persist is not allowed if the DAG is READ-ONLY
14 | * (dag_to is true).
15 | * - parse and validate every DAGop individually. SCRIPTEXECUTE is not allowed if the DAG is
16 | * READ-ONLY.
17 | * - Generate a unique key for every tensor name that appear in the DAG's ops.
18 | * (thus ensure that the operations will be done by the desired order).
19 | * @return Returns REDISMODULE_OK if the command is valid, REDISMODULE_ERR otherwise.
20 | */
21 | int ParseDAGExecuteCommand(RedisAI_RunInfo *rinfo, RedisModuleCtx *ctx, RedisModuleString **argv,
22 | int argc, bool dag_ro);
23 |
24 | /**
25 | * @brief Parse the arguments of the given ops in the DAGRUN command and build every op accordingly.
26 | * @param rinfo The DAG run info that will be populated with the ops if they are valid.
27 | * with its op,
28 | * @param ops A local array of ops, where every op has an argv field that points to an
29 | * array of RedisModule strings arguments, and an argc field which is the number of
30 | * args.
31 | * @return Returns REDISMODULE_OK if the command is valid, REDISMODULE_ERR otherwise.
32 | */
33 | int ParseDAGExecuteOps(RedisAI_RunInfo *rinfo, RAI_DagOp **ops, bool ro);
34 |
35 | int DAGInitialParsing(RedisAI_RunInfo *rinfo, RedisModuleCtx *ctx, RedisModuleString **argv,
36 | int argc, bool dag_ro, RAI_DagOp ***dag_ops);
37 |
--------------------------------------------------------------------------------
/src/execution/parsing/deprecated.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "redismodule.h"
10 | #include "execution/run_info.h"
11 |
12 | /**
13 | * @brief Parse and validate MODELRUN command: create a modelRunCtx based on the model obtained
14 | * from the key space and save it in the op. The keys of the input and output tensors are stored in
15 | * the op's inkeys and outkeys arrays, and the given timeout
16 | * is saved as well (if given, otherwise it is zero).
17 | * @return Returns REDISMODULE_OK if the command is valid, REDISMODULE_ERR otherwise.
18 | */
19 | int ParseModelRunCommand(RedisAI_RunInfo *rinfo, RAI_DagOp *currentOp, RedisModuleString **argv,
20 | int argc);
21 |
22 | int ParseScriptRunCommand(RedisAI_RunInfo *rinfo, RAI_DagOp *currentOp, RedisModuleString **argv,
23 | int argc);
24 |
25 | int ModelSetCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
26 |
27 | int ScriptSetCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
28 |
29 | /**
30 | * @brief Parse the arguments of the given ops in the DAGRUN command and build every op accordingly.
31 | * @param rinfo The DAG run info that will be populated with the ops if they are valid.
32 | * with its op,
33 | * @param ops A local array of ops, where every op has an argv field that points to an
34 | * array of RedisModule strings arguments, and an argc field which is the number of
35 | * args.
36 | * @return Returns REDISMODULE_OK if the command is valid, REDISMODULE_ERR otherwise.
37 | */
38 | int ParseDAGRunOps(RedisAI_RunInfo *rinfo, RAI_DagOp **ops);
39 |
40 | /**
41 | * @brief Parse and validate DAGRUN command (Populate the rinfo object):
42 | * - parse LOAD, PERSIST, and TIMEOUT args. Persist is not allowed if the DAG is READ-ONLY (dag_to
43 | * is true).
44 | * - parse and validate every DAGop individually.
45 | * - Generate a unique key for every tensor name that appear in the DAG's ops.
46 | * (thus ensure that the operations will be done by the desired order).
47 | * @return Returns REDISMODULE_OK if the command is valid, REDISMODULE_ERR otherwise.
48 | */
49 | int ParseDAGRunCommand(RedisAI_RunInfo *rinfo, RedisModuleCtx *ctx, RedisModuleString **argv,
50 | int argc, bool dag_ro);
51 |
--------------------------------------------------------------------------------
/src/execution/parsing/model_commands_parser.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "redismodule.h"
9 | #include "execution/run_info.h"
10 |
11 | /**
12 | * @brief Parse and validate MODELEXECUTE command: create a modelRunCtx based on the model obtained
13 | * from the key space and save it in the op. The keys of the input and output tensors are stored in
14 | * the op's inkeys and outkeys arrays, and the given timeout
15 | * is saved as well (if given, otherwise it is zero).
16 | * @return Returns REDISMODULE_OK if the command is valid, REDISMODULE_ERR otherwise.
17 | */
18 | int ParseModelExecuteCommand(RedisAI_RunInfo *rinfo, RAI_DagOp *currentOp, RedisModuleString **argv,
19 | int argc);
20 |
--------------------------------------------------------------------------------
/src/execution/parsing/parse_utils.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include
8 | #include "parse_utils.h"
9 | #include "string.h"
10 |
11 | int ParseTimeout(RedisModuleString *timeout_arg, RAI_Error *error, long long *timeout) {
12 |
13 | const int retval = RedisModule_StringToLongLong(timeout_arg, timeout);
14 | if (retval != REDISMODULE_OK || *timeout <= 0) {
15 | RAI_SetError(error, RAI_EMODELRUN, "ERR Invalid value for TIMEOUT");
16 | return REDISMODULE_ERR;
17 | }
18 | return REDISMODULE_OK;
19 | }
20 |
21 | const char *ScriptCommand_GetFunctionName(RedisModuleString *functionName) {
22 | const char *functionName_cstr = RedisModule_StringPtrLen(functionName, NULL);
23 | return functionName_cstr;
24 | }
25 |
26 | int ValidateKeysArgs(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, RAI_Error *err) {
27 | if (argc < 3) {
28 | RAI_SetError(err, RAI_EDAGBUILDER, "ERR Missing arguments after KEYS keyword");
29 | return -1;
30 | }
31 |
32 | long long n_keys;
33 | const int retval = RedisModule_StringToLongLong(argv[1], &n_keys);
34 | if (retval != REDISMODULE_OK || n_keys <= 0) {
35 | RAI_SetError(err, RAI_EDAGBUILDER, "ERR Invalid or negative value found in number of KEYS");
36 | return -1;
37 | }
38 |
39 | size_t argpos = 2;
40 | if (argpos + n_keys > argc) {
41 | RAI_SetError(
42 | err, RAI_EDAGBUILDER,
43 | "ERR Number of pre declared KEYS to be used in the command does not match the number "
44 | "of given arguments");
45 | return -1;
46 | }
47 |
48 | // Go over the given args and verify that these keys are located in the local shard.
49 | while (argpos < n_keys + 2) {
50 | if (!VerifyKeyInThisShard(ctx, argv[argpos++])) {
51 | RAI_SetError(err, RAI_EDAGBUILDER,
52 | "ERR Some of the KEYS specified in the command hash to slots which aren't "
53 | "belong to the current shard");
54 | return -1;
55 | }
56 | }
57 | return argpos;
58 | }
59 |
--------------------------------------------------------------------------------
/src/execution/parsing/parse_utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "redismodule.h"
9 | #include "redis_ai_objects/err.h"
10 |
11 | /**
12 | * @brief Parse and validate TIMEOUT argument. If it is valid, store it in timeout.
13 | * Otherwise set an error.
14 | * @return Returns REDISMODULE_OK if the command is valid, REDISMODULE_ERR otherwise.
15 | */
16 | int ParseTimeout(RedisModuleString *timeout_arg, RAI_Error *error, long long *timeout);
17 |
18 | /**
19 | * @brief
20 | *
21 | * @param functionName
22 | * @return const char*
23 | */
24 | const char *ScriptCommand_GetFunctionName(RedisModuleString *functionName);
25 |
26 | /**
27 | * Parse KEYS section in command [* KEYS key1 key2... ]
28 | *
29 | * @param ctx Context in which Redis modules operate
30 | * @param argv Redis command arguments, as an array of strings
31 | * @param argc Redis command number of arguments
32 | * @param err An error object to store an error message if needed.
33 | * @return processed number of arguments on success, or -1 if the parsing failed
34 | */
35 |
36 | int ValidateKeysArgs(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, RAI_Error *err);
37 |
--------------------------------------------------------------------------------
/src/execution/parsing/script_commands_parser.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "redismodule.h"
9 | #include "execution/run_info.h"
10 |
11 | /**
12 | * @brief Parse and validate SCRIPTEXECUTE command: create a scriptRunCtx based on the script
13 | * obtained from the key space and the function name given, and save it in the op. The keys of the
14 | * input and output tensors are stored in the op's inkeys and outkeys arrays,
15 | * and the given timeout is saved as well (if given, otherwise it is zero).
16 | * @return Returns REDISMODULE_OK if the command is valid, REDISMODULE_ERR otherwise.
17 | */
18 | int ParseScriptExecuteCommand(RedisAI_RunInfo *rinfo, RAI_DagOp *currentOp,
19 | RedisModuleString **argv, int argc);
20 |
--------------------------------------------------------------------------------
/src/execution/parsing/tensor_commands_parsing.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "redismodule.h"
10 | #include "redis_ai_objects/err.h"
11 | #include "redis_ai_objects/tensor.h"
12 |
13 | /**
14 | * Helper method to parse AI.TENSORGET arguments
15 | *
16 | * @param argv Redis command arguments, as an array of strings
17 | * @param argc Redis command number of arguments
18 | * @param t Destination tensor to store the parsed data
19 | * @param error error data structure to store error message in the case of
20 | * parsing failures
21 | * @return REDISMODULE_OK on success, or REDISMODULE_ERR if the parsing failed
22 | */
23 | int ParseTensorSetArgs(RedisModuleString **argv, int argc, RAI_Tensor **t, RAI_Error *error);
24 |
25 | /**
26 | * Helper method to parse AI.TENSORGET arguments
27 | *
28 | * @param error error data structure to store error message in the case of
29 | * parsing failures
30 | * @param argv Redis command arguments, as an array of strings
31 | * @param argc Redis command number of arguments
32 | * @return The format in which tensor is returned.
33 | */
34 |
35 | uint ParseTensorGetFormat(RAI_Error *error, RedisModuleString **argv, int argc);
36 |
--------------------------------------------------------------------------------
/src/execution/run_queue_info.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "string_utils.h"
8 | #include "run_queue_info.h"
9 | #include "backends/backends.h"
10 | #include "background_workers.h"
11 |
12 | extern unsigned int BGWorkersCount;
13 |
14 | RunQueueInfo *RunQueue_Create(const char *device_str) {
15 |
16 | size_t device_str_len = strlen(device_str);
17 | char upper_device_str[device_str_len + 1];
18 | RAI_StringToUpper(device_str, upper_device_str, device_str_len + 1);
19 |
20 | // Create new run queue and initialize its inner fields.
21 | RunQueueInfo *run_queue_info = RedisModule_Alloc(sizeof(RunQueueInfo));
22 | run_queue_info->run_queue = queueCreate();
23 | run_queue_info->device_str = RedisModule_Strdup(upper_device_str);
24 | pthread_cond_init(&(run_queue_info->queue_condition_var), NULL);
25 | pthread_mutex_init(&(run_queue_info->run_queue_mutex), NULL);
26 | run_queue_info->threads = array_new(pthread_t, Config_GetNumThreadsPerQueue());
27 | // Save device with its associate run queue info in the dictionary.
28 | if (AI_dictAdd(RunQueues, upper_device_str, run_queue_info) != DICT_OK) {
29 | RunQueue_Free(run_queue_info);
30 | return NULL;
31 | }
32 |
33 | // Create worker threads, update the global counter.
34 | for (int i = 0; i < Config_GetNumThreadsPerQueue(); i++) {
35 | pthread_t thread;
36 | if (pthread_create(&thread, NULL, BGWorker_ThreadMain, run_queue_info) != 0) {
37 | AI_dictDelete(RunQueues, upper_device_str);
38 | RunQueue_Free(run_queue_info);
39 | return NULL;
40 | }
41 | run_queue_info->threads = array_append(run_queue_info->threads, thread);
42 | }
43 | BGWorkersCount += Config_GetNumThreadsPerQueue();
44 |
45 | // Add the new device worker threads to onnx run sessions tracking.
46 | if (RAI_backends.onnx.add_new_device_cb) {
47 | RAI_backends.onnx.add_new_device_cb(device_str);
48 | }
49 | return run_queue_info;
50 | }
51 |
52 | RunQueueInfo *RunQueue_GetInfo(const char *device_str) {
53 | size_t device_str_len = strlen(device_str);
54 | char upper_device_str[device_str_len + 1];
55 | RAI_StringToUpper(device_str, upper_device_str, device_str_len + 1);
56 | AI_dictEntry *entry = AI_dictFind(RunQueues, upper_device_str);
57 | RedisModule_Assert(entry != NULL);
58 | return AI_dictGetVal(entry);
59 | }
60 |
61 | bool RunQueue_IsExists(const char *device_str) {
62 | size_t device_str_len = strlen(device_str);
63 | char upper_device_str[device_str_len + 1];
64 | RAI_StringToUpper(device_str, upper_device_str, device_str_len + 1);
65 | return AI_dictFind(RunQueues, upper_device_str) != NULL;
66 | }
67 |
68 | void RunQueue_Free(RunQueueInfo *run_queue_info) {
69 | RedisModule_Assert(queueLength(run_queue_info->run_queue) == 0);
70 | RedisModule_Free(run_queue_info->run_queue);
71 | RedisModule_Free(run_queue_info->device_str);
72 |
73 | // Wait for workers to exit and free the pool.
74 | for (int i = 0; i < array_len(run_queue_info->threads); i++) {
75 | RedisModule_Assert(pthread_join(run_queue_info->threads[i], NULL) == 0);
76 | RedisModule_Free(run_queue_info->threads);
77 | }
78 | pthread_mutex_destroy(&(run_queue_info->run_queue_mutex));
79 | pthread_cond_destroy(&(run_queue_info->queue_condition_var));
80 | RedisModule_Free(run_queue_info);
81 | }
82 |
--------------------------------------------------------------------------------
/src/execution/run_queue_info.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | /**
10 | * Contains the structure to manage the per-device queues, used for decoupling
11 | * the work from the main thread to the background worker threads. For each of
12 | * the incoming ModelRun, ScriptRun, and DagRun commands, the request is queued
13 | * and evaded asynchronously to one the device queues.
14 | */
15 |
16 | #include "utils.h"
17 | #include "queue.h"
18 | #include "dictionaries.h"
19 |
20 | AI_dict *RunQueues;
21 |
22 | typedef struct RunQueueInfo {
23 | pthread_mutex_t run_queue_mutex;
24 | pthread_cond_t queue_condition_var;
25 | queue *run_queue;
26 | pthread_t *threads;
27 | char *device_str;
28 | } RunQueueInfo;
29 |
30 | /**
31 | * @brief Create a new run queue for a device.
32 | */
33 | RunQueueInfo *RunQueue_Create(const char *device_str);
34 |
35 | /**
36 | * @brief Return true if a ru queue exists for this particular device.
37 | */
38 | bool RunQueue_IsExists(const char *device_str);
39 |
40 | /**
41 | * @brief Return the RunQueueInfo saved in the global RunQueues dict for a certain
42 | * device name, after asserting that it exists.
43 | */
44 | RunQueueInfo *RunQueue_GetInfo(const char *device_str);
45 |
46 | /**
47 | * @brief Terminate all working threads and free the run queue with its inner fields.
48 | */
49 | void RunQueue_Free(RunQueueInfo *info);
50 |
--------------------------------------------------------------------------------
/src/execution/utils.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "utils.h"
8 | #include "redis_ai_objects/model.h"
9 |
10 | int redisMajorVersion;
11 | int redisMinorVersion;
12 | int redisPatchVersion;
13 |
14 | int rlecMajorVersion;
15 | int rlecMinorVersion;
16 | int rlecPatchVersion;
17 | int rlecBuild;
18 |
19 | void RedisAI_SetRedisVersion() {
20 | RedisModuleCtx *ctx = RedisModule_GetThreadSafeContext(NULL);
21 | RedisModuleCallReply *reply = RedisModule_Call(ctx, "info", "c", "server");
22 | assert(RedisModule_CallReplyType(reply) == REDISMODULE_REPLY_STRING);
23 | size_t len;
24 | const char *replyStr = RedisModule_CallReplyStringPtr(reply, &len);
25 |
26 | int n = sscanf(replyStr, "# Server\nredis_version:%d.%d.%d", &redisMajorVersion,
27 | &redisMinorVersion, &redisPatchVersion);
28 |
29 | assert(n == 3);
30 |
31 | rlecMajorVersion = -1;
32 | rlecMinorVersion = -1;
33 | rlecPatchVersion = -1;
34 | rlecBuild = -1;
35 | char *enterpriseStr = strstr(replyStr, "rlec_version:");
36 | if (enterpriseStr) {
37 | n = sscanf(enterpriseStr, "rlec_version:%d.%d.%d-%d", &rlecMajorVersion, &rlecMinorVersion,
38 | &rlecPatchVersion, &rlecBuild);
39 | if (n != 4) {
40 | RedisModule_Log(NULL, "warning", "Could not extract enterprise version");
41 | }
42 | }
43 |
44 | RedisModule_FreeCallReply(reply);
45 | RedisModule_FreeThreadSafeContext(ctx);
46 | }
47 |
48 | void RedisAI_GetRedisVersion(int *major, int *minor, int *patch) {
49 | *major = redisMajorVersion;
50 | *minor = redisMinorVersion;
51 | *patch = redisPatchVersion;
52 | }
53 |
54 | bool IsEnterprise() { return rlecMajorVersion != -1; }
55 |
56 | bool VerifyKeyInThisShard(RedisModuleCtx *ctx, RedisModuleString *key_str) {
57 | if (IsEnterprise()) {
58 | int first_slot, last_slot;
59 | RedisModule_ShardingGetSlotRange(&first_slot, &last_slot);
60 | int key_slot = RedisModule_ShardingGetKeySlot(key_str);
61 |
62 | // If first_slot=last_slot=-1, then sharding is not enabled in enterprise,
63 | // so we definitely don't have a cross shard violation.
64 | if (first_slot != -1 && last_slot != -1 &&
65 | (key_slot < first_slot || key_slot > last_slot)) {
66 | RedisModule_Log(ctx, "warning",
67 | "could not load %s from keyspace,"
68 | " this key's hash slot belongs to a different shard",
69 | RedisModule_StringPtrLen(key_str, NULL));
70 | return false;
71 | }
72 | }
73 | return true;
74 | }
75 |
--------------------------------------------------------------------------------
/src/execution/utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include
10 | #include "redismodule.h"
11 |
12 | /** Use this to check if a command is given a key whose hash slot is not on the current
13 | * shard, when using enterprise cluster.
14 | **/
15 | bool VerifyKeyInThisShard(RedisModuleCtx *ctx, RedisModuleString *key_str);
16 |
17 | /**
18 | * Use this function when loading the model. Stores the version in global variables.
19 | */
20 | void RedisAI_SetRedisVersion();
21 |
22 | /**
23 | * Returns redis version in the major, minor, and patch placeholders.
24 | */
25 | void RedisAI_GetRedisVersion(int *major, int *minor, int *patch);
26 |
27 | /**
28 | * Returns true if Redis is running in enterprise mode.
29 | */
30 | bool IsEnterprise();
31 |
--------------------------------------------------------------------------------
/src/redis_ai_objects/err.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | /**
8 | * err.c
9 | *
10 | * Contains a formal API to create, initialize, get, reset, and free errors
11 | * among different backends.
12 | */
13 |
14 | #include "err.h"
15 |
16 | #include "redismodule.h"
17 | #include "stdlib.h"
18 | #include "string.h"
19 |
20 | char *RAI_Chomp(const char *src) {
21 | char *str = RedisModule_Strdup(src);
22 | size_t len = strlen(src);
23 | for (size_t i = 0; i < len; i++) {
24 | if (str[i] == '\n' || str[i] == '\r') {
25 | str[i] = ' ';
26 | }
27 | }
28 | return str;
29 | }
30 |
31 | const char *RAI_GetError(RAI_Error *err) { return err->detail; }
32 |
33 | const char *RAI_GetErrorOneLine(RAI_Error *err) { return err->detail_oneline; }
34 |
35 | RAI_ErrorCode RAI_GetErrorCode(RAI_Error *err) { return err->code; }
36 |
37 | void RAI_CloneError(RAI_Error *dest, const RAI_Error *src) {
38 | dest->code = src->code;
39 | RedisModule_Assert(!dest->detail);
40 | dest->detail = RedisModule_Strdup(src->detail);
41 | dest->detail_oneline = RAI_Chomp(dest->detail);
42 | }
43 |
44 | void RAI_SetError(RAI_Error *err, RAI_ErrorCode code, const char *detail) {
45 | if (!err) {
46 | return;
47 | }
48 | if (err->code != RAI_OK) {
49 | return;
50 | }
51 | RedisModule_Assert(!err->detail);
52 | err->code = code;
53 |
54 | if (detail) {
55 | err->detail = RedisModule_Strdup(detail);
56 | } else {
57 | err->detail = RedisModule_Strdup("ERR Generic error");
58 | }
59 | err->detail_oneline = RAI_Chomp(err->detail);
60 | }
61 |
62 | /**
63 | * Allocate the memory and initialise the RAI_Error.
64 | * @param result Output parameter to capture allocated RAI_Error.
65 | * @return 0 on success, or 1 if the allocation
66 | * failed.
67 | */
68 | int RAI_InitError(RAI_Error **result) {
69 | RAI_Error *err;
70 | err = (RAI_Error *)RedisModule_Calloc(1, sizeof(RAI_Error));
71 | *result = err;
72 | return REDISMODULE_OK;
73 | }
74 |
75 | void RAI_ClearError(RAI_Error *err) {
76 | if (err) {
77 | if (err->detail) {
78 | RedisModule_Free(err->detail);
79 | err->detail = NULL;
80 | }
81 | if (err->detail_oneline) {
82 | RedisModule_Free(err->detail_oneline);
83 | err->detail_oneline = NULL;
84 | }
85 | err->code = RAI_OK;
86 | }
87 | }
88 |
89 | void RAI_FreeError(RAI_Error *err) {
90 | if (err) {
91 | RAI_ClearError(err);
92 | RedisModule_Free(err);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/redis_ai_objects/err.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | /**
8 | * err.h
9 | *
10 | * Contains the structure and headers for a formal API to create, initialize,
11 | * get, reset, and free errors among different backends.
12 | */
13 |
14 | #pragma once
15 |
16 | typedef enum {
17 | RAI_OK = 0,
18 | RAI_EMODELIMPORT,
19 | RAI_EMODELCONFIGURE,
20 | RAI_EMODELCREATE,
21 | RAI_EMODELRUN,
22 | RAI_EMODELSERIALIZE,
23 | RAI_EMODELFREE,
24 | RAI_ESCRIPTIMPORT,
25 | RAI_ESCRIPTCONFIGURE,
26 | RAI_ESCRIPTCREATE,
27 | RAI_ESCRIPTRUN,
28 | RAI_EUNSUPPORTEDBACKEND,
29 | RAI_EBACKENDNOTLOADED,
30 | RAI_ESCRIPTFREE,
31 | RAI_ETENSORSET,
32 | RAI_ETENSORGET,
33 | RAI_EDAGBUILDER,
34 | RAI_EDAGRUN,
35 | RAI_EFINISHCTX,
36 | RAI_EKEYEMPTY
37 | } RAI_ErrorCode;
38 |
39 | typedef struct RAI_Error {
40 | RAI_ErrorCode code;
41 | char *detail;
42 | char *detail_oneline;
43 | } RAI_Error;
44 |
45 | /**
46 | * Allocate the memory and initialise the RAI_Error.
47 | *
48 | * @param result Output parameter to capture allocated RAI_Error.
49 | * @return 0 on success, or 1 if the allocation
50 | * failed.
51 | */
52 | int RAI_InitError(RAI_Error **err);
53 |
54 | /**
55 | * Populates the RAI_Error data structure with the error details
56 | *
57 | * @param err
58 | * @param code
59 | * @param detail
60 | */
61 | void RAI_SetError(RAI_Error *err, RAI_ErrorCode code, const char *detail);
62 |
63 | /**
64 | * Return the error description
65 | *
66 | * @param err
67 | * @return error description
68 | * @param err
69 | */
70 | const char *RAI_GetError(RAI_Error *err);
71 |
72 | /**
73 | * Return the error description as one line
74 | *
75 | * @param err
76 | * @return error description as one line
77 | * @param err
78 | */
79 | const char *RAI_GetErrorOneLine(RAI_Error *err);
80 |
81 | /**
82 | * Return the error code
83 | *
84 | * @param err
85 | * @return error code
86 | * @param err
87 | */
88 | RAI_ErrorCode RAI_GetErrorCode(RAI_Error *err);
89 |
90 | /**
91 | * Make dest a clone of src
92 | *
93 | * @param dest An allocated error
94 | * @param src The error to copy
95 | */
96 | void RAI_CloneError(RAI_Error *dest, const RAI_Error *src);
97 |
98 | /**
99 | * Resets an previously used/allocated RAI_Error
100 | *
101 | * @param err
102 | */
103 | void RAI_ClearError(RAI_Error *err);
104 |
105 | /**
106 | * Frees the memory of the RAI_Error
107 | *
108 | * @param err
109 | */
110 | void RAI_FreeError(RAI_Error *err);
111 |
--------------------------------------------------------------------------------
/src/redis_ai_objects/model_struct.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "config/config.h"
10 | #include "tensor_struct.h"
11 | #include "redis_ai_objects/stats.h"
12 |
13 | typedef struct RAI_ModelOpts {
14 | size_t batchsize;
15 | size_t minbatchsize;
16 | size_t minbatchtimeout;
17 | long long backends_intra_op_parallelism; // number of threads used within an
18 | // individual op for parallelism.
19 | long long backends_inter_op_parallelism; // number of threads used for parallelism
20 | // between independent operations.
21 | } RAI_ModelOpts;
22 |
23 | typedef struct RAI_Model {
24 | void *model;
25 | // TODO: use session pool? The ideal would be to use one session per client.
26 | // If a client disconnects, we dispose the session or reuse it for
27 | // another client.
28 | void *session;
29 | RAI_Backend backend;
30 | char *devicestr;
31 | RedisModuleString *tag;
32 | RAI_ModelOpts opts;
33 | char **inputs;
34 | size_t ninputs;
35 | char **outputs;
36 | size_t noutputs;
37 | long long refCount;
38 | char *data;
39 | long long datalen;
40 | RAI_RunStats *info;
41 | } RAI_Model;
42 |
--------------------------------------------------------------------------------
/src/redis_ai_objects/script_struct.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "config/config.h"
10 | #include "tensor_struct.h"
11 | #include "redis_ai_objects/stats.h"
12 | #include "util/dict.h"
13 |
14 | typedef enum {
15 | UNKOWN,
16 | TENSOR,
17 | INT,
18 | FLOAT,
19 | STRING,
20 | TENSOR_LIST,
21 | INT_LIST,
22 | FLOAT_LIST,
23 | STRING_LIST
24 | } TorchScriptFunctionArgumentType;
25 |
26 | typedef struct RAI_Script {
27 | void *script;
28 | char *scriptdef;
29 | // TODO: scripts do not have placement in PyTorch
30 | // Placement depends on the inputs, as do outputs
31 | // We keep it here at the moment, until we have a
32 | // CUDA allocator for dlpack
33 | char *devicestr;
34 | RedisModuleString *tag;
35 | long long refCount;
36 | RAI_RunStats *info;
37 | char **entryPoints;
38 | } RAI_Script;
39 |
--------------------------------------------------------------------------------
/src/redis_ai_objects/stats.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | /**
8 | * stats.c
9 | *
10 | * Contains the helper methods to create,
11 | * initialize, get, reset, and free run-time statistics, like call count, error
12 | * count, and aggregate durations of ModelRun and ScriptRun sessions.
13 | *
14 | */
15 |
16 | #include
17 | #include
18 | #include "stats.h"
19 | #include "util/string_utils.h"
20 |
21 | // Global dictionary that stores run statistics for all models and scripts in the shard.
22 | AI_dict *RunStats;
23 |
24 | long long ustime(void) {
25 | struct timeval tv;
26 | long long ust;
27 |
28 | gettimeofday(&tv, NULL);
29 | ust = ((long long)tv.tv_sec) * 1000000;
30 | ust += tv.tv_usec;
31 | return ust;
32 | }
33 |
34 | mstime_t mstime(void) { return ustime() / 1000; }
35 |
36 | RAI_RunStats *RAI_StatsCreate(RedisModuleString *key, RAI_RunType type, RAI_Backend backend,
37 | const char *device_str, RedisModuleString *tag) {
38 | RAI_RunStats *r_stats = RedisModule_Calloc(1, sizeof(RAI_RunStats));
39 | r_stats->key = RedisModule_CreateStringFromString(NULL, key);
40 | r_stats->type = type;
41 | r_stats->backend = backend;
42 | r_stats->device_str = RedisModule_Strdup(device_str);
43 | r_stats->tag = RAI_HoldString(tag);
44 | return r_stats;
45 | }
46 |
47 | void RAI_StatsReset(RAI_RunStats *r_stats) {
48 | RedisModule_Assert(r_stats);
49 | __atomic_store_n(&r_stats->duration_us, 0, __ATOMIC_RELAXED);
50 | __atomic_store_n(&r_stats->samples, 0, __ATOMIC_RELAXED);
51 | __atomic_store_n(&r_stats->calls, 0, __ATOMIC_RELAXED);
52 | __atomic_store_n(&r_stats->n_errors, 0, __ATOMIC_RELAXED);
53 | }
54 |
55 | void RAI_StatsAddDataPoint(RAI_RunStats *r_stats, unsigned long duration, unsigned long calls,
56 | unsigned long errors, unsigned long samples) {
57 | RedisModule_Assert(r_stats);
58 | __atomic_add_fetch(&r_stats->duration_us, duration, __ATOMIC_RELAXED);
59 | __atomic_add_fetch(&r_stats->calls, calls, __ATOMIC_RELAXED);
60 | __atomic_add_fetch(&r_stats->n_errors, errors, __ATOMIC_RELAXED);
61 | __atomic_add_fetch(&r_stats->samples, samples, __ATOMIC_RELAXED);
62 | }
63 |
64 | void RAI_StatsFree(RAI_RunStats *r_stats) {
65 | if (r_stats) {
66 | if (r_stats->device_str) {
67 | RedisModule_Free(r_stats->device_str);
68 | }
69 | if (r_stats->tag) {
70 | RedisModule_FreeString(NULL, r_stats->tag);
71 | }
72 | if (r_stats->key) {
73 | RedisModule_FreeString(NULL, r_stats->key);
74 | }
75 | RedisModule_Free(r_stats);
76 | }
77 | }
78 |
79 | /************************************* Global RunStats dict API *********************************/
80 |
81 | void RAI_StatsStoreEntry(RedisModuleString *key, RAI_RunStats *new_stats_entry) {
82 | AI_dictReplace(RunStats, (void *)key, (void *)new_stats_entry);
83 | }
84 |
85 | void RAI_StatsGetAllEntries(RAI_RunType type, long long *nkeys, RedisModuleString ***keys,
86 | RedisModuleString ***tags) {
87 | AI_dictIterator *stats_iter = AI_dictGetSafeIterator(RunStats);
88 | long long stats_size = AI_dictSize(RunStats);
89 |
90 | *keys = RedisModule_Calloc(stats_size, sizeof(RedisModuleString *));
91 | *tags = RedisModule_Calloc(stats_size, sizeof(RedisModuleString *));
92 | *nkeys = 0;
93 |
94 | AI_dictEntry *stats_entry = AI_dictNext(stats_iter);
95 | RAI_RunStats *r_stats = NULL;
96 |
97 | while (stats_entry) {
98 | r_stats = AI_dictGetVal(stats_entry);
99 | if (r_stats->type == type) {
100 | (*keys)[*nkeys] = r_stats->key;
101 | (*tags)[*nkeys] = r_stats->tag;
102 | *nkeys += 1;
103 | }
104 | stats_entry = AI_dictNext(stats_iter);
105 | }
106 | AI_dictReleaseIterator(stats_iter);
107 | }
108 |
109 | void RAI_StatsRemoveEntry(RedisModuleString *info_key) {
110 | AI_dictEntry *stats_entry = AI_dictFind(RunStats, info_key);
111 |
112 | if (stats_entry) {
113 | AI_dictDelete(RunStats, info_key);
114 | }
115 | }
116 |
117 | RAI_RunStats *RAI_StatsGetEntry(RedisModuleString *runkey) {
118 | RedisModule_Assert(RunStats);
119 | AI_dictEntry *entry = AI_dictFind(RunStats, runkey);
120 | if (!entry) {
121 | return NULL;
122 | }
123 | return AI_dictGetVal(entry);
124 | }
125 |
--------------------------------------------------------------------------------
/src/redis_ai_objects/stats.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | /**
8 | * stats.h
9 | *
10 | * Contains the structure and headers for the helper methods to create,
11 | * initialize, get, reset, and free run-time statics, like call count, error
12 | * count, and aggregate durations of ModelRun and ScriptRun sessions.
13 | *
14 | */
15 |
16 | #pragma once
17 |
18 | #include "config/config.h"
19 | #include "redismodule.h"
20 | #include "util/dict.h"
21 |
22 | typedef struct RAI_RunStats {
23 | RedisModuleString *key;
24 | RAI_RunType type;
25 | RAI_Backend backend;
26 | char *device_str;
27 | RedisModuleString *tag;
28 | unsigned long duration_us;
29 | unsigned long samples;
30 | unsigned long calls;
31 | unsigned long n_errors;
32 | unsigned long ref_count;
33 | } RAI_RunStats;
34 |
35 | long long ustime(void);
36 | mstime_t mstime(void);
37 |
38 | /**
39 | * Adds an entry to the ephemeral run-time statistic. The statistics are not
40 | * saved to the keyspace, and on maximum live for the duration of the DB uptime.
41 | *
42 | * @param key key name to use as unique stats identifier
43 | * @param type type of stats identifier ( one of RAI_MODEL or RAI_SCRIPT )
44 | * @param backend backend identifier (one of RAI_BACKEND_TENSORFLOW,
45 | * RAI_BACKEND_TFLITE, RAI_BACKEND_TORCH, RAI_BACKEND_ONNXRUNTIME,)
46 | * @param device_str device to execute the model on (CPU, GPU, ...)
47 | * @param tag optional tag of Model/Script
48 | * @return A newly heap allocated RedisAI_RunStats object with the given fields.
49 | */
50 | RAI_RunStats *RAI_StatsCreate(RedisModuleString *key, RAI_RunType type, RAI_Backend backend,
51 | const char *device_str, RedisModuleString *tag);
52 |
53 | /**
54 | * @brief Reset atomically counters for a given run_stats of some model/script.
55 | * @param run_stats entry to reset.
56 | */
57 | void RAI_StatsReset(RAI_RunStats *run_stats);
58 |
59 | /**
60 | * Update atomically stats counters after execution.
61 | * @param r_stats runStats entry that matches some model/script.
62 | * @param duration execution runtime in us
63 | * @param calls number of calls to the underline model/script operation.
64 | * @param errors number of errors that had occurred.
65 | * @param samples number of samples that the model execute (batch size)
66 | */
67 | void RAI_StatsAddDataPoint(RAI_RunStats *r_stats, unsigned long duration, unsigned long calls,
68 | unsigned long errors, unsigned long samples);
69 |
70 | /**
71 | * @brief Release RunStats struct.
72 | * @param run_stats entry to remove.
73 | */
74 | void RAI_StatsFree(RAI_RunStats *r_stats);
75 |
76 | /************************************* Global RunStats dict API *********************************/
77 | /**
78 | * Adds an entry to the ephemeral run-time statistic. The statistics are not
79 | * saved to the keyspace, and on maximum live for the duration of the DB uptime.
80 | * If a run stats object already exists for this key, it will override it.
81 | *
82 | * @param keyName key name to use as unique stats identifier.
83 | * @param run_stats_entry RunStats entry pointer to store.
84 | */
85 | void RAI_StatsStoreEntry(RedisModuleString *key, RAI_RunStats *run_stats_entry);
86 |
87 | /**
88 | * @brief: Removes the statistical entry with the provided unique stats identifier
89 | * @param info_key
90 | */
91 | void RAI_StatsRemoveEntry(RedisModuleString *info_key);
92 |
93 | /**
94 | * Returns a list of all statistical entries that match a specific RAI_RunType (
95 | * model or script).
96 | * @param type type of stats identifier to provide the list for (one of
97 | * RAI_MODEL or RAI_SCRIPT).
98 | * @param nkeys output variable containing the number of returned stats.
99 | * @param keys output variable containing the list of returned keys.
100 | * @param tags output variable containing the list of returned tags.
101 | */
102 | void RAI_StatsGetAllEntries(RAI_RunType type, long long *nkeys, RedisModuleString ***keys,
103 | RedisModuleString ***tags);
104 |
105 | /**
106 | * @brief Retrieve the run stats info of run_key from the global RunStat dictionary and set it in
107 | * r_stats.
108 | * @param run_key module/script key name
109 | * @return The RAI_RunStats object that is associated with the key, or NULL if it doesn't exist.
110 | */
111 | RAI_RunStats *RAI_StatsGetEntry(RedisModuleString *run_key);
112 |
--------------------------------------------------------------------------------
/src/redis_ai_objects/tensor_struct.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "limits.h"
10 | #include "config/config.h"
11 | #include "dlpack/dlpack.h"
12 |
13 | #define LEN_UNKNOWN ULONG_MAX
14 | typedef struct RAI_Tensor {
15 | DLManagedTensor tensor;
16 | size_t len;
17 | long long refCount;
18 | size_t blobSize;
19 | } RAI_Tensor;
20 |
--------------------------------------------------------------------------------
/src/redis_ai_types/model_type.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "model_type.h"
8 | #include "redis_ai_objects/model.h"
9 | #include "serialization/AOF/rai_aof_rewrite.h"
10 | #include "serialization/RDB/encoder/rai_rdb_encode.h"
11 | #include "serialization/RDB/decoder/rai_rdb_decoder.h"
12 | #include "serialization/RDB/decoder/decode_previous.h"
13 |
14 | extern RedisModuleType *RedisAI_ModelType;
15 |
16 | static void *RAI_Model_RdbLoad(struct RedisModuleIO *io, int encver) {
17 | if (encver > REDISAI_ENC_VER) {
18 | RedisModule_LogIOError(
19 | io, "error", "Failed loading model, RedisAI version (%d) is not forward compatible.\n",
20 | REDISAI_MODULE_VERSION);
21 | return NULL;
22 | } else if (encver < REDISAI_ENC_VER) {
23 | return Decode_PreviousModel(io, encver);
24 | } else {
25 | return RAI_RDBLoadModel(io);
26 | }
27 | }
28 |
29 | static void RAI_Model_RdbSave(RedisModuleIO *io, void *value) { RAI_RDBSaveModel(io, value); }
30 |
31 | static void RAI_Model_AofRewrite(RedisModuleIO *aof, RedisModuleString *key, void *value) {
32 | RAI_AOFRewriteModel(aof, key, value);
33 | }
34 |
35 | static void RAI_Model_DTFree(void *value) {
36 | RAI_Error err = {0};
37 | RAI_ModelFree(value, &err);
38 | if (err.code != RAI_OK) {
39 | printf("ERR: %s\n", err.detail);
40 | RAI_ClearError(&err);
41 | }
42 | }
43 |
44 | int ModelType_Register(RedisModuleCtx *ctx) {
45 | RedisModuleTypeMethods tmModel = {.version = REDISMODULE_TYPE_METHOD_VERSION,
46 | .rdb_load = RAI_Model_RdbLoad,
47 | .rdb_save = RAI_Model_RdbSave,
48 | .aof_rewrite = RAI_Model_AofRewrite,
49 | .mem_usage = NULL,
50 | .free = RAI_Model_DTFree,
51 | .digest = NULL};
52 |
53 | RedisAI_ModelType = RedisModule_CreateDataType(ctx, "AI__MODEL", REDISAI_ENC_VER, &tmModel);
54 | return RedisAI_ModelType != NULL;
55 | }
56 |
--------------------------------------------------------------------------------
/src/redis_ai_types/model_type.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "redismodule.h"
10 |
11 | int ModelType_Register(RedisModuleCtx *ctx);
12 |
--------------------------------------------------------------------------------
/src/redis_ai_types/script_type.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "script_type.h"
8 | #include "redis_ai_objects/script.h"
9 | #include "serialization/AOF/rai_aof_rewrite.h"
10 | #include "serialization/RDB/encoder/rai_rdb_encode.h"
11 | #include "serialization/RDB/decoder/rai_rdb_decoder.h"
12 | #include "serialization/RDB/decoder/decode_previous.h"
13 |
14 | extern RedisModuleType *RedisAI_ScriptType;
15 |
16 | static void *RAI_Script_RdbLoad(struct RedisModuleIO *io, int encver) {
17 | if (encver > REDISAI_ENC_VER) {
18 | RedisModule_LogIOError(
19 | io, "error", "Failed loading script, RedisAI version (%d) is not forward compatible.\n",
20 | REDISAI_MODULE_VERSION);
21 | return NULL;
22 | } else if (encver < REDISAI_ENC_VER) {
23 | return Decode_PreviousScript(io, encver);
24 | } else {
25 | return RAI_RDBLoadScript(io);
26 | }
27 | }
28 |
29 | static void RAI_Script_RdbSave(RedisModuleIO *io, void *value) { RAI_RDBSaveScript(io, value); }
30 |
31 | static void RAI_Script_AofRewrite(RedisModuleIO *aof, RedisModuleString *key, void *value) {
32 | RAI_AOFRewriteScript(aof, key, value);
33 | }
34 |
35 | static void RAI_Script_DTFree(void *value) {
36 | RAI_Error err = {0};
37 | RAI_ScriptFree(value, &err);
38 | if (err.code != RAI_OK) {
39 | printf("ERR: %s\n", err.detail);
40 | RAI_ClearError(&err);
41 | }
42 | }
43 |
44 | int ScriptType_Register(RedisModuleCtx *ctx) {
45 | RedisModuleTypeMethods tmScript = {.version = REDISMODULE_TYPE_METHOD_VERSION,
46 | .rdb_load = RAI_Script_RdbLoad,
47 | .rdb_save = RAI_Script_RdbSave,
48 | .aof_rewrite = RAI_Script_AofRewrite,
49 | .mem_usage = NULL,
50 | .free = RAI_Script_DTFree,
51 | .digest = NULL};
52 |
53 | RedisAI_ScriptType = RedisModule_CreateDataType(ctx, "AI_SCRIPT", REDISAI_ENC_VER, &tmScript);
54 | return RedisAI_ScriptType != NULL;
55 | }
56 |
--------------------------------------------------------------------------------
/src/redis_ai_types/script_type.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "redismodule.h"
10 |
11 | int ScriptType_Register(RedisModuleCtx *ctx);
12 |
--------------------------------------------------------------------------------
/src/redis_ai_types/tensor_type.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "tensor_type.h"
8 | #include "redis_ai_objects/tensor.h"
9 | #include "serialization/AOF/rai_aof_rewrite.h"
10 | #include "serialization/RDB/encoder/rai_rdb_encode.h"
11 | #include "serialization/RDB/decoder/rai_rdb_decoder.h"
12 | #include "serialization/RDB/decoder/decode_previous.h"
13 |
14 | extern RedisModuleType *RedisAI_TensorType;
15 |
16 | static void RAI_Tensor_RdbSave(RedisModuleIO *io, void *value) { RAI_RDBSaveTensor(io, value); }
17 |
18 | static void *RAI_Tensor_RdbLoad(struct RedisModuleIO *io, int encver) {
19 | if (encver > REDISAI_ENC_VER) {
20 | RedisModule_LogIOError(
21 | io, "error", "Failed loading tensor, RedisAI version (%d) is not forward compatible.\n",
22 | REDISAI_MODULE_VERSION);
23 | return NULL;
24 | } else if (encver < REDISAI_ENC_VER) {
25 | return Decode_PreviousTensor(io, encver);
26 | } else {
27 | return RAI_RDBLoadTensor(io);
28 | }
29 | }
30 |
31 | static void RAI_Tensor_AofRewrite(RedisModuleIO *aof, RedisModuleString *key, void *value) {
32 | RAI_AOFRewriteTensor(aof, key, value);
33 | }
34 |
35 | static void RAI_Tensor_DTFree(void *value) { RAI_TensorFree(value); }
36 |
37 | int TensorType_Register(RedisModuleCtx *ctx) {
38 | RedisModuleTypeMethods tmTensor = {
39 | .version = REDISMODULE_TYPE_METHOD_VERSION,
40 | .rdb_load = RAI_Tensor_RdbLoad,
41 | .rdb_save = RAI_Tensor_RdbSave,
42 | .aof_rewrite = RAI_Tensor_AofRewrite,
43 | .mem_usage = NULL,
44 | .free = RAI_Tensor_DTFree,
45 | .digest = NULL,
46 | };
47 | RedisAI_TensorType = RedisModule_CreateDataType(ctx, "AI_TENSOR", REDISAI_ENC_VER, &tmTensor);
48 | return RedisAI_TensorType != NULL;
49 | }
50 |
--------------------------------------------------------------------------------
/src/redis_ai_types/tensor_type.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "redismodule.h"
10 |
11 | int TensorType_Register(RedisModuleCtx *ctx);
12 |
--------------------------------------------------------------------------------
/src/rmutil/alloc.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 | #include "alloc.h"
11 |
12 | /* A patched implementation of strdup that will use our patched calloc */
13 | char *rmalloc_strndup(const char *s, size_t n) {
14 | char *ret = calloc(n + 1, sizeof(char));
15 | if (ret)
16 | memcpy(ret, s, n);
17 | return ret;
18 | }
19 |
20 | /*
21 | * Re-patching RedisModule_Alloc and friends to the original malloc functions
22 | *
23 | * This function shold be called if you are working with malloc-patched code
24 | * ouside of redis, usually for unit tests. Call it once when entering your unit
25 | * tests' main().
26 | *
27 | * Since including "alloc.h" while defining REDIS_MODULE_TARGET
28 | * replaces all malloc functions in redis with the RM_Alloc family of functions,
29 | * when running that code outside of redis, your app will crash. This function
30 | * patches the RM_Alloc functions back to the original mallocs. */
31 | void RMUTil_InitAlloc() {
32 |
33 | RedisModule_Alloc = malloc;
34 | RedisModule_Realloc = realloc;
35 | RedisModule_Calloc = calloc;
36 | RedisModule_Free = free;
37 | RedisModule_Strdup = strdup;
38 | }
39 |
--------------------------------------------------------------------------------
/src/rmutil/alloc.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | /* Automatic Redis Module Allocation functions monkey-patching.
10 | *
11 | * Including this file while REDIS_MODULE_TARGET is defined, will explicitly
12 | * override malloc, calloc, realloc & free with RedisModule_Alloc,
13 | * RedisModule_Callc, etc implementations, that allow Redis better control and
14 | * reporting over allocations per module.
15 | *
16 | * You should include this file in all c files AS THE LAST INCLUDED FILE
17 | *
18 | * This only has effect when when compiling with the macro REDIS_MODULE_TARGET
19 | * defined. The idea is that for unit tests it will not be defined, but for the
20 | * module build target it will be.
21 | *
22 | */
23 |
24 | #include
25 | #include "redismodule.h"
26 |
27 | char *rmalloc_strndup(const char *s, size_t n);
28 |
29 | #ifdef REDIS_MODULE_TARGET /* Set this when compiling your code as a module */
30 |
31 | #define malloc(size) RedisModule_Alloc(size)
32 | #define calloc(count, size) RedisModule_Calloc(count, size)
33 | #define realloc(ptr, size) RedisModule_Realloc(ptr, size)
34 | #define free(ptr) RedisModule_Free(ptr)
35 |
36 | #ifdef strdup
37 | #undef strdup
38 | #endif
39 | #define strdup(ptr) RedisModule_Strdup(ptr)
40 |
41 | /* More overriding */
42 | // needed to avoid calling strndup->malloc
43 | #ifdef strndup
44 | #undef strndup
45 | #endif
46 | #define strndup(s, n) rmalloc_strndup(s, n)
47 |
48 | #else
49 |
50 | #endif /* REDIS_MODULE_TARGET */
51 | /* This function shold be called if you are working with malloc-patched code
52 | * ouside of redis, usually for unit tests. Call it once when entering your unit
53 | * tests' main() */
54 | void RMUTil_InitAlloc();
55 |
--------------------------------------------------------------------------------
/src/rmutil/sdsalloc.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | /* SDS allocator selection.
8 | *
9 | * This file is used in order to change the SDS allocator at compile time.
10 | * Just define the following defines to what you want to use. Also add
11 | * the include of your alternate allocator if needed (not needed in order
12 | * to use the default libc allocator). */
13 |
14 | #if defined(__MACH__) || defined(__FreeBSD__)
15 | #include
16 | #else
17 | #include
18 | #endif
19 | //#include "zmalloc.h"
20 | #define s_malloc malloc
21 | #define s_realloc realloc
22 | #define s_free free
23 |
--------------------------------------------------------------------------------
/src/serialization/AOF/rai_aof_rewrite.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "../serialization_include.h"
9 |
10 | void RAI_AOFRewriteTensor(RedisModuleIO *aof, RedisModuleString *key, void *value);
11 |
12 | void RAI_AOFRewriteModel(RedisModuleIO *aof, RedisModuleString *key, void *value);
13 |
14 | void RAI_AOFRewriteScript(RedisModuleIO *aof, RedisModuleString *key, void *value);
15 |
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/current/v4/decode_v4.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "decode_v4.h"
8 | #include "../../previous/v3/decode_v3.h"
9 | #include "assert.h"
10 |
11 | /**
12 | * In case of IO errors, the default return values are:
13 | * numbers - 0
14 | * strings - null
15 | * So only when it is necessary check for IO errors.
16 | */
17 |
18 | void *RAI_RDBLoadTensor_v4(RedisModuleIO *io) {
19 | DLDataTypeCode code = RedisModule_LoadUnsigned(io);
20 | uint8_t bits = RedisModule_LoadUnsigned(io);
21 | DLDataType data_type = (DLDataType){.code = code, .bits = bits, .lanes = 1};
22 |
23 | int ndims = (int)RedisModule_LoadSigned(io);
24 | size_t shape[ndims];
25 | for (size_t i = 0; i < ndims; ++i) {
26 | shape[i] = RedisModule_LoadSigned(io);
27 | }
28 |
29 | RAI_Tensor *tensor = RAI_TensorNew(data_type, shape, ndims);
30 |
31 | size_t blob_len;
32 | char *data = RedisModule_LoadStringBuffer(io, &blob_len);
33 | if (RedisModule_IsIOError(io))
34 | goto error;
35 |
36 | tensor->blobSize = blob_len;
37 | tensor->tensor.dl_tensor.data = data;
38 |
39 | if (data_type.code == kDLString) {
40 | for (size_t i = 0; i < RAI_TensorLength(tensor); i++) {
41 | tensor->tensor.dl_tensor.elements_length[i] = RedisModule_LoadUnsigned(io);
42 | }
43 | }
44 | if (RedisModule_IsIOError(io))
45 | goto error;
46 | return tensor;
47 |
48 | error:
49 | RedisModule_LogIOError(io, "error", "Experienced a short read while reading a tensor from RDB");
50 | RAI_TensorFree(tensor);
51 | if (data) {
52 | RedisModule_Free(data);
53 | }
54 | return NULL;
55 | }
56 |
57 | void *RAI_RDBLoadModel_v4(RedisModuleIO *io) { return RAI_RDBLoadModel_v3(io); }
58 |
59 | void *RAI_RDBLoadScript_v4(RedisModuleIO *io) { return RAI_RDBLoadScript_v3(io); }
60 |
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/current/v4/decode_v4.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "serialization/serialization_include.h"
9 |
10 | void *RAI_RDBLoadTensor_v4(RedisModuleIO *io);
11 |
12 | void *RAI_RDBLoadModel_v4(RedisModuleIO *io);
13 |
14 | void *RAI_RDBLoadScript_v4(RedisModuleIO *io);
15 |
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/decode_previous.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "decode_previous.h"
8 | #include "previous/v0/decode_v0.h"
9 | #include "previous/v1/decode_v1.h"
10 | #include "previous/v2/decode_v2.h"
11 | #include "previous/v3/decode_v3.h"
12 |
13 | void *Decode_PreviousTensor(RedisModuleIO *rdb, int encver) {
14 | switch (encver) {
15 | case 0:
16 | return RAI_RDBLoadTensor_v0(rdb);
17 | case 1:
18 | return RAI_RDBLoadTensor_v1(rdb);
19 | case 2:
20 | return RAI_RDBLoadTensor_v2(rdb);
21 | case 3:
22 | return RAI_RDBLoadTensor_v3(rdb);
23 | default:
24 | assert(false && "Invalid encoding version");
25 | }
26 | return NULL;
27 | }
28 |
29 | void *Decode_PreviousModel(RedisModuleIO *rdb, int encver) {
30 | switch (encver) {
31 | case 0:
32 | return RAI_RDBLoadModel_v0(rdb);
33 | case 1:
34 | return RAI_RDBLoadModel_v1(rdb);
35 | case 2:
36 | return RAI_RDBLoadModel_v2(rdb);
37 | case 3:
38 | return RAI_RDBLoadModel_v3(rdb);
39 | default:
40 | assert(false && "Invalid encoding version");
41 | }
42 | return NULL;
43 | }
44 |
45 | void *Decode_PreviousScript(RedisModuleIO *rdb, int encver) {
46 | switch (encver) {
47 | case 0:
48 | return RAI_RDBLoadScript_v0(rdb);
49 | case 1:
50 | return RAI_RDBLoadScript_v1(rdb);
51 | case 2:
52 | return RAI_RDBLoadScript_v2(rdb);
53 | case 3:
54 | return RAI_RDBLoadScript_v3(rdb);
55 | default:
56 | assert(false && "Invalid encoding version");
57 | }
58 | return NULL;
59 | }
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/decode_previous.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "../../serialization_include.h"
9 |
10 | void *Decode_PreviousTensor(RedisModuleIO *rdb, int encver);
11 |
12 | void *Decode_PreviousModel(RedisModuleIO *rdb, int encver);
13 |
14 | void *Decode_PreviousScript(RedisModuleIO *rdb, int encver);
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/previous/v0/decode_v0.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "../../../../serialization_include.h"
9 |
10 | void *RAI_RDBLoadTensor_v0(RedisModuleIO *io);
11 |
12 | void *RAI_RDBLoadModel_v0(RedisModuleIO *io);
13 |
14 | void *RAI_RDBLoadScript_v0(RedisModuleIO *io);
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/previous/v1/decode_v1.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "serialization/serialization_include.h"
9 |
10 | void *RAI_RDBLoadTensor_v1(RedisModuleIO *io);
11 |
12 | void *RAI_RDBLoadModel_v1(RedisModuleIO *io);
13 |
14 | void *RAI_RDBLoadScript_v1(RedisModuleIO *io);
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/previous/v2/decode_v2.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "serialization/serialization_include.h"
9 |
10 | void *RAI_RDBLoadTensor_v2(RedisModuleIO *io);
11 |
12 | void *RAI_RDBLoadModel_v2(RedisModuleIO *io);
13 |
14 | void *RAI_RDBLoadScript_v2(RedisModuleIO *io);
15 |
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/previous/v3/decode_v3.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "serialization/serialization_include.h"
9 |
10 | void *RAI_RDBLoadTensor_v3(RedisModuleIO *io);
11 |
12 | void *RAI_RDBLoadModel_v3(RedisModuleIO *io);
13 |
14 | void *RAI_RDBLoadScript_v3(RedisModuleIO *io);
15 |
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/rai_rdb_decoder.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "rai_rdb_decoder.h"
8 | #include "current/v4/decode_v4.h"
9 |
10 | void *RAI_RDBLoadTensor(RedisModuleIO *io) { return RAI_RDBLoadTensor_v4(io); }
11 |
12 | void *RAI_RDBLoadModel(RedisModuleIO *io) { return RAI_RDBLoadModel_v4(io); }
13 |
14 | void *RAI_RDBLoadScript(RedisModuleIO *io) { return RAI_RDBLoadScript_v4(io); }
15 |
--------------------------------------------------------------------------------
/src/serialization/RDB/decoder/rai_rdb_decoder.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "../../serialization_include.h"
10 |
11 | void *RAI_RDBLoadTensor(RedisModuleIO *io);
12 |
13 | void *RAI_RDBLoadModel(RedisModuleIO *io);
14 |
15 | void *RAI_RDBLoadScript(RedisModuleIO *io);
--------------------------------------------------------------------------------
/src/serialization/RDB/encoder/rai_rdb_encode.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "rai_rdb_encode.h"
8 | #include "v4/encode_v4.h"
9 |
10 | void RAI_RDBSaveTensor(RedisModuleIO *io, void *value) { RAI_RDBSaveTensor_v4(io, value); }
11 |
12 | void RAI_RDBSaveModel(RedisModuleIO *io, void *value) { RAI_RDBSaveModel_v4(io, value); }
13 |
14 | void RAI_RDBSaveScript(RedisModuleIO *io, void *value) { RAI_RDBSaveScript_v4(io, value); }
15 |
--------------------------------------------------------------------------------
/src/serialization/RDB/encoder/rai_rdb_encode.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "../../serialization_include.h"
10 |
11 | void RAI_RDBSaveTensor(RedisModuleIO *io, void *value);
12 |
13 | void RAI_RDBSaveModel(RedisModuleIO *io, void *value);
14 |
15 | void RAI_RDBSaveScript(RedisModuleIO *io, void *value);
16 |
--------------------------------------------------------------------------------
/src/serialization/RDB/encoder/v4/encode_v4.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "encode_v4.h"
8 |
9 | void RAI_RDBSaveTensor_v4(RedisModuleIO *io, void *value) {
10 | RAI_Tensor *tensor = (RAI_Tensor *)value;
11 |
12 | RedisModule_SaveUnsigned(io, tensor->tensor.dl_tensor.dtype.code);
13 | RedisModule_SaveUnsigned(io, tensor->tensor.dl_tensor.dtype.bits);
14 |
15 | size_t ndim = tensor->tensor.dl_tensor.ndim;
16 | RedisModule_SaveSigned(io, ndim);
17 | for (size_t i = 0; i < ndim; i++) {
18 | RedisModule_SaveSigned(io, tensor->tensor.dl_tensor.shape[i]);
19 | }
20 |
21 | size_t size = RAI_TensorByteSize(tensor);
22 | RedisModule_SaveStringBuffer(io, tensor->tensor.dl_tensor.data, size);
23 |
24 | if (tensor->tensor.dl_tensor.dtype.code == kDLString) {
25 | for (size_t i = 0; i < RAI_TensorLength(tensor); i++) {
26 | RedisModule_SaveUnsigned(io, tensor->tensor.dl_tensor.elements_length[i]);
27 | }
28 | }
29 | }
30 |
31 | void RAI_RDBSaveModel_v4(RedisModuleIO *io, void *value) {
32 | RAI_Model *model = (RAI_Model *)value;
33 | char *buffer = NULL;
34 | size_t len = 0;
35 | RAI_Error err = {0};
36 |
37 | int ret = RAI_ModelSerialize(model, &buffer, &len, &err);
38 |
39 | if (err.code != RAI_OK) {
40 | RedisModuleCtx *stats_ctx = RedisModule_GetContextFromIO(io);
41 | printf("ERR: %s\n", err.detail);
42 | RAI_ClearError(&err);
43 | if (buffer) {
44 | RedisModule_Free(buffer);
45 | }
46 | return;
47 | }
48 |
49 | RedisModule_SaveUnsigned(io, model->backend);
50 | RedisModule_SaveStringBuffer(io, model->devicestr, strlen(model->devicestr) + 1);
51 | RedisModule_SaveString(io, model->tag);
52 | RedisModule_SaveUnsigned(io, model->opts.batchsize);
53 | RedisModule_SaveUnsigned(io, model->opts.minbatchsize);
54 | RedisModule_SaveUnsigned(io, model->opts.minbatchtimeout);
55 | RedisModule_SaveUnsigned(io, model->ninputs);
56 | for (size_t i = 0; i < model->ninputs; i++) {
57 | RedisModule_SaveStringBuffer(io, model->inputs[i], strlen(model->inputs[i]) + 1);
58 | }
59 | RedisModule_SaveUnsigned(io, model->noutputs);
60 | for (size_t i = 0; i < model->noutputs; i++) {
61 | RedisModule_SaveStringBuffer(io, model->outputs[i], strlen(model->outputs[i]) + 1);
62 | }
63 | long long chunk_size = Config_GetModelChunkSize();
64 | const size_t n_chunks = len / chunk_size + 1;
65 | RedisModule_SaveUnsigned(io, len);
66 | RedisModule_SaveUnsigned(io, n_chunks);
67 | for (size_t i = 0; i < n_chunks; i++) {
68 | size_t chunk_len = i < n_chunks - 1 ? chunk_size : len % chunk_size;
69 | RedisModule_SaveStringBuffer(io, buffer + i * chunk_size, chunk_len);
70 | }
71 |
72 | if (buffer) {
73 | RedisModule_Free(buffer);
74 | }
75 | }
76 |
77 | void RAI_RDBSaveScript_v4(RedisModuleIO *io, void *value) {
78 | RAI_Script *script = (RAI_Script *)value;
79 |
80 | RedisModule_SaveStringBuffer(io, script->devicestr, strlen(script->devicestr) + 1);
81 | RedisModule_SaveString(io, script->tag);
82 | RedisModule_SaveStringBuffer(io, script->scriptdef, strlen(script->scriptdef) + 1);
83 | size_t nEntryPoints = array_len(script->entryPoints);
84 |
85 | RedisModule_SaveUnsigned(io, nEntryPoints);
86 | for (size_t i = 0; i < nEntryPoints; i++) {
87 | RedisModule_SaveStringBuffer(io, script->entryPoints[i],
88 | strlen(script->entryPoints[i]) + 1);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/serialization/RDB/encoder/v4/encode_v4.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "../../../serialization_include.h"
9 |
10 | void RAI_RDBSaveTensor_v4(RedisModuleIO *io, void *value);
11 |
12 | void RAI_RDBSaveModel_v4(RedisModuleIO *io, void *value);
13 |
14 | void RAI_RDBSaveScript_v4(RedisModuleIO *io, void *value);
15 |
--------------------------------------------------------------------------------
/src/serialization/ai_datatypes.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "serialization_include.h"
8 |
9 | RedisModuleType *RedisAI_TensorType = NULL;
10 | RedisModuleType *RedisAI_ModelType = NULL;
11 | RedisModuleType *RedisAI_ScriptType = NULL;
12 |
--------------------------------------------------------------------------------
/src/serialization/serialization_include.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include "redismodule.h"
10 | #include "redis_ai_objects/stats.h"
11 | #include "redis_ai_objects/model.h"
12 | #include "redis_ai_objects/tensor.h"
13 | #include "redis_ai_objects/script.h"
14 | #include "backends/backends.h"
15 | #include "version.h"
16 | #include "util/string_utils.h"
17 |
--------------------------------------------------------------------------------
/src/util/dictionaries.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "dictionaries.h"
8 | #include "string_utils.h"
9 | #include "arr.h"
10 |
11 | static array_t dict_arr_clone_fn(void *privdata, const void *arr) {
12 | array_t dest;
13 | array_clone(dest, (array_t)arr);
14 | return dest;
15 | }
16 |
17 | static void dict_arr_free_fn(void *privdata, void *arr) { array_free(arr); }
18 |
19 | AI_dictType AI_dictTypeHeapStrings = {
20 | .hashFunction = RAI_StringsHashFunction,
21 | .keyDup = RAI_StringsKeyDup,
22 | .valDup = NULL,
23 | .keyCompare = RAI_StringsKeyCompare,
24 | .keyDestructor = RAI_StringsKeyDestructor,
25 | .valDestructor = NULL,
26 | };
27 |
28 | AI_dictType AI_dictTypeHeapRStrings = {
29 | .hashFunction = RAI_RStringsHashFunction,
30 | .keyDup = RAI_RStringsKeyDup,
31 | .valDup = NULL,
32 | .keyCompare = RAI_RStringsKeyCompare,
33 | .keyDestructor = RAI_RStringsKeyDestructor,
34 | .valDestructor = NULL,
35 | };
36 |
37 | AI_dictType AI_dictType_String_ArrSimple = {
38 | .hashFunction = RAI_StringsHashFunction,
39 | .keyDup = RAI_StringsKeyDup,
40 | .valDup = dict_arr_clone_fn,
41 | .keyCompare = RAI_StringsKeyCompare,
42 | .keyDestructor = RAI_StringsKeyDestructor,
43 | .valDestructor = dict_arr_free_fn,
44 | };
45 |
--------------------------------------------------------------------------------
/src/util/dictionaries.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "dict.h"
9 |
10 | /**
11 | * @brief Dictionary key type: const char*. value type: void*.
12 | *
13 | */
14 | extern AI_dictType AI_dictTypeHeapStrings;
15 |
16 | /**
17 | * @brief Dictionary key type: RedisModuleString*. value type: void*.
18 | *
19 | */
20 | extern AI_dictType AI_dictTypeHeapRStrings;
21 |
22 | /**
23 | * @brief Dictionary key type: const char*. value type: arr.
24 | *
25 | */
26 | extern AI_dictType AI_dictType_String_ArrSimple;
27 |
--------------------------------------------------------------------------------
/src/util/queue.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include "queue.h"
12 | #include "util/redisai_memory.h"
13 | #include "redismodule.h"
14 |
15 | queue *queueCreate(void) {
16 |
17 | queue *queue = RedisModule_Calloc(1, sizeof(*queue));
18 |
19 | queue->front = queue->back = NULL;
20 | queue->len = 0;
21 | queue->free = NULL;
22 | return queue;
23 | }
24 |
25 | void queuePush(queue *queue, void *value) {
26 |
27 | queueItem *item = RedisModule_Calloc(1, sizeof(*item));
28 | item->value = value;
29 | item->next = NULL;
30 | item->prev = NULL;
31 |
32 | if (queue->len == 0) {
33 | queue->front = queue->back = item;
34 | } else {
35 | queue->back->next = item;
36 | item->prev = queue->back;
37 | queue->back = item;
38 | }
39 | queue->len++;
40 | }
41 |
42 | void queuePushFront(queue *queue, void *value) {
43 |
44 | queueItem *item = RedisModule_Calloc(1, sizeof(*item));
45 |
46 | item->value = value;
47 | item->next = NULL;
48 | item->prev = NULL;
49 |
50 | if (queue->len == 0) {
51 | queue->front = queue->back = item;
52 | } else {
53 | queue->front->prev = item;
54 | item->next = queue->front;
55 | queue->front = item;
56 | }
57 | queue->len++;
58 | }
59 |
60 | queueItem *queuePop(queue *queue) {
61 | queueItem *item = queue->front;
62 | if (item == NULL) {
63 | return NULL;
64 | }
65 | queue->front = item->next;
66 | if (queue->front != NULL) {
67 | queue->front->prev = NULL;
68 | }
69 | if (item == queue->back) {
70 | queue->back = NULL;
71 | }
72 | item->next = NULL;
73 | item->prev = NULL;
74 | queue->len--;
75 | return item;
76 | }
77 |
78 | queueItem *queueFront(queue *queue) { return queue->front; }
79 |
80 | queueItem *queueNext(queueItem *item) { return item->next; }
81 |
82 | queueItem *queueEvict(queue *queue, queueItem *item) {
83 | if (item == queue->front) {
84 | return queuePop(queue);
85 | } else if (item == queue->back) {
86 | queue->back = item->prev;
87 | queue->back->next = NULL;
88 | } else {
89 | item->prev->next = item->next;
90 | item->next->prev = item->prev;
91 | }
92 |
93 | item->next = NULL;
94 | item->prev = NULL;
95 | queue->len--;
96 | return item;
97 | }
98 |
99 | unsigned long queueLength(queue *queue) { return queue->len; }
100 |
101 | void queueRelease(queue *queue) {
102 | unsigned long len;
103 | queueItem *current;
104 |
105 | len = queue->len;
106 | while (len--) {
107 | current = queuePop(queue);
108 | if (current && queue->free)
109 | queue->free(current->value);
110 | RedisModule_Free(current);
111 | }
112 | queue->front = queue->back = NULL;
113 | queue->len = 0;
114 | }
115 |
--------------------------------------------------------------------------------
/src/util/queue.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | #include "util/redisai_memory.h"
14 | #include "redismodule.h"
15 |
16 | typedef struct queueItem {
17 | struct queueItem *next;
18 | struct queueItem *prev;
19 | void *value;
20 | } queueItem;
21 |
22 | typedef struct queue {
23 | queueItem *front;
24 | queueItem *back;
25 | void (*free)(void *ptr);
26 | unsigned long len;
27 | } queue;
28 |
29 | queue *queueCreate(void);
30 | void queuePush(queue *queue, void *value);
31 | void queuePushFront(queue *queue, void *value);
32 | queueItem *queuePop(queue *queue);
33 | queueItem *queueFront(queue *queue);
34 | queueItem *queueNext(queueItem *item);
35 | queueItem *queueEvict(queue *queue, queueItem *item);
36 | unsigned long queueLength(queue *queue);
37 | void queueRelease(queue *queue);
38 |
--------------------------------------------------------------------------------
/src/util/redisai_memory.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #ifndef SRC_REDISAI_MEMORY_H_
8 | #define SRC_REDISAI_MEMORY_H_
9 |
10 | #include "redismodule.h"
11 | #include "stdlib.h"
12 | #include
13 |
14 | #ifdef VALGRIND
15 | #define RA_ALLOC malloc
16 | #define RA_CALLOC calloc
17 | #define RA_REALLOC realloc
18 | #define RA_FREE free
19 | #define RA_STRDUP strdup
20 | #else
21 | #define RA_ALLOC RedisModule_Alloc
22 | #define RA_CALLOC RedisModule_Calloc
23 | #define RA_REALLOC RedisModule_Realloc
24 | #define RA_FREE RedisModule_Free
25 | #define RA_STRDUP RedisModule_Strdup
26 | #endif
27 |
28 | #endif /* SRC_REDISAI_MEMORY_H_ */
29 |
--------------------------------------------------------------------------------
/src/util/string_utils.c:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "string_utils.h"
8 | #include "dict.h"
9 | #include
10 | #include
11 | #include "util/redisai_memory.h"
12 |
13 | RedisModuleString *RAI_HoldString(RedisModuleString *str) {
14 | if (str == NULL) {
15 | return NULL;
16 | }
17 | RedisModuleString *out;
18 | if (RMAPI_FUNC_SUPPORTED(RedisModule_HoldString)) {
19 | out = RedisModule_HoldString(NULL, str);
20 | } else {
21 | RedisModule_RetainString(NULL, str);
22 | out = str;
23 | }
24 | return out;
25 | }
26 |
27 | uint64_t RAI_StringsHashFunction(const void *key) {
28 | return AI_dictGenHashFunction(key, strlen((char *)key));
29 | }
30 |
31 | int RAI_StringsKeyCompare(void *privdata, const void *key1, const void *key2) {
32 | const char *strKey1 = key1;
33 | const char *strKey2 = key2;
34 |
35 | return strcmp(strKey1, strKey2) == 0;
36 | }
37 |
38 | void RAI_StringsKeyDestructor(void *privdata, void *key) { RA_FREE(key); }
39 |
40 | void *RAI_StringsKeyDup(void *privdata, const void *key) { return RA_STRDUP((char *)key); }
41 |
42 | uint64_t RAI_RStringsHashFunction(const void *key) {
43 | size_t len;
44 | const char *buffer = RedisModule_StringPtrLen((RedisModuleString *)key, &len);
45 | return AI_dictGenHashFunction(buffer, len);
46 | }
47 |
48 | int RAI_RStringsKeyCompare(void *privdata, const void *key1, const void *key2) {
49 | RedisModuleString *strKey1 = (RedisModuleString *)key1;
50 | RedisModuleString *strKey2 = (RedisModuleString *)key2;
51 |
52 | return RedisModule_StringCompare(strKey1, strKey2) == 0;
53 | }
54 |
55 | void RAI_RStringsKeyDestructor(void *privdata, void *key) {
56 | RedisModule_FreeString(NULL, (RedisModuleString *)key);
57 | }
58 |
59 | void *RAI_RStringsKeyDup(void *privdata, const void *key) {
60 | return RedisModule_CreateStringFromString(NULL, (RedisModuleString *)key);
61 | }
62 |
63 | void RAI_StringToUpper(const char *str, char *upper, size_t str_len) {
64 | // Assumption: upper buffer size is at least str_len. This can be used for
65 | // every binary string, we do not assume that the string is null-terminated.
66 | for (size_t i = 0; i < str_len; i++) {
67 | upper[i] = (char)toupper(str[i]);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/util/string_utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #include "redismodule.h"
8 | #include "dict.h"
9 |
10 | RedisModuleString *RAI_HoldString(RedisModuleString *str);
11 | void RAI_StringToUpper(const char *str, char *upper, size_t str_len);
12 |
13 | uint64_t RAI_StringsHashFunction(const void *key);
14 | int RAI_StringsKeyCompare(void *privdata, const void *key1, const void *key2);
15 | void RAI_StringsKeyDestructor(void *privdata, void *key);
16 | void *RAI_StringsKeyDup(void *privdata, const void *key);
17 |
18 | uint64_t RAI_RStringsHashFunction(const void *key);
19 | int RAI_RStringsKeyCompare(void *privdata, const void *key1, const void *key2);
20 | void RAI_RStringsKeyDestructor(void *privdata, void *key);
21 | void *RAI_RStringsKeyDup(void *privdata, const void *key);
22 |
--------------------------------------------------------------------------------
/src/version.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 |
9 | #define REDISAI_VERSION_MAJOR 99
10 | #define REDISAI_VERSION_MINOR 99
11 | #define REDISAI_VERSION_PATCH 99
12 |
13 | #define REDISAI_MODULE_VERSION \
14 | (REDISAI_VERSION_MAJOR * 10000 + REDISAI_VERSION_MINOR * 100 + REDISAI_VERSION_PATCH)
15 |
16 | /* API versions. */
17 | #define REDISAI_LLAPI_VERSION 1
18 |
19 | static const long long REDISAI_ENC_VER = 4;
20 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedisAI/redis-inference-optimization/c458c5f83e93ee07963af7123e9ad17b52389bcd/tests/__init__.py
--------------------------------------------------------------------------------
/tests/flow/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedisAI/redis-inference-optimization/c458c5f83e93ee07963af7123e9ad17b52389bcd/tests/flow/__init__.py
--------------------------------------------------------------------------------
/tests/flow/test_data_files.txt:
--------------------------------------------------------------------------------
1 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/__init__.py
2 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/Pads.bin
3 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/batchdim_mismatch.onnx
4 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/batchdim_mismatch.pt
5 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/creditcardfraud.pb
6 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/graph.pb
7 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/identity_string.pb
8 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/identity_string.onnx
9 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet/__init__.py
10 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet/data_processing_script.txt
11 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet/cat.jpg
12 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/frozen_bad_model.pb
13 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet/dog.jpg
14 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet/data_processing_script_old.txt
15 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet/model_checker.py
16 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/graph_v2.pb
17 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet/model_saver.py
18 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/creditcard_10K.csv
19 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet/imagenet_class_index.json
20 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet_class_index.json
21 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/linear_iris.onnx
22 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/logreg_iris.onnx
23 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/lite-model_imagenet_mobilenet_v3_small_100_224_classification_5_default_1.tflite
24 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mnist_batched.onnx
25 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mnist.onnx
26 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mnist_model_quant.tflite
27 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mobilenet/__init__.py
28 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/inception-v2-9.onnx
29 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mobilenet/mobilenet_v1_100_224_cpu_NxHxWxC.pb
30 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mobilenet/mobilenet_v1_100_224_gpu_NxHxWxC.pb
31 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mobilenet/model_saver.py
32 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/imagenet/resnet50.pb
33 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mobilenet/mobilenet_v2_1.4_224_frozen.pb
34 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/model_with_infinite_loop.onnx
35 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/model_with_external_initializers.onnx
36 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mul_1.onnx
37 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/one.raw
38 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/onnx_batch.py
39 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/onnx_batchdim_mismatch.py
40 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/onnx_string_identity.py
41 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/panda-224x224.jpg
42 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/panda.jpg
43 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/pt-minimal-bb.pt
44 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/pt_minimal.py
45 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/pt_minimal_bb.py
46 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/pt-minimal.pt
47 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/redis_scripts.py
48 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/rdb_test_prep_script.py
49 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/script_bad.txt
50 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/tf-minimal.py
51 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/tf2-minimal.py
52 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/tf_string_identity.py
53 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mobilenet_v2_1.4_224_frozen.pb
54 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/old_script.txt
55 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/mobilenet/mobilenet_v1_100_224_gpu_NxHxWxC_fp16_trt.pb
56 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/one.png
57 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/script.txt
58 | http://dev.cto.redis.s3.amazonaws.com/RedisAI/test_data/bert-base-cased.onnx
59 |
--------------------------------------------------------------------------------
/tests/flow/tests_sanitizer.py:
--------------------------------------------------------------------------------
1 | # Copyright Redis Ltd. 2018 - present
2 | # Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
3 | # the Server Side Public License v1 (SSPLv1).
4 |
5 | import redis
6 | from functools import wraps
7 | import multiprocessing as mp
8 | from includes import *
9 |
10 | '''
11 | python -m RLTest --test tests_sanitizer.py --module path/to/redisai.so
12 | '''
13 |
14 |
15 | def test_sanitizer_dagrun_mobilenet_v1(env):
16 | if (not TEST_TF or not TEST_PT):
17 | return
18 | con = get_connection(env, '{s}')
19 | mem_allocator = con.info()['mem_allocator']
20 | if 'jemalloc' in mem_allocator:
21 | print("exiting sanitizer tests given we're not using stdlib allocator")
22 | return
23 |
24 | model_name = 'mobilenet_v1{s}'
25 | model_pb, input_var, output_var, labels, img = load_mobilenet_v1_test_data()
26 |
27 | ret = con.execute_command('AI.MODELSTORE', model_name, 'TF', DEVICE,
28 | 'INPUTS', 1, input_var,
29 | 'OUTPUTS', 1, output_var,
30 | 'BLOB', model_pb)
31 | env.assertEqual(ret, b'OK')
32 |
33 | for opnumber in range(1, MAX_ITERATIONS):
34 | image_key = 'image{{s}}{}'.format(opnumber)
35 | class_key = 'output{s}'
36 |
37 | ret = con.execute_command(
38 | 'AI.DAGEXECUTE', 'ROUTING', '{s}', '|>',
39 | 'AI.TENSORSET', image_key, 'FLOAT', 1, 224, 224, 3, 'BLOB', img.tobytes(),
40 | '|>',
41 | 'AI.MODELEXECUTE', model_name, 'INPUTS', 1, image_key, 'OUTPUTS', 1, class_key,
42 | '|>', 'AI.TENSORGET', class_key, 'blob')
43 | env.assertEqual([b'OK', b'OK'], ret[:2])
44 | env.assertEqual(1001.0, len(ret[2])/4)
45 |
46 |
47 | def test_sanitizer_modelrun_mobilenet_v1(env):
48 | if (not TEST_TF or not TEST_PT):
49 | return
50 | con = get_connection(env, '{s}')
51 | mem_allocator = con.info()['mem_allocator']
52 | if 'jemalloc' in mem_allocator:
53 | print("exiting sanitizer tests given we're not using stdlib allocator")
54 | return
55 |
56 | model_name = 'mobilenet_v1{s}'
57 | model_pb, input_var, output_var, labels, img = load_mobilenet_v1_test_data()
58 |
59 | ret = con.execute_command('AI.MODELSTORE', model_name, 'TF', DEVICE,
60 | 'INPUTS', 1, input_var,
61 | 'OUTPUTS', 1, output_var,
62 | 'BLOB', model_pb)
63 | env.assertEqual(ret, b'OK')
64 |
65 | for opnumber in range(1, MAX_ITERATIONS):
66 | image_key = 'image{s}'
67 | temp_key1 = 'temp_key1{s}'
68 | temp_key2 = 'temp_key2{s}'
69 | class_key = 'output{s}'
70 | ret = con.execute_command(
71 | 'AI.TENSORSET', image_key, 'FLOAT', 1, 224, 224, 3, 'BLOB', img.tobytes()
72 | )
73 | env.assertEqual(b'OK', ret)
74 |
75 | ret = con.execute_command(
76 | 'AI.MODELEXECUTE', model_name,
77 | 'INPUTS', 1, image_key,
78 | 'OUTPUTS', 1, class_key
79 | )
80 |
81 | env.assertEqual(b'OK', ret)
82 |
83 | ret = con.execute_command('AI.TENSORGET', class_key, 'blob')
84 |
85 | env.assertEqual(1001.0, len(ret)/4)
86 |
--------------------------------------------------------------------------------
/tests/flow/tests_setup/Install_RedisGears.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
6 | ROOT=$(cd $HERE/../../.. && pwd)
7 | READIES=$ROOT/opt/readies
8 | . $READIES/shibumi/defs
9 |
10 | if [[ "$1" == "--help" || "$1" == "help" || "$HELP" == "1" ]]; then
11 | cat <<-END
12 | Obtain RedisGears module binaries
13 |
14 | Install_RedisGears.sh [--help|help]
15 |
16 | Argument variables:
17 | GEARS_OSNICK=nick Get binaries for give osnick
18 | GEARS_PATH=dir Get binaries from given Gears repo
19 | NOP=1 No operation
20 | HELP=1 Show help
21 |
22 | END
23 | exit 0
24 | fi
25 |
26 | OP=""
27 | [[ "$NOP" == "1" ]] && OP=echo
28 |
29 | os="$($READIES/bin/platform --os)"
30 | arch="$($READIES/bin/platform --arch)"
31 |
32 | if [[ ! -z "$GEARS_PATH" ]]; then
33 | platform="$($READIES/bin/platform -t)"
34 | else
35 | if [[ "$os" != "linux" || "$arch" != "x64" ]]; then
36 | eprint "Cannot match binary artifacts - build RedisGears and set GEARS_PATH"
37 | exit 1
38 | fi
39 |
40 | dist="$($READIES/bin/platform --dist)"
41 | nick="$($READIES/bin/platform --osnick)"
42 |
43 | if [[ $dist == "ubuntu" ]]; then
44 | if [[ $nick != "bionic" && $nick != "xenial" && $nick != "trusty" ]]; then
45 | nick="bionic"
46 | fi
47 | elif [[ $dist == debian ]]; then
48 | nick=bionic
49 | elif [[ $dist == centos || $dist == redhat || $dist == fedora ]]; then
50 | nick=centos7
51 | elif [[ ! -z "$GEARS_OSNICK" ]]; then
52 | nick=$GEARS_OSNICK
53 | else
54 | eprint "Cannot match binary artifacts - build RedisGears and set GEARS_PATH"
55 | exit 1
56 | fi
57 | platform="${os}-${nick}-${arch}"
58 | fi
59 |
60 | GEARS_S3_URL="http://redismodules.s3.amazonaws.com/redisgears/snapshots"
61 | GEARS_MOD="redisgears.${platform}.master.zip"
62 | GEARS_DEPS="redisgears-python.${platform}.master.tgz"
63 |
64 | FINAL_WORK_DIR="$ROOT/bin/$($READIES/bin/platform -t)/RedisGears"
65 |
66 | if [[ -d $FINAL_WORK_DIR && -f $FINAL_WORK_DIR/redisgears.so ]]; then
67 | echo "RedisGears is in ${FINAL_WORK_DIR}"
68 | exit 0
69 | fi
70 |
71 | $OP mkdir -p $(dirname $FINAL_WORK_DIR)
72 | $OP rm -rf ${FINAL_WORK_DIR}.*
73 | WORK_DIR=$(mktemp -d ${FINAL_WORK_DIR}.XXXXXX)
74 | $OP mkdir -p $WORK_DIR
75 |
76 | if [[ -z $GEARS_PATH ]]; then
77 | F_GEARS_MOD="$WORK_DIR/$GEARS_MOD"
78 | if [[ ! -f $F_GEARS_MOD ]]; then
79 | echo "Download RedisGears ..."
80 | $OP wget -q -P $WORK_DIR $GEARS_S3_URL/$GEARS_MOD
81 | fi
82 |
83 | F_GEARS_DEPS="$WORK_DIR/$GEARS_DEPS"
84 | if [[ ! -f $F_GEARS_DEPS ]]; then
85 | echo "Download RedisGears deps ..."
86 | $OP wget -q -P $WORK_DIR $GEARS_S3_URL/$GEARS_DEPS
87 | fi
88 | else
89 | F_GEARS_MOD="${GEARS_PATH}/artifacts/snapshot/${GEARS_MOD}"
90 | F_GEARS_DEPS="${GEARS_PATH}/artifacts/snapshot/${GEARS_DEPS}"
91 | [[ ! -f $F_GEARS_MOD ]] && { eprint "$F_GEARS_MOD is missing"; exit 1; }
92 | [[ ! -f $F_GEARS_DEPS ]] && { eprint "$F_GEARS_DEPS is missing"; exit 1; }
93 | fi
94 |
95 | $OP unzip -q $F_GEARS_MOD -d $WORK_DIR
96 | $OP tar --no-same-owner -C $WORK_DIR -xzf $F_GEARS_DEPS
97 | $OP mv $WORK_DIR $FINAL_WORK_DIR
98 |
--------------------------------------------------------------------------------
/tests/flow/tests_setup/test_requirements.txt:
--------------------------------------------------------------------------------
1 | numpy>=1.19
2 | scikit-image
3 | redisai
4 | redis~=4.1.4
5 | rltest~=0.5.0
6 | ramp-packer~=2.3.0
7 |
--------------------------------------------------------------------------------
/tests/flow/tests_setup/tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | [[ $VERBOSE == 1 ]] && set -x
4 | [[ $IGNERR == 1 ]] || set -e
5 |
6 | error() {
7 | echo "There are errors:"
8 | gawk 'NR>L-4 && NR>> ":""),$0 }' L=$1 $0
9 | exit 1
10 | }
11 |
12 | [[ -z $_Dbg_DEBUGGER_LEVEL ]] && trap 'error $LINENO' ERR
13 |
14 | HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
15 | export ROOT=$(cd $HERE/../../..; pwd)
16 | . $ROOT/opt/readies/shibumi/functions
17 |
18 | cd $HERE
19 |
20 | #----------------------------------------------------------------------------------------------
21 |
22 | help() {
23 | cat <<-END
24 | Run Python tests.
25 |
26 | [ARGVARS...] tests.sh [--help|help] []
27 |
28 | Argument variables:
29 | VERBOSE=1 Print commands
30 | IGNERR=1 Do not abort on error
31 |
32 | MODULE=path Path to redisai.so
33 | TESTMOD=path Path to LLAPI module
34 |
35 | DEVICE=cpu|gpu Device for testing
36 | GEN=0|1 General tests
37 | SLAVES=0|1 Tests with --test-slaves
38 |
39 | TEST=test Run specific test (e.g. test.py:test_name)
40 | LOG=0|1 Write to log
41 | VALGRIND|VGD=1 Run with Valgrind
42 | CALLGRIND|CGD=1 Run with Callgrind
43 |
44 | END
45 | }
46 |
47 | #----------------------------------------------------------------------------------------------
48 |
49 | check_redis_server() {
50 | if ! command -v redis-server > /dev/null; then
51 | echo "Cannot find redis-server. Aborting."
52 | exit 1
53 | fi
54 | }
55 |
56 | #----------------------------------------------------------------------------------------------
57 |
58 | valgrind_config() {
59 | export VG_OPTIONS="
60 | -q \
61 | --leak-check=full \
62 | --show-reachable=no \
63 | --show-possibly-lost=no"
64 |
65 | VALGRIND_SUPRESSIONS=$ROOT/opt/redis_valgrind.sup
66 |
67 | RLTEST_ARGS+="\
68 | --use-valgrind \
69 | --vg-suppressions $VALGRIND_SUPRESSIONS
70 | --cluster_node_timeout 60000"
71 | }
72 |
73 | valgrind_summary() {
74 | # Collect name of each flow log that contains leaks
75 | FILES_WITH_LEAKS=$(grep -l "definitely lost" logs/*.valgrind.log)
76 | if [[ ! -z $FILES_WITH_LEAKS ]]; then
77 | echo "Memory leaks introduced in flow tests."
78 | echo $FILES_WITH_LEAKS
79 | # Print the full Valgrind output for each leaking file
80 | echo $FILES_WITH_LEAKS | xargs cat
81 | exit 1
82 | else
83 | echo Valgrind test ok
84 | fi
85 | }
86 |
87 | #----------------------------------------------------------------------------------------------
88 |
89 | get_tests_data() {
90 | local TEST_DATA_PATH=$ROOT/tests/flow/test_data
91 | if [ ! -d ${TEST_DATA_PATH} ]; then
92 | echo "Downloading tests data from s3..."
93 | wget -q -x -nH --cut-dirs=2 -i $ROOT/tests/flow/test_data_files.txt -P $ROOT/tests/flow/test_data
94 | echo "Done"
95 | fi
96 | }
97 |
98 | #----------------------------------------------------------------------------------------------
99 |
100 | run_tests() {
101 | local title="$1"
102 | [[ ! -z $title ]] && { $ROOT/opt/readies/bin/sep -0; printf "Tests with $title:\n\n"; }
103 | cd $ROOT/tests/flow
104 | $OP python3 -m RLTest --clear-logs --module $MODULE $RLTEST_ARGS
105 | }
106 |
107 | #----------------------------------------------------------------------------------------------
108 |
109 | [[ $1 == --help || $1 == help ]] && { help; exit 0; }
110 |
111 | DEVICE=${DEVICE:-cpu}
112 |
113 | GEN=${GEN:-1}
114 | SLAVES=${SLAVES:-0}
115 |
116 | GDB=${GDB:-0}
117 |
118 | OP=""
119 | [[ $NOP == 1 ]] && OP="echo"
120 |
121 | MODULE=${MODULE:-$1}
122 | [[ -z $MODULE || ! -f $MODULE ]] && { echo "Module not found at ${MODULE}. Aborting."; exit 1; }
123 | TESTMOD=${TESTMOD}
124 | echo "Test module path is ${TESTMOD}"
125 |
126 | [[ $VALGRIND == 1 || $VGD == 1 ]] && valgrind_config
127 |
128 | if [[ ! -z $TEST ]]; then
129 | RLTEST_ARGS+=" --test $TEST"
130 | if [[ $LOG != 1 ]]; then
131 | RLTEST_ARGS+=" -s"
132 | export PYDEBUG=${PYDEBUG:-1}
133 | fi
134 | fi
135 |
136 | [[ $VERBOSE == 1 ]] && RLTEST_ARGS+=" -v"
137 | [[ $GDB == 1 ]] && RLTEST_ARGS+=" -i --verbose"
138 |
139 | #----------------------------------------------------------------------------------------------
140 |
141 | cd $ROOT/tests/flow/tests_setup
142 |
143 | check_redis_server
144 | ./Install_RedisGears.sh
145 | get_tests_data
146 |
147 | [[ ! -z $REDIS ]] && RL_TEST_ARGS+=" --env exiting-env --existing-env-addr $REDIS" run_tests "redis-server: $REDIS"
148 | [[ $GEN == 1 ]] && run_tests
149 | [[ $CLUSTER == 1 ]] && RLTEST_ARGS+=" --env oss-cluster --shards-count 3" run_tests "--env oss-cluster"
150 | [[ $VALGRIND != 1 && $SLAVES == 1 ]] && RLTEST_ARGS+=" --use-slaves" run_tests "--use-slaves"
151 | # [[ $VALGRIND == 1 ]] && valgrind_summary
152 | exit 0
153 |
--------------------------------------------------------------------------------
/tests/flow/tests_setup/valgrind.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | [[ $VERBOSE == 1 ]] && set -x
4 | [[ $IGNERR == 1 ]] || set -e
5 |
6 | error() {
7 | echo "There are errors."
8 | exit 1
9 | }
10 |
11 | # trap error ERR
12 |
13 | HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
14 | export ROOT=$(cd $HERE/../..; pwd)
15 | . $ROOT/opt/readies/shibumi/functions
16 |
17 | cd $HERE
18 |
19 | #----------------------------------------------------------------------------------------------
20 |
21 | help() {
22 | cat <<-END
23 | Run Valgrind/Callgrind on RedisAI.
24 |
25 | [ARGVARS...] valgrind.sh [--help|help] []
26 |
27 | Argument variables:
28 | VERBOSE=1 Print commands
29 | IGNERR=1 Do not abort on error
30 |
31 | CALLGRIND|CGD=1 Run with Callgrind
32 |
33 | END
34 | }
35 |
36 | #----------------------------------------------------------------------------------------------
37 |
38 | check_redis_server() {
39 | if ! command -v redis-server > /dev/null; then
40 | echo "Cannot find redis-server. Aborting."
41 | exit 1
42 | fi
43 | }
44 |
45 | #----------------------------------------------------------------------------------------------
46 |
47 | valgrind_config() {
48 | VALGRIND_SUPRESSIONS=$ROOT/opt/redis_valgrind.sup
49 |
50 | if [[ $CALLGRIND == 1 ]]; then
51 |
52 | VALGRIND_OPTIONS+="\
53 | --tool=callgrind \
54 | --dump-instr=yes \
55 | --simulate-cache=no \
56 | --collect-jumps=no \
57 | --collect-atstart=yes \
58 | --instr-atstart=yes \
59 | --callgrind-out-file=$MODULE.call"
60 | else
61 | VALGRIND_OPTIONS+="\
62 | -q \
63 | --suppressions=$VALGRIND_SUPRESSIONS \
64 | --leak-check=full \
65 | --show-reachable=no \
66 | --show-possibly-lost=no \
67 | --show-leak-kinds=all"
68 | fi
69 |
70 | VALGRIND_OPTIONS+=" -v"
71 | }
72 |
73 | #----------------------------------------------------------------------------------------------
74 |
75 | [[ $1 == --help || $1 == help ]] && { help; exit 0; }
76 |
77 | OP=""
78 | [[ $NOP == 1 ]] && OP="echo"
79 |
80 | MODULE=${MODULE:-$1}
81 | [[ -z $MODULE || ! -f $MODULE ]] && { echo "Module not found. Aborting."; exit 1; }
82 |
83 | VALGRIND_OPTIONS=""
84 | valgrind_config
85 |
86 | #----------------------------------------------------------------------------------------------
87 |
88 | check_redis_server
89 | $OP valgrind $(echo "$VALGRIND_OPTIONS") redis-server --protected-mode no --save '' --appendonly no --loadmodule $MODULE
90 |
--------------------------------------------------------------------------------
/tests/module/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ADD_LIBRARY(testmod SHARED LLAPI.c DAG_utils.c)
2 |
3 | INCLUDE_DIRECTORIES(../../src)
4 | SET_TARGET_PROPERTIES(testmod PROPERTIES PREFIX "")
5 | SET_TARGET_PROPERTIES(testmod PROPERTIES SUFFIX ".so")
6 |
--------------------------------------------------------------------------------
/tests/module/DAG_utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | *Copyright Redis Ltd. 2018 - present
3 | *Licensed under your choice of the Redis Source Available License 2.0 (RSALv2) or
4 | *the Server Side Public License v1 (SSPLv1).
5 | */
6 |
7 | #pragma once
8 | #include "redisai.h"
9 | #include
10 | #include
11 |
12 | #define LLAPIMODULE_OK 0
13 | #define LLAPIMODULE_ERR 1
14 |
15 | typedef struct RAI_RunCtx {
16 | RAI_Tensor **outputs;
17 | RAI_Error *error;
18 | pthread_mutex_t lock;
19 | pthread_cond_t cond;
20 | } RAI_RunCtx;
21 |
22 | int testLoadTensor(RedisModuleCtx *ctx);
23 |
24 | int testModelRunOpError(RedisModuleCtx *ctx);
25 |
26 | int testEmptyDAGError(RedisModuleCtx *ctx);
27 |
28 | int testKeysMismatchError(RedisModuleCtx *ctx);
29 |
30 | int testBuildDAGFromString(RedisModuleCtx *ctx);
31 |
32 | int testSimpleDAGRun(RedisModuleCtx *ctx);
33 |
34 | int testSimpleDAGRun2(RedisModuleCtx *ctx);
35 |
36 | int testSimpleDAGRun2Error(RedisModuleCtx *ctx);
37 |
38 | int testDAGResnet(RedisModuleCtx *ctx);
39 |
--------------------------------------------------------------------------------
/tests/qa/RS_VERSIONS:
--------------------------------------------------------------------------------
1 | 6.2.4-54
2 | 6.2.8-53
3 | 6.2.10-129
4 | 6.2.12-82
5 | 6.2.18-49
6 | 6.4.0-48
7 | 6.4.2-8
8 | 100.0.0-2988
9 |
--------------------------------------------------------------------------------
/tests/qa/RS_VERSIONS-lite:
--------------------------------------------------------------------------------
1 | 6.0.12-58
2 | 6.0.20-101
3 | 6.2.4-54
4 | 6.2.8-53
5 | 6.2.10-129
6 | 6.2.12-82
7 | 6.2.18-49
8 | 6.4.0-48
9 | 6.4.2-8
10 | 100.0.0-2988
11 |
--------------------------------------------------------------------------------
/tests/qa/nightly.json:
--------------------------------------------------------------------------------
1 | {
2 | "service_id": "single_module_test_cycle",
3 | "name": "redisai{{VARIANT}} automation-testing",
4 | "properties": {
5 | "sut_version": "master",
6 | "email_recipients": "redisaidev-aaaacob2o7eeecrhkqwua77kku@redislabs.slack.com",
7 | "sut_environments": [],
8 | "tools_environment": {},
9 | "modules_version": "master",
10 | "test_names_modules": [
11 | "{{RS_MODULE}}"
12 | ],
13 | "cycle_environments_setup": [
14 | {
15 | "teardown": true,
16 | "name": "bionic-amd64-aws",
17 | "concurrency": 1,
18 | "module_url": "http://redismodules.s3.amazonaws.com/{{RS_MODULE_FILE_PREFIX}}/snapshots/{{RS_MODULE_FILE_PREFIX}}-cpu.linux-bionic-x64.master{{VARIANT}}.zip"
19 | }
20 | ]
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/qa/release.json:
--------------------------------------------------------------------------------
1 | {
2 | "service_id": "single_module_test_cycle",
3 | "name": "redisai{{VARIANT}} automation-testing",
4 | "properties": {
5 | "sut_version": "{{RS_VERSION}}",
6 | "email_recipients": "redisaidev-aaaacob2o7eeecrhkqwua77kku@redislabs.slack.com",
7 | "sut_environments": [],
8 | "tools_environment": {},
9 | "modules_version": "{{MODULE_VERSION}}",
10 | "test_names_modules": [
11 | "{{RS_MODULE}}"
12 | ],
13 | "cycle_environments_setup": [
14 | {
15 | "teardown": true,
16 | "name": "bionic-amd64-aws",
17 | "concurrency": 1,
18 | "module_url": "http://redismodules.s3.amazonaws.com/{{RS_MODULE_LC}}/{{RS_MODULE_FILE_PREFIX}}.linux-bionic-x64.{{MODULE_VERSION}}{{VARIANT}}.zip"
19 | },
20 | {
21 | "teardown": true,
22 | "name": "rhel8.5-x86_64-aws",
23 | "concurrency": 1,
24 | "module_url": "http://redismodules.s3.amazonaws.com/{{RS_MODULE_FILE_PREFIX}}/{{RS_MODULE_FILE_PREFIX}}.Linux-rhel8-x86_64.{{MODULE_VERSION}}.zip"
25 | },
26 | {
27 | "teardown": true,
28 | "name": "focal-amd64-aws",
29 | "concurrency": 1,
30 | "module_url": "http://redismodules.s3.amazonaws.com/{{RS_MODULE_LC}}/{{RS_MODULE_FILE_PREFIX}}.Linux-focal-x64.{{MODULE_VERSION}}{{VARIANT}}.zip"
31 | }
32 | ]
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/qa/run:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
4 | ROOT=$(cd $HERE/../.. && pwd)
5 | READIES=$ROOT/opt/readies
6 |
7 | (( VERBOSE > 1 )) && { set -x; PS4='$LINENO: '; }
8 |
9 | if [[ $1 == --help || $1 == help ]]; then
10 | cat <<-END
11 | Invoke QA Automation tests
12 |
13 | [ARGVARS...] run [--help|help]
14 |
15 | Argument variables:
16 | QA_AUTOMATION_TOKEN=token QA automation (Opereto) token
17 | TEST=name Name of .json parameters file
18 | MODULE_VERSION=ver Module version to test. Default: master
19 | NOP=1 Do not execute automation command
20 | VERBOSE=N Set verbosity level (N=1,2)
21 | QUICK=1 Only test one RS version
22 |
23 | Other configuration:
24 | RS_VERSIONS file includes Redis Enterprive versions for release tests.
25 |
26 | END
27 | exit 0
28 | fi
29 |
30 | export RS_MODULE=RedisAI
31 | export RS_MODULE_LC=${RS_MODULE,,}
32 | export RS_MODULE_FILE_PREFIX=redisai-cpu
33 | export VARIANT=${VARIANT} # for variants such as RedisAILite. We append -lite (see circleci for an example)
34 |
35 | if [[ -z $QA_AUTOMATION_TOKEN && $NOP != 1 ]]; then
36 | echo "Variable QA_AUTOMATION_TOKEN is undefined." >&2
37 | exit 1
38 | fi
39 |
40 | export TEST=${TEST:-release}
41 | if [[ ! -f $HERE/$TEST.json ]]; then
42 | echo "Invalid TEST name: $TEST" >&2
43 | exit 1
44 | fi
45 |
46 | run_test() {
47 | set -x
48 | export RS_VERSION=$1
49 |
50 | if [[ -z $MODULE_VERSION ]]; then
51 | export MODULE_VERSION=master
52 | else
53 | export MODULE_VERSION=$(echo "$MODULE_VERSION" | sed 's/^v\(.*\)/\1/')
54 | fi
55 |
56 | results() {
57 | echo "$JSON" | jq "$1" | cut -d\" -f2
58 | }
59 |
60 | cd $HERE
61 |
62 | json_in=$(mktemp /tmp/$TEST.json.XXXX)
63 | $READIES/bin/xtx -e VARIANT -e RS_MODULE -e RS_MODULE_LC -e RS_MODULE_FILE_PREFIX -e MODULE_VERSION -e RS_VERSION $TEST.json > $json_in
64 | (( VERBOSE >= 1 )) && cat $json_in
65 |
66 | if [[ $NOP == 1 ]]; then
67 | echo "Testing RS $RS_VERSION"
68 | return 0
69 | fi
70 |
71 | OPERETO3_URL="opereto.qa.redislabs.com"
72 | JSON=$(curl -sk \
73 | -X POST -H "Content-Type: application/json" \
74 | -H "Authorization: Bearer $QA_AUTOMATION_TOKEN" \
75 | -d @$json_in \
76 | https://$OPERETO3_URL/processes 2>&1)
77 | rc=$?
78 | rm $json_in
79 | status=$(results .status)
80 | if [[ $rc == 0 && $status == success ]]; then
81 | id=$(results .data[0])
82 | echo "Tests running on $MODULE_VERSION for RS $RS_VERSION"
83 | echo "Results: https://$OPERETO3_URL/ui#dashboard/flow/$id"
84 | return 0
85 | else
86 | err=$(results .message)
87 | echo "Failed to run tests on $MODULE_VERSION for RS $RS_VERSION: $err"
88 | return 1
89 | fi
90 | }
91 |
92 | rc=0
93 | # By default we use RS_VERSIONS, but with variants they may need to specify their own redis verisons, hence this file
94 | VERSIONFILE=${HERE}/RS_VERSIONS${VARIANT}
95 | if [[ $QUICK == 1 ]]; then
96 | RS_VERSIONS=$(cat $VERSIONFILE | head -1)
97 | else
98 | RS_VERSIONS=$(cat $VERSIONFILE)
99 | fi
100 | for RS_VERSION in $RS_VERSIONS; do
101 | run_test $RS_VERSION
102 | [[ $? != 0 && $rc == 0 ]] && rc=$?
103 | done
104 | exit $rc
105 |
--------------------------------------------------------------------------------