CoolFace
Modelpublic

cwenzi/neuroflow-cpp

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
1likes
test_tensor.cpp257 linesDownload Raw Back to tests
1/**2 * NeuroFlow Core Tests - Tensor Operations3 */4 5#include <iostream>6#include <cassert>7#include <cmath>8#include <chrono>9#include "../include/neuroflow/tensor.hpp"10 11using namespace neuroflow;12 13void test_tensor_creation() {14    std::cout << "Testing tensor creation..." << std::endl;15    16    Tensor t1;17    assert(t1.data_size_ == 0);18    19    Tensor t2({32, 512});20    assert(t2.shape_.size() == 2);21    assert(t2.shape_[0] == 32);22    assert(t2.shape_[1] == 512);23    assert(t2.numel() == 32 * 512);24    assert(t2.data_size_ == 32 * 512 * 4);25    26    std::cout << "  PASSED: tensor creation" << std::endl;27}28 29void test_tensor_reshape() {30    std::cout << "Testing tensor reshape..." << std::endl;31    32    Tensor t({32, 512});33    Tensor r = t.reshape({16, 1024});34    35    assert(r.shape_[0] == 16);36    assert(r.shape_[1] == 1024);37    assert(r.numel() == t.numel());38    assert(!r.owns_data_);  // 零拷贝39    40    std::cout << "  PASSED: tensor reshape (zero-copy)" << std::endl;41}42 43void test_tensor_clone() {44    std::cout << "Testing tensor clone..." << std::endl;45    46    Tensor t({10, 20});47    float* data = t.as_fp32();48    for (size_t i = 0; i < t.numel(); ++i) {49        data[i] = static_cast<float>(i);50    }51    52    Tensor c = t.clone();53    assert(c.owns_data_);54    assert(c.numel() == t.numel());55    56    float* cdata = c.as_fp32();57    for (size_t i = 0; i < c.numel(); ++i) {58        assert(std::abs(cdata[i] - static_cast<float>(i)) < 1e-6);59    }60    61    std::cout << "  PASSED: tensor clone" << std::endl;62}63 64void test_gemm() {65    std::cout << "Testing GEMM (matrix multiplication)..." << std::endl;66    67    // 简单测试: A(2,3) @ B(3,2) = C(2,2)68    Tensor A({2, 3});69    Tensor B({3, 2});70    Tensor C({2, 2});71    72    float* a = A.as_fp32();73    float* b = B.as_fp32();74    75    // A = [[1,2,3], [4,5,6]]76    a[0] = 1; a[1] = 2; a[2] = 3;77    a[3] = 4; a[4] = 5; a[5] = 6;78    79    // B = [[7,8], [9,10], [11,12]]80    b[0] = 7;  b[1] = 8;81    b[2] = 9;  b[3] = 10;82    b[4] = 11; b[5] = 12;83    84    TensorOps::gemm(A, B, C);85    86    float* c = C.as_fp32();87    88    // C = [[58,64], [139,154]]89    assert(std::abs(c[0] - 58) < 1e-4);90    assert(std::abs(c[1] - 64) < 1e-4);91    assert(std::abs(c[2] - 139) < 1e-4);92    assert(std::abs(c[3] - 154) < 1e-4);93    94    std::cout << "  PASSED: GEMM basic" << std::endl;95}96 97void test_gemm_performance() {98    std::cout << "Testing GEMM performance..." << std::endl;99    100    size_t M = 256, K = 512, N = 256;101    102    Tensor A({M, K});103    Tensor B({K, N});104    Tensor C({M, N});105    106    // 填充随机数据107    float* a = A.as_fp32();108    float* b = B.as_fp32();109    for (size_t i = 0; i < A.numel(); ++i) a[i] = static_cast<float>(std::rand()) / RAND_MAX - 0.5f;110    for (size_t i = 0; i < B.numel(); ++i) b[i] = static_cast<float>(std::rand()) / RAND_MAX - 0.5f;111    112    // 预热113    TensorOps::gemm(A, B, C);114    115    // 性能测试116    int iterations = 10;117    auto start = std::chrono::high_resolution_clock::now();118    119    for (int i = 0; i < iterations; ++i) {120        TensorOps::gemm(A, B, C);121    }122    123    auto end = std::chrono::high_resolution_clock::now();124    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);125    126    double ms = duration.count() / 1000.0 / iterations;127    double gflops = 2.0 * M * K * N / (ms / 1000.0) / 1e9;128    129    std::cout << "  GEMM (256x512x256): " << ms << " ms per iteration, " << gflops << " GFLOPS" << std::endl;130    std::cout << "  PASSED: GEMM performance" << std::endl;131}132 133void test_layer_norm() {134    std::cout << "Testing LayerNorm..." << std::endl;135    136    Tensor x({2, 4});137    Tensor weight({4});138    Tensor bias({4});139    140    float* data = x.as_fp32();141    data[0] = 1; data[1] = 2; data[2] = 3; data[3] = 4;142    data[4] = 5; data[5] = 6; data[6] = 7; data[7] = 8;143    144    float* w = weight.as_fp32();145    float* b = bias.as_fp32();146    for (size_t i = 0; i < 4; ++i) {147        w[i] = 1.0f;148        b[i] = 0.0f;149    }150    151    TensorOps::layer_norm(x, weight, bias);152    153    // 验证均值接近0,方差接近1154    float* out = x.as_fp32();155    156    // 第一行均值157    float mean1 = 0;158    for (size_t i = 0; i < 4; ++i) mean1 += out[i];159    mean1 /= 4;160    assert(std::abs(mean1) < 1e-4);161    162    std::cout << "  PASSED: LayerNorm" << std::endl;163}164 165void test_gelu() {166    std::cout << "Testing GELU..." << std::endl;167    168    Tensor x({5});169    float* data = x.as_fp32();170    data[0] = -1; data[1] = 0; data[2] = 1; data[3] = 2; data[4] = 3;171    172    TensorOps::gelu(x);173    174    // GELU(0) ≈ 0175    assert(std::abs(data[1]) < 1e-4);176    177    // GELU(1) ≈ 0.841178    assert(std::abs(data[2] - 0.841f) < 0.01);179    180    std::cout << "  PASSED: GELU" << std::endl;181}182 183void test_softmax() {184    std::cout << "Testing Softmax..." << std::endl;185    186    Tensor x({2, 4});187    float* data = x.as_fp32();188    data[0] = 1; data[1] = 2; data[2] = 3; data[3] = 4;189    data[4] = 0; data[5] = 0; data[6] = 0; data[7] = 0;190    191    TensorOps::softmax(x);192    193    // 验证每行和为1194    float sum1 = 0;195    for (size_t i = 0; i < 4; ++i) sum1 += data[i];196    assert(std::abs(sum1 - 1.0f) < 1e-4);197    198    float sum2 = 0;199    for (size_t i = 4; i < 8; ++i) sum2 += data[i];200    assert(std::abs(sum2 - 1.0f) < 1e-4);201    202    std::cout << "  PASSED: Softmax" << std::endl;203}204 205void test_quantization() {206    std::cout << "Testing INT8 quantization..." << std::endl;207    208    Tensor fp32({4, 8});209    float* data = fp32.as_fp32();210    for (size_t i = 0; i < fp32.numel(); ++i) {211        data[i] = (static_cast<float>(std::rand()) / RAND_MAX - 0.5f) * 10;212    }213    214    Tensor int8({4, 8}, QuantType::INT8);215    Tensor scale({4});216    217    TensorOps::quantize_int8(fp32, int8, scale);218    219    // 反量化220    Tensor dequant({4, 8});221    TensorOps::dequantize_int8(int8, dequant, scale);222    223    // 验证误差小于量化精度224    float* original = fp32.as_fp32();225    float* restored = dequant.as_fp32();226    227    float max_error = 0;228    for (size_t i = 0; i < fp32.numel(); ++i) {229        float err = std::abs(original[i] - restored[i]);230        max_error = std::max(max_error, err);231    }232    233    std::cout << "  Max quantization error: " << max_error << std::endl;234    std::cout << "  PASSED: INT8 quantization" << std::endl;235}236 237int main(int argc, char** argv) {238    std::cout << "========================================" << std::endl;239    std::cout << "NeuroFlow Core - Tensor Tests" << std::endl;240    std::cout << "========================================" << std::endl;241    242    test_tensor_creation();243    test_tensor_reshape();244    test_tensor_clone();245    test_gemm();246    test_gemm_performance();247    test_layer_norm();248    test_gelu();249    test_softmax();250    test_quantization();251    252    std::cout << "========================================" << std::endl;253    std::cout << "All tests PASSED!" << std::endl;254    std::cout << "========================================" << std::endl;255    256    return 0;257}