【问题标题】:cmake finds cuda but fails to find cuda libraries on Windowscmake 找到 cuda 但无法在 Windows 上找到 cuda 库
【发布时间】:2017-06-02 01:31:54
【问题描述】:

我有一个小型 cmake 项目,它在 Linux 上运行良好,但在最新版本的 cmake 和 CUDA 8 的 Windows 10(我尝试使用两台不同的计算机)上失败。它发现 CUDA 很好,但找不到库.我的 cmake 文件:

cmake_minimum_required(VERSION 3.0)
project(myproject)

find_package(CUDA REQUIRED)

cuda_add_library(myproject STATIC matrix_mm.cu)
target_link_libraries(myproject ${CUDA_CUBLAS_LIBRARIES})

message(STATUS "")
message(STATUS "FoundCUDA              : ${CUDA_FOUND}")
message(STATUS "Cuda cublas libraries  : ${CUDA_CUBLAS_LIBRARIES}")

在同一个文件夹中,我有标题 matrix_mm.cuh:

#include <cstdlib>

namespace myproject {

float* cuda_mm(const float *a, const float *b, const size_t m, const size_t k, const size_t n);

} /* end namespace myproject */

和matrix_mm.cu:

#include <cublas_v2.h>
#include "matrix_mm.cuh"

namespace myproject {

// Adapted from https://solarianprogrammer.com/2012/05/31/matrix-multiplication-cuda-cublas-curand-thrust/

void gpu_blas_mmul(const float *a, const float *b, float *c, const size_t m, const size_t k, const size_t n) {
  int lda = m, ldb = k, ldc = m;
  const float alf = 1;
  const float bet = 0;
  const float *alpha = &alf;
  const float *beta = &bet;

  // Create a handle for CUBLAS
  cublasHandle_t handle;
  cublasCreate(&handle);

  // Do the actual multiplication
  cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc);

  // Destroy the handle
  cublasDestroy(handle);
}

float* cuda_mm(const float *a, const float *b, const size_t m, const size_t k, const size_t n) {
  size_t const a_bytes = m * k * sizeof(float);
  size_t const b_bytes = k * n * sizeof(float);
  size_t const c_bytes = m * n * sizeof(float);
  float* c = (float*)std::malloc(c_bytes);

  float *d_A, *d_B, *d_C;
  cudaMalloc(&d_A, a_bytes);
  cudaMalloc(&d_B, b_bytes);
  cudaMalloc(&d_C, c_bytes);

  cudaMemcpy(d_A, a, a_bytes, cudaMemcpyHostToDevice);
  cudaMemcpy(d_B, b, b_bytes, cudaMemcpyHostToDevice);

  gpu_blas_mmul(d_A, d_B, d_C, m, k, n);

  cudaMemcpy(c, d_C, c_bytes, cudaMemcpyDeviceToHost);

  cudaFree(d_A);
  cudaFree(d_B);
  cudaFree(d_C);

  return c;
}

} /* end namespace myproject */

在 Linux 上我得到:

-- FoundCUDA              : TRUE
-- Toolkit root           : /usr
-- Cuda cublas libraries  : /usr/lib/x86_64-linux-gnu/libcublas.so

虽然我在两台 Windows 10 机器上都得到了

-- FoundCUDA              : TRUE
-- Toolkit root           : C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0
-- Cuda cublas libraries  : CUDA_cublas_LIBRARY-NOTFOUND;CUDA_cublas_device_LIBRARY-NOTFOUND

...当然它无法编译,因为链接器找不到 cublas。

我尝试了很多事情:使 lib SHARED 而不是 STATIC,我确保 Cuda 在 Windows 的环境变量中,等等,但没有任何效果。

【问题讨论】:

  • 无解决方案,但建议阅读 cmakes 的 Modules 目录中的 FindCUDA.cmake。里面有一些提示。
  • @Th.Thielemann 我确实阅读了 FindCUDA 上的文档,奇怪的是它正确设置了 CUDA_TOOLKIT_ROOT_DIR 但找不到库(它们就在那里!)。
  • 在 FINDCUDE.cmake 中我发现set(CUDA_FOUND TRUE) 行没有任何检查。因此,它在脚本执行后立即设置。检查函数cuda_find_library_local_first_with_path_ext 以获取有关库路径的更多提示。您可以使用 message(STATUS ...) 将一些调试输出包含到 FindCUDA.cmake 中
  • 哪个 CMake 版本?
  • @NicolasHolthaus 3.5 在 Linux 上,3.7.1 在 Windows 上。

标签: windows cuda cmake


【解决方案1】:

这是我用来在带有 CMake 3.7.1 的 Windows 10 上查找 CUDA 8 的 CMake sn-p:

cmake_minimum_required(VERSION 3.7)
project(myproject)

# Check for CUDA ENV vars
IF(NOT DEFINED ENV{CUDA_PATH})
    MESSAGE(FATAL_ERROR "CUDA_PATH Environment variable is not set.")
ENDIF(NOT DEFINED ENV{CUDA_PATH})

# Set the toolkit path
FILE(TO_CMAKE_PATH "$ENV{CUDA_PATH}" CUDA_TOOLKIT_ROOT_DIR)
SET(CUDA_TOOLKIT_ROOT_DIR ${CUDA_TOOLKIT_ROOT_DIR} CACHE STRING "Root directory of the Cuda Library" FORCE)

# Find the package
find_package(CUDA REQUIRED)

# Create and interface library as a link target (Requires CMake 3.7.0+)
add_library(cuda INTERFACE)
set_target_properties(cuda PROPERTIES
    INTERFACE_INCLUDE_DIRECTORIES ${CUDA_INCLUDE_DIRS}
    INTERFACE_LINK_LIBRARIES "${CUDA_LIBRARIES};${CUDA_CUFFT_LIBRARIES};${CUDA_CUBLAS_LIBRARIES}"
)

SET(CUDA_HOST_COMPILATION_CPP ON)

cuda_add_library(myproject STATIC matrix_mm.cu)
target_link_libraries(myproject cuda)

我认为库周围的引号很重要,因为 Windows 路径将包含空格。

我还会确保您删除缓存并重新生成项目。当变量值在表面上看起来正确时(或者当您对非FORCE 缓存变量进行更改时),这通常是导致错误的原因。

【讨论】:

  • 天啊...它有效!这是圣诞节的奇迹!非常感谢,我会好好研究这段代码以确保我理解它。
猜你喜欢
  • 2015-01-17
  • 2017-11-27
  • 2013-11-27
  • 1970-01-01
  • 2018-04-30
  • 2022-01-25
  • 1970-01-01
相关资源
最近更新 更多