From a5597cc8195b6c7a2e7a4908bc558ff87b6db325 Mon Sep 17 00:00:00 2001 From: David Wells Date: Sun, 16 Jul 2017 08:50:05 -0400 Subject: [PATCH] Add an option for a unity build. --- cmake/macros/macro_setup_source_list.cmake | 42 +++++++++++++ cmake/macros/macro_setup_unity_target.cmake | 66 +++++++++++++++++++++ cmake/setup_cached_variables.cmake | 6 ++ doc/developers/cmake-internals.html | 25 ++++++++ doc/news/changes/major/20170720DavidWells | 2 + doc/readme.html | 34 +++++++---- source/base/CMakeLists.txt | 19 +++++- source/distributed/CMakeLists.txt | 14 ++++- source/dofs/CMakeLists.txt | 22 +++++-- source/fe/CMakeLists.txt | 26 +++++--- source/grid/CMakeLists.txt | 18 +++++- source/hp/CMakeLists.txt | 16 ++++- source/lac/CMakeLists.txt | 45 ++++++++++---- source/multigrid/CMakeLists.txt | 18 +++++- source/numerics/CMakeLists.txt | 40 ++++++++----- 15 files changed, 335 insertions(+), 58 deletions(-) create mode 100644 cmake/macros/macro_setup_source_list.cmake create mode 100644 cmake/macros/macro_setup_unity_target.cmake create mode 100644 doc/news/changes/major/20170720DavidWells diff --git a/cmake/macros/macro_setup_source_list.cmake b/cmake/macros/macro_setup_source_list.cmake new file mode 100644 index 0000000000..c83b3ccb34 --- /dev/null +++ b/cmake/macros/macro_setup_source_list.cmake @@ -0,0 +1,42 @@ +## --------------------------------------------------------------------- +## +## Copyright (C) 2017 by the deal.II authors +## +## This file is part of the deal.II library. +## +## The deal.II library is free software; you can use it, redistribute +## it, and/or modify it under the terms of the GNU Lesser General +## Public License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## The full text of the license can be found in the file LICENSE at +## the top level of the deal.II distribution. +## +## --------------------------------------------------------------------- + +# +# Usage: +# SETUP_SOURCE_LIST("${_list_of_unity_source_files}" +# "${_list_of_non_unity_source_files}" +# _includes_per_unity_file +# _source_files) +# +# This macro sets up the list of source files for the current directory. If +# DEAL_II_UNITY_BUILD=ON then this script calls SETUP_UNITY_TARGET to do so; +# otherwise, if DEAL_II_UNITY_BUILD=OFF, then all source files are added to the +# variable _source_files. +# +MACRO(SETUP_SOURCE_LIST _unity_include_src _separate_src _n_includes_per_unity_file _output_src) + IF(DEAL_II_UNITY_BUILD) + SETUP_UNITY_TARGET("${_unity_include_src}" ${_n_includes_per_unity_file} ${_output_src}) + SET(${_output_src} + ${${_output_src}} + ${_separate_src} + ) + ELSE() + SET(${_output_src} + ${${_output_src}} + ${_unity_include_src} + ${_separate_src} + ) + ENDIF() +ENDMACRO() diff --git a/cmake/macros/macro_setup_unity_target.cmake b/cmake/macros/macro_setup_unity_target.cmake new file mode 100644 index 0000000000..9293065d1f --- /dev/null +++ b/cmake/macros/macro_setup_unity_target.cmake @@ -0,0 +1,66 @@ +## --------------------------------------------------------------------- +## +## Copyright (C) 2017 by the deal.II authors +## +## This file is part of the deal.II library. +## +## The deal.II library is free software; you can use it, redistribute +## it, and/or modify it under the terms of the GNU Lesser General +## Public License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## The full text of the license can be found in the file LICENSE at +## the top level of the deal.II distribution. +## +## --------------------------------------------------------------------- + +# +# Usage: +# SETUP_UNITY_TARGET("${_list_of_unity_source_files}" _includes_per_unity_file _output_src) +# +# This macro sets up some number of unity build targets given a list of files +# and the number of files to be included per unity file. It generates the unity +# build files and appends their names to _output_src. +# +MACRO(SETUP_UNITY_TARGET _unity_include_src _n_includes_per_unity_file _output_src) + # + # The unity build files need access to the original source files: + # + INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) + + SET(_file_index 0) + FOREACH(_unity_file ${_unity_include_src}) + MATH(EXPR _unity_prefix_index "${_file_index} / ${_n_includes_per_unity_file}") + # + # Get around the fact that CMake does not support nested lists by generating + # a file name and then storing that file name in a list (which we will + # uniquify later) + # + SET(_unity_prefix "unity_${_unity_prefix_index}") + LIST(APPEND _unity_prefixes ${_unity_prefix}) + LIST(APPEND ${_unity_prefix} ${_unity_file}) + + MATH(EXPR _file_index "${_file_index} + 1") + ENDFOREACH() + + LIST(REMOVE_DUPLICATES _unity_prefixes) + + FOREACH(_unity_prefix ${_unity_prefixes}) + SET(_unity_file_name "${CMAKE_CURRENT_BINARY_DIR}/${_unity_prefix}.cc") + # + # Note the CMake weirdness: _output_src is actually a string containing the + # variable name since we are in a macro... + # + SET(${_output_src} + ${${_output_src}} + ${_unity_file_name} + ) + FILE(WRITE "${_unity_file_name}" +"// This file was automatically generated by the deal.II CMake configuration as +// part of the unity build subsystem. Please do not edit this file directly; +// instead, make appropriate changes to the relevant CMakeLists.txt file.\n\n" + ) + FOREACH(_unity_file ${${_unity_prefix}}) + FILE(APPEND "${_unity_file_name}" "#include \"${_unity_file}\"\n") + ENDFOREACH() + ENDFOREACH() +ENDMACRO() diff --git a/cmake/setup_cached_variables.cmake b/cmake/setup_cached_variables.cmake index bb1922f01f..43cfbf5822 100644 --- a/cmake/setup_cached_variables.cmake +++ b/cmake/setup_cached_variables.cmake @@ -34,6 +34,7 @@ # DEAL_II_ALLOW_PLATFORM_INTROSPECTION # DEAL_II_SETUP_DEFAULT_COMPILER_FLAGS # DEAL_II_SETUP_COVERAGE +# DEAL_II_UNITY_BUILD # BUILD_SHARED_LIBS # DEAL_II_PREFER_STATIC_LIBS # DEAL_II_STATIC_EXECUTABLE @@ -158,6 +159,11 @@ OPTION(DEAL_II_SETUP_COVERAGE ) MARK_AS_ADVANCED(DEAL_II_SETUP_COVERAGE) +OPTION(DEAL_II_UNITY_BUILD + "Compile the library by concatenating together source files to form a few large targets instead of many small ones. This lowers total compilation wall time by about 25%." + OFF) +MARK_AS_ADVANCED(DEAL_II_UNITY_BUILD) + SET(BUILD_SHARED_LIBS "ON" CACHE BOOL "Build a shared library" ) diff --git a/doc/developers/cmake-internals.html b/doc/developers/cmake-internals.html index 827bca12a1..45ad8f7423 100644 --- a/doc/developers/cmake-internals.html +++ b/doc/developers/cmake-internals.html @@ -28,6 +28,7 @@
  • ./cmake/modules/Find*.cmake
  • ./cmake/configure/configure_*.cmake
  • Global variables controlling the build process
  • +
  • The unity build subsystem
  • Target definition and installation @@ -604,6 +605,30 @@ DEAL_II_FORCE_BUNDLED_<FEATURE> (an option)

    + +

    The unity build subsystem

    +

    + For a general description of this feature see + the deal.II Readme + entry. Many of the various CMakeLists.txt files split their + source files into two lists: one list of files that are relatively cheap to + compile, which are concatenated into the unity build files, and a list of + files that are more expensive to compile, which are not included in the unity + files. For example: most of the finite element classes take about 5-10 seconds + to compile while the FEValues instantiation files each take about + 60 seconds. In addition, many CMakeLists.txt files define a + variable _n_includes_per_unity_file which specifies how many + files should be concatenated into each unity file. +

    + +

    + A disadvantage to this approach is that it requires profiling the build in two + places: the time and memory usage of all source files must be measured and the + variable _n_includes_per_unity_file should be set so that the + unity build files are not overly expensive in terms of memory and wall + time. The current values were chosen so that the unity files, with GCC, + require about 30 to 60 seconds of wall time and about 2 GB of memory. +

    Target definition and installation

    diff --git a/doc/news/changes/major/20170720DavidWells b/doc/news/changes/major/20170720DavidWells new file mode 100644 index 0000000000..98f847952f --- /dev/null +++ b/doc/news/changes/major/20170720DavidWells @@ -0,0 +1,2 @@ +New: The cmake configuration now supports unity builds with the option -DDEAL_II_UNITY_BUILD=ON. This option speeds up the build by about 10 to 25%. +
    (David Wells, 2017/07/20) diff --git a/doc/readme.html b/doc/readme.html index 32468e0f8c..f85a0197fe 100644 --- a/doc/readme.html +++ b/doc/readme.html @@ -32,7 +32,8 @@
  • Configuring and building the documentation
  • Configuration options
      -
    1. Selecting optional behavior
    2. +
    3. Selecting optional compilation features
    4. +
    5. Selecting optional library features
    6. Optional interfaces to other software packages
    7. More information on configuring @@ -333,7 +334,7 @@
             cmake -DDEAL_II_COMPONENT_DOCUMENTATION=ON -DCMAKE_INSTALL_PREFIX=/path/install/dir ../deal.II
           
      - +

      For this to succeed, you will need Perl 5.x, @@ -342,7 +343,7 @@ the GraphViz package) to be installed.

      - +

      The documentation contains links to pictures (e.g., for the tutorial programs) that are by default stored online at the @@ -351,7 +352,7 @@ the contrib/utilities/makeofflinedoc.sh script in an installed documentation directory to download all images.

      - +

      Finally, the default for locally installed documentation is to render formulas as images. You can force formulas to be displayed via the MathJax system by @@ -398,8 +399,21 @@ options.

      + +

      Selecting optional compilation features

      +
        +

        +

      • Unity build: deal.II may be compiled with a unity build; + that is, one may configure the build process so that the library is + compiled as a few large files instead of many small ones. The unity + build feature may be enabled by passing + the -DDEAL_II_UNITY_BUILD=ON argument + to cmake. This feature is disabled by default. +

        +
      +
      -

      Selecting optional behavior

      +

      Selecting optional library features

      • @@ -543,7 +557,7 @@

        The GNU Scientific Library - provides a wide range of mathematical routines such as random number + provides a wide range of mathematical routines such as random number generators, special functions and least-squares fitting. GSL should be readily packaged by most Linux distributions. (Don't forget @@ -619,11 +633,11 @@ from the official website, as well as with the OpenCASCADE Community Edition (OCE, available at https://github.com/tpaviot/oce), - which offers a cmake + which offers a cmake interface for its compilation. Alternatively, you can install one of the many external applications that ship with - OpenCASCADE internally (for example - SALOME, or + OpenCASCADE internally (for example + SALOME, or FreeCAD). Further installation instructions can be found here. You might also be interested in - CMake for user projects or + CMake for user projects or build system internals.

        diff --git a/source/base/CMakeLists.txt b/source/base/CMakeLists.txt index 87cd9809bd..c90bce420c 100644 --- a/source/base/CMakeLists.txt +++ b/source/base/CMakeLists.txt @@ -15,7 +15,12 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) -SET(_src +# +# All source/base files are sufficiently small that they may be added to the +# unity build file (see the developer documentation on DEAL_II_UNITY_BUILD +# for more information). +# +SET(_unity_include_src auto_derivative_function.cc conditional_ostream.cc config.cc @@ -75,6 +80,18 @@ SET(_src utilities.cc ) +SET(_separate_src + ) + +# determined by profiling +SET(_n_includes_per_unity_file 29) + +SETUP_SOURCE_LIST("${_unity_include_src}" + "${_separate_src}" + ${_n_includes_per_unity_file} + _src + ) + SET(_inst data_out_base.inst.in function.inst.in diff --git a/source/distributed/CMakeLists.txt b/source/distributed/CMakeLists.txt index 40089416ed..56b6974b56 100644 --- a/source/distributed/CMakeLists.txt +++ b/source/distributed/CMakeLists.txt @@ -15,7 +15,7 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) -SET(_src +SET(_unity_include_src grid_refinement.cc solution_transfer.cc tria.cc @@ -24,6 +24,18 @@ SET(_src p4est_wrappers.cc ) +SET(_separate_src + ) + +# concatenate all unity inclusion files in one file +SET(_n_includes_per_unity_file 15) + +SETUP_SOURCE_LIST("${_unity_include_src}" + "${_separate_src}" + ${_n_includes_per_unity_file} + _src + ) + SET(_inst grid_refinement.inst.in solution_transfer.inst.in diff --git a/source/dofs/CMakeLists.txt b/source/dofs/CMakeLists.txt index 76543221fc..8262ccae60 100644 --- a/source/dofs/CMakeLists.txt +++ b/source/dofs/CMakeLists.txt @@ -15,20 +15,32 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) -SET(_src +SET(_unity_include_src block_info.cc + dof_faces.cc + dof_handler.cc + dof_objects.cc + number_cache.cc + ) + +SET(_separate_src dof_accessor.cc dof_accessor_get.cc dof_accessor_set.cc - dof_faces.cc - dof_handler.cc dof_handler_policy.cc - dof_objects.cc dof_renumbering.cc dof_tools.cc dof_tools_constraints.cc dof_tools_sparsity.cc - number_cache.cc + ) + +# concatenate all unity inclusion files in one file +SET(_n_includes_per_unity_file 15) + +SETUP_SOURCE_LIST("${_unity_include_src}" + "${_separate_src}" + ${_n_includes_per_unity_file} + _src ) SET(_inst diff --git a/source/fe/CMakeLists.txt b/source/fe/CMakeLists.txt index 6dc62593b5..b79cfdf5ea 100644 --- a/source/fe/CMakeLists.txt +++ b/source/fe/CMakeLists.txt @@ -15,7 +15,7 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) -SET(_src +SET(_unity_include_src block_mask.cc component_mask.cc fe_abf.cc @@ -47,16 +47,10 @@ SET(_src fe_system.cc fe_enriched.cc fe_tools.cc - fe_tools_interpolate.cc - fe_tools_extrapolate.cc fe_trace.cc - fe_values.cc - fe_values_inst2.cc mapping_c1.cc mapping_cartesian.cc mapping.cc - mapping_fe_field.cc - mapping_fe_field_inst2.cc mapping_q_generic.cc mapping_q1.cc mapping_q1_eulerian.cc @@ -65,6 +59,24 @@ SET(_src mapping_manifold.cc ) +SET(_separate_src + fe_values.cc + fe_values_inst2.cc + mapping_fe_field.cc + mapping_fe_field_inst2.cc + fe_tools_interpolate.cc + fe_tools_extrapolate.cc + ) + +# determined by profiling +SET(_n_includes_per_unity_file 15) + +SETUP_SOURCE_LIST("${_unity_include_src}" + "${_separate_src}" + ${_n_includes_per_unity_file} + _src + ) + SET(_inst fe_abf.inst.in fe_bdm.inst.in diff --git a/source/grid/CMakeLists.txt b/source/grid/CMakeLists.txt index 159cc9ab53..625ec7eb06 100644 --- a/source/grid/CMakeLists.txt +++ b/source/grid/CMakeLists.txt @@ -15,14 +15,13 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) -SET(_src +SET(_unity_include_src cell_id.cc grid_generator.cc grid_in.cc grid_out.cc grid_refinement.cc grid_reordering.cc - grid_tools.cc intergrid_map.cc manifold.cc manifold_lib.cc @@ -30,12 +29,25 @@ SET(_src tria_accessor.cc tria_boundary.cc tria_boundary_lib.cc - tria.cc tria_faces.cc tria_levels.cc tria_objects.cc ) +SET(_separate_src + grid_tools.cc + tria.cc + ) + +# include all files in the unity file +SET(_n_includes_per_unity_file 20) + +SETUP_SOURCE_LIST("${_unity_include_src}" + "${_separate_src}" + ${_n_includes_per_unity_file} + _src + ) + SET(_inst cell_id.inst.in grid_generator.inst.in diff --git a/source/hp/CMakeLists.txt b/source/hp/CMakeLists.txt index 8013a22e4d..be6f74b701 100644 --- a/source/hp/CMakeLists.txt +++ b/source/hp/CMakeLists.txt @@ -15,15 +15,27 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) -SET(_src +SET(_unity_include_src dof_faces.cc - dof_handler.cc dof_level.cc fe_collection.cc fe_values.cc mapping_collection.cc ) +SET(_separate_src + dof_handler.cc + ) + +# concatenate all unity inclusion files in one file +SET(_n_includes_per_unity_file 15) + +SETUP_SOURCE_LIST("${_unity_include_src}" + "${_separate_src}" + ${_n_includes_per_unity_file} + _src + ) + SET(_inst dof_handler.inst.in fe_collection.inst.in diff --git a/source/lac/CMakeLists.txt b/source/lac/CMakeLists.txt index 3c6dba8d11..60f6fdea1b 100644 --- a/source/lac/CMakeLists.txt +++ b/source/lac/CMakeLists.txt @@ -15,7 +15,7 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) -SET(_src +SET(_unity_include_src block_matrix_array.cc block_sparse_matrix.cc block_sparse_matrix_ez.cc @@ -42,8 +42,6 @@ SET(_src sparse_decomposition.cc sparse_direct.cc sparse_ilu.cc - sparse_matrix.cc - sparse_matrix_inst2.cc sparse_matrix_ez.cc sparse_mic.cc sparse_vanka.cc @@ -56,6 +54,11 @@ SET(_src vector_view.cc ) +SET(_separate_src + sparse_matrix.cc + sparse_matrix_inst2.cc + ) + SET(_inst block_sparse_matrix.inst.in block_vector.inst.in @@ -78,12 +81,13 @@ SET(_inst vector_view.inst.in ) + # Add PETSc wrapper files. If PETSc has not been found, # then these files should be empty and there is no need # to even look at them IF(DEAL_II_WITH_PETSC) - SET(_src - ${_src} + SET(_unity_include_src + ${_unity_include_src} petsc_full_matrix.cc petsc_matrix_base.cc petsc_matrix_free.cc @@ -100,8 +104,8 @@ ENDIF() # Same for SLEPc IF(DEAL_II_WITH_SLEPC) - SET(_src - ${_src} + SET(_unity_include_src + ${_unity_include_src} slepc_solver.cc slepc_spectral_transformation.cc ) @@ -109,20 +113,25 @@ ENDIF() # Also add Trilinos wrapper files IF(DEAL_II_WITH_TRILINOS) - SET(_src - ${_src} + SET(_unity_include_src + ${_unity_include_src} trilinos_block_sparse_matrix.cc trilinos_block_vector.cc trilinos_epetra_communication_pattern.cc trilinos_epetra_vector.cc trilinos_precondition.cc trilinos_precondition_ml.cc - trilinos_precondition_muelu.cc trilinos_solver.cc trilinos_sparse_matrix.cc trilinos_sparsity_pattern.cc trilinos_vector.cc ) + + SET(_separate_src + ${_separate_src} + trilinos_precondition_muelu.cc + ) + SET(_inst ${_inst} trilinos_sparse_matrix.inst.in @@ -132,13 +141,25 @@ ENDIF() # Add CUDA wrapper files IF(DEAL_II_WITH_CUDA) - SET(_src - ${_src} + SET(_separate_src + ${_separate_src} cuda_vector.cu ) ENDIF() +# determined by profiling +SET(_n_includes_per_unity_file 30) +IF(DEAL_II_UNITY_BUILD) + # sort files so that the petsc and trilinos files are not together + LIST(SORT _unity_include_src) +ENDIF() + +SETUP_SOURCE_LIST("${_unity_include_src}" + "${_separate_src}" + ${_n_includes_per_unity_file} + _src + ) FILE(GLOB _header ${CMAKE_SOURCE_DIR}/include/deal.II/lac/*.h diff --git a/source/multigrid/CMakeLists.txt b/source/multigrid/CMakeLists.txt index 1e35d202d3..e5bfeeed82 100644 --- a/source/multigrid/CMakeLists.txt +++ b/source/multigrid/CMakeLists.txt @@ -15,18 +15,30 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) -SET(_src +SET(_unity_include_src mg_base.cc mg_level_global_transfer.cc - mg_tools.cc mg_transfer_block.cc mg_transfer_component.cc mg_transfer_internal.cc - mg_transfer_matrix_free.cc mg_transfer_prebuilt.cc multigrid.cc ) +SET(_separate_src + mg_tools.cc + mg_transfer_matrix_free.cc + ) + +# concatenate all unity inclusion files in one file +SET(_n_includes_per_unity_file 15) + +SETUP_SOURCE_LIST("${_unity_include_src}" + "${_separate_src}" + ${_n_includes_per_unity_file} + _src + ) + SET(_inst mg_base.inst.in mg_level_global_transfer.inst.in diff --git a/source/numerics/CMakeLists.txt b/source/numerics/CMakeLists.txt index 85bbf2fabc..8de366e960 100644 --- a/source/numerics/CMakeLists.txt +++ b/source/numerics/CMakeLists.txt @@ -15,39 +15,43 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) -SET(_src +SET(_unity_include_src data_out.cc - data_out_dof_data.cc - data_out_dof_data_codim.cc data_out_faces.cc - data_out_rotation.cc data_out_stack.cc + data_out_rotation.cc data_postprocessor.cc - derivative_approximation.cc dof_output_operator.cc + histogram.cc + matrix_tools_once.cc + matrix_tools.cc + time_dependent.cc + vector_tools_boundary.cc + vector_tools_constraints.cc + vector_tools_mean_value.cc + vector_tools_point_gradient.cc + vector_tools_rhs.cc + ) + +SET(_separate_src + data_out_dof_data.cc + data_out_dof_data_codim.cc + derivative_approximation.cc error_estimator_1d.cc error_estimator.cc error_estimator_inst2.cc fe_field_function.cc - histogram.cc matrix_creator.cc matrix_creator_inst2.cc matrix_creator_inst3.cc - matrix_tools_once.cc - matrix_tools.cc point_value_history.cc solution_transfer.cc solution_transfer_inst2.cc solution_transfer_inst3.cc solution_transfer_inst4.cc - time_dependent.cc - vector_tools_boundary.cc - vector_tools_constraints.cc vector_tools_integrate_difference.cc vector_tools_interpolate.cc - vector_tools_mean_value.cc vector_tools_point_value.cc - vector_tools_point_gradient.cc vector_tools_project.cc vector_tools_project_inst2.cc vector_tools_project_inst3.cc @@ -55,7 +59,15 @@ SET(_src vector_tools_project_codim.cc vector_tools_project_qp.cc vector_tools_project_qpmf.cc - vector_tools_rhs.cc + ) + +# determined by profiling +SET(_n_includes_per_unity_file 8) + +SETUP_SOURCE_LIST("${_unity_include_src}" + "${_separate_src}" + ${_n_includes_per_unity_file} + _src ) SET(_inst -- 2.39.5