How to properly use CUDA pipeline in Visual studio - c++

Hello I am developing CUDA C++ application. I would like to use CUDA interactive debugger in visual studio but cmake projects seem to be not supported (am I wrong?).
So I am trying to switch from cmake to visual studio project. Hovewer I run into strange problem.
Without any importanta changes in code I have error:
Severity Code Description Project File Line Suppression State
Error Multiple definition of '_ZN4cuda3__48pipelineILNS_3std3__48__detail12thread_scopeE2EE25__barrier_try_wait_parityERNS0_7barrierILS5_2ENS3_18__empty_completionEEEb' in 'x64/Debug/MainPassFunctions.cu.obj', first defined in 'x64/Debug/BiggerMainFunctions.cu.obj' CUDADebugB C:\Users\1\source\repos\CUDADebugB\CUDALINK 1
when I try to use function where argument is defined as :
cuda::pipeline< cuda::thread_scope_block>& pipeline
Begining of my cu file
#include "cuda_runtime.h"
#include <cstdint>
#include <cuda/pipeline>
#include <cooperative_groups.h>
#include <cuda_pipeline.h>
using namespace cooperative_groups;
in cmake project all worked well with cmake as below
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(hello LANGUAGES CXX CUDA)
enable_language(CUDA)
find_package(hdf5 CONFIG REQUIRED)
find_package(GTest CONFIG REQUIRED)
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -lineinfo -rdc=true -lcudadevrt")
set(CMAKE_CUDA_ARCHITECTURES 80)
add_executable(hello hello.cu )
include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
target_link_libraries(${PROJECT_NAME} ${CUDA_LIBRARIES})
target_link_libraries(hello PRIVATE hdf5::hdf5-shared hdf5::hdf5_hl-shared hdf5::hdf5_cpp-shared hdf5::hdf5_hl_cpp-shared)
target_link_libraries(hello PRIVATE GTest::gmock GTest::gtest GTest::gmock_main GTest::gtest_main)
now my vs studio project settings
What i should change to make it work?

Answer by
rturrado solved the problem
"
It looks like you have two definitions for the same function, one in the MainPassFunctions object file, and the other in the BiggerMainFunctions object file."
So I just fused two files into one.

Related

How to link CUDA dynamic libraries using CMake?

