Beatmup
Beatmup::NNets::Pooling2D Class Reference

2D pooling operation computed on GPU. More...

#include <pooling2d.h>

Inheritance diagram for Beatmup::NNets::Pooling2D:
Beatmup::NNets::AbstractOperation Beatmup::NNets::SpatialFilteringMixin

Public Types

enum class  Operator { MAX , AVERAGE }
 Pooling operator specification. More...
 

Public Member Functions

 Pooling2D (const std::string &name, const Operator op, const int size, const int stride=1, const Size::Padding padding=Size::Padding::VALID)
 2D pooling layer. More...
 
int getInputCount () const
 Returns number of operation inputs. More...
 
int getOutputCount () const
 Returns number of operation outputs. More...
 
bool acceptsStorageInput (int index=0) const
 Returns true if the operation can take a Storage::View at a specific input. More...
 
bool acceptsStorageOutput (int index=0) const
 Returns true if the operation can take a Storage::View at a specific output. More...
 
Size getOutputSize (int outputIndex=0) const
 Returns full size of a specific operation output. More...
 
Storage::View getOutput (int index=0)
 Returns a storage view bound to a specific operation output. More...
 
void setInput (Storage::View &&storage, int inputIndex=0)
 
void setOutput (Storage::View &&storage, int outputIndex=0)
 
std::map< std::string, std::string > serialize () const
 Returns a serialized representation of th operation;. More...
 
void disconnect ()
 Assigns empty inputs and outputs. More...
 
unsigned long countTexelFetches () const
 Counts (approximate) number of texels fetches. More...
 
- Public Member Functions inherited from Beatmup::NNets::AbstractOperation
virtual ~AbstractOperation ()
 
virtual bool usesGpu () const
 Returns true if the operation is run on GPU. More...
 
virtual bool acceptsVectorInput (int index=0) const
 Returns true if the operation can take a GL::Vector at a specific input. More...
 
virtual bool acceptsTextureInput (int index=0) const
 Returns true if the operation can take a GL::TextureHandler at a specific input. More...
 
virtual bool acceptsVectorOutput (int index=0) const
 Returns true if the operation can take a GL::Vector at a specific output. More...
 
virtual bool acceptsTextureOutput (int index=0) const
 Returns true if the operation can take a GL::TextureHandler at a specific output. More...
 
virtual void getOutput (GL::Vector *&vector, int index=0)
 Returns a GL::Vector bound to a specific operation output. More...
 
virtual void getOutput (GL::TextureHandler *&vector, int index=0)
 Returns a GL::TextureHandler bound to a specific operation output. More...
 
virtual void setInput (GL::Vector &vector, int index=0)
 
virtual void setOutput (GL::Vector &vector, int index=0)
 
virtual void setInput (GL::TextureHandler &image, int index=0)
 
virtual void setOutput (GL::TextureHandler &image, int index=0)
 
virtual unsigned long countMultiplyAdds () const
 Counts (approximate) number of multiply-adds used by this operation. More...
 
std::string getName () const
 

Static Public Member Functions

static Operator operatorFromString (const std::string &str)
 Returns a pooling operator from string. More...
 
static bool initDeserializer ()
 Sets up deserialization of the operation. More...
 

Private Member Functions

void prepare (GraphicPipeline &gpu, ChunkCollection &data, GL::ProgramBank &bank)
 Compiles GLSL shaders. More...
 
void execute (TaskThread &thread, GraphicPipeline &gpu)
 Executes the operation. More...
 
int getInputPadding (int index=0) const
 Retrieves minimum required size of zero padding for a given input. More...
 
void getSampledChannels (int index, int &min, int &max) const
 Retrieves range of input features channels sampled at the same time for a specific input. More...
 

Private Attributes

const Size size
 
const Size stride
 
const Operator op
 
const Size::Padding padding
 
Storage::View input
 
Storage::View output
 
bool ready
 
GL::RenderingProgramprogram
 

Additional Inherited Members

