Skip to content

Commit

Permalink
Merge pull request #101 from BTAS/Reconfig-lapacke+docs
Browse files Browse the repository at this point in the history
Reconfig lapacke+docs
  • Loading branch information
evaleev authored Jan 30, 2020
2 parents d4b5260 + a072fd7 commit e3b31e5
Show file tree
Hide file tree
Showing 26 changed files with 810 additions and 888 deletions.
166 changes: 120 additions & 46 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,33 +1,64 @@
#; -*-CMake-*-

cmake_minimum_required (VERSION 3.1.0)
cmake_minimum_required (VERSION 3.8.0) # cxx_std_11 compile feature
project (BTAS)
enable_language(CXX)

# extra cmake files are shipped with BTAS
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules")

include(FeatureSummary)
include(RedefaultableOption)
include(CMakePackageConfigHelpers)

# Configure options
option(BTAS_BUILD_UNITTEST "Causes building BTAS unit tests" ON)
option(BTAS_EXPERT "BTAS Expert mode: disables automatically downloading or building dependencies" OFF)
option(BTAS_ASSERT_THROWS "Whether BTAS_ASSERT should throw" OFF)
redefaultable_option(BTAS_BUILD_UNITTEST "Whether to build unit tests" OFF)
add_feature_info(BUILD_UNITTEST BTAS_BUILD_UNITTEST "Will build unit tests")
redefaultable_option(BTAS_ASSERT_THROWS "Whether BTAS_ASSERT should throw; enable if BTAS_BUILD_UNITTEST=ON" OFF)
add_feature_info(ASSERT_THROWS BTAS_ASSERT_THROWS "BTAS_ASSERT(x) will throw if x is false, and not be affected by NDEBUG")
redefaultable_option(BTAS_USE_CBLAS_LAPACKE "Whether to use BLAS+LAPACK via CBLAS+LAPACKE" ON)
add_feature_info(USE_CBLAS_LAPACKE BTAS_USE_CBLAS_LAPACKE "Will use BLAS and LAPACK linear algebra libraries via their CBLAS and LAPACKE interfaces")
redefaultable_option(BTAS_ENABLE_MKL "Whether to look for Intel MKL" ON)
add_feature_info(ENABLE_MKL BTAS_ENABLE_MKL "Will look for Intel MKL library")

set(TARGET_MAX_INDEX_RANK 6 CACHE STRING "Determines the rank for which the default BTAS index type will use stack (default: 6); this requires Boost.Container")
add_feature_info("TARGET_MAX_INDEX_RANK=${TARGET_MAX_INDEX_RANK}" TRUE "default BTAS index type will use stack for rank<=${TARGET_MAX_INDEX_RANK}")

# Set BTAS version
set(BTAS_MAJOR_VERSION 0)
set(BTAS_MINOR_VERSION 1)
set(BTAS_MAJOR_VERSION 1)
set(BTAS_MINOR_VERSION 0)
set(BTAS_MICRO_VERSION 0)
set(BTAS_BUILDID alpha)
set(BTAS_VERSION "${BTAS_MAJOR_VERSION}.${BTAS_MINOR_VERSION}.${BTAS_MICRO_VERSION}-${BTAS_BUILDID}")
set(BTAS_PRERELEASE_ID alpha.1)
set(BTAS_VERSION "${BTAS_MAJOR_VERSION}.${BTAS_MINOR_VERSION}.${BTAS_MICRO_VERSION}")
if (BTAS_PRERELEASE_ID)
set(BTAS_EXT_VERSION "${BTAS_VERSION}-${BTAS_PRERELEASE_ID}")
else(BTAS_PRERELEASE_ID)
set(BTAS_EXT_VERSION "${BTAS_VERSION}")
endif(BTAS_PRERELEASE_ID)
set(TARGET_ARCH "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")

# extra cmake files are shipped with BTAS
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules")

include(CMakePushCheckState)
include(GNUInstallDirs)
include(AppendFlags)