I want to know how to use CMake to dynamically link CUDA libraries, I know it seems to require some extra restrictions, but don't know exactly how to do it. Here is a simple example I wrote to illustrate my problem.
Directory structure:
Dir/
├── CMakeLists.txt
├── header.cuh
├── kernel.cu
└── main.cpp
Environment:
OS: Windows 11
GPU: RTX 3060 laptop
CUDA Toolkit: 11.6
Platform: Visual Studio 2022
header.cuh:
#include "stdio.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
extern "C" void f();
kernel.cu:
#include "header.cuh"
void __global__ print()
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
printf("%d\n", idx);
}
void f()
{
print<<<1, 10>>>();
}
main.cpp:
#include "header.cuh"
extern "C" void f();
int main()
{
f();
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.17)
project(test)
set(CMAKE_CXX_STANDARD 17)
find_package(CUDA REQUIRED)
enable_language("CUDA")
set(CMAKE_CUDA_STANDARD 14)
set(CUDA_SEPARABLE_COMPILATION ON)
string(APPEND CMAKE_CUDA_FLAGS " -rdc=true --cudart shared")
add_library(CUDA_COMP SHARED header.cuh kernel.cu)
set_property(TARGET CUDA_COMP PROPERTY CUDA_ARCHITECTURES 86-real 86-virtual)
add_executable(main main.cpp)
target_link_libraries(main CUDA_COMP)
The project can be configured successfully, but a problem with unresolved external symbols f referenced in function main occurs when building it.
I also looked up the corresponding solution on Stackoverflow, but it didn't work. For example, an answer on Stackoverflow mentioned adding " -rdc=true --cudart shared" to cmake, and I did the same (see line 10 of CMakeLists.txt).
This problem has been bothering me for a long time. I hope you can tell me the cause of the problem and how to solve it. Thank you so much!
There is a lot of issues with OP's code.
CUDA/C++ issues:
CUDA nowadays is a C++ dialect, not C. Therefore I would not declare f() to be extern "C".
There seems to be no reason for the header to include anything. When something is needed by the implementation, but not by the interface, the include should not be part of the interface.
If you want to use this header to interface with non-CUDA C++ code (a .cpp file) it should be named .h (or .hpp). I would expect .cuh files to only ever be included by .cu files. One also usually puts the same name on interface and implementation, so I renamed the header to kernel.h.
Header guards are missing.
Why would you redeclare f() in main.cpp? That is what the header is for.
You forgot to synchronize after the kernel launch, so the app will most probably print nothing at all.
CMake issues:
Setting properties etc. in CMakeLists.txt globally is discouraged. One should use the target specific APIs whenever possible. Some of these global properties have to be set before project() to work at all.
CMake sets -rdc=true automatically when CUDA_SEPARABLE_COMPILATION is set.
CUDA separable compilation is only needed when e.g. a kernel uses a device function that is defined in a different translation unit. I am not sure if OP thinks he needs it, or if the part that he needs it for was removed when creating a minimal example.
There is the CUDA_RUNTIME_LIBRARY property for dynamically linking the CUDA runtime.
Using find_package(CUDA) is deprecated in favor of using CUDA as a language. In the rare case where one does not want to use the CUDA language, but still needs to find the CUDA toolkit, there is also FindCUDAToolkit. OP only needs the language. But the linked documentation also lists all the CUDA libraries that come with the toolkit. Here we can see that most libraries provide a _static version to differentiate between static and dynamic linking. When using the CUDA language, these are also available but without the CUDA:: "namespace". Do not use target_link_libraries(... cudart) when using the language, as this will not influence the CUDA_RUNTIME_LIBRARY property, i.e. you might get some kind of undefined CMake behavior. But when you want to dynamically link against e.g. CUBLAS, you can use target_link_libraries(... cublas).
The CUDA architecture should not be hardcoded into the CMakeLists.txt as long as the project does not use some kind of architecture-specific intrinsics. Instead one should specify the architecture at configuration time. CMake 3.18 added CMAKE_CUDA_ARCHITECTURES in version so I would recommend setting the minimum to 3.18 instead of 3.17. Then you can call e.g. cmake -DCMAKE_CUDA_ARCHITECTURES=86 (not sure how this is handled in Visual Studio). I added a default for 86 that can still be overwritten at configuration time when needed.
Fixed Example
The following files work for me under Linux with CMake 3.23.1, CUDA 11.8.0 and GCC 11.3.0:
kernel.h:
#pragma once
void f();
kernel.cu:
#include "kernel.h"
#include <cstdio>
void __global__ print()
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
std::printf("%d\n", idx);
}
void f()
{
print<<<1, 10>>>();
cudaDeviceSynchronize();
}
main.cpp:
#include "kernel.h"
int main()
{
f();
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.18)
# this has to be set before project()
if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
set(CMAKE_CUDA_ARCHITECTURES 86)
endif()
project(test LANGUAGES CXX CUDA)
add_library(cuda_comp SHARED kernel.h kernel.cu)
# this command would only set the minimum standard,
# i.e. CMake can still decide to use -std=c++17 instead
# if the given compilers support C++17
target_compile_features(cuda_comp PRIVATE cuda_std_14)
set_target_properties(cuda_comp
PROPERTIES
CUDA_RUNTIME_LIBRARY Shared
# CUDA_STANDARD 14 # this one cannot be changed by CMake
# CUDA_SEPARABLE_COMPILATION ON # not needed for this example
)
add_executable(main main.cpp)
target_compile_features(main PRIVATE cxx_std_17)
# set_target_properties(main CXX_STANDARD 17)
target_link_libraries(main cuda_comp)

glfwInit() causes segmentation fault with exit code -1073741515 (0xc0000135)