- Protected Member Functions inherited from Beatmup::NNets::AbstractOperation
 AbstractOperation (const std::string &name)
 
virtual void execute (TaskThread &thread)
 Executes the operation within a specific CPU thread. More...
 
- Protected Member Functions inherited from Beatmup::NNets::SpatialFilteringMixin
 SpatialFilteringMixin (const int nbSizeX, const int nbSizeY)
 Initializes spatial filtering mixin. More...
 
 ~SpatialFilteringMixin ()
 
void writeHeader (StringBuilder &code, bool useUniformShift)
 Writes out the very GLSL fragment shader header required for spatial neighborhood sampling. More...
 
void declare (StringBuilder &code, const char *datatype, bool inlineSampling=false)
 Declares GLSL fragment shader main(..) code part required for spatial neighborhood sampling. More...
 
void sample (StringBuilder &code, const char *inputName, const int inputIndex, const Point &shift, const bool isFirstSample=true, const char *suffix="")
 Samples a neighborhood of a given texture. More...
 
void sampleInline (StringBuilder &code, const char *inputName, const int inputIndex, const IntPoint &position, const Point &shift, const char *suffix="")
 
void setup (const int width, const int height)
 Prepares the spatial filtering operation execution. More...
 
void setUniformShift (GL::Program &program, const IntPoint &shift, const IntPoint &inputSize)
 Applies an offset to the sampling position at runtime. More...
 
void setupProgram (GL::Program &program)
 Prepares a given program for spatial filtering. More...
 
IntRectangle getSamplingArea (const IntPoint &size, const IntPoint &stride, const Size::Padding padding) const
 Implements common padding policies by computing a rectangular area of positions the sampling kernel takes in order to get the result with the required padding. More...
 
IntRectangle getSamplingArea (const Storage::View &storage, const int channel, const IntPoint &stride, const Size::Padding padding) const
 Computes area in pixels to sample a given storage according to specific stride and padding. More...
 
Rectangle getTextureCoordinates (const Storage::View &storage, const int channel, const IntPoint &stride, const Size::Padding padding, const IntPoint &outputSize) const
 Computes texture coordinates sampling a specific storage channel for given stride, padding and output size. More...
 
std::string getInputSamplingPos () const
 Retrieves input sampling point position for the current fragment. More...
 
bool isUniformShiftUsed () const
 
- Static Protected Attributes inherited from Beatmup::NNets::SpatialFilteringMixin
static const char * SAMPLE_ID_PREFIX = "i"
 prefix of variables declaring a neighbor sample More...
 

Detailed Description

2D pooling operation computed on GPU.

Has a single input and a single output. Constraints:

  • Input and output are 3D tensors with values in [0, 1] range sampled over 8 bits.
  • Number of feature maps is a multiple of 4.
  • Pooling area is of square shape.
  • Strides are equal along X and Y.
  • Average pooling only accepts valid zero padding,

Raspberry Pi-related constraints:

  • Pi cannot sample more than 256 channels to compute a single output value. Actual practical limit is yet lower: pooling size may be limited by 10. When the limit is reached, Pi OpenGL driver reports an out of memory error (0x505).

Definition at line 40 of file pooling2d.h.

Member Enumeration Documentation

◆ Operator

Pooling operator specification.

Enumerator
MAX 
AVERAGE 

Definition at line 45 of file pooling2d.h.

45  {
46  MAX, // max pooling
47  AVERAGE // average pooling
48  };

Constructor & Destructor Documentation

◆ Pooling2D()

Pooling2D::Pooling2D ( const std::string &  name,
const Operator  op,
const int  size,
const int  stride = 1,
const Size::Padding  padding = Size::Padding::VALID 
)

2D pooling layer.

Parameters
[in]nameLayer name
[in]opPooling operator
[in]sizeSpatial pooling operational size
[in]stridePooling stride; if 0, the size is used
[in]paddingZero padding applied to the input

Definition at line 29 of file pooling2d.cpp.