##########################
# Standard build variables
##########################
set(BTAS_INSTALL_BINDIR "bin"
CACHE PATH "BTAS BIN install directory")
set(BTAS_INSTALL_INCLUDEDIR "include"
CACHE PATH "BTAS INCLUDE install directory")
set(BTAS_INSTALL_LIBDIR "lib"
CACHE PATH "BTAS LIB install directory")
set(BTAS_INSTALL_SHAREDIR "share/BTAS/${BTAS_MAJOR_VERSION}.${BTAS_MINOR_VERSION}.${BTAS_MICRO_VERSION}"
CACHE PATH "BTAS SHARE install directory")
set(BTAS_INSTALL_DATADIR "${BTAS_INSTALL_SHAREDIR}/data"
CACHE PATH "BTAS DATA install directory")
set(BTAS_INSTALL_DOCDIR "${BTAS_INSTALL_SHAREDIR}/doc"
CACHE PATH "BTAS DOC install directory")
set(BTAS_INSTALL_CMAKEDIR "lib/cmake/BTAS"
CACHE PATH "BTAS CMAKE install directory")

##########################
# Standard build variables
##########################
Expand All @@ -44,69 +75,81 @@ endif()
if(NOT CMAKE_EXE_LINKER_FLAGS OR NOT DEFINED CMAKE_EXE_LINKER_FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "$ENV{LDFLAGS}")
endif()

enable_language (CXX)
if (NOT CMAKE_CXX_COMPILER)
message(FATAL_ERROR "C++ compiler not found")
endif()

# Set the default fortran integer type.
set(INTEGER4 "FALSE" CACHE BOOL "Set the default Fortran integer type to integer*4")
mark_as_advanced(INTEGER4)

set(CMAKE_SKIP_RPATH FALSE)
set(BUILD_TESTING FALSE CACHE BOOL "BUILD_TESTING")
set(BUILD_TESTING_STATIC FALSE CACHE BOOL "BUILD_TESTING_STATIC")
set(BUILD_TESTING_SHARED FALSE CACHE BOOL "BUILD_TESTING_SHARED")

##########################
# We use C++11 features
##########################
set(CMAKE_CXX_STANDARD 11)
# but insist on strict standard
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ ISO Standard version")
if (NOT(CMAKE_CXX_STANDARD EQUAL 11 OR CMAKE_CXX_STANDARD EQUAL 14 OR CMAKE_CXX_STANDARD EQUAL 17 OR CMAKE_CXX_STANDARD EQUAL 20))
message(FATAL_ERROR "C++ 2011 ISO Standard or higher is required to compile BTAS")
endif()
# C++20 is only configurable via compile features with cmake 3.12 and older
if (CMAKE_CXX_STANDARD EQUAL 20 AND CMAKE_VERSION VERSION_LESS 3.12.0)
cmake_minimum_required (VERSION 3.12.0)
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Whether to use extensions of C++ ISO Standard version")

# Check type support
include(CheckTypeSize)
check_type_size("long double" BTAS_HAS_LONG_DOUBLE)
check_type_size("long long" BTAS_HAS_LONG_LONG)

#######################################
# create exportable BTAS library target
#######################################
add_library(BTAS INTERFACE)
install(TARGETS BTAS EXPORT btas COMPONENT BTAS)
target_compile_features(BTAS INTERFACE "cxx_std_11")
target_include_directories(BTAS INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/${BTAS_INSTALL_INCLUDEDIR}>)
install(DIRECTORY btas
COMPONENT BTAS
DESTINATION "${BTAS_INSTALL_INCLUDEDIR}"
FILES_MATCHING PATTERN "*.h"
PATTERN "*.h.in" EXCLUDE
)

##########################
# external dependencies
##########################
add_custom_target(External)