I have been trying to get one my older projects to work which uses some OpenGL code. I am unable to produce a working executable. All that happens is, just by calling glfwInit(), is a segmentation fault:
My best guess is that it somehow doesnt use/find the glfw dll i am trying to use.
Let me explain my current setup:
I have installed glfw using msys2:
pacman -S mingw-w64-x86_64-glfw
I have created a glad header and source file
I wrote a simple cmake-file (which also used to work 2 years ago)
cmake_minimum_required(VERSION 3.23)
project(2DGameEngine)
find_package(glfw3 3.3 REQUIRED)
find_package(OpenGL REQUIRED)
set(CMAKE_CXX_STANDARD 23)
file(GLOB_RECURSE SRCS src/*.cpp src/*.c)
add_executable(2DGameEngine ${SRCS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow")
target_link_libraries(2DGameEngine glfw)
target_link_libraries(2DGameEngine OpenGL::GL)
I used the simplest example I could find:
#include "glad.h"
#include <GLFW/glfw3.h>
#include <iostream>
int main()
{
// glfw: initialize and configure
// ------------------------------
if(!glfwInit()){
std::cout << "error" << std::endl;
exit(1);
}
return 0;
}
Yet I am unable to get rid of the segmentation fault when calling glfwInit(). I assume it has to do with some .dll missing but I have no idea how I could check this. I am very happy for any help.
0xc0000135 is the error you get when your Windows OS could not find a required dll when executing your program. There is a handy site that decodes these types of errors here: https://james.darpinian.com/decoder/?q=0xc0000135
Use this program: https://github.com/lucasg/Dependencies to figure out what dll can not be found and then put that dll in the same folder as the executable or edit your OS PATH environment variable to contain the folder which has that dll.
Here is a good article on how to set the OS PATH environment variable: https://www.computerhope.com/issues/ch000549.htm
There are several other options contained in this Microsoft document which explains how and where your OS searches for dlls: https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#search-order-for-desktop-applications

spdlog crash on factory methods

Yesterday I have started including spdlog into a personal project of mine to use for logging. So far I have had some problems with getting library inclusion to work but those are now solved completely.
Now everything compiles just fine, with all headers found however when I try to create loggers or simply set the pattern for logging the code crashes with a segmentation fault. More specifically no matter which function I call from the spdlog namespace for the very first time in the program causes the crash.
I have a class abstracting some parts from spdlog (based on this repo) as follows:
//Logger.hpp
#ifndef TE_LOGGER_HPP
#define TE_LOGGER_HPP
#include <spdlog/spdlog.h>
namespace te {
class Logger {
public:
static void Init();
inline static std::shared_ptr<spdlog::logger> &getCoreLogger() {
return sCoreLogger;
}
inline static std::shared_ptr<spdlog::logger> &getClientLogger() {
return sClientLogger;
}
private:
static std::shared_ptr<spdlog::logger> sCoreLogger;
static std::shared_ptr<spdlog::logger> sClientLogger;
};
}
#endif //TE_LOGGER_HPP
//Logger.cpp
#include "Logger.hpp"
#include <spdlog/sinks/stdout_color_sinks.h>
std::shared_ptr<spdlog::logger> te::Logger::sCoreLogger;
std::shared_ptr<spdlog::logger> te::Logger::sClientLogger;
void te::Logger::Init() {
//The first of any of the following three lines cause a crash
//no matter the order, regardless of the pattern used in set_pattern
spdlog::set_pattern("%v");
sCoreLogger = spdlog::stdout_color_mt("CORE");
sClientLogger = spdlog::stdout_color_mt("CORE");
sCoreLogger->set_level(spdlog::level::trace);
sClientLogger->set_level(spdlog::level::trace);
}
From the stack traces it seems that the issue is with the formatter class in spdlog being set null for some reason somewhere within the library. I am using the latest CLion, C++14 (I am aware that spdlog is C++11, but I need features from 14 later down the line, also setting -std=c++11 doesn't solve the issue) and the latest version of spdlog as of yesterday (pulled straight from their GitHub repo) on Ubuntu 18.04.
EDIT: As per the request in the comments I have created a small project (single cpp file, include spdlog the way I do in the real project, or the same code and library setup as in the real project referenced from the main.cpp file and linked to accordingly) that aims to reproduce the issue and here are my findings:
* The issue is not present when I use spdlog directly in the executable
* The issue is present if the Logger class is moved into a shared library and linked to from there
Here is the error message I am getting:
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
And the CMakeLists.txt files I am using (I nest the library's one into the project since as of now CLion does not support "multiple projects in the same solution" like for example VS does):
#CMakeLists.txt for Library
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(TokenEngine VERSION 0.0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(SOURCE_FILES src/Application.cpp src/Application.hpp src/EntryPoint.hpp src/Logger.cpp src/Logger.hpp)
#include_directories("${CMAKE_CURRENT_SOURCE_DIR}/libs/")
add_library(TokenEngine SHARED ${SOURCE_FILES})
target_include_directories(TokenEngine PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/libs/spdlog-1.x/include")
#Expose the public API of the engine to any project that might use it
target_include_directories(TokenEngine PUBLIC include)
#CMakeLists.txt for top level project
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
add_definitions(-DTE_PLATFORM_LINUX)
project(Build CXX)
add_subdirectory(TokenEngine)
add_subdirectory(Sandbox)
You are using the same name for both loggers, when you run it you'll get:
$ ./logger
libc++abi.dylib: terminating with uncaught exception of type spdlog::spdlog_ex: logger with name 'CORE' already exists
Abort trap: 6
If you change the name of the client logger to something else it works fine:
sCoreLogger = spdlog::stdout_color_mt("CORE");
sClientLogger = spdlog::stdout_color_mt("CLIENT");
The problem is probably that spdlog’s static objects are defined twice - from inside the shared library and from client code that includes your logger header (which incldes spdlog.h).
Try to remove the include to spdlog.h from the header file and (and use forward declaration of spdlog::logger instead), and include spdlog.h only from your Logger.cpp file.
Edit:
spdlog::logger cannot be forward declared across compilation unit boundries.
The solution is to wrap the logger with some simple class defined in logger.cpp and only export it in logger.h

Building project with ARUCO fails

I'm trying to build a project with arUco.
I am using openCV v.3.1, which apparently includes aruco. However, I get the error:
opencv2/aruco/dictionary.hpp: No such file or directory
#include "opencv2/aruco/dictionary.hpp"
^
I then downloaded arUco, built it, and tried to build the example described at the bottom of http://www.uco.es/investiga/grupos/ava/node/26 . I get the error:
fatal error: aruco/aruco.h: No such file or directory
#include <aruco/aruco.h>
^
The CMakeLists.txt used is:
cmake_minimum_required(VERSION 2.8)
project(aruco_testproject)
SET(CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/lib/cmake/ )
MESSAGE(${CMAKE_MODULE_PATH})
find_package(aruco REQUIRED )
add_executable(aruco_simple aruco_simple.cpp)
target_link_libraries(aruco_simple ${aruco_LIBS})
I've copied Findaruco.cmake to /usr/local/lib/cmake/
If anyone could help, that'd be fantastic. I've been looking for a solution for a while and I feel really stuck. Thanks a lot!
You are missing the include_directories stanza. Also I think the correct variable name suffix for the library should be _LIBRARIES, not _LIBS, but afaik, cmake is unable to enforce any rule with rogue cmake modules, so the best bet is probably to try several common suffixes. That's one of cmake's atrocities.
cmake_minimum_required(VERSION 2.8)
project(aruco_testproject)
SET(CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/lib/cmake/ )
MESSAGE(${CMAKE_MODULE_PATH})
find_package(aruco REQUIRED )
add_executable(aruco_simple aruco_simple.cpp)
include_directories(${ARUCO_INCLUDE_DIR} ${ARUCO_INCLUDE_DIRS})
target_link_libraries(aruco_simple ${ARUCO_LIBRARY} ${ARUCO_LIBRARIES})
For the header inclusion, #include <aruco/aruco.h> looks fine, but not #include "opencv2/aruco/xxx".

making boost work with cmake ( fatal error: boost/smart_ptr.hpp: No such file or directory )

After digging for hours on this, I finally need some expert help.
I am new to cmake and trying to port my Visual Studio 2008 project to cmake.
My project uses opencv, qt and boost libraries.
Now I have managed to run simple cmake examples with opencv and qt but I am stuck with boost.
The bottleneck is this: CMake finds the correct boost version, finds the libraries and gives no error while configuration.
But when I try to build the project using make, it gives me:
" fatal error: boost/smart_ptr.hpp: No such file or directory"
Assuming the configuration is done right, cmake should be able to find the boost include directories.
I have set BOOST_ROOT to the correct boost root directory and that's why configuration does not give errors. But what happens while running make? Am I missing something simple here? Need help desperately...
I am sorry if this is a stupid question.
Here's my CMakeLists.txt file:
cmake_minimum_required( VERSION 2.6 )
project (CMakeBoostTutorial)
find_package( Boost 1.46.1 COMPONENTS date_time REQUIRED)
link_directories ( ${Boost_LIBRARY_DIRS} )
include_directories ( ${Boost_INCLUDE_DIRS} )
add_executable ( helloworld helloworld.cc )
target_link_libraries (
helloworld
${Boost_LIBRARIES}
)
And here's my helloworld.cc:
#include <iostream>
#include <stdlib.h>
#include <boost/smart_ptr.hpp>
using namespace std;<br/>
int main(int argc, char *argv[]){
cout<<"Hello World";
return 0;
}
PS: This compiles and runs fine if I remove the #include <boost/smart_ptr.hpp> line