Some checks failed
Linux Build / Linux cpu (push) Has been cancelled
Linux Build / Linux cpu-clang (push) Has been cancelled
Linux Build / Linux vulkan (push) Has been cancelled
mac-build / macOS CPU (push) Has been cancelled
Nix Build / Nix (cpu) (push) Has been cancelled
Nix Build / Nix (vulkan) (push) Has been cancelled
windows-build / Windows CPU (push) Has been cancelled
222 lines
7.8 KiB
C++
222 lines
7.8 KiB
C++
#include "engine/framework/sampling/torch_random.h"
|
|
|
|
#include <cmath>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
void require_close(float actual, float expected, float tolerance, const char * label) {
|
|
if (std::fabs(actual - expected) > tolerance) {
|
|
throw std::runtime_error(
|
|
std::string(label) + " mismatch: expected " + std::to_string(expected) +
|
|
", got " + std::to_string(actual));
|
|
}
|
|
}
|
|
|
|
void require_vector_close(
|
|
const std::vector<float> & actual,
|
|
const std::vector<float> & expected,
|
|
float tolerance,
|
|
const char * label) {
|
|
if (actual.size() != expected.size()) {
|
|
throw std::runtime_error(std::string(label) + " size mismatch");
|
|
}
|
|
for (size_t index = 0; index < actual.size(); ++index) {
|
|
require_close(actual[index], expected[index], tolerance, label);
|
|
}
|
|
}
|
|
|
|
void test_float32_matches_torch_cuda() {
|
|
const std::vector<float> expected_seed_1234 = {
|
|
-1.61649048F, 0.56845516F, -0.510224819F, -0.911339402F,
|
|
-1.15551639F, -0.22615087F, -1.2891326F, 1.065382F,
|
|
-0.7166605F, -0.533334374F, 0.207757875F, -0.979843318F,
|
|
0.744693458F, -0.239484429F, 0.27371496F, 0.092008315F,
|
|
};
|
|
const auto actual = engine::sampling::generate_torch_cuda_randn(
|
|
expected_seed_1234.size(),
|
|
1234,
|
|
engine::sampling::TorchRandnPrecision::Float32);
|
|
require_vector_close(actual, expected_seed_1234, 2.0e-6F, "float32 torch_cuda_randn");
|
|
|
|
const auto extended = engine::sampling::generate_torch_cuda_randn(
|
|
300,
|
|
1234,
|
|
engine::sampling::TorchRandnPrecision::Float32);
|
|
const std::vector<std::pair<size_t, float>> expected_positions = {
|
|
{16, -0.803610802F},
|
|
{17, -1.6377064F},
|
|
{31, -0.300402969F},
|
|
{32, -0.251393795F},
|
|
{63, -0.924830973F},
|
|
{64, 0.799798131F},
|
|
{127, -0.167921364F},
|
|
{128, -0.322486848F},
|
|
{255, -1.76037288F},
|
|
{256, 0.534284174F},
|
|
{299, -0.986868858F},
|
|
};
|
|
for (const auto & [index, expected] : expected_positions) {
|
|
require_close(extended[index], expected, 2.0e-6F, "float32 torch_cuda_randn high index");
|
|
}
|
|
}
|
|
|
|
void test_bfloat16_matches_torch_cuda() {
|
|
const std::vector<float> expected_seed_5678 = {
|
|
-0.65625F, -0.5625F, 0.384765625F, -0.151367188F,
|
|
0.7421875F, 0.244140625F, 0.609375F, 0.00321960449F,
|
|
-0.46875F, 0.306640625F, -0.225585938F, -0.9140625F,
|
|
0.7734375F, 0.120117188F, 0.52734375F, -0.5078125F,
|
|
};
|
|
const auto actual = engine::sampling::generate_torch_cuda_randn(
|
|
expected_seed_5678.size(),
|
|
5678,
|
|
engine::sampling::TorchRandnPrecision::BFloat16);
|
|
require_vector_close(actual, expected_seed_5678, 0.0F, "bfloat16 torch_cuda_randn");
|
|
|
|
const auto extended = engine::sampling::generate_torch_cuda_randn(
|
|
300,
|
|
1234,
|
|
engine::sampling::TorchRandnPrecision::BFloat16);
|
|
const std::vector<std::pair<size_t, float>> expected_positions = {
|
|
{16, -0.8046875F},
|
|
{17, -1.640625F},
|
|
{31, -0.30078125F},
|
|
{32, -0.251953125F},
|
|
{63, -0.92578125F},
|
|
{64, 0.80078125F},
|
|
{127, -0.16796875F},
|
|
{128, -0.322265625F},
|
|
{255, -1.7578125F},
|
|
{256, 0.53515625F},
|
|
{299, -0.98828125F},
|
|
};
|
|
for (const auto & [index, expected] : expected_positions) {
|
|
require_close(extended[index], expected, 0.0F, "bfloat16 torch_cuda_randn high index");
|
|
}
|
|
}
|
|
|
|
void test_fill_matches_vector_api() {
|
|
std::vector<float> filled(257, 0.0F);
|
|
engine::sampling::fill_torch_cuda_randn(
|
|
filled.data(),
|
|
filled.size(),
|
|
1,
|
|
engine::sampling::TorchRandnPrecision::Float32);
|
|
const auto generated = engine::sampling::generate_torch_cuda_randn(
|
|
filled.size(),
|
|
1,
|
|
engine::sampling::TorchRandnPrecision::Float32);
|
|
require_vector_close(filled, generated, 0.0F, "fill/vector torch_cuda_randn");
|
|
}
|
|
|
|
void test_start_index_matches_full_generation_slice() {
|
|
const auto full = engine::sampling::generate_torch_cuda_randn(
|
|
300,
|
|
1234,
|
|
engine::sampling::TorchRandnPrecision::Float32);
|
|
const auto sliced = engine::sampling::generate_torch_cuda_randn(
|
|
32,
|
|
1234,
|
|
engine::sampling::TorchRandnPrecision::Float32,
|
|
128);
|
|
for (size_t index = 0; index < sliced.size(); ++index) {
|
|
require_close(sliced[index], full[128 + index], 0.0F, "torch_cuda_randn start index");
|
|
}
|
|
}
|
|
|
|
void test_uniform_matches_torch_cuda() {
|
|
const std::vector<float> expected_seed_1234 = {
|
|
0.127207950F, 0.816736281F, 0.543999255F, 0.660079062F,
|
|
0.272055715F, 0.973670244F, 0.390334547F, 0.339447320F,
|
|
0.545121968F, 0.731194019F, 0.386437327F, 0.595885396F,
|
|
0.757832348F, 0.212593451F, 0.719796896F, 0.984495401F,
|
|
};
|
|
const auto actual = engine::sampling::generate_torch_cuda_uniform(expected_seed_1234.size(), 1234);
|
|
require_vector_close(actual, expected_seed_1234, 1.0e-7F, "float32 torch_cuda_uniform");
|
|
|
|
const auto extended = engine::sampling::generate_torch_cuda_uniform(300, 1234);
|
|
const std::vector<std::pair<size_t, float>> expected_positions = {
|
|
{16, 0.551820338F},
|
|
{17, 0.0980522931F},
|
|
{31, 0.388187110F},
|
|
{32, 0.797672272F},
|
|
{63, 0.546383321F},
|
|
{64, 0.694423795F},
|
|
{127, 0.768725276F},
|
|
{128, 0.798199594F},
|
|
{255, 0.210613519F},
|
|
{256, 0.294832915F},
|
|
{299, 0.588956773F},
|
|
};
|
|
for (const auto & [index, expected] : expected_positions) {
|
|
require_close(extended[index], expected, 1.0e-7F, "float32 torch_cuda_uniform high index");
|
|
}
|
|
|
|
const auto full = engine::sampling::generate_torch_cuda_uniform(300, 5678);
|
|
const auto sliced = engine::sampling::generate_torch_cuda_uniform(32, 5678, 128);
|
|
for (size_t index = 0; index < sliced.size(); ++index) {
|
|
require_close(sliced[index], full[128 + index], 0.0F, "torch_cuda_uniform start index");
|
|
}
|
|
}
|
|
|
|
void test_tensor_iterator_exponential_matches_torch_cuda() {
|
|
constexpr uint64_t seed = 1234;
|
|
constexpr uint64_t vocab_size = 168565;
|
|
constexpr uint64_t call_index = 104;
|
|
constexpr int64_t multiprocessor_count = 128;
|
|
constexpr int64_t max_threads_per_multiprocessor = 1536;
|
|
const std::vector<std::pair<uint64_t, float>> expected_positions = {
|
|
{167785, 0.301640809F},
|
|
{168248, 0.333908796F},
|
|
{156088, 0.690724790F},
|
|
{162701, 0.975778222F},
|
|
{160228, 3.30194235F},
|
|
{168039, 0.803459823F},
|
|
{163896, 0.841065466F},
|
|
{167841, 1.16925406F},
|
|
{161373, 0.112876698F},
|
|
};
|
|
for (const auto & [index, expected] : expected_positions) {
|
|
const float actual = engine::sampling::torch_cuda_tensor_iterator_exponential_element(
|
|
seed,
|
|
vocab_size,
|
|
index,
|
|
call_index,
|
|
multiprocessor_count,
|
|
max_threads_per_multiprocessor);
|
|
require_close(actual, expected, 2.0e-6F, "torch_cuda_tensor_iterator_exponential");
|
|
}
|
|
}
|
|
|
|
void test_empty_null_output_is_allowed() {
|
|
engine::sampling::fill_torch_cuda_randn(
|
|
nullptr,
|
|
0,
|
|
0,
|
|
engine::sampling::TorchRandnPrecision::Float32);
|
|
engine::sampling::fill_torch_cuda_uniform(nullptr, 0, 0);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main() {
|
|
try {
|
|
test_float32_matches_torch_cuda();
|
|
test_bfloat16_matches_torch_cuda();
|
|
test_fill_matches_vector_api();
|
|
test_start_index_matches_full_generation_slice();
|
|
test_uniform_matches_torch_cuda();
|
|
test_tensor_iterator_exponential_matches_torch_cuda();
|
|
test_empty_null_output_is_allowed();
|
|
} catch (const std::exception & error) {
|
|
std::cerr << error.what() << '\n';
|
|
return 1;
|
|
}
|
|
std::cout << "torch_random_test passed\n";
|
|
return 0;
|
|
}
|