From 46cbb649b498bc49cc1fc73aab75ae4c9ba10419 Mon Sep 17 00:00:00 2001 From: Kai Li Date: Thu, 28 Aug 2014 19:17:07 +0800 Subject: [PATCH 1/3] Replace pthread with boost::thread --- Makefile | 2 +- include/caffe/internal_thread.hpp | 32 +++++++++------------- src/caffe/CMakeLists.txt | 2 +- src/caffe/internal_thread.cpp | 36 +++++++++++++++++++++++++ src/caffe/layers/data_layer.cpp | 4 +-- src/caffe/layers/image_data_layer.cpp | 4 +-- src/caffe/layers/window_data_layer.cpp | 4 +-- src/caffe/test/test_internal_thread.cpp | 23 ++++++++++++++++ 8 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 src/caffe/internal_thread.cpp create mode 100644 src/caffe/test/test_internal_thread.cpp diff --git a/Makefile b/Makefile index 2c3ce5415bd..9c420249887 100644 --- a/Makefile +++ b/Makefile @@ -161,7 +161,7 @@ endif LIBRARIES += \ glog gflags pthread protobuf leveldb snappy \ lmdb \ - boost_system \ + boost_system boost_thread \ hdf5_hl hdf5 \ opencv_core opencv_highgui opencv_imgproc PYTHON_LIBRARIES := boost_python python2.7 diff --git a/include/caffe/internal_thread.hpp b/include/caffe/internal_thread.hpp index bb0f932566d..9989936e519 100644 --- a/include/caffe/internal_thread.hpp +++ b/include/caffe/internal_thread.hpp @@ -1,42 +1,36 @@ #ifndef CAFFE_INTERNAL_THREAD_HPP_ #define CAFFE_INTERNAL_THREAD_HPP_ -#include +#include + +#include "caffe/common.hpp" namespace caffe { /** - * Virutal class encapsulate pthread for use in base class - * The child class will acquire the ability to run a single pthread, + * Virutal class encapsulate boost::thread for use in base class + * The child class will acquire the ability to run a single thread, * by reimplementing the virutal function InternalThreadEntry. */ class InternalThread { public: - InternalThread() {} - virtual ~InternalThread() {} + InternalThread() : thread_(NULL) {} + virtual ~InternalThread(); /** Returns true if the thread was successfully started. **/ - bool StartInternalThread() { - return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0); - } + bool StartInternalThread(); /** Will not return until the internal thread has exited. */ - bool WaitForInternalThreadToExit() { - return pthread_join(_thread, NULL); - } + bool WaitForInternalThreadToExit(); + + bool is_started() const { return thread_ != NULL && thread_->joinable(); } protected: /* Implement this method in your subclass with the code you want your thread to run. */ - virtual void InternalThreadEntry() = 0; - - private: - static void * InternalThreadEntryFunc(void * This) { - reinterpret_cast(This)->InternalThreadEntry(); - return NULL; - } + virtual void InternalThreadEntry() {} - pthread_t _thread; + boost::thread* thread_; }; } // namespace caffe diff --git a/src/caffe/CMakeLists.txt b/src/caffe/CMakeLists.txt index ec756bede71..fa30eb5870f 100644 --- a/src/caffe/CMakeLists.txt +++ b/src/caffe/CMakeLists.txt @@ -57,7 +57,7 @@ find_package(LMDB REQUIRED) include_directories(${LMDB_INCLUDE_DIR}) # Boost -find_package(Boost 1.46 COMPONENTS system REQUIRED) +find_package(Boost 1.46 COMPONENTS system thread REQUIRED) include_directories( ${Boost_INCLUDE_DIR} ) link_directories( ${Boost_LIBRARY_DIRS} ) diff --git a/src/caffe/internal_thread.cpp b/src/caffe/internal_thread.cpp new file mode 100644 index 00000000000..99342090882 --- /dev/null +++ b/src/caffe/internal_thread.cpp @@ -0,0 +1,36 @@ +#include + +#include "caffe/internal_thread.hpp" + +namespace caffe { +using namespace std; + +InternalThread::~InternalThread() { + WaitForInternalThreadToExit(); + if (thread_ != NULL) { + delete thread_; + } +} + +bool InternalThread::StartInternalThread() { + try { + thread_ = new boost::thread(&InternalThread::InternalThreadEntry, this); + } catch (...) { + return false; + } + return true; +} + +/** Will not return until the internal thread has exited. */ +bool InternalThread::WaitForInternalThreadToExit() { + if (is_started()) { + try { + thread_->join(); + } catch (...) { + return false; + } + } + return true; +} + +} // namespace caffe diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 0cc2769bfc9..a09eb34e1cf 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -244,12 +244,12 @@ void DataLayer::CreatePrefetchThread() { data_transformer_.InitRand(); - CHECK(StartInternalThread()) << "Pthread execution failed"; + CHECK(StartInternalThread()) << "Thread execution failed"; } template void DataLayer::JoinPrefetchThread() { - CHECK(!WaitForInternalThreadToExit()) << "Pthread joining failed"; + CHECK(!WaitForInternalThreadToExit()) << "Thread joining failed"; } template diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index dc39e694bbb..8810a381f7f 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -159,7 +159,7 @@ void ImageDataLayer::CreatePrefetchThread() { data_transformer_.InitRand(); // Create the thread. - CHECK(StartInternalThread()) << "Pthread execution failed"; + CHECK(StartInternalThread()) << "Thread execution failed"; } template @@ -172,7 +172,7 @@ void ImageDataLayer::ShuffleImages() { template void ImageDataLayer::JoinPrefetchThread() { - CHECK(!WaitForInternalThreadToExit()) << "Pthread joining failed"; + CHECK(!WaitForInternalThreadToExit()) << "Thread joining failed"; } template diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index bed03d8e8d2..ebd855d48b7 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -408,12 +408,12 @@ void WindowDataLayer::CreatePrefetchThread() { prefetch_rng_.reset(); } // Create the thread. - CHECK(StartInternalThread()) << "Pthread execution failed."; + CHECK(StartInternalThread()) << "Thread execution failed."; } template void WindowDataLayer::JoinPrefetchThread() { - CHECK(!WaitForInternalThreadToExit()) << "Pthread joining failed."; + CHECK(!WaitForInternalThreadToExit()) << "Thread joining failed."; } template diff --git a/src/caffe/test/test_internal_thread.cpp b/src/caffe/test/test_internal_thread.cpp new file mode 100644 index 00000000000..31882b6db1d --- /dev/null +++ b/src/caffe/test/test_internal_thread.cpp @@ -0,0 +1,23 @@ +#include "glog/logging.h" +#include "gtest/gtest.h" + +#include "caffe/internal_thread.hpp" + +#include "caffe/test/test_caffe_main.hpp" + +namespace caffe { + + +class InternalThreadTest : public ::testing::Test {}; + +TEST_F(InternalThreadTest, TestStartAndExit) { + InternalThread thread; + EXPECT_FALSE(thread.is_started()); + EXPECT_TRUE(thread.StartInternalThread()); + EXPECT_TRUE(thread.is_started()); + EXPECT_TRUE(thread.WaitForInternalThreadToExit()); + EXPECT_FALSE(thread.is_started()); +} + +} // namespace caffe + From 425f69ff5bf8c87c7a52bbee2904e9cf6b22d39e Mon Sep 17 00:00:00 2001 From: Kai Li Date: Fri, 29 Aug 2014 00:05:49 +0800 Subject: [PATCH 2/3] Add boost thread in the travis install script --- scripts/travis/travis_install.sh | 2 +- src/caffe/CMakeLists.txt | 9 +++++---- src/caffe/internal_thread.cpp | 3 --- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/scripts/travis/travis_install.sh b/scripts/travis/travis_install.sh index f6a357b5c57..753bae879af 100755 --- a/scripts/travis/travis_install.sh +++ b/scripts/travis/travis_install.sh @@ -6,7 +6,7 @@ sudo apt-get install \ wget git curl \ python-dev python-numpy \ libleveldb-dev libsnappy-dev libopencv-dev \ - libboost-dev libboost-system-dev libboost-python-dev \ + libboost-dev libboost-system-dev libboost-python-dev libboost-thread-dev \ libprotobuf-dev protobuf-compiler \ libatlas-dev libatlas-base-dev \ libhdf5-serial-dev \ diff --git a/src/caffe/CMakeLists.txt b/src/caffe/CMakeLists.txt index fa30eb5870f..139185b52dc 100644 --- a/src/caffe/CMakeLists.txt +++ b/src/caffe/CMakeLists.txt @@ -99,14 +99,15 @@ if(NOT CPU_ONLY) endif() target_link_libraries(caffe proto - ${GLOG_LIBRARIES} + ${BLAS_LIBRARIES} + ${Boost_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} ${GFLAGS_LIBRARIES} + ${GLOG_LIBRARIES} ${HDF5_LIBRARIES} - ${OpenCV_LIBS} ${LEVELDB_LIBS} ${LMDB_LIBRARIES} - ${BLAS_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + ${OpenCV_LIBS} ) #set output directory diff --git a/src/caffe/internal_thread.cpp b/src/caffe/internal_thread.cpp index 99342090882..b89aa2ef061 100644 --- a/src/caffe/internal_thread.cpp +++ b/src/caffe/internal_thread.cpp @@ -1,9 +1,6 @@ -#include - #include "caffe/internal_thread.hpp" namespace caffe { -using namespace std; InternalThread::~InternalThread() { WaitForInternalThreadToExit(); From f2a291c0e92fbde0e1b29d01ffc62b0a35e1fbea Mon Sep 17 00:00:00 2001 From: Kai Li Date: Fri, 29 Aug 2014 00:16:13 +0800 Subject: [PATCH 3/3] The return value of WaitForInternalThreadToExit has reversed --- src/caffe/layers/data_layer.cpp | 2 +- src/caffe/layers/image_data_layer.cpp | 2 +- src/caffe/layers/window_data_layer.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index a09eb34e1cf..a815c4a6a16 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -249,7 +249,7 @@ void DataLayer::CreatePrefetchThread() { template void DataLayer::JoinPrefetchThread() { - CHECK(!WaitForInternalThreadToExit()) << "Thread joining failed"; + CHECK(WaitForInternalThreadToExit()) << "Thread joining failed"; } template diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index 8810a381f7f..ce8338bc028 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -172,7 +172,7 @@ void ImageDataLayer::ShuffleImages() { template void ImageDataLayer::JoinPrefetchThread() { - CHECK(!WaitForInternalThreadToExit()) << "Thread joining failed"; + CHECK(WaitForInternalThreadToExit()) << "Thread joining failed"; } template diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index ebd855d48b7..82bee0ecd19 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -413,7 +413,7 @@ void WindowDataLayer::CreatePrefetchThread() { template void WindowDataLayer::JoinPrefetchThread() { - CHECK(!WaitForInternalThreadToExit()) << "Thread joining failed."; + CHECK(WaitForInternalThreadToExit()) << "Thread joining failed."; } template