Skip to content

Commit

Permalink
adding basic example
Browse files Browse the repository at this point in the history
  • Loading branch information
ajaybati committed Apr 10, 2023
1 parent b974480 commit 4952d20
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 28 deletions.
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,34 @@ We have minimal dependencies.
For example, on MacOS you can get away with just
```
brew install wget make cmake coreutils gcc
pip install torch onnx numpy fypp onnxruntime
pip install torch onnx numpy fypp onnxruntime pandas
```
## Basic Example
Here is a quick example of how **roseNNa** works. With just a few steps, you can see how to convert a basic feed-forward neural network originally built with PyTorch into usable, accurate code in Fortran.

First `cd` into the `fLibrary/` directory.

``` bash
#file to create pytorch model and convert to ONNX
python3 ../goldenFiles/gemm_small/gemm_small.py
```
``` bash
#read and interpret the correspoding output files from last step
python3 modelParserONNX.py -w ../goldenFiles/gemm_samll/gemm_small.onnx -f ../goldenFiles/gemm_samll/gemm_small_weights.onnx
```
``` bash
#compile the library
make library
```
``` bash
#compile "source files" (capiTester.f90), link to the library file created, and run
gfortran -c ../examples/capiTester.f90 -IobjFiles/
gfortran -o flibrary libcorelib.a capiTester.o
./flibrary
```
``` bash
#check whether python output from PyTorch model = roseNNa's output
python3 ../test/testChecker.py
```

## Compiling roseNNa
Expand Down
3 changes: 3 additions & 0 deletions examples/capiTester.f90
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ program name

CALL use_model(inputs, output)

open(1, file = "test.txt")
WRITE(1, *) SHAPE(output)
WRITE(1, *) PACK(RESHAPE(output,(/SIZE(output, dim = 2), SIZE(output, dim = 1)/), order = [2, 1]),.true.)
print *, output

end program name
6 changes: 3 additions & 3 deletions fLibrary/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ output: $(COMP) $(OBJ2)
$(FC) $(FFLAGS) -c $< -o $@


preprocess: modelParserONNX.py
#preprocess: modelParserONNX.py
# arg1 = model structure file (.onnx format)
# arg2 (optional) = weights file (.onnx format)
python3 modelParserONNX.py -f $(args)
#python3 modelParserONNX.py -f $(args)

#for *.mod and *.o files
mkdir -p objFiles

library: output
mkdir -p objFiles
ar crv libcorelib.a $(COMP) $(OBJ2)

clean:
Expand Down
23 changes: 11 additions & 12 deletions fLibrary/reader.f90
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ module reader
INTEGER :: readOrNot

contains

subroutine initialize() bind(c,name="initialize") !add arguments for location of onnxModel.txt and onnxWeights.txt
INTEGER :: Reason
CHARACTER(len = 10), ALLOCATABLE, DIMENSION(:) :: name
Expand All @@ -50,7 +50,7 @@ subroutine initialize() bind(c,name="initialize") !add arguments for location of
open(11, file = "onnxWeights.txt")

read(10, *) numLayers

readloop: DO i = 1, numLayers
read(10, *, IOSTAT=Reason) layerName
if (Reason < 0) then
Expand Down Expand Up @@ -93,7 +93,7 @@ subroutine initialize() bind(c,name="initialize") !add arguments for location of
end if



END DO readloop

end subroutine
Expand Down Expand Up @@ -185,16 +185,16 @@ subroutine read_conv(file1, file2)
read(file2, *) largeWeights
conv(1)%weights = largeWeights
DEALLOCATE(largeWeights)





read(file1, *) w_dim1
ALLOCATE(biases(w_dim1))
read(file2, *) biases
conv(1)%biases = biases
DEALLOCATE(biases)


convLayers = [convLayers, conv]

DEALLOCATE(conv)
Expand All @@ -211,13 +211,13 @@ subroutine read_lstm(file1, file2, readOrNot)
read(file2, *) midWeights
lstm(1)%wih = midWeights
DEALLOCATE(midWeights)

read(file1, *) w_dim1, w_dim2, w_dim3
ALLOCATE(midWeights(w_dim1,w_dim2,w_dim3))
read(file2, *) midWeights
lstm(1)%whh = midWeights
DEALLOCATE(midWeights)


read(file1, *) w_dim1
ALLOCATE(biases(w_dim1))
Expand All @@ -230,7 +230,7 @@ subroutine read_lstm(file1, file2, readOrNot)
read(file2, *) biases
lstm(1)%bhh = biases
DEALLOCATE(biases)

if (readOrNot .eq. 1) then
read(file1, *) w_dim1, w_dim2, w_dim3
ALLOCATE(midWeights(w_dim1,w_dim2,w_dim3))
Expand All @@ -244,7 +244,7 @@ subroutine read_lstm(file1, file2, readOrNot)
lstm(1)%cell = midWeights
DEALLOCATE(midWeights)
endif



lstmLayers = [lstmLayers, lstm]
Expand Down Expand Up @@ -287,6 +287,5 @@ subroutine read_linear(file1, file2)
end subroutine



end module

end module
28 changes: 18 additions & 10 deletions goldenFiles/gemm_small/gemm_small.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
import os
import timeit
import numpy as np
import pathlib
import sys, getopt

opts, args = getopt.getopt(sys.argv[1:],"n")
produce = True
for opt, _ in opts:
if opt == "-n":
produce = False
class NN(nn.Module):
def __init__(self):
super(NN, self).__init__()
Expand All @@ -30,16 +38,16 @@ def forward(self, inp):

model = NN()
inp = torch.ones(1,2)

with open("inputs.fpp",'w') as f:
inputs = inp.flatten().tolist()
inpShapeDict = {'inputs': list(inp.shape)}
inpDict = {'inputs':inputs}
f.write(f"""#:set inpShape = {inpShapeDict}""")
f.write("\n")
f.write(f"""#:set arrs = {inpDict}""")
f.write("\n")
f.write("a")
if produce:
with open("inputs.fpp",'w') as f:
inputs = inp.flatten().tolist()
inpShapeDict = {'inputs': list(inp.shape)}
inpDict = {'inputs':inputs}
f.write(f"""#:set inpShape = {inpShapeDict}""")
f.write("\n")
f.write(f"""#:set arrs = {inpDict}""")
f.write("\n")
f.write("a")

def stringer(mat):
s = ""
Expand Down
4 changes: 2 additions & 2 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ capi: capi.c modelCreator.o
./capi

ex1: $(DIR)/modelParserONNX.py
python3 $(MAIN)/goldenFiles/$(case)/$(case).py
python3 $(DIR)/modelParserONNX.py -f $(MAIN)/goldenFiles/$(case)/$(case).onnx -w $(MAIN)/goldenFiles/$(case)/$(case)_weights.onnx -i $(MAIN)/goldenFiles/$(case)/$(case)_inferred.onnx 1>/dev/null
python3 $(MAIN)goldenFiles/$(case)/$(case).py
python3 $(DIR)/modelParserONNX.py -f $(MAIN)goldenFiles/$(case)/$(case).onnx -w $(MAIN)goldenFiles/$(case)/$(case)_weights.onnx -i $(MAIN)goldenFiles/$(case)/$(case)_inferred.onnx 1>/dev/null


graphs: output
Expand Down

0 comments on commit 4952d20

Please sign in to comment.