oneAPI Math Library (oneMath)扩展开发:如何添加自定义数学函数后端
oneAPI Math Library (oneMath)扩展开发:如何添加自定义数学函数后端
【免费下载链接】oneMKLoneAPI Math Library (oneMath)项目地址: https://gitcode.com/gh_mirrors/on/oneMKL
oneAPI Math Library (oneMath) 是一个功能强大的数学库,支持多种后端集成以满足不同计算需求。本文将详细介绍如何为oneMath添加自定义数学函数后端,帮助开发者扩展其功能,实现特定场景下的性能优化和功能增强。
扩展oneMath后端的核心价值
在科学计算和高性能计算领域,不同的硬件平台和应用场景往往需要特定的数学函数优化。通过为oneMath添加自定义后端,开发者可以:
- 集成专有的数学库以利用硬件加速特性
- 针对特定算法优化函数实现
- 支持新的计算设备或架构
- 满足特殊精度或性能需求
oneMath采用模块化设计,将接口层与后端实现分离,使得添加新后端变得简单高效。下面我们将通过五个关键步骤,详细讲解如何完成自定义后端的集成。
1. 创建头文件:定义接口与调度机制
首先需要创建两个关键头文件:后端包装器的入口点声明和编译时调度接口。这些文件将作为oneMath接口层与新后端实现之间的桥梁。
1.1 后端包装器头文件
创建类似include/oneapi/math/blas/detail/newlib/onemath_blas_newlib.hpp的头文件,声明新后端支持的数学函数:
namespace oneapi { namespace math { namespace newlib { void asum(sycl::queue &queue, std::int64_t n, sycl::buffer<float, 1> &x, std::int64_t incx, sycl::buffer<float, 1> &result); // 其他函数声明... } // namespace newlib } // namespace math } // namespace oneapi1.2 编译时调度接口
创建编译时调度接口模板实例化文件,如include/oneapi/math/blas/detail/newlib/blas_ct.hpp:
namespace oneapi { namespace math { namespace blas { template <> void asum<library::newlib, backend::newdevice>(sycl::queue &queue, std::int64_t n, sycl::buffer<float, 1> &x, std::int64_t incx, sycl::buffer<float, 1> &result) { asum_precondition(queue, n, x, incx, result); oneapi::math::newlib::asum(queue, n, x, incx, result); asum_postcondition(queue, n, x, incx, result); } // 其他函数模板实例化... } // namespace blas } // namespace math } // namespace oneapi这些头文件定义了新后端与oneMath接口层的交互方式,确保函数调用能够正确路由到自定义实现。
2. 集成头文件:更新核心配置
将新创建的头文件集成到oneMath的整体结构中,需要更新以下关键文件:
2.1 添加新后端定义
修改include/oneapi/math/detail/backends.hpp,添加新后端的枚举值和映射关系:
enum class backend { mklcpu, + newbackend, mklgpu, cublas, ... }; static backendmap backend_map = { { backend::mklcpu, "mklcpu" }, + { backend::newbackend, "newbackend" }, { backend::mklgpu, "mklgpu" }, ... };2.2 更新后端设备映射表
修改include/oneapi/math/detail/backends_table.hpp,添加新后端支持的领域和设备:
enum class device : uint16_t { x86cpu, ... + newdevice }; static std::map<domain, std::map<device, std::vector<const char*>>> libraries = { { domain::blas, { { device::x86cpu, { #ifdef ONEMATH_ENABLE_MKLCPU_BACKEND LIB_NAME("blas_mklcpu") #endif } }, + { device::newdevice, + { +#ifdef ONEMATH_ENABLE_NEWLIB_BACKEND + LIB_NAME("blas_newlib") +#endif + } }, ... } ... };2.3 添加设备检测逻辑
修改include/oneapi/math/detail/get_device_id.hpp,实现新设备的检测机制:
inline oneapi::math::device get_device_id(sycl::queue &queue) { oneapi::math::device device_id; + if (queue.is_host()) + device_id=device::newdevice; ... }2.4 包含编译时调度头文件
修改领域主头文件(如include/oneapi/math/blas.hpp),包含新创建的编译时调度头文件:
#include "oneapi/math/blas/detail/mklcpu/blas_ct.hpp" #include "oneapi/math/blas/detail/mklgpu/blas_ct.hpp" +#include "oneapi/math/blas/detail/newlib/blas_ct.hpp"完成这些步骤后,oneMath的接口层就能够识别并调度到新的后端实现了。
3. 创建包装器:实现函数转换与调用
包装器负责将oneMath的DPC++接口转换为第三方库的调用格式。这一步需要创建两个关键文件:函数包装实现和运行时调度符号表。
3.1 函数包装实现
创建src/blas/backends/newlib/newlib_wrappers.cpp,实现DPC++到第三方库的转换逻辑:
#include <sycl/sycl.hpp> #include "oneapi/math/types.hpp" #include "oneapi/math/blas/detail/newlib/onemath_blas_newlib.hpp" #include "newlib.h" // 第三方库头文件 namespace oneapi { namespace math { namespace newlib { void asum(sycl::queue &queue, std::int64_t n, sycl::buffer<float, 1> &x, std::int64_t incx, sycl::buffer<float, 1> &result) { queue.submit(& { auto accessor_x = x.get_access<sycl::access::mode::read>(cgh); auto accessor_result = result.get_access<sycl::access::mode::write>(cgh); cgh.single_task<class newlib_sasum>([=]() { accessor_result[0] = ::newlib_sasum((const int)n, accessor_x.get_pointer(), (const int)incx); }); }); } // 其他函数实现... } // namespace newlib } // namespace math } // namespace oneapi3.2 运行时调度符号表
创建src/blas/backends/newlib/newlib_wrappers_table_dyn.cpp,定义运行时调度所需的符号表结构:
#include "oneapi/math/blas/function_table.hpp" #include "oneapi/math/blas/detail/newlib/onemath_blas_newlib.hpp" namespace oneapi { namespace math { namespace blas { // 定义函数表结构,将符号映射到具体实现 const function_table_t newlib_function_table = { .asum_f = newlib::asum<float>, .asum_d = newlib::asum<double>, // 其他函数映射... }; } // namespace blas } // namespace math } // namespace oneapi这些包装器实现了DPC++数据类型到第三方库数据类型的转换,并处理了设备内存访问和内核提交,确保数学函数能够在目标设备上正确执行。
4. 集成构建系统:配置编译选项与依赖
为了让新后端能够被正确编译和链接,需要更新CMake构建系统配置。
4.1 添加编译选项
在顶级CMakeLists.txt中添加新后端的启用选项:
option(ENABLE_MKLCPU_BACKEND "" ON) option(ENABLE_MKLGPU_BACKEND "" ON) +option(ENABLE_NEWLIB_BACKEND "" ON)4.2 添加子目录
在领域后端目录的CMakeLists.txt(如src/blas/backends/CMakeLists.txt)中添加新后端的子目录:
if(ENABLE_MKLCPU_BACKEND) add_subdirectory(mklcpu) endif() + +if(ENABLE_NEWLIB_BACKEND) + add_subdirectory(newlib) +endif()4.3 创建Find模块
创建cmake/FindNEWLIB.cmake文件,帮助CMake找到第三方库:
include_guard() find_library(NEWLIB_LIBRARY NAMES newlib HINTS ${NEWLIB_ROOT} $ENV{NEWLIBROOT} PATH_SUFFIXES "lib") include(FindPackageHandleStandardArgs) find_package_handle_standard_args(NEWLIB REQUIRED_VARS NEWLIB_LIBRARY) add_library(ONEMATH::NEWLIB::NEWLIB UNKNOWN IMPORTED) set_target_properties(ONEMATH::NEWLIB::NEWLIB PROPERTIES IMPORTED_LOCATION ${NEWLIB_LIBRARY})4.4 配置后端构建
创建src/blas/backends/newlib/CMakeLists.txt文件,指定如何构建新后端:
add_library(onemath_blas_newlib SHARED newlib_wrappers.cpp newlib_wrappers_table_dyn.cpp) target_include_directories(onemath_blas_newlib PRIVATE ${PROJECT_SOURCE_DIR}/include PRIVATE ${NEWLIB_INCLUDE_DIRS}) target_link_libraries(onemath_blas_newlib PUBLIC ONEMATH::SYCL::SYCL PUBLIC ONEMATH::NEWLIB::NEWLIB) set_target_properties(onemath_blas_newlib PROPERTIES OUTPUT_NAME "onemath_blas_newlib" SOVERSION ${PROJECT_VERSION_MAJOR} VERSION ${PROJECT_VERSION}) install(TARGETS onemath_blas_newlib LIBRARY DESTINATION lib)完成这些配置后,可以使用以下命令构建新后端:
cd build/ cmake .. -DNEWLIB_ROOT=<path/to/newlib> \ -DENABLE_MKLCPU_BACKEND=OFF \ -DENABLE_MKLGPU_BACKEND=OFF \ -DENABLE_NEWLIB_BACKEND=ON \ -DBUILD_FUNCTIONAL_TESTS=OFF cmake --build . -j45. 更新测试系统:验证后端功能正确性
为确保新后端的正确性,需要将其集成到oneMath的测试系统中。
5.1 添加测试宏定义
修改src/config.hpp.in,添加新后端的宏定义:
#cmakedefine ONEMATH_ENABLE_MKLCPU_BACKEND +#cmakedefine ONEMATH_ENABLE_NEWLIB_BACKEND5.2 配置测试链接
修改tests/unit_tests/CMakeLists.txt,添加测试与新后端的链接配置:
if(ENABLE_MKLCPU_BACKEND) # MKLCPU后端测试配置... endif() + +if(ENABLE_NEWLIB_BACKEND) + add_dependencies(test_main_ct onemath_blas_newlib) + if(BUILD_SHARED_LIBS) + list(APPEND ONEMATH_LIBRARIES onemath_blas_newlib) + else() + list(APPEND ONEMATH_LIBRARIES -foffload-static-lib=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libonemath_blas_newlib.a) + find_package(NEWLIB REQUIRED) + list(APPEND ONEMATH_LIBRARIES ONEMATH::NEWLIB::NEWLIB) + endif() +endif()5.3 添加测试调度辅助函数
修改tests/unit_tests/include/test_helper.hpp,添加新后端的测试调度辅助函数:
#ifdef ONEMATH_ENABLE_MKLGPU_BACKEND #define TEST_RUN_INTELGPU(q, func, args) \ func<oneapi::math::backend::mklgpu> args #else #define TEST_RUN_INTELGPU(q, func, args) #endif + +#ifdef ONEMATH_ENABLE_NEWLIB_BACKEND + #define TEST_RUN_NEWDEVICE(q, func, args) \ + func<oneapi::math::backend::newbackend> args +#else + #define TEST_RUN_NEWDEVICE(q, func, args) +#endif #define TEST_RUN_CT(q, func, args) \ do { \ + if (q.is_host()) \ + TEST_RUN_NEWDEVICE(q, func, args); \ if (is_intel_gpu(q)) \ TEST_RUN_INTELGPU(q, func, args); \ ... } while (0)5.4 添加测试设备
修改tests/unit_tests/main_test.cpp,添加新后端的测试设备:
#ifdef ONEMATH_ENABLE_MKLGPU_BACKEND devices.push_back(sycl::device(sycl::gpu_selector{})); #endif + +#ifdef ONEMATH_ENABLE_NEWLIB_BACKEND + devices.push_back(sycl::device(sycl::host_selector())); +#endif完成测试配置后,可以使用以下命令构建并运行测试:
cd build/ cmake .. -DNEWLIB_ROOT=<path/to/newlib> \ -DENABLE_MKLCPU_BACKEND=OFF \ -DENABLE_MKLGPU_BACKEND=OFF \ -DENABLE_NEWLIB_BACKEND=ON \ -DBUILD_FUNCTIONAL_TESTS=ON cmake --build . -j4 ctest数学函数后端扩展的实际应用
添加自定义数学函数后端后,开发者可以利用特定优化来提升应用性能。例如,通过集成针对误差函数优化的后端,可以显著提升科学计算中涉及概率分布计算的效率。
误差函数曲线图:展示了误差函数在不同取值范围内的变化趋势,这是许多科学计算应用中的关键函数
反误差函数曲线图:反误差函数在统计分析和数据科学中有着广泛应用
通过本文介绍的方法,开发者可以为这些数学函数添加优化的后端实现,满足特定应用场景的需求。
总结
通过以上五个步骤,我们详细介绍了如何为oneAPI Math Library添加自定义数学函数后端。这个过程包括创建头文件定义接口、集成头文件更新配置、实现包装器转换调用、配置构建系统以及更新测试系统验证正确性。
oneMath的模块化设计使得后端扩展变得简单灵活,开发者可以根据具体需求集成不同的数学库或优化实现。通过这种方式,oneMath能够适应各种硬件平台和应用场景,为科学计算和高性能计算提供强大的数学支持。
如果你想了解更多关于oneMath的开发细节,可以参考项目中的官方文档:CONTRIBUTING.md 和 docs/create_new_backend.rst。
开始你的oneMath扩展开发之旅吧!通过自定义后端,释放数学计算的全部潜力,为你的应用带来显著的性能提升。
【免费下载链接】oneMKLoneAPI Math Library (oneMath)项目地址: https://gitcode.com/gh_mirrors/on/oneMKL
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