35  :
38  size(size, size, 1), stride(stride <= 0 ? this->size : Size(stride, stride, 1)),
39  op(op), padding(padding),
40  ready(false), program(nullptr)
41 {
42  if (op == Operator::AVERAGE)
43  InvalidArgument::check(padding == Size::Padding::VALID, "Average 2D pooling only supports valid padding");
44  OutOfRange::checkMin(size, 2, "Pooling size must be at least 2, %d got");
45 }
static void check(const bool condition, const std::string &message)
Definition: exception.h:75
AbstractOperation(const AbstractOperation &)=delete
disabling copying constructor
const Size::Padding padding
Definition: pooling2d.h:53
const Operator op
Definition: pooling2d.h:52
GL::RenderingProgram * program
Definition: pooling2d.h:56
Operation 3D input/output size.
Definition: storage.h:37
SpatialFilteringMixin(const int nbSizeX, const int nbSizeY)
Initializes spatial filtering mixin.
Definition: operation.cpp:98
static void checkMin(const datatype value, const datatype min, const char *message)
Definition: exception.h:92

Member Function Documentation

◆ prepare()

void Pooling2D::prepare ( GraphicPipeline gpu,
ChunkCollection data,
GL::ProgramBank bank 
)
privatevirtual

Compiles GLSL shaders.

Parameters
[in,out]gpuA graphic pipeline instance
[in,out]dataChunkfile containing operation data (e.g. weights and biases)
[in,out]bankA program bank with existing GLSL programs to be reused when possible. If a new program is built, it is added to the bank.

Implements Beatmup::NNets::AbstractOperation.

Definition at line 48 of file pooling2d.cpp.

48  {
49  // delete the old program
50  if (program)
51  bank.release(gpu, program);
52 
54 
55  code.printf("uniform sampler2D %s[1];", UNIFORM_INPUT);
57 
58  // main
59  code.line("void main() {");
60 
61  // declare neighborhood, inline sampling
62  SpatialFilteringMixin::declare(code, "lowp vec4", true);
63 
64  // declare the result variable
65  switch (op) {
66  case Operator::MAX:
67  code("lowp");
68  break;
69  case Operator::AVERAGE:
70  code("mediump");
71  break;
72  }
73  code.line(" vec4 r;");
74 
75  // compute pooling
76  switch (op) {
77  case Operator::MAX:
78  for (int i = 0; i < size.volume(); ++i) {
79  code(i == 0 ? "r = (" : "r = max(r, ");
81  code.line(");");
82  }
83  code.line("gl_FragColor = r;");
84  break;
85  case Operator::AVERAGE:
86  code("r = ");
87  for (int i = 0; i < size.volume(); ++i) {
88  if (i > 0)
89  code(" + ");
91  }
92  code.line(";");
93  code.printf("gl_FragColor = %0.10f * r;", 1.0f / size.volume());
94  break;
95  }
96 
97  // store the result
98  code("}");
99 
100  // init program
101  program = bank(gpu, code);
102 
103  ready = true;
104 }
static const CustomPoint ZERO
Definition: geometry.h:122
void release(GraphicPipeline &gpu, GL::RenderingProgram *program)
Marks a program as unused any more.
static const char * DECLARE_TEXTURE_COORDINATES_IN_FRAG
Declaring texture coordinates in fragment shader.
int volume() const
Definition: storage.h:79
void sampleInline(StringBuilder &code, const char *inputName, const int inputIndex, const IntPoint &position, const Point &shift, const char *suffix="")
Definition: operation.cpp:174
void writeHeader(StringBuilder &code, bool useUniformShift)
Writes out the very GLSL fragment shader header required for spatial neighborhood sampling.
Definition: operation.cpp:110
void declare(StringBuilder &code, const char *datatype, bool inlineSampling=false)
Declares GLSL fragment shader main(..) code part required for spatial neighborhood sampling.
Definition: operation.cpp:119
StringBuilder including a string container.
CustomPoint< int > IntPoint
Definition: geometry.h:629
static const char * UNIFORM_INPUT
Definition: pooling2d.cpp:26

◆ execute()

