sec fix uniform real op
This commit is contained in:
parent
d512872ca8
commit
2b723e72a5
|
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "src/runtime/kernel/arm/fp32/uniform_real_fp32.h"
|
||||
#include "src/kernel_registry.h"
|
||||
#include "include/errorcode.h"
|
||||
|
|
@ -24,6 +25,177 @@ using mindspore::lite::RET_OK;
|
|||
using mindspore::schema::PrimitiveType_UniformReal;
|
||||
|
||||
namespace mindspore::kernel {
|
||||
|
||||
template <typename T, int ElementCount>
|
||||
class Array {
|
||||
public:
|
||||
Array() {
|
||||
for (int i = 0; i < ElementCount; ++i) {
|
||||
data_[i] = T(0);
|
||||
}
|
||||
}
|
||||
|
||||
const T &operator[](int index) const { return data_[index]; }
|
||||
|
||||
T &operator[](int index) { return data_[index]; }
|
||||
|
||||
private:
|
||||
T data_[ElementCount];
|
||||
};
|
||||
|
||||
class PhiloxRandom {
|
||||
public:
|
||||
using ResultType = Array<uint32_t, 4>;
|
||||
using Key = Array<uint32_t, 2>;
|
||||
|
||||
explicit PhiloxRandom(uint64_t seed_lo, uint64_t seed_hi) {
|
||||
key_[0] = static_cast<uint32_t>(seed_lo);
|
||||
key_[1] = static_cast<uint32_t>(seed_lo >> 32);
|
||||
counter_[2] = static_cast<uint32_t>(seed_hi);
|
||||
counter_[3] = static_cast<uint32_t>(seed_hi >> 32);
|
||||
}
|
||||
|
||||
// Skip the specified number of samples of 128-bits in the current stream.
|
||||
void Skip(uint64_t count) {
|
||||
const uint32_t count_lo = static_cast<uint32_t>(count);
|
||||
uint32_t count_hi = static_cast<uint32_t>(count >> 32);
|
||||
|
||||
counter_[0] += count_lo;
|
||||
if (counter_[0] < count_lo) {
|
||||
++count_hi;
|
||||
}
|
||||
|
||||
counter_[1] += count_hi;
|
||||
if (counter_[1] < count_hi) {
|
||||
if (++counter_[2] == 0) {
|
||||
++counter_[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a group of four random numbers using the underlying Philox
|
||||
// algorithm.
|
||||
ResultType operator()() {
|
||||
ResultType counter = counter_;
|
||||
Key key = key_;
|
||||
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
RaiseKey(&key);
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
RaiseKey(&key);
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
RaiseKey(&key);
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
RaiseKey(&key);
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
RaiseKey(&key);
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
RaiseKey(&key);
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
RaiseKey(&key);
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
RaiseKey(&key);
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
RaiseKey(&key);
|
||||
counter = ComputeSingleRound(counter, key);
|
||||
|
||||
SkipOne();
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
private:
|
||||
// We use the same constants as recommended by the original paper.
|
||||
static constexpr uint32_t kPhiloxW32A = 0x9E3779B9;
|
||||
static constexpr uint32_t kPhiloxW32B = 0xBB67AE85;
|
||||
static constexpr uint32_t kPhiloxM4x32A = 0xD2511F53;
|
||||
static constexpr uint32_t kPhiloxM4x32B = 0xCD9E8D57;
|
||||
|
||||
// Helper function to skip the next sample of 128-bits in the current stream.
|
||||
void SkipOne() {
|
||||
if (++counter_[0] == 0) {
|
||||
if (++counter_[1] == 0) {
|
||||
if (++counter_[2] == 0) {
|
||||
++counter_[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MultiplyHighLow(uint32_t a, uint32_t b, uint32_t *result_low, uint32_t *result_high) {
|
||||
const uint64_t product = static_cast<uint64_t>(a) * b;
|
||||
*result_low = static_cast<uint32_t>(product);
|
||||
*result_high = static_cast<uint32_t>(product >> 32);
|
||||
}
|
||||
|
||||
// Helper function for a single round of the underlying Philox algorithm.
|
||||
static ResultType ComputeSingleRound(const ResultType &counter, const Key &key) {
|
||||
uint32_t lo0;
|
||||
uint32_t hi0;
|
||||
MultiplyHighLow(kPhiloxM4x32A, counter[0], &lo0, &hi0);
|
||||
|
||||
uint32_t lo1;
|
||||
uint32_t hi1;
|
||||
MultiplyHighLow(kPhiloxM4x32B, counter[2], &lo1, &hi1);
|
||||
|
||||
ResultType result;
|
||||
result[0] = hi1 ^ counter[1] ^ key[0];
|
||||
result[1] = lo1;
|
||||
result[2] = hi0 ^ counter[3] ^ key[1];
|
||||
result[3] = lo0;
|
||||
return result;
|
||||
}
|
||||
|
||||
void RaiseKey(Key *key) {
|
||||
(*key)[0] += kPhiloxW32A;
|
||||
(*key)[1] += kPhiloxW32B;
|
||||
}
|
||||
|
||||
private:
|
||||
ResultType counter_;
|
||||
Key key_;
|
||||
};
|
||||
|
||||
float uint32ToFloat(uint32_t x) {
|
||||
const uint32_t man = x & 0x7fffffu; // 23 bit mantissa
|
||||
const uint32_t exp = static_cast<uint32_t>(127);
|
||||
const uint32_t val = (exp << 23) | man;
|
||||
|
||||
// Assumes that endian-ness is same for float and uint32_t.
|
||||
float result;
|
||||
memcpy(&result, &val, sizeof(val));
|
||||
return result - 1.0f;
|
||||
}
|
||||
|
||||
void GetPhiloxRandomFloat(float *data, size_t length, int seed, int seed2) {
|
||||
PhiloxRandom philoxRandom(seed, seed2);
|
||||
if (length < 4) {
|
||||
auto randNum = philoxRandom.operator()();
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
data[i] = uint32ToFloat(randNum[i]);
|
||||
}
|
||||
} else {
|
||||
auto randNum = philoxRandom.operator()();
|
||||
data[0] = uint32ToFloat(randNum[0]);
|
||||
data[1] = uint32ToFloat(randNum[1]);
|
||||
data[2] = uint32ToFloat(randNum[2]);
|
||||
data[3] = uint32ToFloat(randNum[3]);
|
||||
for (size_t i = 1; i < length / 4; i++) {
|
||||
philoxRandom.Skip(0);
|
||||
randNum = philoxRandom.operator()();
|
||||
data[4 * i] = uint32ToFloat(randNum[0]);
|
||||
data[4 * i + 1] = uint32ToFloat(randNum[1]);
|
||||
data[4 * i + 2] = uint32ToFloat(randNum[2]);
|
||||
data[4 * i + 3] = uint32ToFloat(randNum[3]);
|
||||
}
|
||||
philoxRandom.Skip(0);
|
||||
randNum = philoxRandom.operator()();
|
||||
for (size_t i = 0; i < length % 4; i++) {
|
||||
data[4 * (length / 4) + i] = uint32ToFloat(randNum[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int UniformRealCPUKernel::Init() { return RET_OK; }
|
||||
|
||||
int UniformRealCPUKernel::ReSize() { return RET_OK; }
|
||||
|
|
@ -35,6 +207,10 @@ int UniformRealCPUKernel::Run() {
|
|||
MS_LOG(ERROR) << "seed_:" << seed_ << " and seed2_:" << seed2_ << " must be greater than 0!";
|
||||
return RET_ERROR;
|
||||
}
|
||||
if (seed_ > 0 && seed2_ > 0) {
|
||||
GetPhiloxRandomFloat(output0, out_tensors_.at(0)->ElementsNum(), seed_, seed2_);
|
||||
return RET_OK;
|
||||
}
|
||||
std::srand(seed_ || seed2_);
|
||||
for (int i = 0; i < out_tensors_.at(0)->ElementsNum(); ++i) {
|
||||
output0[i] = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
|
||||
|
|
|
|||
|
|
@ -11,3 +11,4 @@ decoder.onnx;2;1,7,512:1,7
|
|||
fasterrcnn_crop.pb;1;420,630,3
|
||||
ml_video_edit_person_divison_video;2
|
||||
hdc_tb_cn_neg.tflite;3
|
||||
ml_tacotron_decoder_step_stf.tflite;9;1,80:1,256:1,1024:1,1024:1,1024:1,1024:1,8:1,1,256:1
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ TEST_F(TestUniformRealFp32, UniformReal) {
|
|||
parameter.op_parameter_.type_ = schema::PrimitiveType_UniformReal;
|
||||
parameter.seed_ = 42;
|
||||
parameter.seed2_ = 959;
|
||||
kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeFloat32, schema::PrimitiveType_UniformReal};
|
||||
kernel::KernelKey desc = {kernel::KERNEL_ARCH::kCPU, kNumberTypeInt32, schema::PrimitiveType_UniformReal};
|
||||
|
||||
auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc);
|
||||
EXPECT_NE(creator, nullptr);
|
||||
|
|
@ -48,6 +48,17 @@ TEST_F(TestUniformRealFp32, UniformReal) {
|
|||
|
||||
auto ret = kernel->Run();
|
||||
EXPECT_EQ(0, ret);
|
||||
EXPECT_NEAR(0.138693, output_data0[0], 0.000001);
|
||||
EXPECT_NEAR(0.511552, output_data0[1], 0.000001);
|
||||
EXPECT_NEAR(0.27194, output_data0[2], 0.000001);
|
||||
EXPECT_NEAR(0.336527, output_data0[3], 0.000001);
|
||||
EXPECT_NEAR(0.896684, output_data0[4], 0.000001);
|
||||
EXPECT_NEAR(0.476402, output_data0[5], 0.000001);
|
||||
EXPECT_NEAR(0.155924, output_data0[6], 0.000001);
|
||||
EXPECT_NEAR(0.817732, output_data0[7], 0.000001);
|
||||
EXPECT_NEAR(0.619868, output_data0[8], 0.000001);
|
||||
EXPECT_NEAR(0.274392, output_data0[9], 0.000001);
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
std::cout << output_data0[i] << " ";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue