четверг, 19 июня 2025 г.

OpenCL: добавление поддержки видеокарт AMD в CMakeLists.txt

 Вот этот пример мы модифицируем так, чтобы он мог компилироваться для AMD видеокарт тоже. CMakeLists.txt получился вот такой:

  1. #
  2. cmake_minimum_required (VERSION 3.8)
  3. project ("MemakePrj")
  4. # Add source to this project's executable.
  5. add_executable (MemakePrj "main.cpp" "Memake/Memake.cpp" "Memake/Vector2d.cpp")
  6. # SDL2 headers
  7. target_include_directories(MemakePrj PRIVATE "SDL2-2.0.14/include")
  8. # gpu vendor: amd, nvidia
  9. set(gpu_vendor "amd")
  10. #
  11. if("${gpu_vendor}" STREQUAL "amd")
  12. message("gpu_vendor is 'amd'")
  13. # set define
  14. target_compile_definitions(MemakePrj PUBLIC GPU_VENDOR_IS_AMD)
  15. # OpenCL library
  16. set(opencl_lib_folder "$ENV{OCL_ROOT}/lib")
  17. # OpenCL headers
  18. target_include_directories(MemakePrj PRIVATE "$ENV{OCL_ROOT}/include")
  19. elseif("${gpu_vendor}" STREQUAL "nvidia")
  20. message("gpu_vendor is 'nvidia'")
  21. # set define
  22. target_compile_definitions(MemakePrj PUBLIC GPU_VENDOR_IS_NVIDIA)
  23. # OpencCL headers
  24. target_include_directories(MemakePrj PRIVATE "$ENV{CUDA_PATH}/include")
  25. # OpenCL library
  26. set(opencl_lib_folder "$ENV{CUDA_PATH}/lib")
  27. else()
  28. message("gpu_vendor is 'UNKNOWN'")
  29. endif()

  30. # add SDL_MAIN_HANDLED definition to avoid
  31. # "LNK2019 unresolved external symbol SDL_main referenced in function main_getcmdline"
  32. add_definitions( -DSDL_MAIN_HANDLED )
  33. # SDL library folder
  34. set(SDL2_lib_folder "${PROJECT_SOURCE_DIR}/SDL2-2.0.14/lib")
  35. message(${CMAKE_BUILD_TYPE})
  36. # check 32 or 64 bits
  37. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  38. # 64 bits
  39. set(SDL2_lib_folder "${SDL2_lib_folder}/x64")
  40. if("${gpu_vendor}" STREQUAL "amd")
  41. set(opencl_lib_folder "${opencl_lib_folder}")
  42. elseif("${gpu_vendor}" STREQUAL "nvidia")
  43. set(opencl_lib_folder "${opencl_lib_folder}/x64")
  44. else()
  45. message("gpu_vendor is 'UNKNOWN'")
  46. endif()
  47. elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
  48. # 32 bits
  49. set(SDL2_lib_folder "${SDL2_lib_folder}/x86")
  50. if("${gpu_vendor}" STREQUAL "amd")
  51. message("do not want to support 32-bit version for amd")
  52. elseif("${gpu_vendor}" STREQUAL "nvidia")
  53. set(opencl_lib_folder "${opencl_lib_folder}/Win32")
  54. else()
  55. message("gpu_vendor is 'UNKNOWN'")
  56. endif()
  57. endif()
  58. # link SDL2 static lib
  59. target_link_libraries(MemakePrj ${SDL2_lib_folder}/SDL2.lib)
  60. target_link_libraries(MemakePrj ${SDL2_lib_folder}/SDL2main.lib)
  61. # link OpenCL library
  62. target_link_libraries(MemakePrj ${opencl_lib_folder}/OpenCL.lib)
  63. # copy dynamic lib to folder with executable file
  64. file(COPY ${SDL2_lib_folder}/SDL2.dll DESTINATION ${PROJECT_BINARY_DIR})

 Получилось гораздо более громоздко и неудобочитаемо, чем было. В строке 12 мы указываем, какой у нас производитель видеокарты (пока что их два: AMD, Nvidia) IF внутри IF - это не то, что способствует облегчению чтения подобного кода, но это, тем не менее, позволяет собрать проект для двух и более производителей видеокарт, а это главное. Позже подумаю, как правильно разбить CMakeLists.txt на части.

В коде же это выглядит так:



вторник, 17 июня 2025 г.

Настройка OpenCL для видеокарт AMD

Прежде, чем начать, отмечу, что компания AMD на данный момент не поддерживает свой OpenCL SDK, к сожалению. Причины мне непонятны, хотя они предлагают вместо него какой-то свой собственный аналог CUDA у NVidia. Последним, к слову, наличие CUDA никак не помешало поддерживать тот же OpenCL. Такое отношение к OpenCL не может радовать, конечно же. Тот набор инструментов, что используется ниже - он поддерживается энтузиастами (за что им огромное спасибо). 

Скачать SDK можно, например, тут. После установки, установим переменную окружения OCL_ROOT и проверим, что она правильно установлена: 


Далее все делаем так же, как мы делали раньше и в тех же местах.



Тут настройка среды закончена и для запуска примера осталось только чуть подредактировать код, вместо заголовка cl.hpp мы возьмем cl2.hpp и добавим определение CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY перед заголовочным файлом для совместимости со старым кодом:


После этого можно запустить пример и убедиться, что он работает:


Заодно проверим как работает перемножение матриц в наивной реализации для CPU и GPU:


Запускалалось на Ryzen 7 7730U with Vega 8 iGPU

Заодно сравним производительность ноутбучного процессора и встроенной видеокарты с результатами настольного ПК: