Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Ci #20

Merged
merged 7 commits into from
Aug 11, 2024
Merged

Ci #20

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions .github/workflows/develop.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,21 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Python requirements
run: pip install -r scripts/requirements.txt

############ Install executorch deps ############
- name: Cache Cpp ExecuTorch compiled libraries
id: cache-executorch-cpp-libs
uses: actions/cache@v4
with:
path: executorch-sys/third-party/executorch/cmake-out
key: cache-executorch-cpp-libs-${{ runner.OS }}-${{ hashFiles('scripts/setup_dev.py') }}
- name: Setup dev env, install executorch and its deps
run: python scripts/setup_dev.py
if: steps.cache-executorch-cpp-libs.outputs.cache-hit != 'true'
run: python scripts/setup_dev.py --skip-executorch-python

############ Build executorch-rs ############
- name: Build
Expand All @@ -53,9 +63,11 @@ jobs:
run: cargo test --workspace --all-features

############ Examples ############
- name: Run 'hello world add no_std' example
# python export_model.py
run: cargo run
working-directory: examples/hello_world_add_no_std
# - name: Run 'hello world add' example
# # python export_model.py
# run: cargo run
# working-directory: examples/hello_world_add
# - name: Run 'hello world add no_std' example
# run: cargo run
# working-directory: examples/hello_world_add_no_std
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,22 @@ Additional libs are required if feature flags are enabled (see next section):
The static libraries of the kernels implementations are required only if your model uses them, and they should be **linked manually** by the binary that uses the `executorch` crate.
For example, the `hello_world_add` example uses a model with a single addition operation, so it compile the C++ library with `DEXECUTORCH_SELECT_OPS_LIST=aten::add.out` and contain the following lines in its `build.rs`:
```rust
println!("cargo::rustc-link-lib=static=portable_kernels");
println!("cargo::rustc-link-lib=static:+whole-archive=portable_kernels");
println!("cargo::rustc-link-lib=static:+whole-archive=portable_ops_lib");

let libs_dir = std::env::var("EXECUTORCH_RS_EXECUTORCH_LIB_DIR").unwrap();
println!("cargo::rustc-link-search={}/kernels/portable/", libs_dir);
```
Note that the `portable_ops_lib` is linked with `+whole-archive` to ensure that all symbols are included in the binary.
Note that the ops and kernels libs are linked with `+whole-archive` to ensure that all symbols are included in the binary.

## Cargo Features
- `data-loader`

include the `FileDataLoader` struct. The `libextension_data_loader.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON`.
Includes the `FileDataLoader` and `MmapDataLoader` structs. Without this feature the only available data loader is `BufferDataLoader`. The `libextension_data_loader.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON`.

- `module`

include the `Module` struct. The `libextension_module_static.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_MODULE=ON`.
Includes the `Module` struct. The `libextension_module_static.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_MODULE=ON`.
Also includes the `std` feature.

- `f16`
Expand Down
1 change: 0 additions & 1 deletion examples/hello_world_add/.gitignore

This file was deleted.

