简体   繁体   English

在 Windows 上的 Qt Creator 中编译 Cuda 代码

[英]Compiling Cuda code in Qt Creator on Windows

I have been trying for days to get a Qt project file running on a 32-bit Windows 7 system, in which I want/need to include Cuda code.我一直在尝试让 Qt 项目文件在 32 位 Windows 7 系统上运行,我想/需要在其中包含 Cuda 代码。 This combination of things is either so simple that no one ever bothered to put an example online, or so difficult that nobody ever succeeded, it seems.这种组合要么非常简单,以至于没有人愿意将示例放在网上,要么非常困难,似乎没有人成功过。 Whatever way, the only helpful forum threads I found were the same issue on Linux or Mac, or with Visual Studio on a Windows.不管怎样,我发现的唯一有用的论坛主题是 Linux 或 Mac 上的相同问题,或者 Windows 上的 Visual Studio。 All of these give all sorts of different errors, however, whether due to linking or clashing libraries, or spaces in file names or non-existing folders in the Windows version of the Cuda SDK.然而,所有这些都会产生各种不同的错误,无论是由于链接或冲突库,还是文件名中的空格或 Windows 版本的 Cuda SDK 中不存在的文件夹。 Is there someone who has a clear .pro file to offer that does the trick?有没有人提供清晰的.pro文件来解决这个问题?

I am aiming to compile a simple programme with ordinary C++ code in Qt style, with Qt 4.8 libraries, which reference several Cuda modules in .cu files.我的目标是用 Qt 风格的普通 C++ 代码编译一个简单的程序,使用 Qt 4.8 库,它引用 .cu 文件中的几个 Cuda 模块。 Something of the form:形式的东西:

TestCUDA \
    TestCUDA.pro
    main.cpp
    test.cu

So I finally managed to assemble a .pro file that works on my and probably on all Windows systems.所以我终于设法组装了一个.pro文件,它适用于我的并且可能适用于所有 Windows 系统。 The following is an easy test programme that should probably do the trick.下面是一个简单的测试程序,应该可以解决问题。 The following is a small project file plus test programme that works at least on my system.以下是至少在我的系统上工作的小项目文件和测试程序。

The file system looks as follows:文件系统如下所示:

TestCUDA \
    TestCUDA.pro
    main.cpp
    vectorAddition.cu

The project file reads:项目文件如下:

TARGET = TestCUDA

# Define output directories
DESTDIR = release
OBJECTS_DIR = release/obj
CUDA_OBJECTS_DIR = release/cuda

# Source files
SOURCES += src/main.cpp

# This makes the .cu files appear in your project
OTHER_FILES +=  vectorAddition.cu

# CUDA settings <-- may change depending on your system
CUDA_SOURCES += src/cuda/vectorAddition.cu
CUDA_SDK = "C:/ProgramData/NVIDIA Corporation/NVIDIA GPU Computing SDK 4.2/C"   # Path to cuda SDK install
CUDA_DIR = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v4.2"            # Path to cuda toolkit install
SYSTEM_NAME = Win32         # Depending on your system either 'Win32', 'x64', or 'Win64'
SYSTEM_TYPE = 32            # '32' or '64', depending on your system
CUDA_ARCH = sm_11           # Type of CUDA architecture, for example 'compute_10', 'compute_11', 'sm_10'
NVCC_OPTIONS = --use_fast_math

# include paths
INCLUDEPATH += $$CUDA_DIR/include \
               $$CUDA_SDK/common/inc/ \
               $$CUDA_SDK/../shared/inc/

# library directories
QMAKE_LIBDIR += $$CUDA_DIR/lib/$$SYSTEM_NAME \
                $$CUDA_SDK/common/lib/$$SYSTEM_NAME \
                $$CUDA_SDK/../shared/lib/$$SYSTEM_NAME
# Add the necessary libraries
LIBS += -lcuda -lcudart

# The following library conflicts with something in Cuda
QMAKE_LFLAGS_RELEASE = /NODEFAULTLIB:msvcrt.lib
QMAKE_LFLAGS_DEBUG   = /NODEFAULTLIB:msvcrtd.lib