if (BTAS_BUILD_UNITTEST)
if (USE_CBLAS)
find_package(CBLAS REQUIRED)
find_package(LAPACKE REQUIRED)
add_definitions(-D_CBLAS_HEADER="${CBLAS_INCLUDE_FILE}" -D_LAPACKE_HEADER="${LAPACKE_INCLUDE_FILE}" -DBTAS_HAS_CBLAS=1)
message(STATUS "** CBLAS_LIBRARIES = ${CBLAS_LIBRARIES}")
message(STATUS "** CBLAS_INCLUDE_DIR = ${CBLAS_INCLUDE_DIR}")
message(STATUS "** CBLAS_INCLUDE_FILE = ${CBLAS_INCLUDE_FILE}")
message(STATUS "** LAPACKE_LIBRARIES = ${LAPACKE_LIBRARIES}")
message(STATUS "** LAPACKE_INCLUDE_DIR = ${LAPACKE_INCLUDE_DIR}")
message(STATUS "** LAPACKE_INCLUDE_FILE = ${LAPACKE_INCLUDE_FILE}")
include_directories(${CBLAS_INCLUDE_DIR} ${LAPACKE_INCLUDE_DIR})
if (MKL_FOUND)
add_definitions(-D_HAS_INTEL_MKL=1)
endif(MKL_FOUND)
endif(USE_CBLAS)
include(external/boost.cmake)
endif()
if (BTAS_USE_CBLAS_LAPACKE)
find_package(CBLAS REQUIRED)
find_package(LAPACKE REQUIRED)
target_compile_definitions(BTAS INTERFACE -DBTAS_CBLAS_HEADER="${CBLAS_INCLUDE_FILE}" -DBTAS_LAPACKE_HEADER="${LAPACKE_INCLUDE_FILE}" -DBTAS_HAS_CBLAS=1 -DBTAS_HAS_LAPACKE=1)
message(STATUS "** CBLAS_LIBRARIES = ${CBLAS_LIBRARIES}")
message(STATUS "** CBLAS_INCLUDE_DIR = ${CBLAS_INCLUDE_DIR}")
message(STATUS "** CBLAS_INCLUDE_FILE = ${CBLAS_INCLUDE_FILE}")
message(STATUS "** LAPACKE_LIBRARIES = ${LAPACKE_LIBRARIES}")
message(STATUS "** LAPACKE_INCLUDE_DIR = ${LAPACKE_INCLUDE_DIR}")
message(STATUS "** LAPACKE_INCLUDE_FILE = ${LAPACKE_INCLUDE_FILE}")
target_include_directories(BTAS INTERFACE ${CBLAS_INCLUDE_DIR} ${LAPACKE_INCLUDE_DIR})
if (MKL_FOUND)
target_compile_definitions(BTAS INTERFACE -DBTAS_HAS_INTEL_MKL=1)
endif(MKL_FOUND)
target_link_libraries(BTAS INTERFACE ${LAPACKE_LIBRARIES} ${CBLAS_LIBRARIES})
endif(BTAS_USE_CBLAS_LAPACKE)

include(external/boost.cmake)

##########################
# configure BTAS_ASSERT
##########################
if (BTAS_ASSERT_THROWS)
add_definitions(-DBTAS_ASSERT_THROWS=1)
target_compile_definitions(BTAS INTERFACE -DBTAS_ASSERT_THROWS=1)
endif(BTAS_ASSERT_THROWS)

##########################
# sources
# dox
##########################

include_directories(${PROJECT_SOURCE_DIR})
add_subdirectory(doc)

##########################
Expand Down Expand Up @@ -134,6 +177,37 @@ ADD_CUSTOM_TARGET(release
COMMENT "Switch CMAKE_BUILD_TYPE to Release"
)

# Create the version file
write_basic_package_version_file(btas-config-version.cmake
VERSION ${BTAS_VERSION} COMPATIBILITY AnyNewerVersion)

## Create the configure file
configure_package_config_file(cmake/btas-config.cmake.in
"${PROJECT_BINARY_DIR}/btas-config.cmake"
INSTALL_DESTINATION "${BTAS_INSTALL_CMAKEDIR}"
PATH_VARS CMAKE_INSTALL_PREFIX BTAS_INSTALL_BINDIR
BTAS_INSTALL_INCLUDEDIR BTAS_INSTALL_LIBDIR
BTAS_INSTALL_DOCDIR BTAS_INSTALL_CMAKEDIR)

## Install config, version, and target files
install(EXPORT btas
FILE "btas-targets.cmake"
DESTINATION "${BTAS_INSTALL_CMAKEDIR}"
NAMESPACE BTAS::
COMPONENT btas-config)
install(FILES
"${PROJECT_BINARY_DIR}/btas-config.cmake"
"${PROJECT_BINARY_DIR}/btas-config-version.cmake"
DESTINATION "${BTAS_INSTALL_CMAKEDIR}"
COMPONENT btas-config)
add_custom_target(install-config
COMMAND ${CMAKE_COMMAND} -DCOMPONENT=btas-config -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
COMMENT "Installing BTAS config components")

