generate_template_specializations.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. # Ceres Solver - A fast non-linear least squares minimizer
  2. # Copyright 2015 Google Inc. All rights reserved.
  3. # http://ceres-solver.org/
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions are met:
  7. #
  8. # * Redistributions of source code must retain the above copyright notice,
  9. # this list of conditions and the following disclaimer.
  10. # * Redistributions in binary form must reproduce the above copyright notice,
  11. # this list of conditions and the following disclaimer in the documentation
  12. # and/or other materials provided with the distribution.
  13. # * Neither the name of Google Inc. nor the names of its contributors may be
  14. # used to endorse or promote products derived from this software without
  15. # specific prior written permission.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. # POSSIBILITY OF SUCH DAMAGE.
  28. #
  29. # Author: sameeragarwal@google.com (Sameer Agarwal)
  30. #
  31. # Script for explicitly generating template specialization of the
  32. # SchurEliminator class. It is a rather large class
  33. # and the number of explicit instantiations is also large. Explicitly
  34. # generating these instantiations in separate .cc files breaks the
  35. # compilation into separate compilation unit rather than one large cc
  36. # file which takes 2+GB of RAM to compile.
  37. #
  38. # This script creates three sets of files.
  39. #
  40. # 1. schur_eliminator_x_x_x.cc and partitioned_matrix_view_x_x_x.cc
  41. # where, the x indicates the template parameters and
  42. #
  43. # 2. schur_eliminator.cc & partitioned_matrix_view.cc
  44. #
  45. # that contains a factory function for instantiating these classes
  46. # based on runtime parameters.
  47. #
  48. # 3. schur_templates.cc
  49. #
  50. # that contains a function which can be queried to determine what
  51. # template specializations are available.
  52. #
  53. # The following list of tuples, specializations indicates the set of
  54. # specializations that is generated.
  55. SPECIALIZATIONS = [(2, 2, 2),
  56. (2, 2, 3),
  57. (2, 2, 4),
  58. (2, 2, "Eigen::Dynamic"),
  59. (2, 3, 3),
  60. (2, 3, 4),
  61. (2, 3, 6),
  62. (2, 3, 9),
  63. (2, 3, "Eigen::Dynamic"),
  64. (2, 4, 3),
  65. (2, 4, 4),
  66. (2, 4, 6),
  67. (2, 4, 8),
  68. (2, 4, 9),
  69. (2, 4, "Eigen::Dynamic"),
  70. (2, "Eigen::Dynamic", "Eigen::Dynamic"),
  71. (3, 3, 3),
  72. (4, 4, 2),
  73. (4, 4, 3),
  74. (4, 4, 4),
  75. (4, 4, "Eigen::Dynamic")]
  76. import schur_eliminator_template
  77. import partitioned_matrix_view_template
  78. import os
  79. import glob
  80. def SuffixForSize(size):
  81. if size == "Eigen::Dynamic":
  82. return "d"
  83. return str(size)
  84. def SpecializationFilename(prefix, row_block_size, e_block_size, f_block_size):
  85. return "_".join([prefix] + list(map(SuffixForSize, (row_block_size,
  86. e_block_size,
  87. f_block_size))))
  88. def GenerateFactoryConditional(row_block_size, e_block_size, f_block_size):
  89. conditionals = []
  90. if (row_block_size != "Eigen::Dynamic"):
  91. conditionals.append("(options.row_block_size == %s)" % row_block_size)
  92. if (e_block_size != "Eigen::Dynamic"):
  93. conditionals.append("(options.e_block_size == %s)" % e_block_size)
  94. if (f_block_size != "Eigen::Dynamic"):
  95. conditionals.append("(options.f_block_size == %s)" % f_block_size)
  96. if (len(conditionals) == 0):
  97. return "%s"
  98. if (len(conditionals) == 1):
  99. return " if " + conditionals[0] + " {\n %s\n }\n"
  100. return " if (" + " &&\n ".join(conditionals) + ") {\n %s\n }\n"
  101. def Specialize(name, data):
  102. """
  103. Generate specialization code and the conditionals to instantiate it.
  104. """
  105. # Specialization files
  106. for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS:
  107. output = SpecializationFilename("generated/" + name,
  108. row_block_size,
  109. e_block_size,
  110. f_block_size) + ".cc"
  111. with open(output, "w") as f:
  112. f.write(data["HEADER"])
  113. f.write(data["SPECIALIZATION_FILE"] %
  114. (row_block_size, e_block_size, f_block_size))
  115. # Generate the _d_d_d specialization.
  116. output = SpecializationFilename("generated/" + name,
  117. "Eigen::Dynamic",
  118. "Eigen::Dynamic",
  119. "Eigen::Dynamic") + ".cc"
  120. with open(output, "w") as f:
  121. f.write(data["HEADER"])
  122. f.write(data["DYNAMIC_FILE"] %
  123. ("Eigen::Dynamic", "Eigen::Dynamic", "Eigen::Dynamic"))
  124. # Factory
  125. with open(name + ".cc", "w") as f:
  126. f.write(data["HEADER"])
  127. f.write(data["FACTORY_FILE_HEADER"])
  128. for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS:
  129. factory_conditional = GenerateFactoryConditional(
  130. row_block_size, e_block_size, f_block_size)
  131. factory = data["FACTORY"] % (row_block_size, e_block_size, f_block_size)
  132. f.write(factory_conditional % factory);
  133. f.write(data["FACTORY_FOOTER"])
  134. QUERY_HEADER = """// Ceres Solver - A fast non-linear least squares minimizer
  135. // Copyright 2017 Google Inc. All rights reserved.
  136. // http://ceres-solver.org/
  137. //
  138. // Redistribution and use in source and binary forms, with or without
  139. // modification, are permitted provided that the following conditions are met:
  140. //
  141. // * Redistributions of source code must retain the above copyright notice,
  142. // this list of conditions and the following disclaimer.
  143. // * Redistributions in binary form must reproduce the above copyright notice,
  144. // this list of conditions and the following disclaimer in the documentation
  145. // and/or other materials provided with the distribution.
  146. // * Neither the name of Google Inc. nor the names of its contributors may be
  147. // used to endorse or promote products derived from this software without
  148. // specific prior written permission.
  149. //
  150. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  151. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  152. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  153. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  154. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  155. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  156. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  157. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  158. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  159. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  160. // POSSIBILITY OF SUCH DAMAGE.
  161. //
  162. // Author: sameeragarwal@google.com (Sameer Agarwal)
  163. //
  164. // What template specializations are available.
  165. //
  166. // ========================================
  167. // THIS FILE IS AUTOGENERATED. DO NOT EDIT.
  168. // THIS FILE IS AUTOGENERATED. DO NOT EDIT.
  169. // THIS FILE IS AUTOGENERATED. DO NOT EDIT.
  170. // THIS FILE IS AUTOGENERATED. DO NOT EDIT.
  171. //=========================================
  172. //
  173. // This file is generated using generate_template_specializations.py.
  174. """
  175. QUERY_FILE_HEADER = """
  176. #include "ceres/internal/eigen.h"
  177. #include "ceres/schur_templates.h"
  178. namespace ceres {
  179. namespace internal {
  180. void GetBestSchurTemplateSpecialization(int* row_block_size,
  181. int* e_block_size,
  182. int* f_block_size) {
  183. LinearSolver::Options options;
  184. options.row_block_size = *row_block_size;
  185. options.e_block_size = *e_block_size;
  186. options.f_block_size = *f_block_size;
  187. *row_block_size = Eigen::Dynamic;
  188. *e_block_size = Eigen::Dynamic;
  189. *f_block_size = Eigen::Dynamic;
  190. #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
  191. """
  192. QUERY_FOOTER = """
  193. #endif
  194. return;
  195. }
  196. } // namespace internal
  197. } // namespace ceres
  198. """
  199. QUERY_ACTION = """ *row_block_size = %s;
  200. *e_block_size = %s;
  201. *f_block_size = %s;
  202. return;"""
  203. def GenerateQueryFile():
  204. """
  205. Generate file that allows querying for available template specializations.
  206. """
  207. with open("schur_templates.cc", "w") as f:
  208. f.write(QUERY_HEADER)
  209. f.write(QUERY_FILE_HEADER)
  210. for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS:
  211. factory_conditional = GenerateFactoryConditional(
  212. row_block_size, e_block_size, f_block_size)
  213. action = QUERY_ACTION % (row_block_size, e_block_size, f_block_size)
  214. f.write(factory_conditional % action)
  215. f.write(QUERY_FOOTER)
  216. if __name__ == "__main__":
  217. for f in glob.glob("generated/*"):
  218. os.remove(f)
  219. Specialize("schur_eliminator",
  220. schur_eliminator_template.__dict__)
  221. Specialize("partitioned_matrix_view",
  222. partitioned_matrix_view_template.__dict__)
  223. GenerateQueryFile()