# The following makes sure all path names (which often include spaces) are put between quotation marks
CUDA_INC = $$join(INCLUDEPATH,'" -I"','-I"','"')

# Configuration of the Cuda compiler
CONFIG(debug, debug|release) {
    # Debug mode
    cuda_d.input = CUDA_SOURCES
    cuda_d.output = $$CUDA_OBJECTS_DIR/${QMAKE_FILE_BASE}_cuda.o
    cuda_d.commands = $$CUDA_DIR/bin/nvcc.exe -D_DEBUG $$NVCC_OPTIONS $$CUDA_INC $$LIBS --machine $$SYSTEM_TYPE -arch=$$CUDA_ARCH -c -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
    cuda_d.dependency_type = TYPE_C
    QMAKE_EXTRA_COMPILERS += cuda_d
}
else {
    # Release mode
    cuda.input = CUDA_SOURCES
    cuda.output = $$CUDA_OBJECTS_DIR/${QMAKE_FILE_BASE}_cuda.o
    cuda.commands = $$CUDA_DIR/bin/nvcc.exe $$NVCC_OPTIONS $$CUDA_INC $$LIBS --machine $$SYSTEM_TYPE -arch=$$CUDA_ARCH -c -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
    cuda.dependency_type = TYPE_C
    QMAKE_EXTRA_COMPILERS += cuda
}

Note the QMAKE_LFLAGS_RELEASE = /NODEFAULTLIB:msvcrt.lib : it took me a long time to figure out, but this library seems to clash with other things in Cuda, which produces strange linking warnings and errors.注意QMAKE_LFLAGS_RELEASE = /NODEFAULTLIB:msvcrt.lib :我花了很长时间才弄明白,但这个库似乎与 Cuda 中的其他东西发生冲突,这会产生奇怪的链接警告和错误。 If someone has an explanation for this, and potentially a prettier way to get around this, I'd like to hear it.如果有人对此有解释,并且可能有更漂亮的方法来解决这个问题,我想听听。

