Skip to content

Commit

Permalink
Adding pipeline for onnx -> secfloat backend via OnnxBridge. (#158)
Browse files Browse the repository at this point in the history
* added onnx-fzpc

* compile script updated

* executable parameter

* added leaky relu

* fixed reshape issue

* bugfix

* input statement added

* for debug

* for debug

* bugs removed, lenet working

* lenet worked helper files added

* check script

* comment

* readme added

* update

* Chunk Size optional command line arg

* readme updated

* gemm modified and chunksize for secfloat commandline

* demo-onnx-fzpc

* update

* mnist model working notable changes

* replace image

* padding done

* padding done

* update readme

* readme update

* update

* update

* sigmoid added

* sigmoid added

* demo image update

* Tanh added

* minor bug

* dependencies updated

* add node step added

* Refractor

* cleartext-secfloat added

* referencing fixed

* readme updated

* update

* update

* update

* added dependency
  • Loading branch information
drunkenlegend authored Jan 12, 2023
1 parent 8b4d2ff commit b4fbd44
Show file tree
Hide file tree
Showing 44 changed files with 24,283 additions and 985 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Build Directory
build/
bin/

mpc_venv
# Vim c_tags files
c_*
SEAL
9 changes: 9 additions & 0 deletions OnnxBridge/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*.onnx
*.txt
*.inp
*.cpp
*.out
*.outp
.DS_Store
.idea/
__pycache__
187 changes: 187 additions & 0 deletions OnnxBridge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# OnnxBridge
An end-to-end compiler for converting Onnx Models to Secure Floating Point backend(SecFloat).
- [Setup](#setup)
- [Usage](#usage)
- [Supported Nodes](#supported-nodes)
- [Add Support for Node](#add-support-for-nodes)

## Setup
If you used the `setup_env_and_build.sh` script the below would already have been installed in the `mpc_venv` environment. We require the below packages to run OnnxBridge.
- onnx==1.12.0
- onnxruntime==1.12.1
- onnxsim==0.4.8
- numpy==1.21.0
- protobuf==3.20.1

Above dependencies can be installed using the `requirements.txt` file as below:
```bash
pip3 install -r requirements.txt
```

#### Along with this SecFloat Backend also need to be build for OnnxBridge to work. Follow the steps from `../SCI/` to build SecFloat.

## Usage

### Generate Binaries:
To compile an onnx file to SecFloat backend, use the below command:
```bash
cd OnnxBridge
python3 main.py --path "/path/to/onnx-file" --generate "code" --backend SECFLOAT
```

To compile SecFloat Code generated from above step and get executable use:
```bash
Secfloat/compile_secfloat.sh "/path/to/file.cpp"
```

---
### To directly generate executable from Onnx File use:
```bash
cd OnnxBridge
python3 main.py --path "/path/to/onnx-file" --generate "executable" --backend SECFLOAT
```
---
### Run Inference:
To run secure inference on networks:

```bash
./<network> r=2 [port=port] [chunk=chunk] < <model_weights_file> // Server
./<network> r=1 [add=server_address] [port=port] [chunk=chunk] < <image_file> // Client
```

### To do the same using cleartext:
```bash
cd OnnxBridge
python3 main.py --path "/path/to/onnx-file" --generate ["executable"/"code"] --backend [SECFLOAT/SECFLOAT_CLEARTEXT]
cat input_input.inp model_input_weights_.inp | ./model_secfloat_ct
```

## Supported Nodes
- Conv
- Relu
- Sigmoid
- Tanh
- Softmax
- MaxPool
- AveragePool
- Concat
- BatchNormalization
- GlobalAveragePool
- Flatten
- Reshape
- Gemm

## Add Support for Nodes
#### Follow below steps to add support for any new node:
#### For example we will consider `"Tanh"` node:
1. Implement the Node in OnnxBridge/Secfloat/lib_secfloat/link_secfloat.cpp` using secfloat backend as follows:
```cpp
// tanh(x) = 2 * sigmoid(2 * x) - 1
void Tanh(int32_t s1, vector<FPArray> &inArr, vector<FPArray> &outArr){

const FPArray one = __public_float_to_baba(1.0, ALICE);
const FPArray two = __public_float_to_baba(2.0, ALICE);

// 2 * x
auto twice_input = make_vector_float(ALICE, s1);
for(int i=0; i<s1; i++){
twice_input[i] = Mul(inArr[i],two);
}

// sigmoid(2 * x)
auto sigmoid_twice_input = make_vector_float(ALICE, s1);
Sigmoid(s1, twice_input, sigmoid_twice_input);


// tanh(x) = 2 * sigmoid(2 * x) - 1
for(int i=0; i<s1; i++){
outArr[i] = Mul(two , sigmoid_twice_input[i]);
outArr[i] = __fp_op->sub(outArr[i], one);
}

}// The operators used can be found in SCI/src/FloatingPoint/floating-point.cpp and SCI/src/library_float.h
```
Above implementation is for 1D FPArray, for multidimentional array its recommended to overload the Tanh function to receive multidimentional array which is then reshaped to 1D array and 1D Tanh implementation is called as below:
```cpp
void Tanh(int32_t s1, int32_t s2, auto &inArr, auto &outArr)
{
int32_t size = (s1 * s2);
auto reshapedInArr = make_vector_float(ALICE, size);
auto reshapedOutArr = make_vector_float(ALICE, size);
for (uint32_t i1 = 0; i1 < s1; i1++)
{
for (uint32_t i2 = 0; i2 < s2; i2++)
{
int32_t linIdx = ((i1 * s2) + i2);
reshapedInArr[linIdx] = inArr[i1][i2];
}
}
Tanh(size, reshapedInArr, reshapedOutArr);
for (uint32_t i1 = 0; i1 < s1; i1++)
{
for (uint32_t i2 = 0; i2 < s2; i2++)
{
int32_t linIdx = ((i1 * s2) + i2);
outArr[i1][i2] = reshapedOutArr[linIdx];
}
}
}
```
This completes the node implementation in backend.


2. Add assertions for node in class `OnnxNode` inside in OnnxBridge/utils/onnx_nodes.py` for various attributes.
```python
@classmethod
def Tanh(cls, node):
assert len(node.inputs) == 1
assert len(node.outputs) == 1
# we can print the node at this step and get info on all node parameters
# additionaly based on your node implementation add assertions or modification on node attributes.
logger.debug("Tanh is OK!")
```
3. Add format for Function Prototype in class `Operator` in OnnxBridge/Secfloat/func_calls.py` for the node as implemented in step-1.
```python
@classmethod
def Tanh(cls, attributes, inputs, outputs, value_info, var_dict, indent):
# :param var_dict: Variable Dictionary {actual variable name}->(used variable name).
# :param value_info: Dictionary {var}->(data-type,shape).
# :param indent: To give indentation to cpp code generated.
logger.debug("Inside Tanh function call.")
cmmnt = comment("Call Tanh(shape,input,output)\n", indent)
return str(
cmmnt + f"{' ' * indent}Tanh("
f"{iterate_list(value_info[inputs[0]][1])}, "
f"{iterate_list([var_dict[x] for x in inputs])}, "
f"{iterate_list([var_dict[x] for x in outputs])}"
f");"
)
```
4. Lastly add node name i.e "Tanh" to the `implemented` list in function `is_compatible` inside class `FzpcBackend` located in `Onnx-FzPC/backend.py`.
```python
implemented = [
"Relu",
"Sigmoid",
"Softmax",
"Conv",
"MaxPool",
"Concat",
"BatchNormalization",
"AveragePool",
"GlobalAveragePool",
"Flatten",
"Reshape",
"Gemm",
"Tanh"
]
```

## Demo
Follow [Demo](Secfloat/demo/Readme.md) for OnnxBridge demo with Secfloat.


Loading

0 comments on commit b4fbd44

Please sign in to comment.