2 changes: 1 addition & 1 deletion examples/hello_world_add/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn main() {
println!("cargo::rustc-link-lib=static=portable_kernels");
println!("cargo::rustc-link-lib=static:+whole-archive=portable_kernels");
println!("cargo::rustc-link-lib=static:+whole-archive=portable_ops_lib");

println!("cargo::rerun-if-env-changed=EXECUTORCH_RS_EXECUTORCH_LIB_DIR");
Expand Down
Binary file added examples/hello_world_add/model.pte
Binary file not shown.
1 change: 0 additions & 1 deletion examples/hello_world_add_no_std/.gitignore

This file was deleted.

2 changes: 1 addition & 1 deletion examples/hello_world_add_no_std/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn main() {
println!("cargo::rustc-link-lib=static=portable_kernels");
println!("cargo::rustc-link-lib=static:+whole-archive=portable_kernels");
println!("cargo::rustc-link-lib=static:+whole-archive=portable_ops_lib");

println!("cargo::rerun-if-env-changed=EXECUTORCH_RS_EXECUTORCH_LIB_DIR");
Expand Down
Binary file added examples/hello_world_add_no_std/model.pte
Binary file not shown.
8 changes: 4 additions & 4 deletions executorch-sys/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,22 @@ Additional libs are required if feature flags are enabled (see next section):
The static libraries of the kernels implementations are required only if your model uses them, and they should be **linked manually** by the binary that uses the `executorch` crate.
For example, the `hello_world_add` example uses a model with a single addition operation, so it compile the C++ library with `DEXECUTORCH_SELECT_OPS_LIST=aten::add.out` and contain the following lines in its `build.rs`:
```rust
println!("cargo::rustc-link-lib=static=portable_kernels");
println!("cargo::rustc-link-lib=static:+whole-archive=portable_kernels");
println!("cargo::rustc-link-lib=static:+whole-archive=portable_ops_lib");

let libs_dir = std::env::var("EXECUTORCH_RS_EXECUTORCH_LIB_DIR").unwrap();
println!("cargo::rustc-link-search={}/kernels/portable/", libs_dir);
```
Note that the `portable_ops_lib` is linked with `+whole-archive` to ensure that all symbols are included in the binary.
Note that the ops and kernels libs are linked with `+whole-archive` to ensure that all symbols are included in the binary.

## Cargo Features
- `data-loader`

include the `FileDataLoader` struct. The `libextension_data_loader.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON`.
Includes the `FileDataLoader` and `MmapDataLoader` structs. Without this feature the only available data loader is `BufferDataLoader`. The `libextension_data_loader.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON`.

- `module`

include the `Module` struct. The `libextension_module_static.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_MODULE=ON`.
Includes the `Module` struct. The `libextension_module_static.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_MODULE=ON`.
Also includes the `std` feature.

- `std`
Expand Down
3 changes: 1 addition & 2 deletions executorch-sys/cpp/executorch_rs_ext/api_utils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#include <cstddef>
#include <vector>

#include "executorch_rs_ext/api_utils.hpp"

Expand Down Expand Up @@ -163,12 +164,10 @@ namespace executorch_rs
return list->get();
}

#if defined(EXECUTORCH_RS_DATA_LOADER)
torch::executor::util::BufferDataLoader BufferDataLoader_new(const void *data, size_t size)
{
return torch::executor::util::BufferDataLoader(data, size);
}
#endif

#if defined(EXECUTORCH_RS_MODULE)
torch::executor::Module Module_new(torch::executor::ArrayRef<char> file_path, torch::executor::Module::MlockConfig mlock_config, torch::executor::EventTracer *event_tracer)
Expand Down
4 changes: 0 additions & 4 deletions executorch-sys/cpp/executorch_rs_ext/api_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
#include "executorch/runtime/core/span.h"
#include "executorch/runtime/core/exec_aten/exec_aten.h"

#if defined(EXECUTORCH_RS_DATA_LOADER)
#include "executorch/extension/data_loader/buffer_data_loader.h"
#endif

#if defined(EXECUTORCH_RS_MODULE)
#include "executorch/extension/module/module.h"
Expand Down Expand Up @@ -90,9 +88,7 @@ namespace executorch_rs
const exec_aten::ArrayRef<int64_t> BoxedEvalueList_i64_get(const torch::executor::BoxedEvalueList<int64_t> *list);
const exec_aten::ArrayRef<exec_aten::Tensor> BoxedEvalueList_Tensor_get(const torch::executor::BoxedEvalueList<exec_aten::Tensor> *list);

#if defined(EXECUTORCH_RS_DATA_LOADER)
torch::executor::util::BufferDataLoader BufferDataLoader_new(const void *data, size_t size);
#endif

#if defined(EXECUTORCH_RS_MODULE)
torch::executor::Module Module_new(torch::executor::ArrayRef<char> file_path, torch::executor::Module::MlockConfig mlock_config, torch::executor::EventTracer *event_tracer);
Expand Down
21 changes: 14 additions & 7 deletions executorch-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
//!
//!
//! To build the library, you need to build the C++ library first.
//! The C++ library allow for great flexibility with many flags, customizing which modules, kernels, and extensions are built.
//! The C++ library allow for great flexibility with many flags, customizing which modules, kernels, and extensions are
//! built.
//! Multiple static libraries are built, and the Rust library links to them.
//! In the following example we build the C++ library with the necessary flags to run example `hello_world_add`:
//! ```bash
Expand Down Expand Up @@ -61,21 +62,27 @@
//! - `libextension_data_loader.a`
//! - `libextension_module_static.a`
//!
//! The static libraries of the kernels implementations are required only if your model uses them, and they should be **linked manually** by the binary that uses the `executorch` crate.
//! For example, the `hello_world_add` example uses a model with a single addition operation, so it compile the C++ library with `DEXECUTORCH_SELECT_OPS_LIST=aten::add.out` and contain the following lines in its `build.rs`:
//! The static libraries of the kernels implementations are required only if your model uses them, and they should be
//! **linked manually** by the binary that uses the `executorch` crate.
//! For example, the `hello_world_add` example uses a model with a single addition operation, so it compile the C++
//! library with `DEXECUTORCH_SELECT_OPS_LIST=aten::add.out` and contain the following lines in its `build.rs`:
//! ```rust
//! println!("cargo::rustc-link-lib=static=portable_kernels");
//! println!("cargo::rustc-link-lib=static:+whole-archive=portable_kernels");
//! println!("cargo::rustc-link-lib=static:+whole-archive=portable_ops_lib");
//!
//! let libs_dir = std::env::var("EXECUTORCH_RS_EXECUTORCH_LIB_DIR").unwrap();
//! println!("cargo::rustc-link-search={}/kernels/portable/", libs_dir);
//! ```
//! Note that the `portable_ops_lib` is linked with `+whole-archive` to ensure that all symbols are included in the binary.
//! Note that the ops and kernels libs are linked with `+whole-archive` to ensure that all symbols are included in the
//! binary.
//!
//! ## Cargo Features
//! By default all features are disabled.
//! - `data-loader`: include the `FileDataLoader` struct. The `libextension_data_loader.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON`.
//! - `module`: include the `Module` struct. The `libextension_module_static.a` static library is required, compile C++ `executorch` with `EXECUTORCH_BUILD_EXTENSION_MODULE=ON`.
//! - `data-loader`: Includes the `FileDataLoader` and `MmapDataLoader` structs. Without this feature the only available
//! data loader is `BufferDataLoader`. The `libextension_data_loader.a` static library is required, compile C++
//! `executorch` with `EXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON`.
//! - `module`: Includes the `Module` struct. The `libextension_module_static.a` static library is required, compile C++
//! `executorch` with `EXECUTORCH_BUILD_EXTENSION_MODULE=ON`.

#![cfg_attr(not(feature = "std"), no_std)]

Expand Down
9 changes: 9 additions & 0 deletions scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake
pyyaml
setuptools>=63
tomli
wheel
zstd
torch==2.4.0
# torchvision==0.19.0
# torchaudio==2.4.0
57 changes: 31 additions & 26 deletions scripts/setup_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ def main():
action="store_true",
help="Remove the existing executorch directory before cloning",
)
parser.add_argument(
"--skip-executorch-python",
action="store_true",
help="Remove the existing executorch directory before cloning",
)
args = parser.parse_args()