Also, since Windows file paths often include spaces (and NVIDIA's SDK by default does so too), it is necessary to artificially add quotation marks around the include paths.此外,由于 Windows 文件路径通常包含空格(默认情况下 NVIDIA 的 SDK 也是如此),因此有必要在包含路径周围人为地添加引号。 Again, if someone knows a more elegant way of solving this problem, I'd be interested to know.同样,如果有人知道解决这个问题的更优雅的方法,我很想知道。

The main.cpp file looks like this: main.cpp文件如下所示:

#include <cuda.h>
#include <builtin_types.h>
#include <drvapi_error_string.h>

#include <QtCore/QCoreApplication>
#include <QDebug>

// Forward declare the function in the .cu file
void vectorAddition(const float* a, const float* b, float* c, int n);

void printArray(const float* a, const unsigned int n) {
    QString s = "(";
    unsigned int ii;
    for (ii = 0; ii < n - 1; ++ii)
        s.append(QString::number(a[ii])).append(", ");
    s.append(QString::number(a[ii])).append(")");

    qDebug() << s;
}

int main(int argc, char* argv [])
{
    QCoreApplication(argc, argv);

    int deviceCount = 0;
    int cudaDevice = 0;
    char cudaDeviceName [100];

    unsigned int N = 50;
    float *a, *b, *c;

    cuInit(0);
    cuDeviceGetCount(&deviceCount);
    cuDeviceGet(&cudaDevice, 0);
    cuDeviceGetName(cudaDeviceName, 100, cudaDevice);
    qDebug() << "Number of devices: " << deviceCount;
    qDebug() << "Device name:" << cudaDeviceName;

    a = new float [N];    b = new float [N];    c = new float [N];
    for (unsigned int ii = 0; ii < N; ++ii) {
        a[ii] = qrand();
        b[ii] = qrand();
    }

    // This is the function call in which the kernel is called
    vectorAddition(a, b, c, N);

    qDebug() << "input a:"; printArray(a, N);
    qDebug() << "input b:"; printArray(b, N);
    qDebug() << "output c:"; printArray(c, N);

    if (a) delete a;
    if (b) delete b;
    if (c) delete c;
}

The Cuda file vectorAddition.cu , which describes a simple vector addition, look like this: Cuda 文件vectorAddition.cu描述了一个简单的向量加法,如下所示:

#include <cuda.h>
#include <builtin_types.h>

extern "C"
__global__ void vectorAdditionCUDA(const float* a, const float* b, float* c, int n)
{
    int ii = blockDim.x * blockIdx.x + threadIdx.x;
    if (ii < n)
        c[ii] = a[ii] + b[ii];
}

void vectorAddition(const float* a, const float* b, float* c, int n) {
    float *a_cuda, *b_cuda, *c_cuda;
    unsigned int nBytes = sizeof(float) * n;
    int threadsPerBlock = 256;
    int blocksPerGrid   = (n + threadsPerBlock - 1) / threadsPerBlock;

    // allocate and copy memory into the device
    cudaMalloc((void **)& a_cuda, nBytes);
    cudaMalloc((void **)& b_cuda, nBytes);
    cudaMalloc((void **)& c_cuda, nBytes);
    cudaMemcpy(a_cuda, a, nBytes, cudaMemcpyHostToDevice);
    cudaMemcpy(b_cuda, b, nBytes, cudaMemcpyHostToDevice);

    vectorAdditionCUDA<<<blocksPerGrid, threadsPerBlock>>>(a_cuda, b_cuda, c_cuda, n);

    // load the answer back into the host
    cudaMemcpy(c, c_cuda, nBytes, cudaMemcpyDeviceToHost);

    cudaFree(a_cuda);
    cudaFree(b_cuda);
    cudaFree(c_cuda);
}

If you get this to work, then more complicated examples are self-evident, I think.如果你让它起作用,那么更复杂的例子是不言而喻的,我想。

Edit (24-1-2013): I added the QMAKE_LFLAGS_DEBUG = /NODEFAULTLIB:msvcrtd.lib and the CONFIG(debug) with the extra D_DEBUG flag, such that it also compiles in debug mode.编辑(24-1-2013):我添加了QMAKE_LFLAGS_DEBUG = /NODEFAULTLIB:msvcrtd.lib和带有额外D_DEBUG标志的CONFIG(debug) ,这样它也可以在调试模式下编译。

Using msvc 2010 I found that the linker does not accept the -l parameter, however nvcc needs it.使用 msvc 2010 我发现链接器不接受 -l 参数,但是 nvcc 需要它。 Therefore I made a simple change in the .pro file:因此我在 .pro 文件中做了一个简单的更改:

# Add the necessary libraries
CUDA_LIBS = cuda cudart
# The following makes sure all path names (which often include spaces) are put between quotation marks
CUDA_INC = $$join(INCLUDEPATH,'" -I"','-I"','"')
# LIBRARIES IN FORMAT NEEDED BY NVCC
NVCC_LIBS = $$join(CUDA_LIBS,' -l','-l', '')
# LIBRARIES IN FORMAT NEEDED BY VISUAL C++ LINKER
LIBS += $$join(CUDA_LIBS,'.lib ', '', '.lib')

And the nvcc command (release version):和 nvcc 命令(发布版本):

cuda.commands = $$CUDA_DIR/bin/nvcc.exe $$NVCC_OPTIONS $$CUDA_INC $$NVCC_LIBS --machine $$SYSTEM_TYPE -arch=$$CUDA_ARCH -c -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}

$$NVCC_LIBS was inserted instead of $$LIBS.插入了 $$NVCC_LIBS 而不是 $$LIBS。 The whole .pro file, which works for me:整个 .pro 文件,对我有用:

QT       += core

QT       -= gui

TARGET = TestCUDA
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app

# Define output directories
DESTDIR = release
OBJECTS_DIR = release/obj
CUDA_OBJECTS_DIR = release/cuda

# Source files
SOURCES += main.cpp