feature_summary(WHAT ALL
DESCRIPTION "=== BTAS Feature Info ===")

DESCRIPTION "=== BTAS Package/Feature Info ===")

###############################################################################
# appendix: misc details
###############################################################################
SET(CMAKE_COLOR_MAKEFILE ON)
8 changes: 4 additions & 4 deletions bin/travisci_build_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ fi

cd ${BUILD_PREFIX}

########## test with cblas ##########
########## test with blas+lapack ##########
mkdir build_cblas
cd build_cblas
cmake ${TRAVIS_BUILD_DIR} -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBTAS_ASSERT_THROWS=ON -DUSE_CBLAS=ON -DBoost_FOUND=ON -DBoost_INCLUDE_DIRS=/usr/include/boost -DBoost_LIBRARIES=/usr/lib/x86_64-linux-gnu/libboost_serialization.a -DSKIP_BOOST_SEARCH=ON
cmake ${TRAVIS_BUILD_DIR} -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBTAS_ASSERT_THROWS=ON -DBTAS_BUILD_UNITTEST=ON
make VERBOSE=1
make check VERBOSE=1
cd ..

########## test without cblas ##########
########## test without blas+lapack ##########
mkdir build
cd build
cmake ${TRAVIS_BUILD_DIR} -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBTAS_ASSERT_THROWS=ON -DBoost_FOUND=ON -DBoost_INCLUDE_DIRS=/usr/include/boost -DBoost_LIBRARIES=/usr/lib/x86_64-linux-gnu/libboost_serialization.a -DSKIP_BOOST_SEARCH=ON
cmake ${TRAVIS_BUILD_DIR} -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBTAS_ASSERT_THROWS=ON -DBTAS_BUILD_UNITTEST=ON -DBTAS_USE_CBLAS_LAPACKE=OFF
make VERBOSE=1
make check VERBOSE=1
cd ..
Expand Down
29 changes: 24 additions & 5 deletions btas/generic/converge_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,13 @@ namespace btas {
int rank_; // Rank of the CP problem
};

