一、環境配置
1、網上很多教程都有,安裝合適自己電腦的CUDA,我已安裝完畢
2、CMake編譯opencv4.1+opencv_contrib4.1+CUDA,網上依舊很多教程。我前幾次編譯時,遇到外網下載、下載超時原因報錯很多,但後來按照網上的辦法自己線下到報錯的網址下載後放到對應報錯文件夾下,就解決了。中途我自己下載了這些文件:
現在cmake第一次configure後,只有下面一個地方報紅色:
log如下:
The CXX compiler identification is MSVC 19.0.24215.1
The C compiler identification is MSVC 19.0.24215.1
Check for working CXX compiler: E:/VS2015/VS/VC/bin/x86_amd64/cl.exe
Check for working CXX compiler: E:/VS2015/VS/VC/bin/x86_amd64/cl.exe -- works
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
Detecting CXX compile features
Detecting CXX compile features - done
Check for working C compiler: E:/VS2015/VS/VC/bin/x86_amd64/cl.exe
Check for working C compiler: E:/VS2015/VS/VC/bin/x86_amd64/cl.exe -- works
Detecting C compiler ABI info
Detecting C compiler ABI info - done
Performing Test HAVE_CXX11 (check file: cmake/checks/cxx11.cpp)
Performing Test HAVE_CXX11 - Success
Found PythonInterp: E:/anaconda/anaconda3.5.1/python.exe (found suitable version "3.6.4", minimum required is "2.7")
CMake Warning at cmake/OpenCVDetectPython.cmake:81 (message):
CMake's 'find_host_package(PythonInterp 2.7)' founds wrong Python version:
PYTHON_EXECUTABLE=E:/anaconda/anaconda3.5.1/python.exe
PYTHON_VERSION_STRING=3.6.4
Consider specify 'PYTHON2_EXECUTABLE' variable via CMake command line or
environment variables
Call Stack (most recent call first):
cmake/OpenCVDetectPython.cmake:275 (find_python)
CMakeLists.txt:689 (include)
Consider using CMake 3.12+ for better Python support
Could NOT find PythonInterp: Found unsuitable version "1.4", but required is at least "3.2" (found C:/Users/admin/AppData/Local/Microsoft/WindowsApps/python3.exe)
Performing Test HAVE_CPU_SSE3_SUPPORT (check file: cmake/checks/cpu_sse3.cpp)
Performing Test HAVE_CPU_SSE3_SUPPORT - Success
Performing Test HAVE_CPU_SSSE3_SUPPORT (check file: cmake/checks/cpu_ssse3.cpp)
Performing Test HAVE_CPU_SSSE3_SUPPORT - Success
Performing Test HAVE_CPU_SSE4_1_SUPPORT (check file: cmake/checks/cpu_sse41.cpp)
Performing Test HAVE_CPU_SSE4_1_SUPPORT - Success
Performing Test HAVE_CPU_POPCNT_SUPPORT (check file: cmake/checks/cpu_popcnt.cpp)
Performing Test HAVE_CPU_POPCNT_SUPPORT - Success
Performing Test HAVE_CPU_SSE4_2_SUPPORT (check file: cmake/checks/cpu_sse42.cpp)
Performing Test HAVE_CPU_SSE4_2_SUPPORT - Success
Performing Test HAVE_CXX_ARCH:AVX (check file: cmake/checks/cpu_fp16.cpp)
Performing Test HAVE_CXX_ARCH:AVX - Success
Performing Test HAVE_CXX_ARCH:AVX2 (check file: cmake/checks/cpu_avx2.cpp)
Performing Test HAVE_CXX_ARCH:AVX2 - Success
Performing Test HAVE_CPU_AVX_512F_SUPPORT (check file: cmake/checks/cpu_avx512.cpp)
Performing Test HAVE_CPU_AVX_512F_SUPPORT - Failed
AVX_512F is not supported by C++ compiler
Performing Test HAVE_CPU_AVX512_SKX_SUPPORT (check file: cmake/checks/cpu_avx512skx.cpp)
Performing Test HAVE_CPU_AVX512_SKX_SUPPORT - Failed
AVX512_SKX is not supported by C++ compiler
Dispatch optimization AVX512_SKX is not available, skipped
Performing Test HAVE_CPU_BASELINE_FLAGS
Performing Test HAVE_CPU_BASELINE_FLAGS - Success
Performing Test HAVE_CPU_DISPATCH_FLAGS_SSE4_1
Performing Test HAVE_CPU_DISPATCH_FLAGS_SSE4_1 - Success
Performing Test HAVE_CPU_DISPATCH_FLAGS_SSE4_2
Performing Test HAVE_CPU_DISPATCH_FLAGS_SSE4_2 - Success
Performing Test HAVE_CPU_DISPATCH_FLAGS_FP16
Performing Test HAVE_CPU_DISPATCH_FLAGS_FP16 - Success
Performing Test HAVE_CPU_DISPATCH_FLAGS_AVX
Performing Test HAVE_CPU_DISPATCH_FLAGS_AVX - Success
Performing Test HAVE_CPU_DISPATCH_FLAGS_AVX2
Performing Test HAVE_CPU_DISPATCH_FLAGS_AVX2 - Success
Check if the system is big endian
Searching 16 bit integer
Looking for sys/types.h
Looking for sys/types.h - found
Looking for stdint.h
Looking for stdint.h - found
Looking for stddef.h
Looking for stddef.h - found
Check size of unsigned short
Check size of unsigned short - done
Using unsigned short
Check if the system is big endian - little endian
Looking for fseeko
Looking for fseeko - not found
Check size of off64_t
Check size of off64_t - failed
libjpeg-turbo: VERSION = 2.0.2, BUILD = opencv-4.1.0-libjpeg-turbo
Check size of size_t
Check size of size_t - done
Check size of unsigned long
Check size of unsigned long - done
Looking for include file intrin.h
Looking for include file intrin.h - found
Looking for assert.h
Looking for assert.h - found
Looking for fcntl.h
Looking for fcntl.h - found
Looking for inttypes.h
Looking for inttypes.h - found
Looking for io.h
Looking for io.h - found
Looking for limits.h
Looking for limits.h - found
Looking for malloc.h
Looking for malloc.h - found
Looking for memory.h
Looking for memory.h - found
Looking for search.h
Looking for search.h - found
Looking for string.h
Looking for string.h - found
Performing Test C_HAS_inline
Performing Test C_HAS_inline - Success
Check size of signed short
Check size of signed short - done
Check size of unsigned short
Check size of unsigned short - done
Check size of signed int
Check size of signed int - done
Check size of unsigned int
Check size of unsigned int - done
Check size of signed long
Check size of signed long - done
Check size of signed long long
Check size of signed long long - done
Check size of unsigned long long
Check size of unsigned long long - done
Check size of unsigned char *
Check size of unsigned char * - done
Check size of ptrdiff_t
Check size of ptrdiff_t - done
Looking for memmove
Looking for memmove - found
Looking for setmode
Looking for setmode - found
Looking for strcasecmp
Looking for strcasecmp - not found
Looking for strchr
Looking for strchr - found
Looking for strrchr
Looking for strrchr - found
Looking for strstr
Looking for strstr - found
Looking for strtol
Looking for strtol - found
Looking for strtol
Looking for strtol - found
Looking for strtoull
Looking for strtoull - found
Looking for lfind
Looking for lfind - found
Performing Test HAVE_SNPRINTF
Performing Test HAVE_SNPRINTF - Success
Check if the system is big endian
Searching 16 bit integer
Using unsigned short
Check if the system is big endian - little endian
IPPICV: Download: ippicv_2019_win_intel64_20180723_general.zip
found Intel IPP (ICV version): 2019.0.0 [2019.0.0 Gold]
at: E:/opencv/opencv4.1.0/opencv-4.1.0/build/3rdparty/ippicv/ippicv_win/icv
found Intel IPP Integration Wrappers sources: 2019.0.0
at: E:/opencv/opencv4.1.0/opencv-4.1.0/build/3rdparty/ippicv/ippicv_win/iw
Could not find OpenBLAS include. Turning OpenBLAS_FOUND off
Could not find OpenBLAS lib. Turning OpenBLAS_FOUND off
Looking for pthread.h
Looking for pthread.h - not found
Found Threads: TRUE
A library with BLAS API not found. Please specify library location.
LAPACK requires BLAS
A library with LAPACK API not found. Please specify library location.
Could NOT find JNI (missing: JAVA_AWT_LIBRARY JAVA_JVM_LIBRARY JAVA_INCLUDE_PATH JAVA_INCLUDE_PATH2 JAVA_AWT_INCLUDE_PATH)
VTK is not found. Please set -DVTK_DIR in CMake to VTK build directory, or to VTK install subdirectory with VTKConfig.cmake file
ADE: Download: v0.1.1d.zip
OpenCV Python: during development append to PYTHONPATH: E:/opencv/opencv4.1.0/opencv-4.1.0/build/python_loader
Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)
FFMPEG: Download: opencv_ffmpeg.dll
FFMPEG: Download: opencv_ffmpeg_64.dll
FFMPEG: Download: ffmpeg_version.cmake
Looking for mfapi.h
Looking for mfapi.h - found
Looking for d3d11_4.h
Looking for d3d11_4.h - not found
Excluding from source files list: modules/imgproc/src/sumpixels.avx512_skx.cpp
Excluding from source files list: <BUILD>/modules/dnn/layers/layers_common.avx512_skx.cpp
General configuration for OpenCV 4.1.0 =====================================
Version control: unknown
Platform:
Timestamp: 2020-04-24T02:26:33Z
Host: Windows 10.0.18362 AMD64
CMake: 3.6.3
CMake generator: Visual Studio 14 2015 Win64
CMake build tool: C:/Program Files (x86)/MSBuild/14.0/bin/MSBuild.exe
MSVC: 1900
CPU/HW features:
Baseline: SSE SSE2 SSE3
requested: SSE3
Dispatched code generation: SSE4_1 SSE4_2 FP16 AVX AVX2
requested: SSE4_1 SSE4_2 AVX FP16 AVX2 AVX512_SKX
SSE4_1 (15 files): + SSSE3 SSE4_1
SSE4_2 (2 files): + SSSE3 SSE4_1 POPCNT SSE4_2
FP16 (1 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 AVX
AVX (5 files): + SSSE3 SSE4_1 POPCNT SSE4_2 AVX
AVX2 (29 files): + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2
C/C++:
Built as dynamic libs?: YES
C++ Compiler: E:/VS2015/VS/VC/bin/x86_amd64/cl.exe (ver 19.0.24215.1)
C++ flags (Release): /DWIN32 /D_WINDOWS /W4 /GR /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /EHa /wd4127 /wd4251 /wd4324 /wd4275 /wd4512 /wd4589 /MP6 /MD /O2 /Ob2 /DNDEBUG
C++ flags (Debug): /DWIN32 /D_WINDOWS /W4 /GR /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /EHa /wd4127 /wd4251 /wd4324 /wd4275 /wd4512 /wd4589 /MP6 /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1
C Compiler: E:/VS2015/VS/VC/bin/x86_amd64/cl.exe
C flags (Release): /DWIN32 /D_WINDOWS /W3 /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /MP6 /MD /O2 /Ob2 /DNDEBUG
C flags (Debug): /DWIN32 /D_WINDOWS /W3 /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS /Gy /bigobj /Oi /MP6 /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1
Linker flags (Release): /machine:x64 /INCREMENTAL:NO
Linker flags (Debug): /machine:x64 /debug /INCREMENTAL
ccache: NO
Precompiled headers: YES
Extra dependencies:
3rdparty dependencies:
OpenCV modules:
To be built: calib3d core dnn features2d flann gapi highgui imgcodecs imgproc ml objdetect photo stitching ts video videoio
Disabled: world
Disabled by dependency: -
Unavailable: java js python2 python3
Applications: tests perf_tests apps
Documentation: NO
Non-free algorithms: NO
Windows RT support: NO
GUI:
Win32 UI: YES
VTK support: NO
Media I/O:
ZLib: build (ver 1.2.11)
JPEG: build-libjpeg-turbo (ver 2.0.2-62)
WEBP: build (ver encoder: 0x020e)
PNG: build (ver 1.6.36)
TIFF: build (ver 42 - 4.0.10)
JPEG 2000: build (ver 1.900.1)
OpenEXR: build (ver 1.7.1)
HDR: YES
SUNRASTER: YES
PXM: YES
PFM: YES
Video I/O:
DC1394: NO
FFMPEG: YES (prebuilt binaries)
avcodec: YES (58.35.100)
avformat: YES (58.20.100)
avutil: YES (56.22.100)
swscale: YES (5.3.100)
avresample: YES (4.0.0)
GStreamer: NO
DirectShow: YES
Media Foundation: YES
DXVA: NO
Parallel framework: Concurrency
Trace: YES (with Intel ITT)
Other third-party libraries:
Intel IPP: 2019.0.0 Gold [2019.0.0]
at: E:/opencv/opencv4.1.0/opencv-4.1.0/build/3rdparty/ippicv/ippicv_win/icv
Intel IPP IW: sources (2019.0.0)
at: E:/opencv/opencv4.1.0/opencv-4.1.0/build/3rdparty/ippicv/ippicv_win/iw
Lapack: NO
Eigen: NO
Custom HAL: NO
Protobuf: build (3.5.1)
OpenCL: YES (NVD3D11)
Include path: E:/opencv/opencv4.1.0/opencv-4.1.0/3rdparty/include/opencl/1.2
Link libraries: Dynamic load
Python (for build): NO
Java:
ant: NO
JNI: NO
Java wrappers: NO
Java tests: NO
Install to: E:/opencv/opencv4.1.0/opencv-4.1.0/build/install
-----------------------------------------------------------------
Configuring done
有的說python版本報錯沒關係,可以直接忽略。
3、然後我直接打開VS2015開始生成,但始終最後有很多失敗。而且沒有看到生成的opencv的庫:
可以看到,我試過多次,依舊失敗。後來終於找到 : https://www.cnblogs.com/Vince-Wu/p/11805075.html 找到這個人講述的關於win10 SDK與VS2015的問題:
我按照他的方法準備試下,對比發現我的cmake日誌中沒有檢測WIN10 SDK版本的相關內容,所以我準備手動下載一個版本。然後重新cmake並添加環境變量,重啓VS編譯出現
E:/opencv/opencv4.1.0/opencv_contrib-4.1.0/modules/cudaimgproc/src/cuda/clahe.cu(191): error : identifier "__shfl_down" is undefined
CUSTOMBUILD : nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
我查了下網上很多解決辦法:
將CUDA_ARCH_BIN的值改成我的顯卡的6.1就可以了,重來以後VS編譯時還是有問題:
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(804): error C2065: “ID3D11Multithread”: 未聲明的標識符
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(804): error C2923: “`anonymous-namespace'::ComPtr”: 對於參數“T”,“ID3D11Multithread”不是有效的 模板 類型變量
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(804): error C2133: “D3DDevMT”: 未知的大小
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(804): error C2512: “`anonymous-namespace'::ComPtr”: 沒有合適的默認構造函數可用
18> E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(127): note: 參見“`anonymous-namespace'::ComPtr”的聲明
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(806): error C2100: 非法的間接尋址
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(806): error C2672: “IID_PPV_ARGS_Helper”: 未找到匹配的重載函數
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(806): error C2784: “void **IID_PPV_ARGS_Helper(T **)”: 未能從“`anonymous-namespace'::ComPtr *”爲“T **”推導 模板 參數
18> C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\um\combaseapi.h(231): note: 參見“IID_PPV_ARGS_Helper”的聲明
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(806): error C2660: “IUnknown::QueryInterface”: 函數不接受 1 個參數
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(808): error C2678: 二進制“->”: 沒有找到接受“`anonymous-namespace'::ComPtr”類型的左操作數的運算符(或沒有可接受的轉換)
18> E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(149): note: 可能是“T *`anonymous-namespace'::ComPtr<T>::operator ->(void) const”
18> E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(808): note: 嘗試匹配參數列表“(`anonymous-namespace'::ComPtr)”時
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(808): error C2039: “SetMultithreadProtected”: 不是“`anonymous-namespace'::ComPtr”的成員
18> E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(127): note: 參見“`anonymous-namespace'::ComPtr”的聲明
18>E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(809): error C2662: “void `anonymous-namespace'::ComPtr<T>::Release(void)”: 不能將“this”指針從“`anonymous-namespace'::ComPtr”轉換爲“`anonymous-namespace'::ComPtr<T> &”
18> E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(809): note: 原因如下: 無法從“`anonymous-namespace'::ComPtr”轉換爲“`anonymous-namespace'::ComPtr<T>”
18> E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp(809): note: 轉換要求第二個用戶定義的轉換運算符或構造函數
這個問題網上說是SDK版本10586帶來的問題,所以我重新下載了一個比10586還低一點的版本,當然配置相應改變如下圖:
然後重新編譯,出現
modules\videoio\src\cap_msmf.cpp(67): fatal error C1083: 無法打開包括文件: “d3d11_4.h”: No such file or directory
我在10586版本下看到了這個文件,10240下的確沒找到這個文件。於是我把這個文件複製到10240裏了:
重新編譯:出現:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\um\d3d11_4.h(57): fatal error C1083: 無法打開包括文件: “dxgi1_5.h”: No such file or directory (編譯源文件 E:\opencv\opencv4.1.0\opencv-4.1.0\modules\videoio\src\cap_msmf.cpp)
然後我又把10586下的這個文件拷貝到10240對應位置,重新編譯,竟然又出現了之前10586那個目標平臺版本錯誤的信息,於是我又查看屬性,發現目前平臺版本怎麼又變成了10586,明明我已經手動設置成了10240啊。(好像是每一次編譯都會改變,所以編譯前一定要確認),最後又重新編譯還是出現error:C2065那些錯誤。於是我又重新cmake:
把這兩個勾選的取消掉。重新編譯重新來一次:
看了一下:
18> 正在創建庫 E:/opencv/opencv4.1.0/opencv-4.1.0/build/lib/Debug/opencv_world410d.lib 和對象 E:/opencv/opencv4.1.0/opencv-4.1.0/build/lib/Debug/opencv_world410d.exp
18>LINK : fatal error LNK1210: 已超過內部 ILK 大小限制;鏈接時使用 /INCREMENTAL:NO
報的這個錯好像不是大問題,所以我沒有管。文件夾下生成了opencv_world的lib。
現在準備全部重新生成解決方案一次:
成功,只有一個錯,就是上面那個超出大小限制的錯,可忽略。然後我又將INSTALL生成一次:
可以看到成功,同時生成了install對應文件夾。這樣Debug下的編譯已基本完成。
然後我將Debug換成Release重新生成解決方案以及INSTALL重新生成:
可以看到,均成功。
至此,環境搭建終於完畢。
但是還是看到只有opencv_world410.dll,沒有opencv_world410d.dll,應該還是與那個我忽略的錯誤有關,即:超出ILK大小限制。可能這個錯誤不該忽略,導致沒有生成debug下的dll。寫個小例子測試時果然報錯:
error LNK2019: 無法解析的外部符號 "void __cdecl cv::imshow(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class cv::debug_build_guard::_InputArray const &)" (?imshow@cv@@YAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV_InputArray@debug_build_guard@1@@Z),該符號在函數 main 中被引用
1>E:\CUDA\hellocuda\x64\Debug\hellocuda.exe : fatal error LNK1120: 1 個無法解析的外部命令
可能還是需要opencv_world410d.dll。所以我還是得編譯出來debug下的庫。於是根據之前那個ILK超出大小限制的報錯,我按如下設置:“使用鏈接時間代碼生成”即網上提供的解決辦法LTCG
然後重新編譯opencv_world410d.dll,果然成功,
18>LINK : warning LNK4075: 忽略“/INCREMENTAL”(由於“/LTCG”規範)
18> 正在創建庫 E:/opencv/opencv4.1.0/opencv-4.1.0/build/lib/Debug/opencv_world410d.lib 和對象 E:/opencv/opencv4.1.0/opencv-4.1.0/build/lib/Debug/opencv_world410d.exp
18> 正在生成代碼
18> 已完成代碼的生成
18> opencv_world.vcxproj -> E:\opencv\opencv4.1.0\opencv-4.1.0\build\bin\Debug\opencv_world410d.dll
========== 全部重新生成: 成功 18 個,失敗 0 個,跳過 0 個 ==========
並拷貝到這裏:
然後測試:
無論使用哪種辦法,都還是有彈出下面的警告,雖然不影響運行結果。
“hellocuda.exe”(Win32): 已加載“E:\CUDA\hellocuda\x64\Debug\hellocuda.exe”。已加載符號。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\ntdll.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\kernel32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\KernelBase.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\vcruntime140d.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\msvcp140d.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\ucrtbased.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\ucrtbased.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已卸載“C:\Windows\System32\ucrtbased.dll”
“hellocuda.exe”(Win32): 已加載“E:\opencv\opencv4.1.0\opencv-4.1.0\build\install\x64\vc14\bin\opencv_world410d.dll”。已加載符號。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\user32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\win32u.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\gdi32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\gdi32full.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\msvcp_win.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\ucrtbase.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\ole32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\combase.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\rpcrt4.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\bcryptprimitives.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\advapi32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\msvcrt.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\sechost.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\oleaut32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\comdlg32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\SHCore.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\shlwapi.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\shell32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\cfgmgr32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.18362.778_none_2a29d4a64667eb69\comctl32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\windows.storage.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\profapi.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\powrprof.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\umpdc.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\kernel.appcore.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\cryptsp.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\cudart64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nppicc64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nppc64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nppial64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nppidei64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nppig64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nppim64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nppif64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nppist64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\nppitc64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\cublas64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\npps64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\nvcuda.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\concrt140d.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\nvcuvid.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\bin\cufft64_80.dll”。模塊已生成,不包含符號。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\setupapi.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\bcrypt.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\setupapi.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已卸載“C:\Windows\System32\setupapi.dll”
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\ws2_32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\version.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\winmm.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\winmmbase.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\winmmbase.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\winmmbase.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已卸載“C:\Windows\System32\winmmbase.dll”
“hellocuda.exe”(Win32): 已卸載“C:\Windows\System32\winmmbase.dll”
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\imm32.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\uxtheme.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\msctf.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\TextInputFramework.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\CoreMessaging.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\CoreUIComponents.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\ntmarta.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\WinTypes.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\WinTypes.dll”。無法查找或打開 PDB 文件。
“hellocuda.exe”(Win32): 已卸載“C:\Windows\System32\WinTypes.dll”
“hellocuda.exe”(Win32): 已加載“C:\Windows\System32\iertutil.dll”。無法查找或打開 PDB 文件。
線程 0x8688 已退出,返回值爲 0 (0x0)。
線程 0x9c30 已退出,返回值爲 0 (0x0)。
線程 0x50e0 已退出,返回值爲 0 (0x0)。
線程 0x770c 已退出,返回值爲 0 (0x0)。
線程 0x10f4 已退出,返回值爲 0 (0x0)。
線程 0x4580 已退出,返回值爲 0 (0x0)。
線程 0x7e8c 已退出,返回值爲 0 (0x0)。
線程 0x7e24 已退出,返回值爲 0 (0x0)。
線程 0x4ca8 已退出,返回值爲 0 (0x0)。
線程 0x5d84 已退出,返回值爲 0 (0x0)。
線程 0x25d8 已退出,返回值爲 0 (0x0)。
線程 0x55bc 已退出,返回值爲 0 (0x0)。
線程 0x21c8 已退出,返回值爲 0 (0x0)。
程序“[34632] hellocuda.exe”已退出,返回值爲 0 (0x0)。
我查了下這種PDB的警告,網上https://www.cnblogs.com/andyanut/p/5599000.html給的辦法都試了,比如用F5、win32控制檯應用程序、在工具-option-下開啓windows源以及symbol server等重啓VS,結果都不行。依舊是這樣的警告!!!!
很惆悵。雖然網上都說這些找不到PDB文件調試時進不到文件內部,沒關係。因爲可以看到opencv_world那一欄沒有報這個錯,所以當我調試時可以進到opencv函數內部。所以不用管這些警告。
但就是我的輸出一閃而過,於是加上#include <stdlib.h> 且在程序最後句(return之前)添加system("pause"); 這樣輸出窗口就不會一閃而過了。但PDB的警告依舊在,實在無能爲力了。
反正搭建成這樣就行了。不影響我學CUDA就行了。測試程序:
int main( void ) {
cudaDeviceProp prop;
int count;
HANDLE_ERROR( cudaGetDeviceCount( &count ) );
for (int i=0; i< count; i++) {
HANDLE_ERROR( cudaGetDeviceProperties( &prop, i ) );
printf( " --- General Information for device %d ---\n", i );
printf( "Name: %s\n", prop.name );
printf( "Compute capability: %d.%d\n", prop.major, prop.minor );
printf( "Clock rate: %d\n", prop.clockRate );
printf( "Device copy overlap: " );
if (prop.deviceOverlap)
printf( "Enabled\n" );
else
printf( "Disabled\n");
printf( "Kernel execution timeout : " );
if (prop.kernelExecTimeoutEnabled)
printf( "Enabled\n" );
else
printf( "Disabled\n" );
printf( " --- Memory Information for device %d ---\n", i );
printf( "Total global mem: %ld\n", prop.totalGlobalMem );
printf( "Total constant Mem: %ld\n", prop.totalConstMem );
printf( "Max mem pitch: %ld\n", prop.memPitch );
printf( "Texture Alignment: %ld\n", prop.textureAlignment );
printf( " --- MP Information for device %d ---\n", i );
printf( "Multiprocessor count: %d\n",
prop.multiProcessorCount );
printf( "Shared mem per mp: %ld\n", prop.sharedMemPerBlock );
printf( "Registers per mp: %d\n", prop.regsPerBlock );
printf( "Threads in warp: %d\n", prop.warpSize );
printf( "Max threads per block: %d\n",
prop.maxThreadsPerBlock );
printf( "Max thread dimensions: (%d, %d, %d)\n",
prop.maxThreadsDim[0], prop.maxThreadsDim[1],
prop.maxThreadsDim[2] );
printf( "Max grid dimensions: (%d, %d, %d)\n",
prop.maxGridSize[0], prop.maxGridSize[1],
prop.maxGridSize[2] );
printf( "\n" );
}
}
二、《GPU高性能編程CUDA實戰》的學習
因爲以前稍微用過OpenCL,所以看這個稍微容易點。學到了很多知識,雖然以前也看過,完全忘了。
第一個例子dot:
可以看到有紅色提示線:未定義的標識符atomicCAS、__syncthreads。但沒關係,不影響運行以及結果:
結果正確就可以,忽略提示線。
實例1:向量加法1:
#define Nnum (32 * 1024)
__global__ void add(int *a, int *b, int *c) {
int tid = blockIdx.x;
while (tid < Nnum) {
c[tid] = a[tid] + b[tid];
tid += gridDim.x;
}
}
add << <128, 1 >> >(dev_a, dev_b, dev_c);
其實就是相當於有128組工程隊,每組工程隊裏只有1個工人(每個工人每次只能搬一塊磚),現在要將32 * 1024這麼多塊磚搬完(這麼多磚整齊排成一行),所以第一個工程隊的那個工人(編號爲0)搬完第0塊磚、然後去搬第128、再去搬256塊磚....同時第二個工程隊的那個工人(編號爲1)搬完第1塊磚、再去搬129、再去搬257,第三個工程隊的那個工人(編號爲2)搬完第2塊磚、再去搬第130塊...這樣所有工人合作將磚搬完。
顯然這樣還是太慢,要麼多請幾個工程隊,要麼每個工程隊裏多招一些工人。所以這就有了第五章的例子:
實例2:向量加法2:
#define N (33 * 1024)
__global__ void add( int *a, int *b, int *c ) {
int tid = threadIdx.x + blockIdx.x * blockDim.x;
while (tid < N) {
c[tid] = a[tid] + b[tid];
tid += blockDim.x * gridDim.x;
}
}
add<<<128,128>>>( dev_a, dev_b, dev_c );
現在128組工程隊,每隊裏128個工人(每個工人每次可搬兩塊磚,來自於a和b)。那麼第一個大隊(編號block:0)裏的第一個工人(thread:0)就去搬第一塊磚(a[0]、b[0]),block:0裏的第二個工人就去搬第二塊磚(a[1]、b[1]),.....很簡單不贅述。
實例3:點積
__global__ void dot(float *a, float *b, float *c) {
__shared__ float cache[threadsPerBlock];
int tid = threadIdx.x + blockIdx.x * blockDim.x;
int cacheIndex = threadIdx.x;
float temp = 0;
while (tid < N) {
temp += a[tid] * b[tid];
tid += blockDim.x * gridDim.x;
}
// set the cache values
cache[cacheIndex] = temp;
// synchronize threads in this block
__syncthreads();
// for reductions, threadsPerBlock must be a power of 2
// because of the following code
int i = blockDim.x / 2;
while (i != 0) {
if (cacheIndex < i)
cache[cacheIndex] += cache[cacheIndex + i];
__syncthreads();
i /= 2;
}
if (cacheIndex == 0)
c[blockIdx.x] = cache[0];
}
可以這樣理解:
這裏要特別注意:
1、__syncthreads()常伴隨共享內存出現,對共享內存寫完之後,如果還要讀,就一定要加。
2、__syncthreads()是對block內的所有threads(不管是做事的,還是享受特權不做事的--比如if()給其特權不做事
)做同步,即等待block內所有threads做完事情。如果block內有人有特權不做事,那就相當於等待不做事的人做完事(因爲不可能發現)。這就會導致永久等待,即卡死。這也就是“線程發散”問題。
實例4:常量內存某些情況下提升性能的原因可以瞭解下
實例5:紋理內存也可用於通用計算
我覺得很適合圖像處理,卷積啊濾波之類的,反正與鄰域相關的。
實例6:原子操作
//////////////////////////use global memory
__global__ void histo_kernel(unsigned char *buffer,
long size,
unsigned int *histo) {
// calculate the starting index and the offset to the next
// block that each thread will be processing
int i = threadIdx.x + blockIdx.x * blockDim.x;
int stride = blockDim.x * gridDim.x;
while (i < size) {
atomicAdd(&histo[buffer[i]], 1);
i += stride;
}
}
//////////////////////////////////use shared memory and global memory
__global__ void histom_kernel(unsigned char *buffer,
long size,
unsigned int *histo) {
// clear out the accumulation buffer called temp
// since we are launched with 256 threads, it is easy
// to clear that memory with one write per thread
__shared__ unsigned int temp[256];
temp[threadIdx.x] = 0;
__syncthreads();
// calculate the starting index and the offset to the next
// block that each thread will be processing
int i = threadIdx.x + blockIdx.x * blockDim.x;
int stride = blockDim.x * gridDim.x;
while (i < size) {
atomicAdd(&temp[buffer[i]], 1);
i += stride;
}
// sync the data from the above writes to shared memory
// then add the shared memory values to the values from
// the other thread blocks using global memory
// atomic adds
// same as before, since we have 256 threads, updating the
// global histogram is just one write per thread!
__syncthreads();
atomicAdd(&(histo[threadIdx.x]), temp[threadIdx.x]);
}
我覺得這個例子所講的策略(假設總線程N個,每個block內線程m個,(m<<N))就是本來第一個核函數極端情況下,可能有N個線程要訪問全局內存的同一個位置,第一個線程在操作這個地址時原子操作則讓N-1個去等待;第二個改進核函數極端情況下只有m個線程訪問共享內存同一個位置,第一個線程在操作這個地址時原子操作讓m-1個去等待。這減輕了原子操作的劣勢(競爭程度)。所以一個功能怎麼設計核函數很重要。
實例7:頁鎖定內存
CPU和GPU都可分配主機內存,CPU-malloc()而GPU-cudahostAlloc()。書上講了物理內存允許情況下,爲什麼GPU分配主機內存可以提升性能,就是因爲減少了分配臨時頁鎖定內存這個步驟。
的確有提升效果。
實例8:使用單個流
// now loop over full data, in bite-sized chunks
for (int i = 0; i<FULL_DATA_SIZE; i += N) {
// copy the locked memory to the device, async
HANDLE_ERROR(cudaMemcpyAsync(dev_a, host_a + i,
N * sizeof(int),
cudaMemcpyHostToDevice,
stream));
HANDLE_ERROR(cudaMemcpyAsync(dev_b, host_b + i,
N * sizeof(int),
cudaMemcpyHostToDevice,
stream));
kernel << <N / 256, 256, 0, stream >> >(dev_a, dev_b, dev_c);
// copy the data from device to locked memory
HANDLE_ERROR(cudaMemcpyAsync(host_c + i, dev_c,
N * sizeof(int),
cudaMemcpyDeviceToHost,
stream));
}
我的理解是for循環內有4個語句,並不像CPU程序一樣第一個語句執行完執行第二個,第二個執行完執行第三個...,而是for裏這種寫法只是代表一種開始執行時刻的先後,即第二個語句開始之前第一個語句已經開始執行(然而不知是否已執行完畢),第三個語句開始之前第二個語句已經開始執行(然而也不知道是否已執行完畢)....。注意cudaMemcpyAsync()只能操作頁鎖定內存。
注意若要確保GPU上所有任務已執行完畢使用cudaStreamSynchronize函數。
實例9:多個流
for (int i = 0; i<FULL_DATA_SIZE; i += N * 2) {
// enqueue copies of a in stream0 and stream1
HANDLE_ERROR(cudaMemcpyAsync(dev_a0, host_a + i,
N * sizeof(int),
cudaMemcpyHostToDevice,
stream0));
HANDLE_ERROR(cudaMemcpyAsync(dev_a1, host_a + i + N,
N * sizeof(int),
cudaMemcpyHostToDevice,
stream1));
// enqueue copies of b in stream0 and stream1
HANDLE_ERROR(cudaMemcpyAsync(dev_b0, host_b + i,
N * sizeof(int),
cudaMemcpyHostToDevice,
stream0));
HANDLE_ERROR(cudaMemcpyAsync(dev_b1, host_b + i + N,
N * sizeof(int),
cudaMemcpyHostToDevice,
stream1));
// enqueue kernels in stream0 and stream1
kernel << <N / 256, 256, 0, stream0 >> >(dev_a0, dev_b0, dev_c0);
kernel << <N / 256, 256, 0, stream1 >> >(dev_a1, dev_b1, dev_c1);
// enqueue copies of c from device to locked memory
HANDLE_ERROR(cudaMemcpyAsync(host_c + i, dev_c0,
N * sizeof(int),
cudaMemcpyDeviceToHost,
stream0));
HANDLE_ERROR(cudaMemcpyAsync(host_c + i + N, dev_c1,
N * sizeof(int),
cudaMemcpyDeviceToHost,
stream1));
}
HANDLE_ERROR(cudaStreamSynchronize(stream0));
HANDLE_ERROR(cudaStreamSynchronize(stream1));
多個流時要注意按GPU硬件調度方式來編程,而不是按任務來。
實例10:零拷貝內存