Ambarella deployment
DENKflow can run Hub-exported vision pipelines directly on supported Ambarella chips. The model is compiled for one specific chip when it is exported and is executed by that chip's Cavalry accelerator.
You do not need the DENKflow source code, the Ambarella SDK, or a compiler.
Use the compiled DENKflow package supplied for Linux ARM64 together with an
Ambarella .denkflow export from the Vision AI Hub.
Supported chips and export targets
Select the export target that exactly matches the device:
- CV22:
AMBARELLA_CV22 - CV72:
AMBARELLA_CV72 - CV75:
AMBARELLA_CV75 - N1 / N1X:
AMBARELLA_N1X - N1-655 / N1-655X:
AMBARELLA_N1_655X
An Ambarella export is target-specific. For example, a CV22 export cannot run on an N1-655 device. DENKflow checks the model target and runtime version during initialization and stops with an error instead of falling back to CPU.
Supported Ambarella pipelines include image classification, object detection (including oriented boxes), semantic segmentation, and instance segmentation. The exact tasks available to you depend on the export options enabled in your Vision AI Hub account.
Install the compiled package
- Python
- C / C++
Create a virtual environment and install the Linux ARM64 package from the DENKweit private package registry:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "denkflow[cpu]" \
--extra-index-url https://__token__:gldt-JCgXB7jPAo_b6JXAckFV@gitlab.com/api/v4/projects/69262737/packages/pypi/simple
The cpu extra installs the ARM64 ONNX Runtime library used to host the
exported graph and Ambarella custom operator. Inference itself runs on the
Ambarella Cavalry accelerator.
Download the Linux ARM64 package from
DENKflow C-API Releases.
The package provides denkflow.h, libdenkflow.so, and the required runtime
libraries; no source build is required.
Keep the supplied shared libraries together and make their directory visible to the dynamic linker:
export DENKFLOW_C_API_DIR=/path/to/extracted/denkflow-c-api
export LD_LIBRARY_PATH="$DENKFLOW_C_API_DIR:$LD_LIBRARY_PATH"
Compile your application against the header and shared library:
g++ main.cpp \
-I"$DENKFLOW_C_API_DIR" \
-L"$DENKFLOW_C_API_DIR" \
-ldenkflow \
-o app
Device prerequisites
The device image must already provide:
- 64-bit Linux on the matching Ambarella chip;
- the Ambarella Cavalry kernel driver and firmware;
- a usable
/dev/cavalrydevice; - permission for the DENKflow process to access
/dev/cavalry; - enough storage for the compiled model and runtime files.
The board vendor normally supplies the driver and firmware as part of the device image. They are not installed by the DENKflow package.
Check device access before starting DENKflow:
test -r /dev/cavalry && test -w /dev/cavalry \
&& echo "Cavalry device is accessible" \
|| echo "Cavalry device is missing or not accessible"
Runtime download on first use
The model records the exact Ambarella runtime version it requires. On the first initialization, DENKflow uses your Hub credentials to download the matching runtime for both the model and the current chip. Files are verified before use and cached under:
<DENKFLOW_DATA_DIRECTORY>/dependencies/ambarella/<chip>/
Keep DENKFLOW_DATA_DIRECTORY on persistent storage so later starts reuse the
verified runtime:
export DENKFLOW_DATA_DIRECTORY="$HOME/.local/share/denkflow"
mkdir -p "$DENKFLOW_DATA_DIRECTORY"
Interactive applications ask for confirmation before downloading. For unattended services or containers, accept the configured terms non-interactively:
export DENKFLOW_NONINTERACTIVE=1
For devices without Hub access, download the matching .denkdependency archive
from Vision AI Hub > Software > DENKflow Dependencies on another machine and
copy it directly into <DENKFLOW_DATA_DIRECTORY>/dependencies/. See
Runtime dependencies for the complete offline procedure.
Running an exported pipeline
SimplifiedPipeline automatically selects the image tensor type declared by
the graph. This is the recommended API for compiled Ambarella packages:
- Python
- C / C++
import denkflow
pipeline = denkflow.Pipeline.from_denkflow(
"model.denkflow",
pat="YOUR-PAT",
)
simplified = denkflow.SimplifiedPipeline(pipeline)
results = simplified.run("image.jpg", confidence_threshold=0.5)
for image_result in results:
for result in image_result.results:
if result.bounding_box:
box = result.bounding_box
print(box.class_label.name, box.confidence)
For direct topic access with the classic Pipeline API, publish raw RGB
uint8 images when the graph input is ImageTensorU8:
image = denkflow.ImageTensorU8.from_file("image.jpg")
pipeline = denkflow.Pipeline.from_denkflow("model.denkflow", pat="YOUR-PAT")
pipeline.initialize()
receiver = pipeline.subscribe("YOUR_OUTPUT_TOPIC")
pipeline.publish_image_tensor_u8("YOUR_INPUT_TOPIC", image)
pipeline.run(timeout=60)
#include "denkflow.h"
#include <stdio.h>
#include <stdlib.h>
static void check(enum DenkflowResult result) {
if (result == DenkflowResult_Ok) {
return;
}
char error[DENKFLOW_ERROR_BUFFER_SIZE];
denkflow_get_last_error(error);
fprintf(stderr, "DENKflow error: %s\n", error);
exit(EXIT_FAILURE);
}
int main(void) {
DenkflowHubLicenseSource* hub = NULL;
DenkflowPipeline* pipeline = NULL;
DenkflowSimplifiedPipeline* simplified = NULL;
DenkflowImageInferenceResults* results = NULL;
check(denkflow_hub_license_source_from_pat(
&hub, "YOUR-PAT", NULL, NULL));
check(denkflow_pipeline_from_denkflow(
&pipeline, "model.denkflow", (void*)hub));
// Consumes and initializes pipeline. The Ambarella graph remains bound
// to the chip selected during export.
check(denkflow_simplified_pipeline_new(&simplified, &pipeline));
check(denkflow_simplified_pipeline_run_from_file(
&results, simplified, "image.jpg", 0.5f));
for (size_t batch = 0; batch < results->image_results_length; ++batch) {
DenkflowImageInferenceResult* image = &results->image_results[batch];
for (size_t i = 0; i < image->results_length; ++i) {
DenkflowInferenceResult* result = &image->results[i];
if (result->bounding_box != NULL) {
printf("%s: %.3f\n",
result->bounding_box->class_label.name,
result->bounding_box->confidence);
}
}
}
denkflow_inference_results_free(&results);
denkflow_simplified_pipeline_free(&simplified);
denkflow_free_object((void**)&hub);
return 0;
}
Input and output topic names are part of the exported graph. Use
SimplifiedPipeline when you do not need direct topic access.
Performance recommendations
- Initialize the pipeline once and reuse it for all images.
- Prefer
SimplifiedPipelineorImageTensorU8; avoid converting images to floating point before publishing them to an Ambarella graph. - Exclude pipeline initialization and the first few runs from steady-state benchmarks.
- Keep the dependency directory and model files on local persistent storage.
- Leave the default preprocessing enabled. Compatible object-detection graphs automatically use the optimized resize and quantization path.
Troubleshooting
The runtime cannot be downloaded
Confirm that the PAT can access the Hub, the device has network access, and
DENKFLOW_DATA_DIRECTORY is writable. For an offline device, use the matching
.denkdependency archive instead.
The model target does not match the device
Export the pipeline again using the target for the actual chip. Renaming the file or copying a runtime from another chip does not make the model compatible.
/dev/cavalry is missing or permission is denied
Install or enable the board vendor's Cavalry driver and firmware, then grant
the application user access to /dev/cavalry. This must be fixed in the device
image or its service configuration; reinstalling DENKflow does not install the
kernel driver.
A shared library cannot be found
For Python, confirm that the virtual environment containing denkflow[cpu] is
active. For C/C++, keep the shared libraries from the release package together
and include their directory in the library search path:
export LD_LIBRARY_PATH="/path/to/denkflow-package:$LD_LIBRARY_PATH"
When requesting support, include the Ambarella chip, export target, DENKflow package version, Linux image version, and the complete initialization error.