Caffe is a deep learning framework popular in Linux with Python or Matlab interface. I just managed to compile Caffe in Windows, and I think it’s worth sharing. niuzhiheng’s GitHub was of great help. This repository is organized in a way that future update merging from Caffe’s GitHub would be very straight forward. For quick setup and usage go to my GitHub.
For quick and dirty start, go to Caffe + vs2013 + OpenCV in Windows Tutorial (I) – Setup, where I’ll provide 1) the modified file that can be compiled in windows right away; 2) the vs2013 project that I’m currently using.
Below is my step by step record to compile Caffe from source in Windows 8.1 + vs2013 + OpenCV 2.4.9 + CUDA 6.5.
- Download source from Caffe’s GitHub and unzip.
- Create a new project in Visual Studio 2013.
- File -> New -> Project
- Choose Win32 Console Application
- Set location to the root of Caffe
- Change Name to caffe (the generated exe file later is named after the project name, so please use this low case word)
- Click OK
- Check Empty project, and then Finish
- Change the platform from Win32 to
- Build -> Configuration Manager -> Active solution platform -> new -> x64 -> OK
- An empty project called caffe is generated into the root of Caffe now. To compile big project like Caffe, good practice is to compile a few *.cpp files first and figure out dependencies one by one.
- Drag files in caffe/src/caffe to Source Files in VS.
- Let’s set some directories of the project.
- In Property Manager, both Debug|x64 and Release|x64 need to be set:
- In Configuration Properties -> General, set Output Directory to ‘../bin’. The generated exe files will be easy to use later. Change for both Debug and Release mode.
- In Configuration Properties -> C/C++ -> General, edit Additional Include Directories (Both Debug and Release) to include:
- Make sure to check Inherit from parent or project defaults.
- Now let’s fix dependencies one by one: (My pre-built 3rdparty folder can be downloaded: 3rdparty.zip, if you are using Windows 64bit + vs2013)
- CUDA 6.5
- Download and install (You have to have a GPU on your PC lol)
- OpenCV 2.4.9 + CUDA 6.5
- Add OpenCV + CUDA + Boost into the project:
- I used to put these 3 libraries outside Caffe folder because they are so useful.
- Add include path to Additional Include Directories: (Both Debug and Release)
$(CUDA_PATH_V6_5)\include $(OPENCV_X64_VS2013_2_4_9)\include $(OPENCV_X64_VS2013_2_4_9)\include\opencv $(BOOST_1_56_0)
- CUDA_PATH_V6_5 is added by CUDA initialization. OPENCV_X64_VS2013_2_4_9 and BOOST_1_56_0 need to be added to the Environment Variables Also, the bin (e.g. /to/opencv-2.4.9/x64-vs2013/bin) folder of OpenCV need to be added to Path. You may need to log off to enable them.
- Add lib path to Additional Library Directories in Configuration Properties -> Linker -> General: (Both Debug and Release)
$(CUDA_PATH_V6_5)\lib\$(PlatformName) $(OPENCV_X64_VS2013_2_4_9)\lib $(BOOST_1_56_0)\lib64-msvc-12.0
- Add libraries to Additional Dependencies in Configuration Properties -> Linker -> Input
- GFlags + GLog + ProtoBuf + LevelDB
- Download source code from the internet.
- Use CMake to generate .sln for vs2013. Remember to set “CMAKE_INSTALL_PREFIX”, which is where the output files will be generated by build “INSTALL”.
- Build in vs2013. Usually build “BUILD_ALL” first, then “INSTALL”. Both Debug and Release mode.
- Copy compiled files to caffe/3rdparty. Debug versions should be renamed “+d” before copy, e.g. “lib” -> “gflagsd.lib”.
- Google’s code are very good maintained. Nothing much to say.
- Download source code form the internet.
- In CMake, enable HDF5_BUILD_HL_LIB.
- Copy compiled files to caffe/3rdparty.
- Download source code from the internet.
- In Visual Studio 2013, File -> New -> Project From Existing Code…
- In c, a header file called unistd.h is needed. A walk around is found here. Or one can download here: unistd.h, getopt.h and getopt.c.
- The compiled LMDB has some problem which I’ll mention later.
- Copy some .dll files so that caffe can run
- Copy libglog.dll from GLog to caffe/bin.
- Copy libopenblas.dll from OpenBLAS to caffe/bin.
- Copy msvcp120.dll and msvcr120.dll from HDF5 to caffe/bin.
- More paths added to Additional Include Directories (Both Debug and Release):
../3rdparty/include; ../3rdparty/include/openblas; ../3rdparty/include/hdf5; ../3rdparty/include/lmdb;
- More paths added to Additional Library Directories (Both Debug and Release):
- More files added to Additional Dependencies:
- My pre-built 3rdparty folder can be downloaded: 3rdparty.zip, if you are using Windows 64bit + vs2013.
- Now compile “common.cpp” to fix errors.
- Add “#include <process.h>” to common.cpp fix “getpid” error.
- Add “_CRT_SECURE_NO_WARNINGS” to Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions to fix “fopen_s” error.
- Change the line used “getpid” in common.cpp to fix POSIX error.
// port for Win32 #ifndef _MSC_VER pid = getpid(); #else pid = _getpid(); #endif
- common.cpp should be compiled without error now.
- Now compile “blob.cpp”
- To enable #include “caffe/proto/caffe.pb.h”. We need to generate it from caffe.proto.
- Put proto.exe in caffe/3rdparty/bin folder.
- Put GeneratePB.bat in caffe/scripts folder.
- Add the line below (with the quote mark) to Configuration Properties -> Build Events -> Pre-Build Event -> Command Line:
- Right click caffe to build to project, you will see “caffe.pb.h is being generated” and “caffe_pretty_print.pb.h is being generated”
- Now blop.cpp can be compiled without errors.
- Now compile “net.cpp”
- “unistd.h” missing error can be fixed like above. (also included in 3rdparty.zip already)
- “mkstemp” missing error can be fixed according to this (download here: mkstep.h and mkstep.cpp or find in 3rdparty.zip)
- Add “#include “mkstemp.h”” to io.hpp.
- Change the line used “close” the below in io.hpp to fix close error. (Don’t do “#define close _close” in io.hpp. Such define are dangerous in any .hpp files, but acceptable in .cpp files)
#ifndef _MSC_VER close(fd); #else _close(fd); #endif
- Change the line used “mkdtemp” function to below in io.hpp (to use _mktemp_s as a walk-around for mkdtemp):
#ifndef _MSC_VER char* mkdtemp_result = mkdtemp(temp_dirname_cstr); #else errno_t mkdtemp_result = _mktemp_s(temp_dirname_cstr, sizeof(temp_dirname_cstr)); #endif
- Now compile “solver.cpp”
- Add these line to solver.cpp to fix “snprintf” error to below:
// port for Win32 #ifdef _MSC_VER #define snprintf sprintf_s #endif
- Now compile files in caffe/src/layers
- Create a folder in Source Files and drag ONE .cu files in layer folder into it.
- Enable CUDA 6.5(.targets, .props) in PROJECT -> Build Customization.
- In the property of any .cu file, change Item Type to CUDA C/C++
- Drag the rest files in layer folder to the project. All new added .cu file will have its Item Type Otherwise you have to change them one by one.
- In bnll_layer.cu, change “const float kBNLL_THRESHOLD = 50.;” to “#define kBNLL_THRESHOLD 50.0” to avoid error.
- Now every files in layer folder compiles fine.
- Now compile files in caffe/src/util folder
- Goto ReadProtoFromBinaryFile function. Change “O_RDONLY” to “O_RDONLY | O_BINARY”. When loading a binary file in Windows, you have to specify that it’s binary. Otherwise you might have error loading a *_mean.binaryproto file later.
- Add these lines to io.cpp file to avoid POSIX error:
// port for Win32 #ifdef _MSC_VER #define open _open
#define close _close#endif
- Change “close()” to “_close()” manually expect the “file.close()”.
- Add these lines to math_functions.cpp to fix __builtin_popcount and __builtin_popcountl error:
#define __builtin_popcount __popcnt #define __builtin_popcountl __popcnt
- Now compile files in caffe/src/proto
- Previously 2 .cc files were generated by GeneratePB.bat.
- Create a folder in Source Files and drag 2 .cc files (“caffe.pb.cc” and “caffe_pretty_print.pb.cc”) into it.
- Add “-D_SCL_SECURE_NO_WARNINGS” to Configuration Properties -> C/C++ -> Command Line (Both Debug and Release mode) to fix ‘std::_Copy_impl’ unsafe error.
- Now we have every file compliable in Visual Studio.
- Finally compile caffe.cpp in caffe/tools folder
- Drag caffe/tools/caffe.cpp file into Visual Studio’s Source Files
- Right click project name caffe, and BUILD!
- Now everything should work! If you got some linking error, check the missing function’s name to decide what library is missing.
- Change to Release mode and BUILD again to get a caffe/bin/caffe.exe of Release mode.
- Copy caffe.exe to get a backup, e.g. caffe-backup.exe. For if you build the project again, caffe.exe will be overwritten.
- Let’s do a QUICK TEST on MNIST!
- Get MNIST Dataset
- Generate convert_mnist_data.exe
- Check the project in Visual Studio is in Release|x64.
- Exclude “caffe.cpp” from the project.
- Drag “caffe/examples/mnist/convert_mnist_data.cpp” to the project.
- Add these lines in convert_mnist_data.cpp:
// port for Win32 #ifdef _MSC_VER #include <direct.h> #define snprintf sprintf_s #endif
- Change “mkdir” to “_mkdir” in convert_mnist_data.cpp:
// port for Win32 #ifndef _MSC_VER CHECK_EQ(mkdir(db_path, 0744), 0) << “mkdir ” << db_path << “failed”; #else CHECK_EQ(_mkdir(db_path), 0) << “mkdir ” << db_path << “failed”; #endif
- The “potentially uninitialized local pointer variable” error can be fixed by initialize db, mdb_env and mdb_txn with NULL in convert_mnist_data.cpp. Change “MDB_env *mdb_env;” to “MDB_env *mdb_env = NULL;”, and similar for “mdb_txn” and “db”.
- BUILD the project to get caffe.exe in caffe/bin. Rename it to convert_mnist_data.exe.
- Create LevelDB data for training
- Put create_mnist.bat in caffe/examples/mnist and run. Here we generate mnist_train_leveldb and mnist_test_leveldb. If lmdb was used as backend, error occurs. Fortunately, leveldb works fine. It would be great if someone can fix the error of lmdb.
- Let’s get caffe.exe back from the copied caffe-backup.exe if you copied it before.
- Now modify caffe/examples/mnist/lenet_train_test.prototxt, substitute “lmdb” with “leveldb”, because we generate “leveldb” data instead of “lmdb”.
- Do training
- Put train_lenet.bat in caffe/examples/mnist and run. Cool! The training is on! The accuracy is around 0.98 after hundreds of iterations.
Update – 2015.1.26
- The above steps didn’t include cuDNN acceleration.
- One can add “USE_CUDNN” to Preprocessor of the project to enable cuDNN. (Currently Caffe works with cuDNN v1. The set-up is pretty straight forward. Noted that the “Code Generation” for CUDA should be at least “compute_30, sm_30”.)
- My practice showed that for LeNet layout, testing 800 images with the size of 32*32 (excluding the time for reading input images):
- CPU takes around 400~500 ms
- GPU takes around 50 ms
- cuDNN takes around 15 ms