# This makes the .cu files appear in your project
OTHER_FILES +=  vectorAddition.cu

# CUDA settings <-- may change depending on your system
CUDA_SOURCES += vectorAddition.cu
#CUDA_SDK = "C:/ProgramData/NVIDIA Corporation/NVIDIA GPU Computing SDK 4.2/C"   # Path to cuda SDK install
CUDA_DIR = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v5.0"           # Path to cuda toolkit install
SYSTEM_NAME = win32         # Depending on your system either 'Win32', 'x64', or 'Win64'
SYSTEM_TYPE = 32            # '32' or '64', depending on your system
CUDA_ARCH = sm_11           # Type of CUDA architecture, for example 'compute_10', 'compute_11', 'sm_10'
NVCC_OPTIONS = --use_fast_math

# include paths
INCLUDEPATH += $$CUDA_DIR/include
               #$$CUDA_SDK/common/inc/ \
               #$$CUDA_SDK/../shared/inc/

# library directories
QMAKE_LIBDIR += $$CUDA_DIR/lib/$$SYSTEM_NAME
                #$$CUDA_SDK/common/lib/$$SYSTEM_NAME \
                #$$CUDA_SDK/../shared/lib/$$SYSTEM_NAME


# The following library conflicts with something in Cuda
QMAKE_LFLAGS_RELEASE = /NODEFAULTLIB:msvcrt.lib
QMAKE_LFLAGS_DEBUG   = /NODEFAULTLIB:msvcrtd.lib

# Add the necessary libraries
CUDA_LIBS = cuda cudart
# The following makes sure all path names (which often include spaces) are put between quotation marks
CUDA_INC = $$join(INCLUDEPATH,'" -I"','-I"','"')
NVCC_LIBS = $$join(CUDA_LIBS,' -l','-l', '')
LIBS += $$join(CUDA_LIBS,'.lib ', '', '.lib')

# Configuration of the Cuda compiler
CONFIG(debug, debug|release) {
    # Debug mode
    cuda_d.input = CUDA_SOURCES
    cuda_d.output = $$CUDA_OBJECTS_DIR/${QMAKE_FILE_BASE}_cuda.o
    cuda_d.commands = $$CUDA_DIR/bin/nvcc.exe -D_DEBUG $$NVCC_OPTIONS $$CUDA_INC $$NVCC_LIBS --machine $$SYSTEM_TYPE -arch=$$CUDA_ARCH -c -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
    cuda_d.dependency_type = TYPE_C
    QMAKE_EXTRA_COMPILERS += cuda_d
}
else {
    # Release mode
    cuda.input = CUDA_SOURCES
    cuda.output = $$CUDA_OBJECTS_DIR/${QMAKE_FILE_BASE}_cuda.o
    cuda.commands = $$CUDA_DIR/bin/nvcc.exe $$NVCC_OPTIONS $$CUDA_INC $$NVCC_LIBS --machine $$SYSTEM_TYPE -arch=$$CUDA_ARCH -c -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
    cuda.dependency_type = TYPE_C
    QMAKE_EXTRA_COMPILERS += cuda
}

I also added some essential declarations, ie QT += core for the app to work, and also removed the SDK part, which I did not find useful in this case.我还添加了一些必要的声明,即 QT += core 以使应用程序工作,并删除了 SDK 部分,我认为在这种情况下没有用。

I tried this combination to work.我试过这种组合起作用。 Could not make it work due to a number of dependencies in my project.由于我的项目中有许多依赖项,因此无法使其工作。 My final solution was to break the application into two separate applications on Windows 1)我的最终解决方案是在 Windows 上将应用程序分解为两个单独的应用程序 1)

  1. CUDA application developed in VC and running as a service/DLL in Windows在 VC 中开发并在 Windows 中作为服务/DLL 运行的 CUDA 应用程序
  2. GUI interface developed in QT and using the DLL for CUDA related tasks.在 QT 中开发的 GUI 界面并使用 DLL 进行 CUDA 相关任务。

Hope it saves some time of others希望它可以节省其他人的一些时间

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM