You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中复用基准测试函数处理不同类型的单/双参数学函数

解决方案

单参测试函数:用模板替代重载

直接把你现有的单参float测试函数改成模板函数,靠C++模板的类型推导自动适配float和double类型,完全复用函数逻辑,不用复制粘贴或写重载:

#include <chrono>
#include <cmath>
#include <vector>
#include <type_traits>

template<typename T>
void timeit_single_arg(T(*func)(T), const std::vector<T>& test_inputs, const std::string& func_name) {
    // 计时逻辑
    auto start = std::chrono::high_resolution_clock::now();
    for (T input : test_inputs) {
        // 用volatile防止编译器优化掉函数调用
        volatile T result = func(input);
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    std::cout << func_name << " 执行时间: " << duration.count() << " us\n";

    // 精度测试逻辑
    double max_error = 0.0;
    for (T input : test_inputs) {
        T custom_result = func(input);
        // 根据T的类型调用对应的库函数
        T lib_result = std::is_same_v<T, float> ? std::expf(input) : std::exp(input);
        double error = std::abs(static_cast<double>(custom_result - lib_result)) / std::abs(static_cast<double>(lib_result));
        if (error > max_error) max_error = error;
    }
    std::cout << func_name << " 最大相对误差: " << max_error << "\n";
}

调用时直接传对应类型的自定义函数即可,模板会自动推导T:

// 测试float版自定义exp
timeit_single_arg(&custom_exp_float, float_test_inputs, "custom_exp_float");
// 测试double版自定义exp
timeit_single_arg(&custom_exp_double, double_test_inputs, "custom_exp_double");

双参测试函数:模板适配多类型第二个参数

双参函数的第二个参数类型不影响测试逻辑,同样用模板处理第二个参数的类型,实现一次编写适配所有合法参数组合:

template<typename T, typename Arg2>
void timeit_double_arg(T(*func)(T, Arg2), const std::vector<T>& test_inputs, const std::vector<Arg2>& arg2_inputs, const std::string& func_name) {
    // 计时逻辑
    auto start = std::chrono::high_resolution_clock::now();
    for (size_t i = 0; i < test_inputs.size(); ++i) {
        volatile T result = func(test_inputs[i], arg2_inputs[i]);
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    std::cout << func_name << " 执行时间: " << duration.count() << " us\n";

    // 精度测试逻辑
    double max_error = 0.0;
    for (size_t i = 0; i < test_inputs.size(); ++i) {
        T custom_result = func(test_inputs[i], arg2_inputs[i]);
        T lib_result;
        // 编译期判断类型,调用对应库函数
        if constexpr (std::is_same_v<T, float>) {
            if constexpr (std::is_same_v<Arg2, int>) {
                lib_result = std::powf(test_inputs[i], arg2_inputs[i]);
            } else {
                lib_result = std::powf(test_inputs[i], static_cast<float>(arg2_inputs[i]));
            }
        } else {
            if constexpr (std::is_same_v<Arg2, int>) {
                lib_result = std::pow(test_inputs[i], arg2_inputs[i]);
            } else {
                lib_result = std::pow(test_inputs[i], static_cast<double>(arg2_inputs[i]));
            }
        }
        double error = std::abs(static_cast<double>(custom_result - lib_result)) / std::abs(static_cast<double>(lib_result));
        if (error > max_error) max_error = error;
    }
    std::cout << func_name << " 最大相对误差: " << max_error << "\n";
}

调用时自动适配第二个参数的int/float/double类型:

// 测试double+int版自定义pow
timeit_double_arg(&custom_pow_double_int, double_inputs, int_args, "custom_pow_double_int");
// 测试float+float版自定义pow
timeit_double_arg(&custom_pow_float_float, float_inputs, float_args, "custom_pow_float_float");

关于std::variant的替代说明

你之前尝试用std::variant处理多类型输入完全没必要,模板的类型推导已经能完美解决类型适配问题,还避免了variant需要手动判断类型、值比较繁琐的问题。如果一定要用variant存储测试数据,可以结合std::visit来分发处理,但模板方案在你的测试场景下更简洁高效。

内容的提问来源于stack exchange,提问作者Ξένη Γήινος

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 11:59:55