31 #include <type_traits>
39 #include <cereal/cereal.hpp>
40 #include <cereal/archives/json.hpp>
41 #include <cereal/archives/binary.hpp>
42 #include <cereal/types/string.hpp>
43 #include <cereal/types/vector.hpp>
44 #include <cereal/types/deque.hpp>
46 #include "tiny_dnn/config.h"
47 #include "tiny_dnn/util/macro.h"
48 #include "tiny_dnn/util/aligned_allocator.h"
49 #include "tiny_dnn/util/nn_error.h"
50 #include "tiny_dnn/util/parallel_for.h"
51 #include "tiny_dnn/util/random.h"
53 #if defined(USE_OPENCL) || defined(USE_CUDA)
55 #include "third_party/CLCudaAPI/clpp11.h"
57 #include "third_party/CLCudaAPI/cupp11.h"
65 typedef serial_size_t label_t;
67 typedef serial_size_t layer_size_t;
69 typedef std::vector<float_t, aligned_allocator<float_t, 64>> vec_t;
71 typedef std::vector<vec_t> tensor_t;
73 enum class net_phase {
84 T* reverse_endian(T* p) {
85 std::reverse(
reinterpret_cast<char*
>(p),
reinterpret_cast<char*
>(p) +
sizeof(T));
89 inline bool is_little_endian() {
91 return *(
char*) &x != 0;
96 size_t max_index(
const T& vec) {
97 auto begin_iterator = std::begin(vec);
98 return std::max_element(begin_iterator, std::end(vec)) - begin_iterator;
101 template<
typename T,
typename U>
102 U rescale(T x, T src_min, T src_max, U dst_min, U dst_max) {
103 U value =
static_cast<U
>(((x - src_min) * (dst_max - dst_min)) / (src_max - src_min) + dst_min);
104 return std::min(dst_max, std::max(value, dst_min));
112 template <
typename T>
inline T sqr(T value) {
return value*value; }
114 inline bool isfinite(float_t x) {
118 template <
typename Container>
inline bool has_infinite(
const Container& c) {
120 if (!isfinite(v))
return true;
124 template <
typename Container>
125 serial_size_t max_size(
const Container& c) {
126 typedef typename Container::value_type value_t;
127 const auto max_size = std::max_element(c.begin(), c.end(),
128 [](
const value_t& left,
const value_t& right) { return left.size() < right.size(); })->size();
129 assert(max_size <= std::numeric_limits<serial_size_t>::max());
130 return static_cast<serial_size_t
>(max_size);
133 inline std::string format_str(
const char *fmt, ...) {
134 static char buf[2048];
137 #pragma warning(disable:4996)
141 vsnprintf(buf,
sizeof(buf), fmt, args);
144 #pragma warning(default:4996)
146 return std::string(buf);
149 template <
typename T>
151 index3d(T width, T height, T depth) {
152 reshape(width, height, depth);
155 index3d() : width_(0), height_(0), depth_(0) {}
157 void reshape(T width, T height, T depth) {
162 if ((
long long) width * height * depth > std::numeric_limits<T>::max())
164 format_str(
"error while constructing layer: layer size too large for tiny-dnn\nWidthxHeightxChannels=%dx%dx%d >= max size of [%s](=%d)",
165 width, height, depth,
typeid(T).name(), std::numeric_limits<T>::max()));
168 T get_index(T x, T y, T channel)
const {
169 assert(x >= 0 && x < width_);
170 assert(y >= 0 && y < height_);
171 assert(channel >= 0 && channel < depth_);
172 return (height_ * channel + y) * width_ + x;
176 return width_ * height_;
180 return width_ * height_ * depth_;
183 template <
class Archive>
184 void serialize(Archive & ar) {
185 ar(cereal::make_nvp(
"width", width_));
186 ar(cereal::make_nvp(
"height", height_));
187 ar(cereal::make_nvp(
"depth", depth_));
197 template <
typename T>
199 return (lhs.width_ == rhs.width_) && (lhs.height_ == rhs.height_) && (lhs.depth_ == rhs.depth_);
202 template <
typename T>
203 bool operator != (
const index3d<T>& lhs,
const index3d<T>& rhs) {
204 return !(lhs == rhs);
207 template <
typename Stream,
typename T>
208 Stream& operator << (Stream& s,
const index3d<T>& d) {
209 s << d.width_ <<
"x" << d.height_ <<
"x" << d.depth_;
213 template <
typename T>
214 std::ostream& operator << (std::ostream& s,
const index3d<T>& d) {
215 s << d.width_ <<
"x" << d.height_ <<
"x" << d.depth_;
219 template <
typename Stream,
typename T>
220 Stream& operator << (Stream& s,
const std::vector<index3d<T>>& d) {
222 for (serial_size_t i = 0; i < d.size(); i++) {
224 s <<
"[" << d[i] <<
"]";
231 template <
typename T>
232 std::string to_string(T value) {
233 std::ostringstream os;
239 #define CNN_USE_LAYER_MEMBERS using layer::parallelize_; \
240 using feedforward_layer<Activation>::h_
243 #define CNN_LOG_VECTOR(vec, name)
262 template <
typename T,
typename Pred,
typename Sum>
263 serial_size_t sumif(
const std::vector<T>& vec, Pred p, Sum s) {
264 serial_size_t sum = 0;
265 for (serial_size_t i = 0; i < static_cast<serial_size_t>(vec.size()); i++) {
266 if (p(i)) sum += s(vec[i]);
271 template <
typename T,
typename Pred>
272 std::vector<T> filter(
const std::vector<T>& vec, Pred p) {
274 for (
size_t i = 0; i < vec.size(); i++) {
275 if (p(i)) res.push_back(vec[i]);
280 template <
typename Result,
typename T,
typename Pred>
281 std::vector<Result> map_(
const std::vector<T>& vec, Pred p) {
282 std::vector<Result> res;
283 for (
auto& v : vec) {
289 enum class vector_type : int32_t {
301 inline std::string to_string(vector_type vtype) {
304 case tiny_dnn::vector_type::data:
306 case tiny_dnn::vector_type::weight:
308 case tiny_dnn::vector_type::bias:
310 case tiny_dnn::vector_type::label:
312 case tiny_dnn::vector_type::aux:
319 inline std::ostream& operator << (std::ostream& os, vector_type vtype) {
320 os << to_string(vtype);
324 inline vector_type operator & (vector_type lhs, vector_type rhs) {
325 return (vector_type)(
static_cast<int32_t
>(lhs) &
static_cast<int32_t
>(rhs));
328 inline bool is_trainable_weight(vector_type vtype) {
329 return (vtype & vector_type::weight) == vector_type::weight;
332 inline std::vector<vector_type> std_input_order(
bool has_bias) {
334 return{ vector_type::data, vector_type::weight, vector_type::bias };
337 return{ vector_type::data, vector_type::weight };
341 inline std::vector<vector_type> std_output_order(
bool has_activation) {
342 if (has_activation) {
343 return{ vector_type::data, vector_type::aux };
346 return{ vector_type::data };
350 inline void fill_tensor(tensor_t& tensor, float_t value) {
351 for (
auto& t : tensor) {
352 std::fill(t.begin(), t.end(), value);
356 inline void fill_tensor(tensor_t& tensor, float_t value, serial_size_t size) {
357 for (
auto& t : tensor) {
358 t.resize(size, value);
362 inline serial_size_t conv_out_length(serial_size_t in_length,
363 serial_size_t window_size,
364 serial_size_t stride,
366 serial_size_t output_length;
368 if (pad_type == padding::same) {
369 output_length = in_length;
371 else if (pad_type == padding::valid) {
372 output_length = in_length - window_size + 1;
375 throw nn_error(
"Not recognized pad_type.");
377 return (output_length + stride - 1) / stride;
383 inline void printAvailableDevice(
const serial_size_t platform_id,
384 const serial_size_t device_id) {
385 #if defined(USE_OPENCL) || defined(USE_CUDA)
388 auto platform = CLCudaAPI::Platform(platform_id);
389 auto device = CLCudaAPI::Device(platform, device_id);
393 printf(
"\n## Printing device information...\n");
394 printf(
" > Platform ID %zu\n", platform_id);
395 printf(
" > Device ID %zu\n", device_id);
396 printf(
" > Framework version %s\n", device.Version().c_str());
397 printf(
" > Vendor %s\n", device.Vendor().c_str());
398 printf(
" > Device name %s\n", device.Name().c_str());
399 printf(
" > Device type %s\n", device.Type().c_str());
400 printf(
" > Max work-group size %zu\n", device.MaxWorkGroupSize());
401 printf(
" > Max thread dimensions %zu\n", device.MaxWorkItemDimensions());
402 printf(
" > Max work-group sizes:\n");
403 for (
auto i=
size_t{0}; i<device.MaxWorkItemDimensions(); ++i) {
404 printf(
" - in the %zu-dimension %zu\n", i, device.MaxWorkItemSizes()[i]);
406 printf(
" > Local memory per work-group %zu bytes\n", device.LocalMemSize());
407 printf(
" > Device capabilities %s\n", device.Capabilities().c_str());
408 printf(
" > Core clock rate %zu MHz\n", device.CoreClock());
409 printf(
" > Number of compute units %zu\n", device.ComputeUnits());
410 printf(
" > Total memory size %zu bytes\n", device.MemorySize());
411 printf(
" > Maximum allocatable memory %zu bytes\n", device.MaxAllocSize());
412 printf(
" > Memory clock rate %zu MHz\n", device.MemoryClock());
413 printf(
" > Memory bus width %zu bits\n", device.MemoryBusWidth());
415 nn_warn(
"TinyDNN was not build with OpenCL or CUDA support.");
419 template<
typename T,
typename... Args>
420 std::unique_ptr<T> make_unique(Args&&... args)
422 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
error exception class for tiny-dnn
Definition: nn_error.h:37