void Pooling2D::execute ( TaskThread thread,
GraphicPipeline gpu 
)
privatevirtual

Executes the operation.

The operation should be prepared.

Parameters
[in,out]threadCalling CPU thread descriptor
[in,out]gpuA graphic pipeline instance

Implements Beatmup::NNets::AbstractOperation.

Definition at line 107 of file pooling2d.cpp.

107  {
108  if (!ready)
109  throw NotReady(this);
110  RuntimeError::check(input, "Input is not provided to a Pooling2D operation.");
111  RuntimeError::check(output, "Output is not provided to Pooling2D operation " + getName());
112  RuntimeError::check(input.getDepth() == output.getDepth(), "Input / output depth mismatch.");
113 
114  // prepare deltas
115  program->enable(gpu);
118 
119  // setup texture coordinates
124  );
125 
126  // for each output channel
127  const IntPoint origin = input.getChannelOrigin(0);
128  Storage::Binder bind(gpu);
129  for (int channel = 0; channel < input.getDepth(); channel += 4) {
130  // bind things to program
131  bind.begin(*program, output, channel);
132  bind(input, UNIFORM_INPUT, channel);
133 
134  // setup
136 
137  // run
138  program->blend();
139  }
140 }
void enable(const GraphicPipeline &gpu)
Definition: program.cpp:250
void blend(bool onScreen)
Definition: program.cpp:548
void setTextureCoordinates(const Rectangle &coords)
Specifies texture coordinates for the next rendering pass.
Definition: pipeline.cpp:966
std::string getName() const
Definition: operation.h:242
Storage::View input
Definition: pooling2d.h:54
Storage::View output
Definition: pooling2d.h:54
void setup(const int width, const int height)
Prepares the spatial filtering operation execution.
Definition: operation.cpp:197
void setupProgram(GL::Program &program)
Prepares a given program for spatial filtering.
Definition: operation.cpp:217
IntRectangle getSamplingArea(const IntPoint &size, const IntPoint &stride, const Size::Padding padding) const
Implements common padding policies by computing a rectangular area of positions the sampling kernel t...
Definition: operation.cpp:223
void setUniformShift(GL::Program &program, const IntPoint &shift, const IntPoint &inputSize)
Applies an offset to the sampling position at runtime.
Definition: operation.cpp:209
Binding of different input/output storages/texture handlers to a GLSL program.
Definition: storage.h:419
int getTextureHeight() const
Returns height in pixels of all the textures.
Definition: storage.h:375
IntPoint getChannelOrigin(int channel) const
Returns origin in pixels of a given channel within the texture containing it.
Definition: storage.cpp:509
IntPoint getTextureSize() const
Definition: storage.h:377
IntPoint getSpatialSize() const
Returns the spatial size (width and height) of the storage in pixels.
Definition: storage.h:389
int getTextureWidth() const
Returns width in pixels of all the textures.
Definition: storage.h:370
static void check(const bool condition, const std::string &message)
Definition: exception.h:64
bitmap bind(jenv, jobj)

◆ getInputPadding()

int Pooling2D::getInputPadding ( int  index = 0) const
privatevirtual

Retrieves minimum required size of zero padding for a given input.

Operations that sample a neighborhood of a pixel may need the input to be padded with zeros, if some of the neighboring samples fall out of the are containing data. In Beatmup the zero padding is handled by allocating a bigger input and putting zeros around the area that is actually filled with data.

Returns
number of zero columns and rows to be added to the input area.

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 143 of file pooling2d.cpp.

