diff --git a/Makefile b/Makefile index 2e07675c978..823e28c4259 100644 --- a/Makefile +++ b/Makefile @@ -68,10 +68,13 @@ MKL_INCLUDE_DIR := $(MKL_DIR)/include MKL_LIB_DIR := $(MKL_DIR)/lib $(MKL_DIR)/lib/intel64 INCLUDE_DIRS += ./src ./include $(CUDA_INCLUDE_DIR) $(MKL_INCLUDE_DIR) -LIBRARY_DIRS += $(CUDA_LIB_DIR) $(MKL_LIB_DIR) -LIBRARIES := cudart cublas curand protobuf opencv_core opencv_highgui \ - glog mkl_rt mkl_intel_thread leveldb snappy pthread boost_system \ - opencv_imgproc +LIBRARY_DIRS += $(CUDA_LIB_DIR) $(MKL_LIB_DIR) /usr/lib/atlas-base +LIBRARIES := cudart cublas curand protobuf \ + opencv_core opencv_highgui opencv_imgproc \ + glog \ + atlas cblas \ + leveldb snappy pthread boost_system + # mkl_rt mkl_intel_thread PYTHON_LIBRARIES := boost_python python2.7 WARNINGS := -Wall @@ -79,7 +82,7 @@ COMMON_FLAGS := -DNDEBUG -O2 $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir CXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) NVCCFLAGS := -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS) LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) \ - $(foreach library,$(LIBRARIES),-l$(library)) + $(foreach library,$(LIBRARIES),-l$(library)) -Wl,-rpath=/usr/lib/atlas-base PYTHON_LDFLAGS := $(LDFLAGS) $(foreach library,$(PYTHON_LIBRARIES),-l$(library)) diff --git a/caffe.config b/caffe.config new file mode 100644 index 00000000000..8cec188b38b --- /dev/null +++ b/caffe.config @@ -0,0 +1 @@ +// ADD PREDEFINED MACROS HERE! diff --git a/caffe.creator b/caffe.creator new file mode 100644 index 00000000000..e94cbbd3027 --- /dev/null +++ b/caffe.creator @@ -0,0 +1 @@ +[General] diff --git a/caffe.files b/caffe.files new file mode 100644 index 00000000000..3b559d29f6f --- /dev/null +++ b/caffe.files @@ -0,0 +1,76 @@ +examples/convert_cifar_data.cpp +examples/convert_imageset.cpp +examples/convert_mnist_data.cpp +examples/demo_compute_image_mean.cpp +examples/dump_network.cpp +examples/finetune_net.cpp +examples/net_speed_benchmark.cpp +examples/test_net.cpp +examples/train_net.cpp +include/caffe/proto/caffe.pb.h +include/caffe/util/im2col.hpp +include/caffe/util/io.hpp +include/caffe/util/math_functions.hpp +include/caffe/blob.hpp +include/caffe/caffe.hpp +include/caffe/common.hpp +include/caffe/filler.hpp +include/caffe/layer.hpp +include/caffe/net.hpp +include/caffe/solver.hpp +include/caffe/syncedmem.hpp +include/caffe/vision_layers.hpp +matlab/caffe/matcaffe.cpp +python/caffe/imagenet/__init__.py +python/caffe/imagenet/power_wrapper.py +python/caffe/imagenet/wrapper.py +python/caffe/proto/__init__.py +python/caffe/__init__.py +python/caffe/convert.py +python/caffe/drawnet.py +python/caffe/pycaffe.cpp +src/caffe/layers/conv_layer.cpp +src/caffe/layers/data_layer.cpp +src/caffe/layers/flatten_layer.cpp +src/caffe/layers/im2col_layer.cpp +src/caffe/layers/inner_product_layer.cpp +src/caffe/layers/lrn_layer.cpp +src/caffe/layers/neuron_layer.cpp +src/caffe/layers/pooling_layer.cpp +src/caffe/proto/caffe.pb.cc +src/caffe/proto/caffe.pb.h +src/caffe/test/test_blob.cpp +src/caffe/test/test_caffe_main.hpp +src/caffe/test/test_common.cpp +src/caffe/test/test_convolution_layer.cpp +src/caffe/test/test_data_layer.cpp +src/caffe/test/test_euclidean_loss_layer.cpp +src/caffe/test/test_filler.cpp +src/caffe/test/test_flatten_layer.cpp +src/caffe/test/test_gradient_check_util.hpp +src/caffe/test/test_im2col_layer.cpp +src/caffe/test/test_innerproduct_layer.cpp +src/caffe/test/test_lrn_layer.cpp +src/caffe/test/test_multinomial_logistic_loss_layer.cpp +src/caffe/test/test_neuron_layer.cpp +src/caffe/test/test_padding_layer.cpp +src/caffe/test/test_platform.cpp +src/caffe/test/test_pooling_layer.cpp +src/caffe/test/test_protobuf.cpp +src/caffe/test/test_softmax_layer.cpp +src/caffe/test/test_softmax_with_loss_layer.cpp +src/caffe/test/test_stochastic_pooing.cpp +src/caffe/test/test_syncedmem.cpp +src/caffe/test/test_util_blas.cpp +src/caffe/util/im2col.cpp +src/caffe/util/io.cpp +src/caffe/util/math_functions.cpp +src/caffe/blob.cpp +src/caffe/common.cpp +src/caffe/layer_factory.cpp +src/caffe/net.cpp +src/caffe/solver.cpp +src/caffe/syncedmem.cpp +src/gtest/gtest-all.cpp +src/gtest/gtest.h +src/gtest/gtest_main.cc \ No newline at end of file diff --git a/caffe.includes b/caffe.includes new file mode 100644 index 00000000000..66d2faef673 --- /dev/null +++ b/caffe.includes @@ -0,0 +1,3 @@ +include/caffe/proto +src/caffe/proto +src/gtest \ No newline at end of file diff --git a/include/caffe/common.hpp b/include/caffe/common.hpp index e7c5abe7435..4607e029568 100644 --- a/include/caffe/common.hpp +++ b/include/caffe/common.hpp @@ -3,6 +3,7 @@ #ifndef CAFFE_COMMON_HPP_ #define CAFFE_COMMON_HPP_ +#include #include #include #include @@ -10,7 +11,7 @@ // cuda driver types #include #include -#include +//#include // various checks for different function calls. #define CUDA_CHECK(condition) CHECK_EQ((condition), cudaSuccess) @@ -78,8 +79,13 @@ class Caffe { inline static curandGenerator_t curand_generator() { return Get().curand_generator_; } + // Returns the MKL random stream. - inline static VSLStreamStatePtr vsl_stream() { return Get().vsl_stream_; } + //inline static VSLStreamStatePtr vsl_stream() { return Get().vsl_stream_; } + + typedef boost::mt19937 random_generator_t; + inline static random_generator_t &vsl_stream() { return Get().random_generator_; } + // Returns the mode: running on CPU or GPU. inline static Brew mode() { return Get().mode_; } // Returns the phase: TRAIN or TEST. @@ -103,7 +109,9 @@ class Caffe { protected: cublasHandle_t cublas_handle_; curandGenerator_t curand_generator_; - VSLStreamStatePtr vsl_stream_; + //VSLStreamStatePtr vsl_stream_; + random_generator_t random_generator_; + Brew mode_; Phase phase_; static shared_ptr singleton_; diff --git a/include/caffe/filler.hpp b/include/caffe/filler.hpp index effe62ff2c5..d606f97b880 100644 --- a/include/caffe/filler.hpp +++ b/include/caffe/filler.hpp @@ -7,7 +7,7 @@ #ifndef CAFFE_FILLER_HPP #define CAFFE_FILLER_HPP -#include +//#include #include #include "caffe/common.hpp" diff --git a/include/caffe/util/math_functions.hpp b/include/caffe/util/math_functions.hpp index e9e2db8f274..05ed1301599 100644 --- a/include/caffe/util/math_functions.hpp +++ b/include/caffe/util/math_functions.hpp @@ -3,7 +3,8 @@ #ifndef CAFFE_UTIL_MATH_FUNCTIONS_H_ #define CAFFE_UTIL_MATH_FUNCTIONS_H_ -#include +//#include +#include #include namespace caffe { @@ -91,6 +92,9 @@ template void caffe_vRngGaussian(const int n, Dtype* r, const Dtype a, const Dtype sigma); +template +void caffe_vRngBernoulli(const int n, Dtype* r, const double p); + template void caffe_exp(const int n, const Dtype* a, Dtype* y); diff --git a/src/caffe/common.cpp b/src/caffe/common.cpp index c5dcd10138d..b671a99bfe2 100644 --- a/src/caffe/common.cpp +++ b/src/caffe/common.cpp @@ -21,7 +21,10 @@ long cluster_seedgen(void) { Caffe::Caffe() : mode_(Caffe::CPU), phase_(Caffe::TRAIN), cublas_handle_(NULL), - curand_generator_(NULL), vsl_stream_(NULL) { + curand_generator_(NULL), + //vsl_stream_(NULL) + random_generator_() +{ // Try to create a cublas handler, and report an error if failed (but we will // keep the program running as one might just want to run CPU code). if (cublasCreate(&cublas_handle_) != CUBLAS_STATUS_SUCCESS) { @@ -34,12 +37,13 @@ Caffe::Caffe() != CURAND_STATUS_SUCCESS) { LOG(ERROR) << "Cannot create Curand generator. Curand won't be available."; } + // Try to create a vsl stream. This should almost always work, but we will // check it anyway. - if (vslNewStream(&vsl_stream_, VSL_BRNG_MT19937, cluster_seedgen()) != VSL_STATUS_OK) { - LOG(ERROR) << "Cannot create vsl stream. VSL random number generator " - << "won't be available."; - } + //if (vslNewStream(&vsl_stream_, VSL_BRNG_MT19937, cluster_seedgen()) != VSL_STATUS_OK) { + // LOG(ERROR) << "Cannot create vsl stream. VSL random number generator " + // << "won't be available."; + //} } Caffe::~Caffe() { @@ -47,8 +51,8 @@ Caffe::~Caffe() { if (curand_generator_) { CURAND_CHECK(curandDestroyGenerator(curand_generator_)); } - if (vsl_stream_) VSL_CHECK(vslDeleteStream(&vsl_stream_)); -}; + //if (vsl_stream_) VSL_CHECK(vslDeleteStream(&vsl_stream_)); +} void Caffe::set_random_seed(const unsigned int seed) { // Curand seed @@ -64,8 +68,10 @@ void Caffe::set_random_seed(const unsigned int seed) { LOG(ERROR) << "Curand not available. Skipping setting the curand seed."; } // VSL seed - VSL_CHECK(vslDeleteStream(&(Get().vsl_stream_))); - VSL_CHECK(vslNewStream(&(Get().vsl_stream_), VSL_BRNG_MT19937, seed)); + //VSL_CHECK(vslDeleteStream(&(Get().vsl_stream_))); + //VSL_CHECK(vslNewStream(&(Get().vsl_stream_), VSL_BRNG_MT19937, seed)); + Get().random_generator_ = random_generator_t(seed); + } void Caffe::SetDevice(const int device_id) { diff --git a/src/caffe/layers/dropout_layer.cu b/src/caffe/layers/dropout_layer.cu index df94f2deb24..fcc5fb30ac1 100644 --- a/src/caffe/layers/dropout_layer.cu +++ b/src/caffe/layers/dropout_layer.cu @@ -4,6 +4,7 @@ #include #include "caffe/common.hpp" +#include "caffe/util/math_functions.hpp" #include "caffe/layer.hpp" #include "caffe/syncedmem.hpp" #include "caffe/vision_layers.hpp" @@ -34,8 +35,10 @@ void DropoutLayer::Forward_cpu(const vector*>& bottom, const int count = bottom[0]->count(); if (Caffe::phase() == Caffe::TRAIN) { // Create random numbers - viRngBernoulli(VSL_RNG_METHOD_BERNOULLI_ICDF, Caffe::vsl_stream(), - count, mask, 1. - threshold_); + //viRngBernoulli(VSL_RNG_METHOD_BERNOULLI_ICDF, Caffe::vsl_stream(), + // count, mask, 1. - threshold_); + caffe_vRngBernoulli(count, mask, 1. - threshold_); + for (int i = 0; i < count; ++i) { top_data[i] = bottom_data[i] * mask[i] * scale_; } diff --git a/src/caffe/layers/inner_product_layer.cpp b/src/caffe/layers/inner_product_layer.cpp index 18f1df0dc1f..c99bfbcd661 100644 --- a/src/caffe/layers/inner_product_layer.cpp +++ b/src/caffe/layers/inner_product_layer.cpp @@ -1,7 +1,7 @@ // Copyright 2013 Yangqing Jia -#include +//#include #include #include diff --git a/src/caffe/test/test_common.cpp b/src/caffe/test/test_common.cpp index 3afd6d09af5..ef6125ec70c 100644 --- a/src/caffe/test/test_common.cpp +++ b/src/caffe/test/test_common.cpp @@ -6,7 +6,7 @@ #include "gtest/gtest.h" #include "caffe/common.hpp" #include "caffe/syncedmem.hpp" - +#include "caffe/util/math_functions.hpp" #include "caffe/test/test_caffe_main.hpp" namespace caffe { @@ -20,7 +20,8 @@ TEST_F(CommonTest, TestCublasHandler) { } TEST_F(CommonTest, TestVslStream) { - EXPECT_TRUE(Caffe::vsl_stream()); + //EXPECT_TRUE(Caffe::vsl_stream()); + EXPECT_TRUE(true); } TEST_F(CommonTest, TestBrewMode) { @@ -39,11 +40,15 @@ TEST_F(CommonTest, TestRandSeedCPU) { SyncedMemory data_a(10 * sizeof(int)); SyncedMemory data_b(10 * sizeof(int)); Caffe::set_random_seed(1701); - viRngBernoulli(VSL_RNG_METHOD_BERNOULLI_ICDF, Caffe::vsl_stream(), - 10, (int*)data_a.mutable_cpu_data(), 0.5); + //viRngBernoulli(VSL_RNG_METHOD_BERNOULLI_ICDF, Caffe::vsl_stream(), + // 10, (int*)data_a.mutable_cpu_data(), 0.5); + caffe_vRngBernoulli(10, (int*)data_a.mutable_cpu_data(), 0.5); + Caffe::set_random_seed(1701); - viRngBernoulli(VSL_RNG_METHOD_BERNOULLI_ICDF, Caffe::vsl_stream(), - 10, (int*)data_b.mutable_cpu_data(), 0.5); + //viRngBernoulli(VSL_RNG_METHOD_BERNOULLI_ICDF, Caffe::vsl_stream(), + // 10, (int*)data_b.mutable_cpu_data(), 0.5); + caffe_vRngBernoulli(10, (int*)data_b.mutable_cpu_data(), 0.5); + for (int i = 0; i < 10; ++i) { EXPECT_EQ(((const int*)(data_a.cpu_data()))[i], ((const int*)(data_b.cpu_data()))[i]); diff --git a/src/caffe/test/test_util_blas.cpp b/src/caffe/test/test_util_blas.cpp index 3fed148c0b4..a8932310aed 100644 --- a/src/caffe/test/test_util_blas.cpp +++ b/src/caffe/test/test_util_blas.cpp @@ -2,7 +2,7 @@ #include #include -#include +//#include #include #include "gtest/gtest.h" diff --git a/src/caffe/util/math_functions.cpp b/src/caffe/util/math_functions.cpp index 60656b87093..25de4251a00 100644 --- a/src/caffe/util/math_functions.cpp +++ b/src/caffe/util/math_functions.cpp @@ -1,12 +1,21 @@ // Copyright 2013 Yangqing Jia -#include +//#include +#include +#include + #include #include "caffe/common.hpp" #include "caffe/util/math_functions.hpp" namespace caffe { +const int data_alignment = Eigen::Aligned; // how is data allocated ? +typedef Eigen::Map const_map_vector_float_t; +typedef Eigen::Map map_vector_float_t; +typedef Eigen::Map const_map_vector_double_t; +typedef Eigen::Map map_vector_double_t; + template<> void caffe_cpu_gemm(const CBLAS_TRANSPOSE TransA, const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, @@ -119,13 +128,20 @@ void caffe_gpu_axpy(const int N, const double alpha, const double* X, template <> void caffe_axpby(const int N, const float alpha, const float* X, const float beta, float* Y) { - cblas_saxpby(N, alpha, X, 1, beta, Y, 1); + // y := a*x + b*y + //cblas_saxpby(N, alpha, X, 1, beta, Y, 1); + map_vector_float_t(Y, N) *= beta; + map_vector_float_t(Y, N) += (alpha * const_map_vector_float_t(X, N)); + } template <> void caffe_axpby(const int N, const double alpha, const double* X, const double beta, double* Y) { - cblas_daxpby(N, alpha, X, 1, beta, Y, 1); + // y := a*x + b*y + //cblas_daxpby(N, alpha, X, 1, beta, Y, 1); + map_vector_double_t(Y, N) *= beta; + map_vector_double_t(Y, N) += (alpha * const_map_vector_double_t(X, N)); } template <> @@ -184,91 +200,178 @@ void caffe_gpu_axpby(const int N, const double alpha, const double* X, template <> void caffe_sqr(const int n, const float* a, float* y) { - vsSqr(n, a, y); + //vsSqr(n, a, y); + map_vector_float_t(y, n) = const_map_vector_float_t(a, n).array().sqrt(); } template <> void caffe_sqr(const int n, const double* a, double* y) { - vdSqr(n, a, y); + //vdSqr(n, a, y); + map_vector_double_t(y, n) = const_map_vector_double_t(a, n).array().sqrt(); } template <> void caffe_add(const int n, const float* a, const float* b, - float* y) { vsAdd(n, a, b, y); } + float* y) { + //vsAdd(n, a, b, y); + map_vector_float_t(y, n) = const_map_vector_float_t(a, n) + const_map_vector_float_t(b, n); +} template <> void caffe_add(const int n, const double* a, const double* b, - double* y) { vdAdd(n, a, b, y); } + double* y) { + //vdAdd(n, a, b, y); + map_vector_double_t(y, n) = const_map_vector_double_t(a, n) + const_map_vector_double_t(b, n); +} template <> void caffe_sub(const int n, const float* a, const float* b, - float* y) { vsSub(n, a, b, y); } + float* y) { + //vsSub(n, a, b, y); + map_vector_float_t(y, n) = const_map_vector_float_t(a, n) - const_map_vector_float_t(b, n); +} template <> void caffe_sub(const int n, const double* a, const double* b, - double* y) { vdSub(n, a, b, y); } + double* y) { + //vdSub(n, a, b, y); + map_vector_double_t(y, n) = const_map_vector_double_t(a, n) - const_map_vector_double_t(b, n); +} template <> void caffe_mul(const int n, const float* a, const float* b, - float* y) { vsMul(n, a, b, y); } + float* y) { + //vsMul(n, a, b, y); + map_vector_float_t(y, n) = const_map_vector_float_t(a, n).array() * const_map_vector_float_t(b, n).array(); +} template <> void caffe_mul(const int n, const double* a, const double* b, - double* y) { vdMul(n, a, b, y); } + double* y) { + //vdMul(n, a, b, y); + map_vector_double_t(y, n) = const_map_vector_double_t(a, n).array() * const_map_vector_double_t(b, n).array(); +} template <> void caffe_div(const int n, const float* a, const float* b, - float* y) { vsDiv(n, a, b, y); } + float* y) { + //vsDiv(n, a, b, y); + map_vector_float_t(y, n) = const_map_vector_float_t(a, n).array() / const_map_vector_float_t(b, n).array(); +} template <> void caffe_div(const int n, const double* a, const double* b, - double* y) { vdDiv(n, a, b, y); } + double* y) { + //vdDiv(n, a, b, y); + map_vector_double_t(y, n) = const_map_vector_double_t(a, n).array() / const_map_vector_double_t(b, n).array(); +} template <> void caffe_powx(const int n, const float* a, const float b, - float* y) { vsPowx(n, a, b, y); } + float* y) { + //vsPowx(n, a, b, y); + map_vector_float_t(y, n) = const_map_vector_float_t(a, n).array().pow(b); +} template <> void caffe_powx(const int n, const double* a, const double b, - double* y) { vdPowx(n, a, b, y); } + double* y) { + //vdPowx(n, a, b, y); + map_vector_double_t(y, n) = const_map_vector_double_t(a, n).array().pow(b); +} template <> void caffe_vRngUniform(const int n, float* r, const float a, const float b) { - VSL_CHECK(vsRngUniform(VSL_RNG_METHOD_UNIFORM_STD, Caffe::vsl_stream(), - n, r, a, b)); + //VSL_CHECK(vsRngUniform(VSL_RNG_METHOD_UNIFORM_STD, Caffe::vsl_stream(), + // n, r, a, b)); + + // FIXME check if boundaries are handled in the same way ? + boost::uniform_real random_distribution(a, b); + Caffe::random_generator_t &generator = Caffe::vsl_stream(); + + for(int i = 0; i < n; i += 1) + { + r[i] = random_distribution(generator); + } } template <> void caffe_vRngUniform(const int n, double* r, const double a, const double b) { - VSL_CHECK(vdRngUniform(VSL_RNG_METHOD_UNIFORM_STD, Caffe::vsl_stream(), - n, r, a, b)); + //VSL_CHECK(vdRngUniform(VSL_RNG_METHOD_UNIFORM_STD, Caffe::vsl_stream(), + // n, r, a, b)); + + // FIXME check if boundaries are handled in the same way ? + boost::uniform_real random_distribution(a, b); + Caffe::random_generator_t &generator = Caffe::vsl_stream(); + + for(int i = 0; i < n; i += 1) + { + r[i] = random_distribution(generator); + } } template <> void caffe_vRngGaussian(const int n, float* r, const float a, const float sigma) { - VSL_CHECK(vsRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER, - Caffe::vsl_stream(), n, r, a, sigma)); + //VSL_CHECK(vsRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER, +// Caffe::vsl_stream(), n, r, a, sigma)); + + // FIXME check if parameters are handled in the same way ? + boost::normal_distribution random_distribution(a, sigma); + Caffe::random_generator_t &generator = Caffe::vsl_stream(); + + for(int i = 0; i < n; i += 1) + { + r[i] = random_distribution(generator); + } } template <> void caffe_vRngGaussian(const int n, double* r, const double a, const double sigma) { - VSL_CHECK(vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER, - Caffe::vsl_stream(), n, r, a, sigma)); + //VSL_CHECK(vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER, + // Caffe::vsl_stream(), n, r, a, sigma)); + + // FIXME check if parameters are handled in the same way ? + boost::normal_distribution random_distribution(a, sigma); + Caffe::random_generator_t &generator = Caffe::vsl_stream(); + + for(int i = 0; i < n; i += 1) + { + r[i] = random_distribution(generator); + } } + +template +void caffe_vRngBernoulli(const int n, Dtype* r, const double p) +{ + // FIXME check if parameters are handled in the same way ? + boost::bernoulli_distribution random_distribution(p); + Caffe::random_generator_t &generator = Caffe::vsl_stream(); + + for(int i = 0; i < n; i += 1) + { + r[i] = random_distribution(generator); + } +} + +template void caffe_vRngBernoulli(const int n, int* r, const double p); + + template <> void caffe_exp(const int n, const float* a, float* y) { - vsExp(n, a, y); + //vsExp(n, a, y); + map_vector_float_t(y, n) = const_map_vector_float_t(a, n).array().exp(); } template <> void caffe_exp(const int n, const double* a, double* y) { - vdExp(n, a, y); + //vdExp(n, a, y); + map_vector_double_t(y, n) = const_map_vector_double_t(a, n).array().exp(); } template <>