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,
)
def export(export_folder_name, graphview, scheduler):
def export(export_folder_name, graphview, scheduler, mem_wrapping=False):
export_folder = Path().absolute() / export_folder_name
......@@ -62,6 +62,9 @@ def export(export_folder_name, graphview, scheduler):
raise RuntimeError(f"Operator not supported: {node.type()} !")
# 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)
# Generate the memory file
......@@ -94,7 +97,7 @@ def export(export_folder_name, graphview, scheduler):
for node in graphview.get_nodes():
if len(node.get_children()) == 0:
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_file(
......
import os
import shutil
from typing import List
from pathlib import Path
import aidge_core
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:
#define ENV_MEM_SIZE 3
#define ENV_OFFSET 0
......@@ -11,7 +28,7 @@ MEMORY_INFO_TEMPLATE = ["layer_name", "size", "offset"]
# Default memory management, which can be used for development
def compute_default_mem_info(scheduler: aidge_core.Scheduler):
list_forward_nodes = scheduler.get_static_scheduling()
mem_info = []
mem_size = 0
......@@ -27,23 +44,83 @@ def compute_default_mem_info(scheduler: aidge_core.Scheduler):
# Add memeory info
mem_info.append([node.name(), mem, mem_size])
# Increment offset for the next layer
mem_size += mem
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):
# 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
# 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_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_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
\ No newline at end of file
name = node.name()
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
This diff is collapsed.
......@@ -7,10 +7,10 @@
* @param[in] lo Saturating lower bound
* @param[in] hi Saturating higher bound
* @returns Value clamped between lo and hi
*
*
*/
__attribute__((always_inline)) static inline
int clamp (int v, int lo, int hi)
int clamp (int v, int lo, int hi)
{
if(v < lo) {
return lo;
......@@ -27,7 +27,7 @@ int clamp (int v, int lo, int hi)
* @brief Maximum of two integer values
*/
__attribute__((always_inline)) static inline
int max (int lhs, int rhs)
int max (int lhs, int rhs)
{
return (lhs >= rhs) ? lhs : rhs;
}
......@@ -36,7 +36,7 @@ int max (int lhs, int rhs)
* @brief Minimum of two integer values
*/
__attribute__((always_inline)) static inline
int min (int lhs, int rhs)
int min (int lhs, int 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 @@
#define {{ name|upper }}_LAYER_H
{# 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 }}_ACTIVATION {{ activation }}
static const {{ rescaling }} {{ name|upper }}_RESCALING = {};
......
......@@ -3,12 +3,7 @@
#define {{ name|upper }}_LAYER_H
{# For layer configuration -#}
#define {{ name|upper }}_NB_CHANNELS {{ input_dims[0] }}
#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] }}
{% include "./_def_io.jinja" %}
#define {{ name|upper }}_ACTIVATION {{ activation }}
#define {{ name|upper }}_EPSILON {{ epsilon }}
......
......@@ -3,27 +3,22 @@
#define {{ name|upper }}_LAYER_H
{# For layer configuration -#}
#define {{ name|upper }}_NB_CHANNELS {{ input_dims[0] }}
#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] }}
{% include "./_def_io.jinja" %}
#define {{ name|upper }}_PADDING_Y {{ padding[1] }}
#define {{ name|upper }}_PADDING_X {{ padding[0] }}
#define {{ name|upper }}_STRIDE_Y {{ stride[1] }}
#define {{ name|upper }}_STRIDE_X {{ stride[0] }}
#define {{ name|upper }}_DILATION_Y {{ dilation[1] }}
#define {{ name|upper }}_DILATION_X {{ dilation[0] }}
#define {{ name|upper }}_KERNEL_HEIGHT {{ kernel[1] }}
#define {{ name|upper }}_KERNEL_WIDTH {{ kernel[0] }}
#define {{ name|upper }}_STRIDE_Y {{ stride_dims[1] }}
#define {{ name|upper }}_STRIDE_X {{ stride_dims[0] }}
#define {{ name|upper }}_DILATION_Y {{ dilation_dims[1] }}
#define {{ name|upper }}_DILATION_X {{ dilation_dims[0] }}
#define {{ name|upper }}_KERNEL_HEIGHT {{ kernel_dims[1] }}
#define {{ name|upper }}_KERNEL_WIDTH {{ kernel_dims[0] }}
#define {{ name|upper }}_ACTIVATION {{ activation }}
static const {{ rescaling }} {{ name|upper }}_RESCALING = {};
{#- 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 }}_BIASES_SIZE {{ output_dims[0] }}
#define {{ name|upper }}_BIASES_SIZE {{ out_chan[0] }}
#endif /* {{ name|upper }}_LAYER_H */
......@@ -3,7 +3,7 @@
#define {{ name|upper }}_LAYER_H
{# 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 }}_ELEM_OP {{ elemwise_op }}
static const {{ rescaling }} {{ name|upper }}_RESCALING = {};
......
......@@ -3,19 +3,13 @@
#define {{ name|upper }}_LAYER_H
{# For layer configuration -#}
#define {{ name|upper }}_NB_CHANNELS {{ input_dims[0] }}
#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] }}
{% include "./_def_io.jinja" %}
#define {{ name|upper }}_ACTIVATION {{ activation }}
static const {{ rescaling }} {{ name|upper }}_RESCALING = {};
{#- 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 }}_BIASES_SIZE {{ output_dims[0] }}
#define {{ name|upper }}_BIASES_SIZE {{ out_chan[0] }}
#endif /* {{ name|upper }}_LAYER_H */
......@@ -3,18 +3,13 @@
#define {{ name|upper }}_LAYER_H
{# For layer configuration -#}
#define {{ name|upper }}_NB_CHANNELS {{ input_dims[0] }}
#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] }}
{% include "./_def_io.jinja" %}
#define {{ name|upper }}_PADDING_Y {{ padding[1] }}
#define {{ name|upper }}_PADDING_X {{ padding[0] }}
#define {{ name|upper }}_STRIDE_Y {{ stride[1] }}
#define {{ name|upper }}_STRIDE_X {{ stride[0] }}
#define {{ name|upper }}_KERNEL_HEIGHT {{ kernel[1] }}
#define {{ name|upper }}_KERNEL_WIDTH {{ kernel[0] }}
#define {{ name|upper }}_STRIDE_Y {{ stride_dims[1] }}
#define {{ name|upper }}_STRIDE_X {{ stride_dims[0] }}
#define {{ name|upper }}_KERNEL_HEIGHT {{ kernel_dims[1] }}
#define {{ name|upper }}_KERNEL_WIDTH {{ kernel_dims[0] }}
#define {{ name|upper }}_POOLING_TYPE {{ pool_type }}
#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,
{{name|upper}}_ACTIVATION>
({{input_name}}, {{output_name}}, {{name|upper}}_RESCALING);
\ No newline at end of file
({{in_name[0]}}, {{out_name[0]}}, {{name|upper}}_RESCALING);
{% include "./_save_outputs.jinja" %}
......@@ -2,4 +2,5 @@ batchnorm_forward<{{name|upper}}_NB_OUTPUTS,
{{name|upper}}_OUTPUTS_HEIGHT,
{{name|upper}}_OUTPUTS_WIDTH,
{{name|upper}}_ACTIVATION>
({{input_name}}, {{output_name}}, {{biases_name}}, {{variances_name}}, {{means_name}}, {{scales_name}}, {{name|upper}}_EPSILON);
\ No newline at end of file
({{input_name}}, {{output_name}}, {{biases_name}}, {{variances_name}}, {{means_name}}, {{scales_name}}, {{name|upper}}_EPSILON);
{% 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,
{{name|upper}}_CHANNELS_HEIGHT,
{{name|upper}}_CHANNELS_WIDTH,
......@@ -13,4 +16,5 @@ convolution_forward<{{name|upper}}_NB_CHANNELS,
{{name|upper}}_KERNEL_HEIGHT,
{{name|upper}}_KERNEL_WIDTH,
{{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,
{{name|upper}}_ELEM_OP,
{{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,
{{name|upper}}_CHANNELS_HEIGHT,
{{name|upper}}_CHANNELS_WIDTH,
......@@ -5,4 +8,5 @@ fullyconnected_forward<{{name|upper}}_NB_CHANNELS,
{{name|upper}}_OUTPUTS_HEIGHT,
{{name|upper}}_OUTPUTS_WIDTH,
{{name|upper}}_ACTIVATION>
({{inputs_name}}, {{outputs_name}}, {{weights_name}}, {{biases_name}}, {{name|upper}}_RESCALING);
\ No newline at end of file
({{in_name[0]}}, {{out_name[0]}}, {{in_name[1]}}, {{in_name[2]}}, {{name|upper}}_RESCALING);
{% include "./_save_outputs.jinja" %}
leakyrelu_forward<{{name|upper}}_NB_DATA>
({{input_name}}, {{output_name}}, {{name|upper}}_ALPHA);
\ No newline at end of file
({{input_name}}, {{output_name}}, {{name|upper}}_ALPHA);
{% 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,
{{name|upper}}_CHANNELS_HEIGHT,
{{name|upper}}_CHANNELS_WIDTH,
......@@ -12,4 +15,5 @@ pooling_forward<{{name|upper}}_NB_CHANNELS,
{{name|upper}}_KERNEL_WIDTH,
{{name|upper}}_POOLING_TYPE,
{{name|upper}}_ACTIVATION>
({{input_name}}, {{output_name}});
\ No newline at end of file
({{in_name[0]}}, {{out_name[0]}});
{% include "./_save_outputs.jinja" %}
......@@ -2,6 +2,11 @@
#include <stdint.h>
#ifdef SAVE_OUTPUTS
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "network/rescaling.hpp"
// Layer & memory configurations
......@@ -17,7 +22,15 @@ static {{inputs[0][0]}} mem[MEMORY_SIZE];
{#- 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 %})
{
#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 %}
{{ action }}
{%- 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