if args.clean:
Expand All @@ -28,23 +33,19 @@ def main():
# TODO setup a venv here

clone_executorch()

# subprocess.check_call(["./install_requirements.sh"], cwd=DEV_EXECUTORCH_DIR)
subprocess.check_call(
[
"pip",
"install",
if not args.skip_executorch_python:
subprocess.check_call(["./install_requirements.sh"], cwd=DEV_EXECUTORCH_DIR)
else:
deps = [
"cmake",
"pyyaml",
"setuptools>=63",
"tomli",
"wheel",
"zstd",
"torch==2.4.0",
]
)

build_executorch()
subprocess.check_call([get_pip(), "install", *deps])
build_executorch_with_dev_cfg()


def clone_executorch():
Expand All @@ -70,23 +71,12 @@ def clone_executorch():
subprocess.check_call(
["git", "submodule", "update", "--init"], cwd=DEV_EXECUTORCH_DIR
)
# git submodule update --init backends/xnnpack/third-party/cpuinfo
# git submodule update --init backends/xnnpack/third-party/pthreadpool
# git submodule update --init third-party/prelude
# git submodule update --init third-party/gflags
# git submodule update --init third-party/googletest
# git submodule update --init third-party/flatbuffers
# git submodule update --init third-party/flatcc
# git submodule update --init backends/xnnpack/third-party/XNNPACK
# git submodule update --init backends/xnnpack/third-party/FXdiv
# git submodule update --init third-party/pytorch


def build_executorch():


def build_executorch_with_dev_cfg():
cmake_out_dir = DEV_EXECUTORCH_DIR / "cmake-out"
if cmake_out_dir.exists():
shutil.rmtree(cmake_out_dir)
cmake_out_dir.mkdir()
if not cmake_out_dir.exists():
cmake_out_dir.mkdir()
subprocess.check_call(
[
"cmake",
Expand All @@ -110,5 +100,20 @@ def build_executorch():
)


def get_pip():
try:
subprocess.run(['pip3', '--version'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return 'pip3'
except (subprocess.CalledProcessError, FileNotFoundError):
pass

try:
subprocess.run(['pip', '--version'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return 'pip'
except (subprocess.CalledProcessError, FileNotFoundError):
pass

raise RuntimeError("Neither 'pip3' nor 'pip' is installed on this system.")

if __name__ == "__main__":
main()
60 changes: 30 additions & 30 deletions src/data_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,53 @@
//! To include the data loader functionality, enable the `data-loader` feature.

use std::cell::UnsafeCell;
use std::marker::PhantomData;

use crate::et_c;
use crate::{et_c, et_rs_c};

/// Loads from a data source.
///
/// This struct is like a base class for data loaders. All other data loaders implement `AsRef<DataLoader>` and other
/// structs, such as `Program`, take a reference to `DataLoader` instead of the concrete data loader type.
pub struct DataLoader(pub(crate) UnsafeCell<et_c::DataLoader>);

/// A DataLoader that wraps a pre-allocated buffer. The FreeableBuffers
/// that it returns do not actually free any data.
///
/// This can be used to wrap data that is directly embedded into the firmware
/// image, or to wrap data that was allocated elsewhere.
#[allow(dead_code)]
pub struct BufferDataLoader<'a>(
UnsafeCell<et_c::util::BufferDataLoader>,
PhantomData<&'a ()>,
);
impl<'a> BufferDataLoader<'a> {
/// Creates a new BufferDataLoader that wraps the given data.
pub fn new(data: &'a [u8]) -> Self {
let loader =
unsafe { et_rs_c::BufferDataLoader_new(data.as_ptr() as *const _, data.len()) };
Self(UnsafeCell::new(loader), PhantomData)
}
}
impl AsRef<DataLoader> for BufferDataLoader<'_> {
fn as_ref(&self) -> &DataLoader {
// SAFETY: BufferDataLoader has a single field of (UnsafeCell of) et_c::util::BufferDataLoader, which is a
// subclass of et_c::DataLoader, and DataLoaders has a single field of (UnsafeCell of) et_c::DataLoader.
unsafe { std::mem::transmute::<&BufferDataLoader, &DataLoader>(self) }
}
}

#[cfg(feature = "data-loader")]
pub use file_data_loader::{BufferDataLoader, FileDataLoader, MlockConfig, MmapDataLoader};
pub use file_data_loader::{FileDataLoader, MlockConfig, MmapDataLoader};

#[cfg(feature = "data-loader")]
mod file_data_loader {
use std::cell::UnsafeCell;
use std::ffi::CStr;
use std::marker::PhantomData;

use crate::error::Result;
use crate::et_c;
use crate::util::IntoRust;
use crate::{et_c, et_rs_c};

use super::DataLoader;

Expand Down Expand Up @@ -182,32 +208,6 @@ mod file_data_loader {
}
}

/// A DataLoader that wraps a pre-allocated buffer. The FreeableBuffers
/// that it returns do not actually free any data.
///
/// This can be used to wrap data that is directly embedded into the firmware
/// image, or to wrap data that was allocated elsewhere.
#[allow(dead_code)]
pub struct BufferDataLoader<'a>(
UnsafeCell<et_c::util::BufferDataLoader>,
PhantomData<&'a ()>,
);
impl<'a> BufferDataLoader<'a> {
/// Creates a new BufferDataLoader that wraps the given data.
pub fn new(data: &'a [u8]) -> Self {
let loader =
unsafe { et_rs_c::BufferDataLoader_new(data.as_ptr() as *const _, data.len()) };
Self(UnsafeCell::new(loader), PhantomData)
}
}
impl AsRef<DataLoader> for BufferDataLoader<'_> {
fn as_ref(&self) -> &DataLoader {
// SAFETY: BufferDataLoader has a single field of (UnsafeCell of) et_c::util::BufferDataLoader, which is a
// subclass of et_c::DataLoader, and DataLoaders has a single field of (UnsafeCell of) et_c::DataLoader.
unsafe { std::mem::transmute::<&BufferDataLoader, &DataLoader>(self) }
}
}

/// Describes how and whether to lock loaded pages with `mlock()`.
///
/// Using `mlock()` typically loads all of the pages immediately, and will
Expand Down
Loading