// From Tensor Toolbox :
// The "fit" is defined as 1 - norm(X-full(M))/norm(X) and is
// loosely the proportion of the data described by the CP model, i.e., a
// fit of 1 is perfect.
/**
\brief Class used to decide when ALS problem is converged
The "fit" is defined as \f$ 1 - \frac{\|X-full(M)\|}{\|X\|} \leq \epsilon\f$
where X is the exact tensor and M is the reconstructed CP tensor.
This fit is loosely the proportion of the data described by the
CP model, i.e., a fit of 1 is perfect.
**/
template<typename Tensor>
class FitCheck{
public:
Expand Down Expand Up @@ -109,7 +112,9 @@ namespace btas {

double fitChange = abs(fitOld_ - fit);
fitOld_ = fit;
//std::cout << fit << "\t" << fitChange << std::endl;
if(verbose_) {
std::cout << fit << "\t" << fitChange << std::endl;
}
if(fitChange < tol_) {
converged_num++;
if(converged_num == 2){
Expand Down Expand Up @@ -137,6 +142,10 @@ namespace btas {
return final_fit_;
}

void verbose(bool verb){
verbose_ = verb;
}

private:
double tol_;
double fitOld_ = -1.0;
Expand All @@ -145,6 +154,7 @@ namespace btas {
int iter_ = 0;
int converged_num = 0;
Tensor MtKRP_;
bool verbose_ = false;

double norm(const std::vector<Tensor> & btas_factors){
auto rank = btas_factors[0].extent(1);
Expand Down Expand Up @@ -172,6 +182,15 @@ namespace btas {
}
};

/**
\brief Class used to decide when ALS problem is converged
The "fit" is defined as \f$ 1 - \frac{\|X_1-full(M_1)\|}{\|X_1\|} -
\frac{\|X_2-full(M_2)\|}{\|X_2\|}\leq \epsilon\f$
where \f$ X_1 \f$ and \f$ X_2 \f$ are tensors coupled by a single mode
\f$ M_1 \f$ and \f$ M_2 \f$ are the coupled reconstructed CP tensors.
This fit is loosely the proportion of the data described by the
CP model, i.e., a fit of 1 is perfect.
**/
template <typename Tensor>
class CoupledFitCheck{
public:
Expand Down
15 changes: 4 additions & 11 deletions btas/generic/coupled_cp_als.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <btas/generic/converge_class.h>
#include <btas/generic/rals_helper.h>
#include <btas/generic/reconstruct.h>
#include <btas/generic/linear_algebra.h>

namespace btas{

Expand Down Expand Up @@ -78,7 +79,6 @@ namespace btas{
public:
using CP<Tensor,ConvClass>::A;
using CP<Tensor,ConvClass>::ndim;
using CP<Tensor,ConvClass>::pseudoInverse;
using CP<Tensor,ConvClass>::normCol;
using CP<Tensor,ConvClass>::generate_KRP;
using CP<Tensor,ConvClass>::generate_V;
Expand Down Expand Up @@ -122,7 +122,6 @@ namespace btas{
"Tensor describing symmetries must be defined for all dimensions");
}

#ifdef _HAS_INTEL_MKL
/// \brief Computes decomposition of the order-N tensor \c tensor
/// with rank = \c RankStep * \c panels * max_dim(reference_tensor) + max_dim(reference_tensor)
/// Initial guess for factor matrices start at rank = max_dim(reference_tensor)
Expand All @@ -147,7 +146,6 @@ namespace btas{
int max_als = 20,bool fast_pI = false, bool calculate_epsilon = false, bool direct = true) override{
BTAS_EXCEPTION("Function not yet implemented");
}
#endif //_HAS_INTEL_MKL

protected:
Tensor& tensor_ref_left; // Tensor in first term of the loss function
Expand Down Expand Up @@ -183,7 +181,6 @@ namespace btas{
// If its the first time into build and SVD_initial_guess
// build and optimize the initial guess based on the left
// singular vectors of the reference tensor.
#ifdef _HAS_INTEL_MKL
if (A.empty() && SVD_initial_guess) {
if (SVD_rank == 0) BTAS_EXCEPTION("Must specify the rank of the initial approximation using SVD");

Expand Down Expand Up @@ -220,8 +217,7 @@ namespace btas{
gemm(CblasNoTrans, CblasTrans, 1.0, flatten(tensor_ref, i), flatten(tensor_ref, i), 0.0, S);

// Find the Singular vectors of the matrix using eigenvalue decomposition
auto info = LAPACKE_dsyev(LAPACK_COL_MAJOR, 'V', 'U', R, S.data(), R, lambda.data());
if (info) BTAS_EXCEPTION("Error in computing the SVD initial guess");
eigenvalue_decomp(S, lambda);

// Fill a factor matrix with the singular vectors with the largest corresponding singular
// values
Expand Down Expand Up @@ -267,9 +263,6 @@ namespace btas{
// Optimize this initial guess.
ALS(SVD_rank, converge_test, direct, max_als, calculate_epsilon, epsilon, fast_pI);
}
#else // _HAS_INTEL_MKL
if (SVD_initial_guess) BTAS_EXCEPTION("Computing the SVD requires LAPACK");
#endif // _HAS_INTEL_MKL
// This loop keeps track of column dimension
for (auto i = (A.empty()) ? 0 : A.at(0).extent(1); i < rank; i += step) {
// This loop walks through the factor matrices
Expand Down Expand Up @@ -480,7 +473,7 @@ namespace btas{
}
// Finally Form the product of K * J^\dagger
Tensor a0(coupled_dim, rank);
gemm(CblasNoTrans, CblasNoTrans, 1.0, K, pseudoInverse(J1), 0.0, a0);
gemm(CblasNoTrans, CblasNoTrans, 1.0, K, pseudoInverse(J1, fast_pI), 0.0, a0);
this->normCol(a0);
A[0] = a0;
}
Expand Down Expand Up @@ -556,7 +549,7 @@ namespace btas{
else if(n == this->ndim - 1)
detail::set_MtKRPR(converge_test, contract_tensor);
Tensor an(skip_dim, rank);
gemm(CblasNoTrans, CblasNoTrans, 1.0, contract_tensor, pseudoInverse(G), 0.0, an);
gemm(CblasNoTrans, CblasNoTrans, 1.0, contract_tensor, pseudoInverse(G, fast_pI), 0.0, an);
this->normCol(an);
A[n] = an;
}
Expand Down
Loading

0 comments on commit e3b31e5

Please sign in to comment.