summaryrefslogtreecommitdiff
path: root/compiler/souschef/src/Gaussian.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/souschef/src/Gaussian.cpp')
-rw-r--r--compiler/souschef/src/Gaussian.cpp121
1 files changed, 91 insertions, 30 deletions
diff --git a/compiler/souschef/src/Gaussian.cpp b/compiler/souschef/src/Gaussian.cpp
index 4a5083d8e..71ab56792 100644
--- a/compiler/souschef/src/Gaussian.cpp
+++ b/compiler/souschef/src/Gaussian.cpp
@@ -22,26 +22,32 @@
#include <cassert>
#include <stdexcept>
+#include <limits> // std::numeric_limits
+
+#include <fp16.h>
namespace souschef
{
-std::vector<uint8_t> GaussianFloat32DataChef::generate(int32_t count) const
+template <typename T>
+static std::vector<uint8_t> generate_gaussian(int32_t count, float mean, float stddev,
+ std::minstd_rand::result_type seed)
{
- // TODO Support seed value override
- auto seed = std::chrono::system_clock::now().time_since_epoch().count();
-
std::minstd_rand rand{static_cast<std::minstd_rand::result_type>(seed)};
- std::normal_distribution<float> dist{_mean, _stddev};
+ std::normal_distribution<float> dist{mean, stddev};
std::vector<uint8_t> res;
+ constexpr float max_cap = std::numeric_limits<T>::max();
+ constexpr float min_cap = std::numeric_limits<T>::lowest();
for (uint32_t n = 0; n < count; ++n)
{
- auto const value = dist(rand);
+ float raw_value = dist(rand);
+ const float capped_value = std::max(min_cap, std::min(max_cap, raw_value));
+ auto const value = static_cast<T>(capped_value);
auto const arr = reinterpret_cast<const uint8_t *>(&value);
- for (uint32_t b = 0; b < sizeof(float); ++b)
+ for (uint32_t b = 0; b < sizeof(T); ++b)
{
res.emplace_back(arr[b]);
}
@@ -50,22 +56,42 @@ std::vector<uint8_t> GaussianFloat32DataChef::generate(int32_t count) const
return res;
}
-std::vector<uint8_t> GaussianInt32DataChef::generate(int32_t count) const
+template <typename T>
+static std::vector<uint8_t> generate_gaussian(int32_t count, float mean, float stddev)
{
- // TODO Support seed value override
- auto seed = std::chrono::system_clock::now().time_since_epoch().count();
+ auto time_stamp = std::chrono::system_clock::now().time_since_epoch().count();
+
+ // Note this is implementation defined, change if needed.
+ auto seed = static_cast<std::minstd_rand::result_type>(time_stamp);
+
+ return generate_gaussian<T>(count, mean, stddev, seed);
+}
+
+std::vector<uint8_t> GaussianFloat32DataChef::generate(int32_t count) const
+{
+ return generate_gaussian<float>(count, _mean, _stddev);
+}
+
+std::vector<uint8_t> GaussianFloat16DataChef::generate(int32_t count) const
+{
+ auto time_stamp = std::chrono::system_clock::now().time_since_epoch().count();
+ auto seed = static_cast<std::minstd_rand::result_type>(time_stamp);
std::minstd_rand rand{static_cast<std::minstd_rand::result_type>(seed)};
std::normal_distribution<float> dist{_mean, _stddev};
std::vector<uint8_t> res;
+ constexpr float max_cap = 1e9;
+ constexpr float min_cap = -1e9;
for (uint32_t n = 0; n < count; ++n)
{
- auto const value = static_cast<int32_t>(dist(rand));
+ float raw_value = dist(rand);
+ const float capped_value = std::max(min_cap, std::min(max_cap, raw_value));
+ const uint16_t value = fp16_ieee_from_fp32_value(capped_value);
auto const arr = reinterpret_cast<const uint8_t *>(&value);
- for (uint32_t b = 0; b < sizeof(int32_t); ++b)
+ for (uint32_t b = 0; b < sizeof(uint16_t); ++b)
{
res.emplace_back(arr[b]);
}
@@ -74,28 +100,24 @@ std::vector<uint8_t> GaussianInt32DataChef::generate(int32_t count) const
return res;
}
-std::vector<uint8_t> GaussianUint8DataChef::generate(int32_t count) const
+std::vector<uint8_t> GaussianInt32DataChef::generate(int32_t count) const
{
- // TODO Support seed value override
- auto seed = std::chrono::system_clock::now().time_since_epoch().count();
-
- std::minstd_rand rand{static_cast<std::minstd_rand::result_type>(seed)};
- std::normal_distribution<float> dist{_mean, _stddev};
-
- std::vector<uint8_t> res;
+ return generate_gaussian<int32_t>(count, _mean, _stddev);
+}
- for (uint32_t n = 0; n < count; ++n)
- {
- auto const value = static_cast<uint8_t>(dist(rand)); // uint8_t for data type
- auto const arr = reinterpret_cast<const uint8_t *>(&value); // uint8_t for byte streaming
+std::vector<uint8_t> GaussianInt16DataChef::generate(int32_t count) const
+{
+ return generate_gaussian<int16_t>(count, _mean, _stddev);
+}
- for (uint32_t b = 0; b < sizeof(uint8_t); ++b)
- {
- res.emplace_back(arr[b]);
- }
- }
+std::vector<uint8_t> GaussianUint8DataChef::generate(int32_t count) const
+{
+ return generate_gaussian<uint8_t>(count, _mean, _stddev);
+}
- return res;
+std::vector<uint8_t> GaussianInt8DataChef::generate(int32_t count) const
+{
+ return generate_gaussian<int8_t>(count, _mean, _stddev);
}
std::unique_ptr<DataChef> GaussianFloat32DataChefFactory::create(const Arguments &args) const
@@ -124,6 +146,19 @@ std::unique_ptr<DataChef> GaussianInt32DataChefFactory::create(const Arguments &
return std::unique_ptr<DataChef>{new GaussianInt32DataChef{mean, stddev}};
}
+std::unique_ptr<DataChef> GaussianInt16DataChefFactory::create(const Arguments &args) const
+{
+ if (args.count() != 2)
+ {
+ throw std::runtime_error{"invalid argument count: two arguments (mean/stddev) are expected"};
+ }
+
+ auto const mean = to_number<float>(args.value(0));
+ auto const stddev = to_number<float>(args.value(1));
+
+ return std::unique_ptr<DataChef>{new GaussianInt16DataChef{mean, stddev}};
+}
+
std::unique_ptr<DataChef> GaussianUint8DataChefFactory::create(const Arguments &args) const
{
if (args.count() != 2)
@@ -137,4 +172,30 @@ std::unique_ptr<DataChef> GaussianUint8DataChefFactory::create(const Arguments &
return std::unique_ptr<DataChef>{new GaussianUint8DataChef{mean, stddev}};
}
+std::unique_ptr<DataChef> GaussianInt8DataChefFactory::create(const Arguments &args) const
+{
+ if (args.count() != 2)
+ {
+ throw std::runtime_error{"invalid argument count: two arguments (mean/stddev) are expected"};
+ }
+
+ auto const mean = to_number<float>(args.value(0));
+ auto const stddev = to_number<float>(args.value(1));
+
+ return std::unique_ptr<DataChef>{new GaussianInt8DataChef{mean, stddev}};
+}
+
+std::unique_ptr<DataChef> GaussianFloat16DataChefFactory::create(const Arguments &args) const
+{
+ if (args.count() != 2)
+ {
+ throw std::runtime_error{"invalid argument count: two arguments (mean/stddev) are expected"};
+ }
+
+ auto const mean = to_number<float>(args.value(0));
+ auto const stddev = to_number<float>(args.value(1));
+
+ return std::unique_ptr<DataChef>{new GaussianFloat16DataChef{mean, stddev}};
+}
+
} // namespace souschef