Skip to content
Snippets Groups Projects
Commit 67f2d20a authored by Cyril Moineau's avatar Cyril Moineau
Browse files

Update export with new ExportNode refactoring.

parent 9b5a4e86
No related branches found
No related tags found
3 merge requests!27v0.2.0,!22v0.4.0,!15Export refactor
Showing
with 254 additions and 279 deletions
...@@ -35,7 +35,7 @@ def generate_input_file(export_folder:str, ...@@ -35,7 +35,7 @@ def generate_input_file(export_folder:str,
) )
def export(export_folder_name, graphview, scheduler): def export(export_folder_name, graphview, scheduler, mem_wrapping=False):
export_folder = Path().absolute() / export_folder_name export_folder = Path().absolute() / export_folder_name
...@@ -62,6 +62,9 @@ def export(export_folder_name, graphview, scheduler): ...@@ -62,6 +62,9 @@ def export(export_folder_name, graphview, scheduler):
raise RuntimeError(f"Operator not supported: {node.type()} !") raise RuntimeError(f"Operator not supported: {node.type()} !")
# Memory management # Memory management
# stats_folder = export_folder / "statistics"
# os.makedirs(str(stats_folder), exist_ok=True)
# mem_size, mem_info = generate_optimized_memory_info(stats_folder, scheduler, mem_wrapping)
mem_size, mem_info = compute_default_mem_info(scheduler) mem_size, mem_info = compute_default_mem_info(scheduler)
# Generate the memory file # Generate the memory file
...@@ -94,7 +97,7 @@ def export(export_folder_name, graphview, scheduler): ...@@ -94,7 +97,7 @@ def export(export_folder_name, graphview, scheduler):
for node in graphview.get_nodes(): for node in graphview.get_nodes():
if len(node.get_children()) == 0: if len(node.get_children()) == 0:
export_type = aidge2c(node.get_operator().get_output(0).dtype()) export_type = aidge2c(node.get_operator().get_output(0).dtype())
list_outputs_name.append((export_type, node.name())) list_outputs_name.append((export_type, f"{node.name()}_output_0"))
# Generate forward file # Generate forward file
generate_file( generate_file(
......
import os
import shutil
from typing import List
from pathlib import Path
import aidge_core import aidge_core
import aidge_backend_cpu import aidge_backend_cpu
from typing import List
# for each layer, name: [size, offset start] # for each layer,
# name [size, stride, length, count, contigious offset, contigious size, wrapping offset, wrapping size]
# true values [nb_outputs, nb_outputs, width, width, offset start, total size, 0, 0]
# Example:
#define ENV_MEM_SIZE 3
#define ENV_MEM_STRIDE 3
#define ENV_MEM_LENGTH 224
#define ENV_MEM_COUNT 224
#define ENV_MEM_CONT_OFFSET 0
#define ENV_MEM_CONT_SIZE 150528
#define ENV_MEM_WRAP_OFFSET 0
#define ENV_MEM_WRAP_SIZE 0
# MEMORY_INFO_TEMPLATE = ["layer_name", "size", "offset", "stride", "length", "count", "cont_offset", "cont_size", "wrap_offset", "wrap_size"]
# for each layer, name: [size, offset start] (old style)
# Example: # Example:
#define ENV_MEM_SIZE 3 #define ENV_MEM_SIZE 3
#define ENV_OFFSET 0 #define ENV_OFFSET 0
...@@ -11,7 +28,7 @@ MEMORY_INFO_TEMPLATE = ["layer_name", "size", "offset"] ...@@ -11,7 +28,7 @@ MEMORY_INFO_TEMPLATE = ["layer_name", "size", "offset"]
# Default memory management, which can be used for development # Default memory management, which can be used for development
def compute_default_mem_info(scheduler: aidge_core.Scheduler): def compute_default_mem_info(scheduler: aidge_core.Scheduler):
list_forward_nodes = scheduler.get_static_scheduling() list_forward_nodes = scheduler.get_static_scheduling()
mem_info = [] mem_info = []
mem_size = 0 mem_size = 0
...@@ -27,23 +44,83 @@ def compute_default_mem_info(scheduler: aidge_core.Scheduler): ...@@ -27,23 +44,83 @@ def compute_default_mem_info(scheduler: aidge_core.Scheduler):
# Add memeory info # Add memeory info
mem_info.append([node.name(), mem, mem_size]) mem_info.append([node.name(), mem, mem_size])
# Increment offset for the next layer # Increment offset for the next layer
mem_size += mem mem_size += mem
return mem_size, mem_info return mem_size, mem_info
def generate_optimized_memory_info(scheduler: aidge_core.Scheduler, def generate_optimized_memory_info(stats_folder: Path,
scheduler: aidge_core.Scheduler,
wrapping:bool = False): wrapping:bool = False):
# The forward dims has to done outside the function
# The forward dims has to done outside the function
# Also supposed the generation of the scheduler has been performed outside
# Otherwise decomment the following line
# scheduler.generate_scheduling()
# Generate the memory manager # Generate the memory manager
# So far, the Producers are not take in consideration in the meory manager => inc_producers=False
mem_manager = scheduler.generate_memory(inc_producers=False, wrap_around_buffer=wrapping) mem_manager = scheduler.generate_memory(inc_producers=False, wrap_around_buffer=wrapping)
mem_size = 0 # List of nodes which are connected at the input of the graph (None if input is not connected)
nodes_at_input = [n[0] for n in scheduler.graph_view().inputs()]
# Use gnuplot to generate the log
try:
os.makedirs(str(stats_folder / "graph"), exist_ok=True)
mem_manager.log("memory_info")
os.chmod("memory_info_plot.gnu", 0o777)
os.system("./memory_info_plot.gnu")
shutil.move("memory_info", str(stats_folder / "graph"/ "memory_info"))
shutil.move("memory_info_plot.png", str(stats_folder / "graph" / "memory_info_plot.png"))
os.remove("memory_info_plot.gnu")
except:
print("Please install gnuplot if you want memory plot from MemoryManager.")
# In the export, we currently use an unified memory buffer whose size
# is determined by the memory peak usage
mem_size = mem_manager.get_peak_usage()
mem_info = [] mem_info = []
mem_planes = mem_manager.get_planes()
for node in scheduler.get_static_scheduling():
if node.type() == "Producer":
continue # Skipping memory management for producers
if node in nodes_at_input:
# Input memory management (suppose tensor ends with [:, channel, height, width]))
tensor = node.get_operator().get_output(0)
if tensor is None:
raise RuntimeError("Warning input producer not provided")
if len(tensor.dims()) < 3:
raise RuntimeError(f"Input producer dimensions must be with [:, channel, height, width] but got {tensor.dims()} instead")
return mem_size, mem_info name = node.name()
\ No newline at end of file offset = 0 # Suppose input data is stored outside the export function
# so the memory offset is not important to consider
size = tensor.dims()[-3] # Should be nb_channels
stride = tensor.dims()[-3] # Should be nb_channels
length = tensor.dims()[-1] # Should be width
count = tensor.dims()[-2] # Should be height
cont_offset = 0 # Suppose input data is stored outside the export function
# so the memory offset is not important to consider
cont_size = tensor.dims()[-1] * tensor.dims()[-2] * tensor.dims()[-3] # Size of input
wrap_offset = 0 # No wrapping
wrap_size = 0 # No wrapping
else:
plane = mem_planes[node][0]
name = node.name()
offset = plane.offset
size = plane.size
stride = plane.stride
length = plane.length
count = plane.count
cont_offset = plane.get_contiguous_offset()
cont_size = plane.get_contiguous_size()
wrap_offset = plane.get_wrapped_offset()
wrap_size = plane.get_wrapped_size()
mem_info.append([name, size, offset, stride, length, count,
cont_offset, cont_size, wrap_offset, wrap_size])
return mem_size, mem_info
...@@ -53,14 +53,6 @@ def export_params(name:str, ...@@ -53,14 +53,6 @@ def export_params(name:str,
) )
##############################################
################### Actions ##################
##############################################
def set_up_output(name, datatype):
return f"{datatype}* {name} = ({datatype}*) mem + {name.upper()}_OFFSET;"
############################################## ##############################################
############## Operators helper ############## ############## Operators helper ##############
############################################## ##############################################
...@@ -71,7 +63,6 @@ class ProducerCPP(ExportNode): ...@@ -71,7 +63,6 @@ class ProducerCPP(ExportNode):
def __init__(self, node): def __init__(self, node):
super().__init__(node) super().__init__(node)
self.constant = self.operator.attr.constant
self.values = np.array(self.operator.get_output(0)) self.values = np.array(self.operator.get_output(0))
if len(self.values.shape) == 4: # Note: export in HWC if len(self.values.shape) == 4: # Note: export in HWC
...@@ -79,11 +70,11 @@ class ProducerCPP(ExportNode): ...@@ -79,11 +70,11 @@ class ProducerCPP(ExportNode):
def export(self, export_folder:Path, list_configs:list): def export(self, export_folder:Path, list_configs:list):
list_configs.append(f"parameters/{self.name}.h") list_configs.append(f"parameters/{self.attributes['name']}.h")
export_params( export_params(
self.name, self.attributes['out_name'][0],
self.values.reshape(-1), self.values.reshape(-1),
str(export_folder / "parameters" / f"{self.name}.h")) str(export_folder / "parameters" / f"{self.attributes['name']}.h"))
return list_configs return list_configs
...@@ -97,9 +88,6 @@ class ReLUCPP(ExportNode): ...@@ -97,9 +88,6 @@ class ReLUCPP(ExportNode):
def __init__(self, node): def __init__(self, node):
super().__init__(node) super().__init__(node)
self.nb_data = 1
for i in self.inputs_dims[0]:
self.nb_data *= i
def export(self, export_folder:Path, list_configs:list): def export(self, export_folder:Path, list_configs:list):
...@@ -107,27 +95,22 @@ class ReLUCPP(ExportNode): ...@@ -107,27 +95,22 @@ class ReLUCPP(ExportNode):
str(export_folder / "include" / "kernels")) str(export_folder / "include" / "kernels"))
list_configs.append("kernels/activation.hpp") list_configs.append("kernels/activation.hpp")
list_configs.append(f"layers/{self.name}.h") list_configs.append(f"layers/{self.attributes['name']}.h")
generate_file( generate_file(
str(export_folder / "layers" / f"{self.name}.h"), str(export_folder / "layers" / f"{self.attributes['name']}.h"),
str(ROOT / "templates" / "configuration" / "activation_config.jinja"), str(ROOT / "templates" / "configuration" / "activation_config.jinja"),
name=self.name,
nb_data=self.nb_data,
activation="Rectifier", activation="Rectifier",
rescaling="NoScaling") rescaling="NoScaling",
**self.attributes
)
return list_configs return list_configs
def forward(self, list_actions:list): def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_str( list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "activation_forward.jinja"), str(ROOT / "templates" / "kernel_forward" / "activation_forward.jinja"),
name=self.name, **self.attributes
input_name=f"{self.name}_input" if self.inputs[0] is None else self.inputs[0].name(),
output_name=self.name
)) ))
return list_actions return list_actions
...@@ -137,26 +120,17 @@ class ConvCPP(ExportNode): ...@@ -137,26 +120,17 @@ class ConvCPP(ExportNode):
def __init__(self, node): def __init__(self, node):
super().__init__(node) super().__init__(node)
self.kernel = node.get_operator().attr.kernel_dims # self.kernel = node.get_operator().attr.kernel_dims
self.stride = node.get_operator().attr.stride_dims # self.stride = node.get_operator().attr.stride_dims
self.dilation = node.get_operator().attr.dilation_dims # self.dilation = node.get_operator().attr.dilation_dims
# No padding with Conv # No padding with Conv
# Use PaddedConv to add padding attribute # Use PaddedConv to add padding attribute
self.padding = [0, 0] self.attributes["padding"] = [0, 0]
self.nb_channels = node.get_operator().in_channels() # self.nb_channels = node.get_operator().in_channels()
self.nb_outputs = node.get_operator().out_channels() # self.nb_outputs = node.get_operator().out_channels()
if len(self.inputs_dims[0]) == 4:
# if dims == [batch, nb_channels, height, width]
# transform to [nb_channels, height, width]
self.inputs_dims[0] = self.inputs_dims[0][1:]
if len(self.outputs_dims[0]) == 4:
# if dims == [batch, nb_outputs]
# transform to [nb_outputs, 1, 1]
self.outputs_dims[0] = self.outputs_dims[0][1:]
def export(self, export_folder:Path, list_configs:list): def export(self, export_folder:Path, list_configs:list):
...@@ -168,33 +142,21 @@ class ConvCPP(ExportNode): ...@@ -168,33 +142,21 @@ class ConvCPP(ExportNode):
str(export_folder / "include" / "kernels")) str(export_folder / "include" / "kernels"))
list_configs.append("kernels/convolution.hpp") list_configs.append("kernels/convolution.hpp")
list_configs.append(f"layers/{self.name}.h") list_configs.append(f"layers/{self.attributes['name']}.h")
generate_file( generate_file(
str(export_folder / "layers" / f"{self.name}.h"), str(export_folder / "layers" / f"{self.attributes['name']}.h"),
str(ROOT / "templates" / "configuration" / "convolution_config.jinja"), str(ROOT / "templates" / "configuration" / "convolution_config.jinja"),
name=self.name,
input_dims=self.inputs_dims[0],
output_dims=self.outputs_dims[0],
kernel=self.kernel,
stride=self.stride,
padding=self.padding,
dilation=self.dilation,
activation="Linear", activation="Linear",
rescaling="NoScaling") rescaling="NoScaling",
**self.attributes,
)
return list_configs return list_configs
def forward(self, list_actions:list): def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_str( list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "convolution_forward.jinja"), str(ROOT / "templates" / "kernel_forward" / "convolution_forward.jinja"),
name=self.name, **self.attributes
input_name=f"{self.name}_input_0" if self.inputs[0] is None else self.inputs[0].name(),
output_name=self.name,
weights_name=f"{self.name}_input_1" if self.inputs[1] is None else self.inputs[1].name(),
biases_name=f"{self.name}_input_2" if self.inputs[2] is None else self.inputs[2].name()
)) ))
return list_actions return list_actions
...@@ -204,23 +166,14 @@ class PaddedConvCPP(ConvCPP): ...@@ -204,23 +166,14 @@ class PaddedConvCPP(ConvCPP):
def __init__(self, node): def __init__(self, node):
ExportNode.__init__(self, node) ExportNode.__init__(self, node)
# TODO find a way to retrive attr for meta op
for n in self.operator.get_micro_graph().get_nodes(): for n in self.operator.get_micro_graph().get_nodes():
if n.type() == "Pad": if n.type() == "Pad":
self.padding = n.get_operator().attr.begin_end_borders self.attributes["padding"] = n.get_operator().attr.begin_end_borders
if n.type() == "Conv": if n.type() == "Conv":
self.kernel = n.get_operator().attr.kernel_dims self.attributes["kernel_dims"] = n.get_operator().attr.kernel_dims
self.stride = n.get_operator().attr.stride_dims self.attributes["stride_dims"] = n.get_operator().attr.stride_dims
self.dilation = n.get_operator().attr.dilation_dims self.attributes["dilation_dims"] = n.get_operator().attr.dilation_dims
if len(self.inputs_dims[0]) == 4:
# if dims == [batch, nb_channels, height, width]
# transform to [nb_channels, height, width]
self.inputs_dims[0] = self.inputs_dims[0][1:]
if len(self.outputs_dims[0]) == 4:
# if dims == [batch, nb_outputs]
# transform to [nb_outputs, 1, 1]
self.outputs_dims[0] = self.outputs_dims[0][1:]
@operator_register("Add") @operator_register("Add")
class AddCPP(ExportNode): class AddCPP(ExportNode):
...@@ -228,32 +181,26 @@ class AddCPP(ExportNode): ...@@ -228,32 +181,26 @@ class AddCPP(ExportNode):
super().__init__(node) super().__init__(node)
def export(self, export_folder:str, list_configs:list): def export(self, export_folder:str, list_configs:list):
list_configs.append(f"layers/{self.name}.h") list_configs.append(f"layers/{self.attributes['name']}.h")
list_configs.append("kernels/elemwise.hpp") list_configs.append("kernels/elemwise.hpp")
copyfile(str(ROOT / "kernels" / "elemwise.hpp"), copyfile(str(ROOT / "kernels" / "elemwise.hpp"),
str(export_folder / "include" / "kernels")) str(export_folder / "include" / "kernels"))
generate_file( generate_file(
str(export_folder / "layers" / f"{self.name}.h"), str(export_folder / "layers" / f"{self.attributes['name']}.h"),
str(ROOT / "templates" / "configuration" / "elemwise_config.jinja"), str(ROOT / "templates" / "configuration" / "elemwise_config.jinja"),
name=self.name,
nb_elts=np.prod(self.inputs_dims[0]),
activation="Linear", activation="Linear",
elemwise_op="Add", elemwise_op="Add",
rescaling="NoScaling") rescaling="NoScaling",
**self.attributes)
return list_configs return list_configs
def forward(self, list_actions:list): def forward(self, list_actions:list):
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_str( list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja"), str(ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja"),
name=self.name, **self.attributes
inputs1_name=self.inputs[0].name() if self.inputs[0] else self.name + "_input1",
inputs2_name=self.inputs[1].name() if self.inputs[1] else self.name + "_input2",
output_name=self.name
)) ))
return list_actions return list_actions
...@@ -263,30 +210,24 @@ class SubCPP(ExportNode): ...@@ -263,30 +210,24 @@ class SubCPP(ExportNode):
super().__init__(node) super().__init__(node)
def export(self, export_folder:str, list_configs:list): def export(self, export_folder:str, list_configs:list):
list_configs.append(f"layers/{self.name}.h") list_configs.append(f"layers/{self.attributes['name']}.h")
list_configs.append("kernels/elemwise.hpp") list_configs.append("kernels/elemwise.hpp")
copyfile(str(ROOT / "kernels" / "elemwise.hpp"), copyfile(str(ROOT / "kernels" / "elemwise.hpp"),
str(export_folder / "include" / "kernels")) str(export_folder / "include" / "kernels"))
generate_file( generate_file(
str(export_folder / "layers" / f"{self.name}.h"), str(export_folder / "layers" / f"{self.attributes['name']}.h"),
str(ROOT / "templates" / "configuration" / "elemwise_config.jinja"), str(ROOT / "templates" / "configuration" / "elemwise_config.jinja"),
name=self.name,
nb_elts=np.prod(self.inputs_dims[0]),
activation="Linear", activation="Linear",
elemwise_op="Sub", elemwise_op="Sub",
rescaling="NoScaling") rescaling="NoScaling",
**self.attributes)
return list_configs return list_configs
def forward(self, list_actions:list): def forward(self, list_actions:list):
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_str( list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja"), str(ROOT / "templates" / "kernel_forward" / "elemwise_forward.jinja"),
name=self.name, **self.attributes
inputs1_name=f"{self.name}_input_0" if self.inputs[0] is None else self.inputs[0].name(),
inputs2_name=f"{self.name}_input_1" if self.inputs[1] is None else self.inputs[1].name(),
output_name=self.name
)) ))
return list_actions return list_actions
...@@ -297,20 +238,10 @@ class PaddedMaxPoolCPP(ExportNode): ...@@ -297,20 +238,10 @@ class PaddedMaxPoolCPP(ExportNode):
super().__init__(node) super().__init__(node)
for n in self.operator.get_micro_graph().get_nodes(): for n in self.operator.get_micro_graph().get_nodes():
if n.type() == "Pad": if n.type() == "Pad":
self.padding = n.get_operator().attr.begin_end_borders self.attributes["padding"] = n.get_operator().attr.begin_end_borders
if n.type() == "MaxPooling": if n.type() == "MaxPooling":
self.kernel = n.get_operator().attr.kernel_dims self.attributes["kernel_dims"] = n.get_operator().attr.kernel_dims
self.stride = n.get_operator().attr.stride_dims self.attributes["stride_dims"] = n.get_operator().attr.stride_dims
if len(self.inputs_dims[0]) == 4:
# if dims == [batch, nb_channels, height, width]
# transform to [nb_channels, height, width]
self.inputs_dims[0] = self.inputs_dims[0][1:]
if len(self.outputs_dims[0]) == 4:
# if dims == [batch, nb_outputs]
# transform to [nb_outputs, 1, 1]
self.outputs_dims[0] = self.outputs_dims[0][1:]
def export(self, export_folder:Path, list_configs:list): def export(self, export_folder:Path, list_configs:list):
...@@ -318,32 +249,21 @@ class PaddedMaxPoolCPP(ExportNode): ...@@ -318,32 +249,21 @@ class PaddedMaxPoolCPP(ExportNode):
str(export_folder / "include" / "kernels")) str(export_folder / "include" / "kernels"))
list_configs.append("kernels/pooling.hpp") list_configs.append("kernels/pooling.hpp")
list_configs.append(f"layers/{self.name}.h") list_configs.append(f"layers/{self.attributes['name']}.h")
generate_file( generate_file(
str(export_folder / "layers" / f"{self.name}.h"), str(export_folder / "layers" / f"{self.attributes['name']}.h"),
str(ROOT / "templates" / "configuration" / "pooling_config.jinja"), str(ROOT / "templates" / "configuration" / "pooling_config.jinja"),
name=self.name,
input_dims=self.inputs_dims[0],
output_dims=self.outputs_dims[0],
kernel=self.kernel,
stride=self.stride,
padding=self.padding,
pool_type="Max", pool_type="Max",
activation="Linear") activation="Linear",
**self.attributes)
return list_configs return list_configs
def forward(self, list_actions:list): def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_str( list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja"), str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja"),
name=self.name, **self.attributes
input_name=f"{self.name}_input_0" if self.inputs[0] is None else self.inputs[0].name(),
output_name=self.name
)) ))
return list_actions return list_actions
...@@ -352,22 +272,9 @@ class MaxPoolCPP(ExportNode): ...@@ -352,22 +272,9 @@ class MaxPoolCPP(ExportNode):
def __init__(self, node): def __init__(self, node):
super().__init__(node) super().__init__(node)
self.kernel = node.get_operator().attr.kernel_dims
self.stride = node.get_operator().attr.stride_dims
# No padding with MaxPooling # No padding with MaxPooling
# Use PaddedMaxPooling to add padding attribute # Use PaddedMaxPooling to add padding attribute
self.padding = [0, 0] self.attributes["padding"] = [0, 0]
if len(self.inputs_dims[0]) == 4:
# if dims == [batch, nb_channels, height, width]
# transform to [nb_channels, height, width]
self.inputs_dims[0] = self.inputs_dims[0][1:]
if len(self.outputs_dims[0]) == 4:
# if dims == [batch, nb_outputs]
# transform to [nb_outputs, 1, 1]
self.outputs_dims[0] = self.outputs_dims[0][1:]
def export(self, export_folder:Path, list_configs:list): def export(self, export_folder:Path, list_configs:list):
...@@ -375,32 +282,21 @@ class MaxPoolCPP(ExportNode): ...@@ -375,32 +282,21 @@ class MaxPoolCPP(ExportNode):
str(export_folder / "include" / "kernels")) str(export_folder / "include" / "kernels"))
list_configs.append("kernels/pooling.hpp") list_configs.append("kernels/pooling.hpp")
list_configs.append(f"layers/{self.name}.h") list_configs.append(f"layers/{self.attributes['name']}.h")
generate_file( generate_file(
str(export_folder / "layers" / f"{self.name}.h"), str(export_folder / "layers" / f"{self.attributes['name']}.h"),
str(ROOT / "templates" / "configuration" / "pooling_config.jinja"), str(ROOT / "templates" / "configuration" / "pooling_config.jinja"),
name=self.name,
input_dims=self.inputs_dims[0],
output_dims=self.outputs_dims[0],
kernel=self.kernel,
stride=self.stride,
padding=self.padding,
pool_type="Max", pool_type="Max",
activation="Linear") activation="Linear",
**self.attributes)
return list_configs return list_configs
def forward(self, list_actions:list): def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_str( list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja"), str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja"),
name=self.name, **self.attributes
input_name=self.inputs[0].name() if self.inputs[0] else self.name + "_input",
output_name=self.name
)) ))
return list_actions return list_actions
...@@ -409,25 +305,14 @@ class GlobalAveragePoolCPP(ExportNode): ...@@ -409,25 +305,14 @@ class GlobalAveragePoolCPP(ExportNode):
def __init__(self, node): def __init__(self, node):
super().__init__(node) super().__init__(node)
self.stride = [1, 1] self.attributes["stride_dims"] = [1, 1]
# No padding with MaxPooling # No padding with MaxPooling
# Use PaddedMaxPooling to add padding attribute # Use PaddedMaxPooling to add padding attribute
self.padding = [0, 0] self.attributes["padding"] = [0, 0]
self.attributes["kernel_dims"] = [
if len(self.inputs_dims[0]) == 4: self.attributes["in_height"][0],
# if dims == [batch, nb_channels, height, width] self.attributes["in_width"][0],
# transform to [nb_channels, height, width] ]
self.inputs_dims[0] = self.inputs_dims[0][1:]
self.kernel = self.inputs_dims[0][1:]
else:
raise RuntimeError("Input dims != 4 not supported.")
if len(self.outputs_dims[0]) == 4:
# if dims == [batch, nb_outputs]
# transform to [nb_outputs, 1, 1]
self.outputs_dims[0] = self.outputs_dims[0][1:]
elif len(self.outputs_dims[0]) == 2:
self.outputs_dims[0] = [self.outputs_dims[0][1], 1, 1]
def export(self, export_folder:Path, list_configs:list): def export(self, export_folder:Path, list_configs:list):
...@@ -435,32 +320,21 @@ class GlobalAveragePoolCPP(ExportNode): ...@@ -435,32 +320,21 @@ class GlobalAveragePoolCPP(ExportNode):
str(export_folder / "include" / "kernels")) str(export_folder / "include" / "kernels"))
list_configs.append("kernels/pooling.hpp") list_configs.append("kernels/pooling.hpp")
list_configs.append(f"layers/{self.name}.h") list_configs.append(f"layers/{self.attributes['name']}.h")
generate_file( generate_file(
str(export_folder / "layers" / f"{self.name}.h"), str(export_folder / "layers" / f"{self.attributes['name']}.h"),
str(ROOT / "templates" / "configuration" / "pooling_config.jinja"), str(ROOT / "templates" / "configuration" / "pooling_config.jinja"),
name=self.name,
input_dims=self.inputs_dims[0],
output_dims=self.outputs_dims[0],
kernel=self.kernel,
stride=self.stride,
padding=self.padding,
pool_type="Average", pool_type="Average",
activation="Linear") activation="Linear",
**self.attributes)
return list_configs return list_configs
def forward(self, list_actions:list): def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_str( list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja"), str(ROOT / "templates" / "kernel_forward" / "pooling_forward.jinja"),
name=self.name, **self.attributes
input_name=self.inputs[0].name() if self.inputs[0] else self.name + "_input",
output_name=self.name
)) ))
return list_actions return list_actions
...@@ -469,22 +343,13 @@ class GlobalAveragePoolCPP(ExportNode): ...@@ -469,22 +343,13 @@ class GlobalAveragePoolCPP(ExportNode):
class FcCPP(ExportNode): class FcCPP(ExportNode):
def __init__(self, node): def __init__(self, node):
super().__init__(node) super().__init__(node)
copy_includes ={
if len(self.inputs_dims[0]) == 4: }
# if dims == [batch, nb_channels, height, width] includes = []
# transform to [nb_channels, height, width] templates()
self.inputs_dims[0] = self.inputs_dims[0][1:]
elif len(self.inputs_dims[0]) == 2:
# if dims == [batch, nb_channels]
# transform to [nb_channels, 1, 1]
self.inputs_dims[0] = [self.inputs_dims[0][1], 1, 1]
if len(self.outputs_dims[0]) == 2:
# if dims == [batch, nb_outputs]
# transform to [nb_outputs, 1, 1]
self.outputs_dims[0] = [self.outputs_dims[0][1], 1, 1]
---
def export(self, export_folder:Path, list_configs:list): def export(self, export_folder:Path, list_configs:list):
copyfile(str(ROOT / "kernels" / "fullyconnected.hpp"), copyfile(str(ROOT / "kernels" / "fullyconnected.hpp"),
...@@ -496,30 +361,20 @@ class FcCPP(ExportNode): ...@@ -496,30 +361,20 @@ class FcCPP(ExportNode):
# Add to config list the include of configurations # Add to config list the include of configurations
list_configs.append("kernels/fullyconnected.hpp") list_configs.append("kernels/fullyconnected.hpp")
list_configs.append(f"layers/{self.name}.h") list_configs.append(f"layers/{self.attributes['name']}.h")
# Export configuration file # Export configuration file
generate_file( generate_file(
str(export_folder / "layers" / f"{self.name}.h"), str(export_folder / "layers" / f"{self.attributes['name']}.h"),
str(ROOT / "templates" / "configuration" / "fullyconnected_config.jinja"), str(ROOT / "templates" / "configuration" / "fullyconnected_config.jinja"),
name=self.name, **self.attributes)
input_dims=self.inputs_dims[0],
output_dims=self.outputs_dims[0],
activation="Linear",
rescaling="NoScaling")
return list_configs return list_configs
def forward(self, list_actions:list): def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_str( list_actions.append(generate_str(
str(ROOT / "templates" / "kernel_forward" / "fullyconnected_forward.jinja"), str(ROOT / "templates" / "kernel_forward" / "fullyconnected_forward.jinja"),
name=self.name, **self.attributes
inputs_name=f"{self.name}_input" if self.inputs[0] is None else self.inputs[0].name(),
weights_name=self.inputs[1].name(),
biases_name=self.inputs[2].name(), # TODO we should check if bias
outputs_name=self.name
)) ))
return list_actions return list_actions
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
* @param[in] lo Saturating lower bound * @param[in] lo Saturating lower bound
* @param[in] hi Saturating higher bound * @param[in] hi Saturating higher bound
* @returns Value clamped between lo and hi * @returns Value clamped between lo and hi
* *
*/ */
__attribute__((always_inline)) static inline __attribute__((always_inline)) static inline
int clamp (int v, int lo, int hi) int clamp (int v, int lo, int hi)
{ {
if(v < lo) { if(v < lo) {
return lo; return lo;
...@@ -27,7 +27,7 @@ int clamp (int v, int lo, int hi) ...@@ -27,7 +27,7 @@ int clamp (int v, int lo, int hi)
* @brief Maximum of two integer values * @brief Maximum of two integer values
*/ */
__attribute__((always_inline)) static inline __attribute__((always_inline)) static inline
int max (int lhs, int rhs) int max (int lhs, int rhs)
{ {
return (lhs >= rhs) ? lhs : rhs; return (lhs >= rhs) ? lhs : rhs;
} }
...@@ -36,7 +36,7 @@ int max (int lhs, int rhs) ...@@ -36,7 +36,7 @@ int max (int lhs, int rhs)
* @brief Minimum of two integer values * @brief Minimum of two integer values
*/ */
__attribute__((always_inline)) static inline __attribute__((always_inline)) static inline
int min (int lhs, int rhs) int min (int lhs, int rhs)
{ {
return (lhs <= rhs) ? lhs : rhs; return (lhs <= rhs) ? lhs : rhs;
} }
......
{# NOTE: Suppose input is first #}
#define {{ name|upper }}_NB_CHANNELS {{ in_chan[0] }}
#define {{ name|upper }}_CHANNELS_HEIGHT {{ in_height[0] }}
#define {{ name|upper }}_CHANNELS_WIDTH {{ in_width[0] }}
#define {{ name|upper }}_NB_OUTPUTS {{ out_chan[0] }}
#define {{ name|upper }}_OUTPUTS_HEIGHT {{ out_height[0] }}
#define {{ name|upper }}_OUTPUTS_WIDTH {{ out_width[0] }}
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#define {{ name|upper }}_LAYER_H #define {{ name|upper }}_LAYER_H
{# For layer configuration -#} {# For layer configuration -#}
{%- set nb_data = in_chan[0] * in_height[0] * in_width[0] %}
#define {{ name|upper }}_NB_DATA {{ nb_data }} #define {{ name|upper }}_NB_DATA {{ nb_data }}
#define {{ name|upper }}_ACTIVATION {{ activation }} #define {{ name|upper }}_ACTIVATION {{ activation }}
static const {{ rescaling }} {{ name|upper }}_RESCALING = {}; static const {{ rescaling }} {{ name|upper }}_RESCALING = {};
......
...@@ -3,12 +3,7 @@ ...@@ -3,12 +3,7 @@
#define {{ name|upper }}_LAYER_H #define {{ name|upper }}_LAYER_H
{# For layer configuration -#} {# For layer configuration -#}
#define {{ name|upper }}_NB_CHANNELS {{ input_dims[0] }} {% include "./_def_io.jinja" %}
#define {{ name|upper }}_CHANNELS_HEIGHT {{ input_dims[1] }}
#define {{ name|upper }}_CHANNELS_WIDTH {{ input_dims[2] }}
#define {{ name|upper }}_NB_OUTPUTS {{ output_dims[0] }}
#define {{ name|upper }}_OUTPUTS_HEIGHT {{ output_dims[1] }}
#define {{ name|upper }}_OUTPUTS_WIDTH {{ output_dims[2] }}
#define {{ name|upper }}_ACTIVATION {{ activation }} #define {{ name|upper }}_ACTIVATION {{ activation }}
#define {{ name|upper }}_EPSILON {{ epsilon }} #define {{ name|upper }}_EPSILON {{ epsilon }}
......
...@@ -3,27 +3,22 @@ ...@@ -3,27 +3,22 @@
#define {{ name|upper }}_LAYER_H #define {{ name|upper }}_LAYER_H
{# For layer configuration -#} {# For layer configuration -#}
#define {{ name|upper }}_NB_CHANNELS {{ input_dims[0] }} {% include "./_def_io.jinja" %}
#define {{ name|upper }}_CHANNELS_HEIGHT {{ input_dims[1] }}
#define {{ name|upper }}_CHANNELS_WIDTH {{ input_dims[2] }}
#define {{ name|upper }}_NB_OUTPUTS {{ output_dims[0] }}
#define {{ name|upper }}_OUTPUTS_HEIGHT {{ output_dims[1] }}
#define {{ name|upper }}_OUTPUTS_WIDTH {{ output_dims[2] }}
#define {{ name|upper }}_PADDING_Y {{ padding[1] }} #define {{ name|upper }}_PADDING_Y {{ padding[1] }}
#define {{ name|upper }}_PADDING_X {{ padding[0] }} #define {{ name|upper }}_PADDING_X {{ padding[0] }}
#define {{ name|upper }}_STRIDE_Y {{ stride[1] }} #define {{ name|upper }}_STRIDE_Y {{ stride_dims[1] }}
#define {{ name|upper }}_STRIDE_X {{ stride[0] }} #define {{ name|upper }}_STRIDE_X {{ stride_dims[0] }}
#define {{ name|upper }}_DILATION_Y {{ dilation[1] }} #define {{ name|upper }}_DILATION_Y {{ dilation_dims[1] }}
#define {{ name|upper }}_DILATION_X {{ dilation[0] }} #define {{ name|upper }}_DILATION_X {{ dilation_dims[0] }}
#define {{ name|upper }}_KERNEL_HEIGHT {{ kernel[1] }} #define {{ name|upper }}_KERNEL_HEIGHT {{ kernel_dims[1] }}
#define {{ name|upper }}_KERNEL_WIDTH {{ kernel[0] }} #define {{ name|upper }}_KERNEL_WIDTH {{ kernel_dims[0] }}
#define {{ name|upper }}_ACTIVATION {{ activation }} #define {{ name|upper }}_ACTIVATION {{ activation }}
static const {{ rescaling }} {{ name|upper }}_RESCALING = {}; static const {{ rescaling }} {{ name|upper }}_RESCALING = {};
{#- Calculate sizes #} {#- Calculate sizes #}
{%- set weights_size = output_dims[0] * input_dims[0] * kernel[1] * kernel[0] %} {%- set weights_size = out_chan[0] * in_chan[0] * kernel_dims[1] * kernel_dims[0] %}
#define {{ name|upper }}_WEIGHTS_SIZE {{ weights_size }} #define {{ name|upper }}_WEIGHTS_SIZE {{ weights_size }}
#define {{ name|upper }}_BIASES_SIZE {{ output_dims[0] }} #define {{ name|upper }}_BIASES_SIZE {{ out_chan[0] }}
#endif /* {{ name|upper }}_LAYER_H */ #endif /* {{ name|upper }}_LAYER_H */
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#define {{ name|upper }}_LAYER_H #define {{ name|upper }}_LAYER_H
{# For layer configuration -#} {# For layer configuration -#}
#define {{ name|upper }}_NB_ELTS {{ nb_elts }} #define {{ name|upper }}_NB_ELTS {{ in_dims[0]|join('*') }}
#define {{ name|upper }}_ACTIVATION {{ activation }} #define {{ name|upper }}_ACTIVATION {{ activation }}
#define {{ name|upper }}_ELEM_OP {{ elemwise_op }} #define {{ name|upper }}_ELEM_OP {{ elemwise_op }}
static const {{ rescaling }} {{ name|upper }}_RESCALING = {}; static const {{ rescaling }} {{ name|upper }}_RESCALING = {};
......
...@@ -3,19 +3,13 @@ ...@@ -3,19 +3,13 @@
#define {{ name|upper }}_LAYER_H #define {{ name|upper }}_LAYER_H
{# For layer configuration -#} {# For layer configuration -#}
#define {{ name|upper }}_NB_CHANNELS {{ input_dims[0] }} {% include "./_def_io.jinja" %}
#define {{ name|upper }}_CHANNELS_HEIGHT {{ input_dims[1] }}
#define {{ name|upper }}_CHANNELS_WIDTH {{ input_dims[2] }}
#define {{ name|upper }}_NB_OUTPUTS {{ output_dims[0] }}
#define {{ name|upper }}_OUTPUTS_HEIGHT {{ output_dims[1] }}
#define {{ name|upper }}_OUTPUTS_WIDTH {{ output_dims[2] }}
#define {{ name|upper }}_ACTIVATION {{ activation }} #define {{ name|upper }}_ACTIVATION {{ activation }}
static const {{ rescaling }} {{ name|upper }}_RESCALING = {}; static const {{ rescaling }} {{ name|upper }}_RESCALING = {};
{#- Calculate sizes #} {#- Calculate sizes #}
{%- set weights_size = output_dims[0] * input_dims[0] * input_dims[1] * input_dims[2] %} {%- set weights_size = out_chan[0] * in_chan[0] * in_height[0] * in_width[0] %}
#define {{ name|upper }}_WEIGHTS_SIZE {{ weights_size }} #define {{ name|upper }}_WEIGHTS_SIZE {{ weights_size }}
#define {{ name|upper }}_BIASES_SIZE {{ output_dims[0] }} #define {{ name|upper }}_BIASES_SIZE {{ out_chan[0] }}
#endif /* {{ name|upper }}_LAYER_H */ #endif /* {{ name|upper }}_LAYER_H */
...@@ -3,18 +3,13 @@ ...@@ -3,18 +3,13 @@
#define {{ name|upper }}_LAYER_H #define {{ name|upper }}_LAYER_H
{# For layer configuration -#} {# For layer configuration -#}
#define {{ name|upper }}_NB_CHANNELS {{ input_dims[0] }} {% include "./_def_io.jinja" %}
#define {{ name|upper }}_CHANNELS_HEIGHT {{ input_dims[1] }}
#define {{ name|upper }}_CHANNELS_WIDTH {{ input_dims[2] }}
#define {{ name|upper }}_NB_OUTPUTS {{ output_dims[0] }}
#define {{ name|upper }}_OUTPUTS_HEIGHT {{ output_dims[1] }}
#define {{ name|upper }}_OUTPUTS_WIDTH {{ output_dims[2] }}
#define {{ name|upper }}_PADDING_Y {{ padding[1] }} #define {{ name|upper }}_PADDING_Y {{ padding[1] }}
#define {{ name|upper }}_PADDING_X {{ padding[0] }} #define {{ name|upper }}_PADDING_X {{ padding[0] }}
#define {{ name|upper }}_STRIDE_Y {{ stride[1] }} #define {{ name|upper }}_STRIDE_Y {{ stride_dims[1] }}
#define {{ name|upper }}_STRIDE_X {{ stride[0] }} #define {{ name|upper }}_STRIDE_X {{ stride_dims[0] }}
#define {{ name|upper }}_KERNEL_HEIGHT {{ kernel[1] }} #define {{ name|upper }}_KERNEL_HEIGHT {{ kernel_dims[1] }}
#define {{ name|upper }}_KERNEL_WIDTH {{ kernel[0] }} #define {{ name|upper }}_KERNEL_WIDTH {{ kernel_dims[0] }}
#define {{ name|upper }}_POOLING_TYPE {{ pool_type }} #define {{ name|upper }}_POOLING_TYPE {{ pool_type }}
#define {{ name|upper }}_ACTIVATION {{ activation }} #define {{ name|upper }}_ACTIVATION {{ activation }}
......
/* COMMENTED FOR THE MOMENT
#ifdef SAVE_OUTPUTS
FILE* {{name|upper}}_STREAM = fopen("outputs/{{name}}_output.txt", "w");
saveOutputs(
{{name|upper}}_NB_OUTPUTS,
{{name|upper}}_OUTPUTS_HEIGHT,
{{name|upper}}_OUTPUTS_WIDTH,
{{name|upper}}_CONT_OFFSET,
{{name|upper}}_CONT_SIZE,
{{name|upper}}_WRAP_OFFSET,
{{name|upper}}_WRAP_SIZE,
{{name|upper}}_STRIDE,
{{out_name[0]}},
{{name|upper}}_STREAM, Network::Format::CHW);
fclose({{name|upper}}_STREAM);
#endif
*/
{% if not is_output %}
{{out_cdtype[0]}}* {{out_name[0]}} = ({{out_cdtype[0]}}*) mem + {{name|upper}}_OFFSET;
{% endif %}
activation_forward<{{name|upper}}_NB_DATA, activation_forward<{{name|upper}}_NB_DATA,
{{name|upper}}_ACTIVATION> {{name|upper}}_ACTIVATION>
({{input_name}}, {{output_name}}, {{name|upper}}_RESCALING); ({{in_name[0]}}, {{out_name[0]}}, {{name|upper}}_RESCALING);
\ No newline at end of file {% include "./_save_outputs.jinja" %}
...@@ -2,4 +2,5 @@ batchnorm_forward<{{name|upper}}_NB_OUTPUTS, ...@@ -2,4 +2,5 @@ batchnorm_forward<{{name|upper}}_NB_OUTPUTS,
{{name|upper}}_OUTPUTS_HEIGHT, {{name|upper}}_OUTPUTS_HEIGHT,
{{name|upper}}_OUTPUTS_WIDTH, {{name|upper}}_OUTPUTS_WIDTH,
{{name|upper}}_ACTIVATION> {{name|upper}}_ACTIVATION>
({{input_name}}, {{output_name}}, {{biases_name}}, {{variances_name}}, {{means_name}}, {{scales_name}}, {{name|upper}}_EPSILON); ({{input_name}}, {{output_name}}, {{biases_name}}, {{variances_name}}, {{means_name}}, {{scales_name}}, {{name|upper}}_EPSILON);
\ No newline at end of file {% include "./_save_outputs.jinja" %}
{% if not is_output %}
{{out_cdtype[0]}}* {{out_name[0]}} = ({{out_cdtype[0]}}*) mem + {{name|upper}}_OFFSET;
{% endif %}
convolution_forward<{{name|upper}}_NB_CHANNELS, convolution_forward<{{name|upper}}_NB_CHANNELS,
{{name|upper}}_CHANNELS_HEIGHT, {{name|upper}}_CHANNELS_HEIGHT,
{{name|upper}}_CHANNELS_WIDTH, {{name|upper}}_CHANNELS_WIDTH,
...@@ -13,4 +16,5 @@ convolution_forward<{{name|upper}}_NB_CHANNELS, ...@@ -13,4 +16,5 @@ convolution_forward<{{name|upper}}_NB_CHANNELS,
{{name|upper}}_KERNEL_HEIGHT, {{name|upper}}_KERNEL_HEIGHT,
{{name|upper}}_KERNEL_WIDTH, {{name|upper}}_KERNEL_WIDTH,
{{name|upper}}_ACTIVATION> {{name|upper}}_ACTIVATION>
({{input_name}}, {{output_name}}, {{weights_name}}, {{biases_name}}, {{name|upper}}_RESCALING); ({{in_name[0]}}, {{out_name[0]}}, {{in_name[1]}}, {{in_name[2]}}, {{name|upper}}_RESCALING);
{% include "./_save_outputs.jinja" %}
{% if not is_output %}
{{out_cdtype[0]}}* {{out_name[0]}} = ({{out_cdtype[0]}}*) mem + {{name|upper}}_OFFSET;
{% endif %}
elemwise_forward<{{name|upper}}_NB_ELTS, elemwise_forward<{{name|upper}}_NB_ELTS,
{{name|upper}}_ELEM_OP, {{name|upper}}_ELEM_OP,
{{name|upper}}_ACTIVATION> {{name|upper}}_ACTIVATION>
({{output_name}}, {{name|upper}}_RESCALING, {{inputs1_name}}, {{inputs2_name}}); ({{out_name[0]}}, {{name|upper}}_RESCALING, {{in_name[0]}}, {{in_name[1]}});
{% include "./_save_outputs.jinja" %}
{% if not is_output %}
{{out_cdtype[0]}}* {{out_name[0]}} = ({{out_cdtype[0]}}*) mem + {{name|upper}}_OFFSET;
{% endif %}
fullyconnected_forward<{{name|upper}}_NB_CHANNELS, fullyconnected_forward<{{name|upper}}_NB_CHANNELS,
{{name|upper}}_CHANNELS_HEIGHT, {{name|upper}}_CHANNELS_HEIGHT,
{{name|upper}}_CHANNELS_WIDTH, {{name|upper}}_CHANNELS_WIDTH,
...@@ -5,4 +8,5 @@ fullyconnected_forward<{{name|upper}}_NB_CHANNELS, ...@@ -5,4 +8,5 @@ fullyconnected_forward<{{name|upper}}_NB_CHANNELS,
{{name|upper}}_OUTPUTS_HEIGHT, {{name|upper}}_OUTPUTS_HEIGHT,
{{name|upper}}_OUTPUTS_WIDTH, {{name|upper}}_OUTPUTS_WIDTH,
{{name|upper}}_ACTIVATION> {{name|upper}}_ACTIVATION>
({{inputs_name}}, {{outputs_name}}, {{weights_name}}, {{biases_name}}, {{name|upper}}_RESCALING); ({{in_name[0]}}, {{out_name[0]}}, {{in_name[1]}}, {{in_name[2]}}, {{name|upper}}_RESCALING);
\ No newline at end of file {% include "./_save_outputs.jinja" %}
leakyrelu_forward<{{name|upper}}_NB_DATA> leakyrelu_forward<{{name|upper}}_NB_DATA>
({{input_name}}, {{output_name}}, {{name|upper}}_ALPHA); ({{input_name}}, {{output_name}}, {{name|upper}}_ALPHA);
\ No newline at end of file {% include "./_save_outputs.jinja" %}
{% if not is_output %}
{{out_cdtype[0]}}* {{out_name[0]}} = ({{out_cdtype[0]}}*) mem + {{name|upper}}_OFFSET;
{% endif %}
pooling_forward<{{name|upper}}_NB_CHANNELS, pooling_forward<{{name|upper}}_NB_CHANNELS,
{{name|upper}}_CHANNELS_HEIGHT, {{name|upper}}_CHANNELS_HEIGHT,
{{name|upper}}_CHANNELS_WIDTH, {{name|upper}}_CHANNELS_WIDTH,
...@@ -12,4 +15,5 @@ pooling_forward<{{name|upper}}_NB_CHANNELS, ...@@ -12,4 +15,5 @@ pooling_forward<{{name|upper}}_NB_CHANNELS,
{{name|upper}}_KERNEL_WIDTH, {{name|upper}}_KERNEL_WIDTH,
{{name|upper}}_POOLING_TYPE, {{name|upper}}_POOLING_TYPE,
{{name|upper}}_ACTIVATION> {{name|upper}}_ACTIVATION>
({{input_name}}, {{output_name}}); ({{in_name[0]}}, {{out_name[0]}});
\ No newline at end of file {% include "./_save_outputs.jinja" %}
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
#include <stdint.h> #include <stdint.h>
#ifdef SAVE_OUTPUTS
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "network/rescaling.hpp" #include "network/rescaling.hpp"
// Layer & memory configurations // Layer & memory configurations
...@@ -17,7 +22,15 @@ static {{inputs[0][0]}} mem[MEMORY_SIZE]; ...@@ -17,7 +22,15 @@ static {{inputs[0][0]}} mem[MEMORY_SIZE];
{#- Support multiple inputs with different datatypes and multiple outputs with different datatypes -#} {#- Support multiple inputs with different datatypes and multiple outputs with different datatypes -#}
void model_forward({% for inp in inputs %}const {{inp[0]}}* {{inp[1]}}, {% endfor %}{% for out in outputs %}{{out[0]}}* {{out[1]}}{{ ", " if not loop.last else "" }}{% endfor %}) void model_forward({% for inp in inputs %}const {{inp[0]}}* {{inp[1]}}, {% endfor %}{% for out in outputs %}{{out[0]}}* {{out[1]}}{{ ", " if not loop.last else "" }}{% endfor %})
{ {
#ifdef SAVE_OUTPUTS
// Creation of the outputs directory
struct stat st = {0};
if (stat("outputs", &st) == -1) {
mkdir("outputs", 0700);
}
#endif
{%- for action in actions %} {%- for action in actions %}
{{ action }} {{ action }}
{%- endfor %} {%- endfor %}
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment