diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4e475f3c6..75ebd1e3b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -424,6 +424,10 @@ if(WITH_CAMBRICON) target_compile_options(infiniops PUBLIC "$<$:SHELL:-idirafter /usr/local/neuware/lib/clang/11.1.0/include>" ) + set(_cambricon_host_bang_compat_option + "$<$:SHELL:-include ${CMAKE_CURRENT_SOURCE_DIR}/native/cambricon/host_bang_compat.h>") + target_compile_options(infiniops PRIVATE + "${_cambricon_host_bang_compat_option}") endif() list(APPEND DEVICE_LIST "cambricon") @@ -1507,6 +1511,11 @@ if(GENERATE_PYTHON_BINDINGS) "$<$:-Wno-deprecated-declarations>" ) + if(WITH_CAMBRICON AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(ops PRIVATE + "${_cambricon_host_bang_compat_option}") + endif() + if(GENERATE_OPERATOR_CALL_INSTANTIATIONS) target_compile_definitions(ops PRIVATE INFINI_OPS_USE_OPERATOR_CALL_INSTANTIATIONS=1) diff --git a/src/native/cambricon/host_bang_compat.h b/src/native/cambricon/host_bang_compat.h new file mode 100644 index 000000000..f9c5a3cbc --- /dev/null +++ b/src/native/cambricon/host_bang_compat.h @@ -0,0 +1,34 @@ +#ifndef INFINI_OPS_NATIVE_CAMBRICON_HOST_BANG_COMPAT_H_ +#define INFINI_OPS_NATIVE_CAMBRICON_HOST_BANG_COMPAT_H_ + +// Neuware 6.0 leaves __BANG_HOSTDEVICE__ empty when its FP16/BF16 headers are +// parsed by a host C++ compiler. Consequently, the function definitions in +// those headers have external linkage and collide across translation units. +// Pre-include each header with the BANG annotations mapped to standard C++ +// inline semantics. The vendor include guards then keep later cnrt/cnnl +// includes from emitting the non-inline definitions. +#if !defined(__BANGCC__) && !defined(__CUDACC__) +#pragma push_macro("__BANGCC__") +#pragma push_macro("__mlu_host__") +#pragma push_macro("__mlu_func__") +#define __BANGCC__ 1 +#define __mlu_host__ +#define __mlu_func__ +#include +#pragma pop_macro("__mlu_func__") +#pragma pop_macro("__mlu_host__") +#pragma pop_macro("__BANGCC__") + +#pragma push_macro("__BANGCC__") +#pragma push_macro("__mlu_host__") +#pragma push_macro("__mlu_func__") +#define __BANGCC__ 1 +#define __mlu_host__ inline +#define __mlu_func__ +#include +#pragma pop_macro("__mlu_func__") +#pragma pop_macro("__mlu_host__") +#pragma pop_macro("__BANGCC__") +#endif + +#endif diff --git a/tests/test_generate_wrappers.py b/tests/test_generate_wrappers.py index 0f34483a0..cd1cc87df 100644 --- a/tests/test_generate_wrappers.py +++ b/tests/test_generate_wrappers.py @@ -1133,3 +1133,19 @@ def test_shared_triton_config_parser_has_one_explicit_schema(): assert "namespace infini::ops::triton::jit" in parser_header assert "namespace detail" in parser_header + + +def test_cmake_configures_cambricon_half_compatibility(): + root = pathlib.Path(__file__).parents[1] + source_cmake = (root / "src" / "CMakeLists.txt").read_text(encoding="utf-8") + compatibility_header = ( + root / "src" / "native" / "cambricon" / "host_bang_compat.h" + ).read_text(encoding="utf-8") + + assert "native/cambricon/host_bang_compat.h" in source_cmake + assert "target_compile_options(infiniops PRIVATE" in source_cmake + assert "target_compile_options(ops PRIVATE" in source_cmake + assert source_cmake.count("_cambricon_host_bang_compat_option}") == 2 + assert "#include " in compatibility_header + assert "#include " in compatibility_header + assert "#define __mlu_host__ inline" in compatibility_header