Я пытаюсь выбрать свой бэкэнд массива, основываясь на доступных бэкэндах и их возможностях (если бэкэнд поддерживает double, то используйте его, иначе нет). Поэтому я создал файл CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(arrayfire_test)
if(USE_EXTERNAL_PATHS)
set(CMAKE_C_COMPILER ${C_COMPILER})# CACHE PATH "" FORCE)
set(CMAKE_CXX_COMPILER ${CXX_COMPILER})#CACHE PATH "" FORCE)
else()
set(CMAKE_C_COMPILER mpicc)
set(CMAKE_CXX_COMPILER mpic++)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -fopenmp-simd")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
set(CXX_FLAGS "${CMAKE_CXX_FLAGS} -xHost")
endif()
set(C_FLAGS "${CMAKE_C_FLAGS} ${CXX_FLAGS} -fPIC -flto -march=native -fopenmp -O2 -funroll-loops -funroll-all-loops -fstrict-aliasing -std=gnu++14")
set(CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAGS} -fPIC -flto -march=native -fopenmp -O2 -funroll-loops -funroll-all-loops -fstrict-aliasing -std=gnu++14")
string(REPLACE " " ";" REPLACED_CXX_FLAGS ${CXX_FLAGS})
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/lib)
set(ArrayFire_DIR "/opt/arrayfire/share/ArrayFire/cmake")
FIND_PACKAGE(ArrayFire)
find_package(Armadillo REQUIRED PATHS "/opt/armadillo")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp -std=c++11 -O0 -g3 -flto -march=native")
set(FORGE_LIBRARIES "/opt/arrayfire/lib/libforge.so")
INCLUDE_DIRECTORIES(${ArrayFire_INCLUDE_DIRS}
${ARMADILLO_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} "source/main.cpp")
target_compile_options(${PROJECT_NAME} PRIVATE ${REPLACED_CXX_FLAGS})
TARGET_LINK_LIBRARIES(${PROJECT_NAME}
${ArrayFire_Unified_LIBRARIES}
${ARMADILLO_LIBRARIES})# ${FORGE_LIBRARIES})
и основной файл:
int main(void){
int backends = af::getAvailableBackends ();
std::cout << backends << "\n";
std::vector<af_backend> possible_backends;
if(backends & AF_BACKEND_CUDA)
possible_backends.push_back(AF_BACKEND_CUDA);
if(backends & AF_BACKEND_OPENCL)
possible_backends.push_back(AF_BACKEND_OPENCL);
if(backends & AF_BACKEND_CPU)
possible_backends.push_back(AF_BACKEND_CPU);
if(possible_backends.size() == 0){
std::cerr << "No backends available\n";
return -1;
}
for(size_t i = 0; i < possible_backends.size(); ++i){
af::setBackend (possible_backends[i]);
af::setDevice (0);
if(af::isDoubleAvailable (0)){
std::cout << "Backend " << af::getActiveBackend () << " supports double\n";
break;
}
}
std::cout << "Backend " << af::getActiveBackend () << " is in use\n";
return 0;
}
Согласно http://arrayfire.org/docs/unifiedbackend.htm, мне нужно используйте ${ArrayFire_Unified_LIBRARIES}
при использовании этого бэкэнда. Но при выполнении кода я получаю
0
No backends available
, хотя у меня есть и CPU, и OpenCL в качестве бэкэнда. При замене ${ArrayFire_Unified_LIBRARIES}
на ${ArrayFire_CPU_LIBRARIES} ${ArrayFire_OpenCL_LIBRARIES}
я получаю вывод
1
Backend 1 supports double
Backend 1 is in use
При переключении порядка библиотек я получаю
4
Backend 4 is in use
и, таким образом, указываю, что только один сервер может быть увиденным, хотя у меня есть два возможных бэкэнда. Таким образом, есть ли ошибка в моем коде, или мой подход неверен?