143  {
144  return (padding == Size::Padding::SAME) ? std::max(size[0], size[1]) / 2 : 0;
145 }
@ SAME
operation output size matches its input size for unit strides
CustomPoint< numeric > max(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:728

◆ getSampledChannels()

void Pooling2D::getSampledChannels ( int  index,
int &  min,
int &  max 
) const
privatevirtual

Retrieves range of input features channels sampled at the same time for a specific input.

The operation would typically take the entire storage and sample it at once, if needed. If the number of textures in a storage exceeds the number of texture samplers that the GPU may use simultaneously, an exception occurs. This function provides the necessary information to limit the number of textures in the storage when allocating it. When the limit is reached, multiple channels are packed into a single texture in the storage.

Parameters
[in]indexThe input index. Expected to fall in the valid range, i.e. from zero to getInputCount() - 1 inclusive.
[out]minThe minimum number of channels that can be sampled at once
[out]maxThe maximum number of channels that can be sampled at once

Implements Beatmup::NNets::AbstractOperation.

Definition at line 148 of file pooling2d.cpp.

148  {
149  min = max = (index == 0 ? 4 : 0);
150 }
CustomPoint< numeric > min(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:724
jlong jint index

◆ getInputCount()

int Beatmup::NNets::Pooling2D::getInputCount ( ) const
inlinevirtual

Returns number of operation inputs.

Inputs are then indexed from zero to the returned value minus one inclusive.

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 80 of file pooling2d.h.

80 { return 1; }

◆ getOutputCount()

int Beatmup::NNets::Pooling2D::getOutputCount ( ) const
inlinevirtual

Returns number of operation outputs.

Outputs are then indexed from zero to the returned value minus one inclusive.

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 81 of file pooling2d.h.

81 { return 1; }

◆ acceptsStorageInput()

bool Beatmup::NNets::Pooling2D::acceptsStorageInput ( int  index = 0) const
inlinevirtual

Returns true if the operation can take a Storage::View at a specific input.

Neural network operations may accept different kinds of data containers on inputs and outputs, namely Storage::View, GL::Vector and textures. This function is used to check whether a given operation accepts a storage view on input.

Parameters
[in]indexThe input index. Expected to fall in the valid range, i.e. from zero to getInputCount() - 1 inclusive.

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 83 of file pooling2d.h.

83 { return index == 0; }

◆ acceptsStorageOutput()

bool Beatmup::NNets::Pooling2D::acceptsStorageOutput ( int  index = 0) const
inlinevirtual

Returns true if the operation can take a Storage::View at a specific output.

Neural network operations may accept different kinds of data containers on outputs and outputs, namely Storage::View, GL::Vector and textures. This function is used to check whether a given operation accepts a storage view on output.

Parameters
[in]indexThe output index. Expected to fall in the valid range, i.e. from zero to getOutputCount() - 1 inclusive.

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 84 of file pooling2d.h.

84 { return index == 0; }

◆ getOutputSize()

Size Pooling2D::getOutputSize ( int  outputIndex = 0) const
virtual

Returns full size of a specific operation output.

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 153 of file pooling2d.cpp.

153  {
154  if (outputIndex == 0) {
155  RuntimeError::check(input, "Input is not provided to a Pooling2D operation.");
157  RuntimeError::check(result.volume() > 0, "Invalid (zero or negative) output size got in " + getName());
158  return result;
159  }
160  return Size::EMPTY;
161 }
static const Size EMPTY
Definition: storage.h:50
Size transform(Size kernel, Size stride, Padding padding, int depth=0) const
Computes operation output size in function of operation kernel, padding, stride and depth,...
Definition: storage.cpp:58
Beatmup::IntPoint result

◆ getOutput()

Storage::View Beatmup::NNets::Pooling2D::getOutput ( int  index = 0)
inlinevirtual

Returns a storage view bound to a specific operation output.

If no view is bound, returns empty view.

Parameters
[in]indexThe output index. Expected to fall in the valid range, i.e. from zero to getOutputCount() - 1 inclusive.

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 88 of file pooling2d.h.

88 { return output; }

◆ setInput()

void Pooling2D::setInput ( Storage::View &&  storage,
int  inputIndex = 0 
)
virtual

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 164 of file pooling2d.cpp.

164  {
165  OutOfRange::check(inputIndex, 0, 0, "Input index out of range: %d");
166  RuntimeError::check(view.getStorage().getPadding() >= getInputPadding(inputIndex), "The storage has insufficient padding");
167  this->input = std::move(view);
168 }
int getInputPadding(int index=0) const
Retrieves minimum required size of zero padding for a given input.
Definition: pooling2d.cpp:143
static void check(const datatype value, const datatype min, const datatype max, const char *message)
Definition: exception.h:86

◆ setOutput()

void Pooling2D::setOutput ( Storage::View &&  storage,
int  outputIndex = 0 
)
virtual

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 171 of file pooling2d.cpp.

171  {
172  OutOfRange::check(outputIndex, 0, 0, "Output index out of range: %d");
173  this->output = std::move(storage);
174 }

◆ serialize()

std::map< std::string, std::string > Pooling2D::serialize ( ) const
virtual

Returns a serialized representation of th operation;.

Implements Beatmup::NNets::AbstractOperation.

Definition at line 177 of file pooling2d.cpp.

177  {
178  return {
179  { "_name", getName() },
180  { "_type", "pooling2d" },
181  { "operator", std::to_string(op) },
182  { "size", std::to_string(size[0]) },
183  { "stride", std::to_string(stride[0]) },
184  { "padding", std::to_string(padding) }
185  };
186 }
std::string to_string(Beatmup::NNets::ActivationFunction function)

◆ disconnect()

void Pooling2D::disconnect ( )
virtual

Assigns empty inputs and outputs.

Implements Beatmup::NNets::AbstractOperation.

Definition at line 219 of file pooling2d.cpp.

219  {
220  this->input = Storage::View();
221  this->output = Storage::View();
222 }
friend class View
Definition: storage.h:135

◆ countTexelFetches()

unsigned long Pooling2D::countTexelFetches ( ) const
virtual

Counts (approximate) number of texels fetches.

Reimplemented from Beatmup::NNets::AbstractOperation.

Definition at line 225 of file pooling2d.cpp.

225  {
226  return getOutputSize(0).volume() * size.volume() / 4;
227 }
Size getOutputSize(int outputIndex=0) const
Returns full size of a specific operation output.
Definition: pooling2d.cpp:153

◆ operatorFromString()

Pooling2D::Operator Pooling2D::operatorFromString ( const std::string &  str)
static

Returns a pooling operator from string.

The conversion is case-insensitive. Raises an exception if cannot interpret the string.

Parameters
[in]strThe input string

Definition at line 230 of file pooling2d.cpp.

230  {
231  const std::string lc = StringUtils::lowercase(str);
232  if (lc == "average")
233  return Operator::AVERAGE;
234  if (lc == "max")
235  return Operator::MAX;
236  throw InvalidArgument("Invalid pooling operator: " + str);
237  return Operator::AVERAGE;
238 }
std::string lowercase(const std::string &str)
Converts a string to lower case (latin letters only).
JNIEnv jobject jstring str

◆ initDeserializer()

static bool Beatmup::NNets::Pooling2D::initDeserializer ( )
static

Sets up deserialization of the operation.

Member Data Documentation

◆ size

const Size Beatmup::NNets::Pooling2D::size
private

Definition at line 51 of file pooling2d.h.

◆ stride

const Size Beatmup::NNets::Pooling2D::stride
private

Definition at line 51 of file pooling2d.h.

◆ op

const Operator Beatmup::NNets::Pooling2D::op
private

Definition at line 52 of file pooling2d.h.

◆ padding

const Size::Padding Beatmup::NNets::Pooling2D::padding
private

Definition at line 53 of file pooling2d.h.

◆ input

Storage::View Beatmup::NNets::Pooling2D::input
private

Definition at line 54 of file pooling2d.h.

◆ output

Storage::View Beatmup::NNets::Pooling2D::output
private

Definition at line 54 of file pooling2d.h.

◆ ready

bool Beatmup::NNets::Pooling2D::ready
private

Definition at line 55 of file pooling2d.h.

◆ program

GL::RenderingProgram* Beatmup::NNets::Pooling2D::program
private

Definition at line 56 of file pooling2d.h.


The documentation for this class was generated from the following files: