gpu.cpp 0.1.0
 
Loading...
Searching...
No Matches
array_utils.h
Go to the documentation of this file.
1/*
2 * array_utils.h
3 *
4 * This file contains utility functions for working with arrays. These are
5 * mostly convenience functions for setting up and inspecting data for testing.
6 * They are not optimized and are not intended for use in performance-critical
7 * code.
8 *
9 */
10
11#ifndef ARRAY_UTILS_H
12#define ARRAY_UTILS_H
13
14#include <algorithm> // std::max_element
15#include <array>
16#include <cmath>
17#include <random>
18#include <stdexcept>
19#include <string>
20#include <utility>
21
22#include "utils/logging.h"
23
24namespace gpu {
25
26static constexpr int kShowMaxRows = 8;
27static constexpr int kShowMaxCols = 8;
28
42template <typename numtype>
43std::string show(const numtype *a, size_t rows, size_t cols,
44 const std::string &name = "") {
45 std::string output = "\n";
46 if (name != "") {
47 output += "\n" + name + " (" + std::to_string(rows) + ", " +
48 std::to_string(cols) + ")\n\n";
49 } else {
50 output +=
51 "\n(" + std::to_string(rows) + ", " + std::to_string(cols) + ")\n\n";
52 }
53 // spacing as log10 of max value
54 int spacing = 1;
55 numtype max = *std::max_element(a, a + rows * cols);
56 if constexpr (std::is_same<numtype, int>::value) {
57 spacing = std::max(0, (int)log10(max + .01)) + 2;
58 } else if constexpr (std::is_same<numtype, float>::value) {
59 // spacing = std::max(0, (int)log10(max + .01)) + 1;
60 spacing = 8; // scientific notation
61 } else {
62 throw std::runtime_error("Unsupported number type for show()");
63 }
64 // print to stdout line break for each row
65 for (size_t i = 0; i < rows; i++) {
66 if (i == kShowMaxRows / 2 && rows > kShowMaxRows) {
67 output += "...\n";
68 i = rows - kShowMaxRows / 2;
69 }
70 for (size_t j = 0; j < cols; j++) {
71 if (j == kShowMaxCols / 2 && cols > kShowMaxCols) {
72 output += " ..";
73 j = cols - kShowMaxCols / 2;
74 }
75 char buffer[50];
76 if constexpr (std::is_same<numtype, int>::value) {
77 snprintf(buffer, spacing, "%*d", spacing, a[i * cols + j]);
78 } else if constexpr (std::is_same<numtype, float>::value) {
79 if (std::abs(a[i * cols + j]) < 1000 &&
80 std::abs(a[i * cols + j]) > 0.01 ||
81 a[i * cols + j] == 0.0) {
82 snprintf(buffer, 16, "%9.2f", a[i * cols + j]);
83 } else
84 snprintf(buffer, 16, "%10.2e", a[i * cols + j]);
85 } else {
86 throw std::runtime_error("Unsupported number type for show()");
87 }
88 output += buffer;
89 }
90 output += "\n";
91 }
92 output += "\n";
93 return output;
94}
95
107template <typename numtype, size_t rows, size_t cols>
108std::string show(const std::array<numtype, rows * cols> &a,
109 const std::string &name = "") {
110 return show<numtype>(a.data(), rows, cols, name);
111}
112
125template <size_t rows, size_t cols>
126std::string show(const std::array<float, rows * cols> &a,
127 const std::string &name = "") {
128 return show<float, rows, cols>(a, name);
129}
130
139void range(float *input, size_t N, float start = 0.0, float step = 1.0) {
140 // TODO(avh): currently unused - check
141 float curr = start;
142 for (size_t i = 0; i < N; i++) {
143 input[i] = curr;
144 curr += step;
145 }
146}
147
154template <size_t N>
155void range(std::array<float, N> &input, float start = 0.0, float step = 1.0) {
156 float curr = start;
157 for (size_t i = start; i < N; i++) {
158 input[i] = curr;
159 curr += step;
160 }
161}
162
171void randint(float *a, size_t N, std::mt19937 &gen, int min = -1, int max = 1) {
172 std::uniform_int_distribution<> dist(min, max);
173 for (int i = 0; i < N; i++) {
174 a[i] = static_cast<float>(dist(gen));
175 }
176}
177
185template <typename numtype, size_t size>
186void randint(std::array<numtype, size> &a, std::mt19937 &gen, int min = -1,
187 int max = 1) {
188 std::uniform_int_distribution<> dist(min, max);
189 for (int i = 0; i < size; i++) {
190 a[i] = static_cast<numtype>(dist(gen));
191 }
192}
193
202void randn(float *a, size_t N, std::mt19937 &gen, float mean = 0.0,
203 float std = 1.0) {
204 std::normal_distribution<float> dist(mean, std);
205 for (int i = 0; i < N; i++) {
206 a[i] = static_cast<float>(dist(gen));
207 }
208}
209
217template <size_t size>
218void randn(std::array<float, size> &a, std::mt19937 &gen, float mean = 0.0,
219 float std = 1.0) {
220 std::normal_distribution<float> dist(mean, std);
221 for (int i = 0; i < size; i++) {
222 a[i] = static_cast<float>(dist(gen));
223 }
224}
225
231inline void eye(float *a, size_t N) {
232 for (size_t i = 0; i < N; i++) {
233 for (size_t j = 0; j < N; j++) {
234 a[i * N + j] = (i == j) ? 1.0 : 0.0;
235 }
236 }
237}
238
239// Note transformation operations here are purely for testing - they are not
240// optimized to be used in hot paths.
241
249inline void transpose(float *input, float *output, size_t M, size_t N) {
250 for (size_t i = 0; i < M; i++) {
251 for (size_t j = 0; j < N; j++) {
252 output[j * M + i] = input[i * N + j];
253 }
254 }
255}
256
264inline void flip(float *a, size_t R, size_t C, bool horizontal = true) {
265 if (horizontal) {
266 for (size_t i = 0; i < R; i++) {
267 for (size_t j = 0; j < C / 2; j++) {
268 std::swap(a[i * C + j], a[i * C + C - j - 1]);
269 }
270 }
271 } else {
272 for (size_t i = 0; i < R / 2; i++) {
273 for (size_t j = 0; j < C; j++) {
274 std::swap(a[i * C + j], a[(R - i - 1) * C + j]);
275 }
276 }
277 }
278}
279
288bool isclose(float *a, float *b, size_t n, float tol = 1e-3) {
289 for (size_t i = 0; i < n; i++) {
290 if (std::abs(a[i] - b[i]) > tol || std::isnan(a[i]) || std::isnan(b[i])) {
291 LOG(kDefLog, kError, "Mismatch at index %d: %f != %f", i, a[i], b[i]);
292 return false;
293 }
294 }
295 return true;
296}
297
298} // namespace gpu
299
300#endif
Definition gpu.h:27
static Logger kDefLog
Default logger for logging messages to stdout at the info level. Output stream and logging level for ...
Definition logging.h:64
void range(float *input, size_t N, float start=0.0, float step=1.0)
Populate the array with a range of values. This is mostly for testing purposes.
void LOG(Logger &logger, int level, const char *message,...)
Log a message to the logger. If NDEBUG is defined in a source or as a compiler flag,...
Definition logging.h:34
void eye(float *a, size_t N)
Populate a square matrix with the identity matrix.
void randn(float *a, size_t N, std::mt19937 &gen, float mean=0.0, float std=1.0)
Populate the array with random floats, generated from a Gaussian distribution.
bool isclose(float *a, float *b, size_t n, float tol=1e-3)
Determine if the values of two arrays are close to each other.
std::string show(const numtype *a, size_t rows, size_t cols, const std::string &name="")
Show a 2D array as a string, base implementation.
Definition array_utils.h:43
@ kError
Definition logging.h:9
void transpose(float *input, float *output, size_t M, size_t N)
Transpose a matrix.
void randint(float *a, size_t N, std::mt19937 &gen, int min=-1, int max=1)
Populate the array with random integers.
static constexpr int kShowMaxCols
Definition array_utils.h:27
size_t size(const Shape &shape)
Returns the number of elements in a tensor with the given shape, which is equal to the product of the...
Definition gpu.h:80
static constexpr int kShowMaxRows
Definition array_utils.h:26
void flip(float *a, size_t R, size_t C, bool horizontal=true)
Flip a matrix horizontally or vertically.