Beatmup
dense.cpp
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2020, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "dense.h"
20 #include "deserialized_model.h"
21 
22 using namespace Beatmup;
23 using namespace NNets;
24 
25 
26 const char *Dense::MATRIX_CHUNK_SUFFIX = "/w";
27 const char *Dense::BIAS_CHUNK_SUFFIX = "/b";
28 
29 
30 Dense::Dense(Context& context, const std::string& name, const int numOutputDims, bool useBias):
32  LinearMapping(context, false),
33  numOutputDims(numOutputDims), useBias(useBias), inputVector(nullptr), outputVector(nullptr)
34 {
35  OutOfRange::checkMin(numOutputDims, 1, "Positive number of output dimensions expected, %d got");
37 }
38 
39 
40 void Dense::getOutput(GL::Vector* &vector, int index) {
41  OutOfRange::check(index, 0, 1, "Output index out of range: %d");
42  vector = this->outputVector;
43 }
44 
45 
46 void Dense::setInput(Storage::View&& view, int index) {
47  OutOfRange::check(index, 0, 1, "Input index out of range: %d");
48  if (view) {
49  RuntimeError::check(view.getStorage().getPadding() == 0, "Storages with padding are not supported");
50  const auto& storage = view.getStorage();
51  RuntimeError::check(view.getNumberOfTextures() == 1 && storage.getTextureWidth() == 1, "Input size mismatch: a column-like view is expected");
52  }
53  inputStorage = std::move(view);
54  inputVector = nullptr;
55 }
56 
57 
58 void Dense::setInput(GL::Vector& vector, int index) {
59  OutOfRange::check(index, 0, 1, "Input index out of range: %d");
61  inputVector = &vector;
62 }
63 
64 
65 void Dense::setOutput(GL::Vector& vector, int index) {
66  outputVector = &vector;
67 }
68 
69 
71 #ifdef BEATMUP_OPENGLVERSION_GLES20
73 #else
75 #endif
76 }
77 
78 
79 std::map<std::string, std::string> Dense::serialize() const {
80  return {
81  { "_name", getName() },
82  { "_type", "dense" },
83  { "output_dims", std::to_string(numOutputDims) },
84  { "use_bias", useBias ? "true" : "false" },
85  };
86 }
87 
88 
90  static class DenseDeserializer : public AbstractOperation::Deserializer {
91  public:
92  DenseDeserializer() : Deserializer("dense") {}
93  AbstractOperation* deserialize(Context& context, const Listing::Block& block) {
94  /** \page NNetsOpsSerialization
95  \section Dense
96  \code{yaml}
97  - _name: arbitrary operation name
98  _type: dense # fixed string
99  use_bias: true # bias addition, "true" or "false"
100  \endcode
101  */
102  return new Dense(context,
103  block["_name"],
104  block.get<int>("output_dims"),
105  block.get<bool>("use_bias")
106  );
107  }
108  } john;
109 
110  return true;
111 }
112 
113 
115  inputVector = nullptr;
117  outputVector = nullptr;
118 }
119 
120 
121 unsigned long Dense::countMultiplyAdds() const {
122  const int numInputDims = inputVector ? inputVector->getSize() : inputStorage.getSize().volume();
123  return numInputDims * numOutputDims;
124 }
125 
126 
127 unsigned long Dense::countTexelFetches() const {
128  const unsigned long numInputDims = inputVector ? inputVector->getSize() : inputStorage.getSize().volume();
129  // sampling the matrix
130  unsigned long count = numInputDims * numOutputDims / 4;
131  // sampling the bias
132  if (useBias)
133  count += numOutputDims / 4;
134 #ifdef BEATMUP_OPENGLVERSION_GLES20
135  // using 16 bit fixed point format
136  count *= 2;
137 #endif
138  // sampling the input vector
140  return count;
141 }
142 
143 
145  RuntimeError::check(inputVector || inputStorage, "Input is not provided to Dense operation " + getName());
146  RuntimeError::check(outputVector, "Output is not provided to Dense operation " + getName());
147 
148  const int numInputDims = inputVector ? inputVector->getSize() : inputStorage.getSize().volume();
149 
150  // set matrix
151  const Chunk matrix(data, getName() + MATRIX_CHUNK_SUFFIX);
152  if (matrix.size() != numInputDims * numOutputDims * sizeof(float))
153  throw InconsistentModelData(this, "Matrix size mismatch");
154  LinearMapping::setMatrix(gpu, numInputDims, numOutputDims, matrix.ptr<float>());
155 
156  // set bias
157  if (useBias) {
158  const Chunk bias(data, getName() + BIAS_CHUNK_SUFFIX);
159  if (bias.size() != numOutputDims * sizeof(float))
160  throw InconsistentModelData(this, "Bias size mismatch");
161  LinearMapping::setBias(gpu, numOutputDims, bias.ptr<float>());
162  }
163 
164  // prepare
165  if (inputVector) {
166  LinearMapping::prepare(gpu, *outputVector, *inputVector, &bank);
167  }
168  else {
169  Storage::TextureHandler inputHandle(inputStorage, 0);
170  LinearMapping::prepare(gpu, *outputVector, inputHandle, &bank);
171  }
172 }
173 
174 
176  if (inputVector) {
177  LinearMapping::process(gpu, *outputVector, *inputVector);
178  }
179  else {
180  Storage::TextureHandler inputHandle(inputStorage, 0);
181  LinearMapping::process(gpu, *outputVector, inputHandle);
182  }
183 }
184 
185 
186 void Dense::getSampledChannels(int index, int& min, int& max) const {
187  min = max = (index == 0 ? 4 : 0);
188 }
A key-value pair set storing pieces of arbitrary data (chunks) under string keys.
Definition: chunkfile.h:36
Simply a piece of binary data of a specific size.
Definition: chunkfile.h:210
Basic class: task and memory management, any kind of static data.
Definition: context.h:59
Matrix * matrix
the matrix ("A")
Vector * bias
optional bias vector ("b")
Stores linked GLSL programs and their associated fragment shader codes.
Definition: program_bank.h:31
Real-valued vector usable by GPU.
const int getHeight() const
Height of the texture in pixels.
const int size
number of samples in the vector
int getSize() const
Returns the length of the vector.
Format
Vector data format.
@ FIXED16
16 bit per element
@ FLOAT
32 bit per element, floating point
Internal low-level GPU control API.
Definition: pipeline.h:33
Set of key-value pairs.
Definition: listing.h:46
T get(const std::string &key) const
Returns a value by key casted to a given type.
Enables construction of an operation from its serialized representation.
Definition: operation.h:248
Abstract neural net operation (layer).
Definition: operation.h:46
std::string getName() const
Definition: operation.h:242
static const char * BIAS_CHUNK_SUFFIX
suffix added to the op name to get the bias chunk id in the model data
Definition: dense.h:56
GL::Vector * outputVector
pointer to the output vector
Definition: dense.h:47
GL::Vector * inputVector
if not null, points the input vector x; otherwise the input is a storage view
Definition: dense.h:46
void setInput(Storage::View &&view, int index=0)
Definition: dense.cpp:46
static const char * MATRIX_CHUNK_SUFFIX
suffix added to the op name to get the matrix chunk id in the model data
Definition: dense.h:55
void setOutput(GL::Vector &vector, int index=0)
Definition: dense.cpp:65
unsigned long countMultiplyAdds() const
Counts (approximate) number of multiply-adds used by this operation.
Definition: dense.cpp:121
GL::Vector::Format getOutputVectorFormat() const
Definition: dense.cpp:70
unsigned long countTexelFetches() const
Counts (approximate) number of texels fetches.
Definition: dense.cpp:127
void getOutput(GL::Vector *&, int index=0)
Returns a GL::Vector bound to a specific operation output.
Definition: dense.cpp:40
Storage::View inputStorage
if not empty, contains the input features; otherwise the input is a GL vector
Definition: dense.h:48
void getSampledChannels(int index, int &min, int &max) const
Retrieves range of input features channels sampled at the same time for a specific input.
Definition: dense.cpp:186
std::map< std::string, std::string > serialize() const
Returns a serialized representation of th operation;.
Definition: dense.cpp:79
static bool initDeserializer()
Sets up deserialization of the operation.
void execute(TaskThread &thread, GraphicPipeline &gpu)
Executes the operation.
Definition: dense.cpp:175
Dense(Context &context, const std::string &name, int numOutputDims, bool useBias)
Creates a Dense operation.
Definition: dense.cpp:30
const bool useBias
if true, the bias vector b is searched in the model data to add to the output
Definition: dense.h:45
const int numOutputDims
output feature vector size / number of rows in A
Definition: dense.h:44
void prepare(GraphicPipeline &gpu, ChunkCollection &data, GL::ProgramBank &bank)
Compiles GLSL shaders.
Definition: dense.cpp:144
void disconnect()
Assigns empty inputs and outputs.
Definition: dense.cpp:114
int volume() const
Definition: storage.h:79
TextureHandler representation of a pack of 4 channels from a non-empty View.
Definition: storage.h:403
Maps a 3D tensor onto a storage.
Definition: storage.h:308
friend class View
Definition: storage.h:135
static void checkChannelNumber(int channel)
Checks whether a channel number points to the first channel in a texture.
Definition: storage.h:290
static void checkMin(const datatype value, const datatype min, const char *message)
Definition: exception.h:92
static void check(const datatype value, const datatype min, const datatype max, const char *message)
Definition: exception.h:86
static void check(const bool condition, const std::string &message)
Definition: exception.h:64
Thread executing tasks.
Definition: parallelism.h:154
std::string to_string(Beatmup::NNets::ActivationFunction function)
CustomPoint< numeric > min(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:724
CustomPoint< numeric > max(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:728
return(jlong) new Beatmup jlong jstring name
jlong jint index
JNIEnv jlong jint jint count