timeMatrixOps.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /* ----------------------------------------------------------------------------
  2. * GTSAM Copyright 2010, Georgia Tech Research Corporation,
  3. * Atlanta, Georgia 30332-0415
  4. * All Rights Reserved
  5. * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
  6. * See LICENSE for the license information
  7. * -------------------------------------------------------------------------- */
  8. /**
  9. * @file timeublas.cpp
  10. * @brief Tests to help determine which way of accomplishing something with Eigen is faster
  11. * @author Richard Roberts
  12. * @date Sep 18, 2010
  13. */
  14. #include <boost/format.hpp>
  15. #include <boost/lambda/lambda.hpp>
  16. #include <gtsam/base/timing.h>
  17. #include <gtsam/base/Matrix.h>
  18. #include <iostream>
  19. #include <random>
  20. #include <vector>
  21. #include <utility>
  22. using namespace std;
  23. //namespace ublas = boost::numeric::ublas;
  24. //using namespace Eigen;
  25. using boost::format;
  26. using namespace boost::lambda;
  27. static std::mt19937 rng;
  28. static std::uniform_real_distribution<> uniform(-1.0, 0.0);
  29. //typedef ublas::matrix<double> matrix;
  30. //typedef ublas::matrix_range<matrix> matrix_range;
  31. //typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> matrix;
  32. //typedef Eigen::Block<matrix> matrix_block;
  33. //using ublas::range;
  34. //using ublas::triangular_matrix;
  35. int main(int argc, char* argv[]) {
  36. if(true) {
  37. cout << "\nTiming matrix_block:" << endl;
  38. // We use volatile here to make these appear to the optimizing compiler as
  39. // if their values are only known at run-time.
  40. volatile size_t m=500;
  41. volatile size_t n=300;
  42. volatile size_t nReps = 1000;
  43. assert(m > n);
  44. std::uniform_int_distribution<size_t> uniform_i(0,m-1);
  45. std::uniform_int_distribution<size_t> uniform_j(0,n-1);
  46. gtsam::Matrix mat((int)m,(int)n);
  47. gtsam::SubMatrix full = mat.block(0, 0, m, n);
  48. gtsam::SubMatrix top = mat.block(0, 0, n, n);
  49. gtsam::SubMatrix block = mat.block(m/4, n/4, m-m/2, n-n/2);
  50. cout << format(" Basic: %1%x%2%\n") % (int)m % (int)n;
  51. cout << format(" Full: mat(%1%:%2%, %3%:%4%)\n") % 0 % (int)m % 0 % (int)n;
  52. cout << format(" Top: mat(%1%:%2%, %3%:%4%)\n") % 0 % (int)n % 0 % (int)n;
  53. cout << format(" Block: mat(%1%:%2%, %3%:%4%)\n") % size_t(m/4) % size_t(m-m/4) % size_t(n/4) % size_t(n-n/4);
  54. cout << endl;
  55. {
  56. double basicTime, fullTime, topTime, blockTime;
  57. cout << "Row-major matrix, row-major assignment:" << endl;
  58. // Do a few initial assignments to let any cache effects stabilize
  59. for(size_t rep=0; rep<1000; ++rep)
  60. for(size_t i=0; i<(size_t)mat.rows(); ++i)
  61. for(size_t j=0; j<(size_t)mat.cols(); ++j)
  62. mat(i,j) = uniform(rng);
  63. gttic_(basicTime);
  64. for(size_t rep=0; rep<nReps; ++rep)
  65. for(size_t i=0; i<(size_t)mat.rows(); ++i)
  66. for(size_t j=0; j<(size_t)mat.cols(); ++j)
  67. mat(i,j) = uniform(rng);
  68. gttoc_(basicTime);
  69. tictoc_getNode(basicTimeNode, basicTime);
  70. basicTime = basicTimeNode->secs();
  71. gtsam::tictoc_reset_();
  72. cout << format(" Basic: %1% mus/element") % double(1000000 * basicTime / double(mat.rows()*mat.cols()*nReps)) << endl;
  73. gttic_(fullTime);
  74. for(size_t rep=0; rep<nReps; ++rep)
  75. for(size_t i=0; i<(size_t)full.rows(); ++i)
  76. for(size_t j=0; j<(size_t)full.cols(); ++j)
  77. full(i,j) = uniform(rng);
  78. gttoc_(fullTime);
  79. tictoc_getNode(fullTimeNode, fullTime);
  80. fullTime = fullTimeNode->secs();
  81. gtsam::tictoc_reset_();
  82. cout << format(" Full: %1% mus/element") % double(1000000 * fullTime / double(full.rows()*full.cols()*nReps)) << endl;
  83. gttic_(topTime);
  84. for(size_t rep=0; rep<nReps; ++rep)
  85. for(size_t i=0; i<(size_t)top.rows(); ++i)
  86. for(size_t j=0; j<(size_t)top.cols(); ++j)
  87. top(i,j) = uniform(rng);
  88. gttoc_(topTime);
  89. tictoc_getNode(topTimeNode, topTime);
  90. topTime = topTimeNode->secs();
  91. gtsam::tictoc_reset_();
  92. cout << format(" Top: %1% mus/element") % double(1000000 * topTime / double(top.rows()*top.cols()*nReps)) << endl;
  93. gttic_(blockTime);
  94. for(size_t rep=0; rep<nReps; ++rep)
  95. for(size_t i=0; i<(size_t)block.rows(); ++i)
  96. for(size_t j=0; j<(size_t)block.cols(); ++j)
  97. block(i,j) = uniform(rng);
  98. gttoc_(blockTime);
  99. tictoc_getNode(blockTimeNode, blockTime);
  100. blockTime = blockTimeNode->secs();
  101. gtsam::tictoc_reset_();
  102. cout << format(" Block: %1% mus/element") % double(1000000 * blockTime / double(block.rows()*block.cols()*nReps)) << endl;
  103. cout << endl;
  104. }
  105. {
  106. double basicTime, fullTime, topTime, blockTime;
  107. cout << "Row-major matrix, column-major assignment:" << endl;
  108. // Do a few initial assignments to let any cache effects stabilize
  109. for(size_t rep=0; rep<1000; ++rep)
  110. for(size_t j=0; j<(size_t)mat.cols(); ++j)
  111. for(size_t i=0; i<(size_t)mat.rows(); ++i)
  112. mat(i,j) = uniform(rng);
  113. gttic_(basicTime);
  114. for(size_t rep=0; rep<nReps; ++rep)
  115. for(size_t j=0; j<(size_t)mat.cols(); ++j)
  116. for(size_t i=0; i<(size_t)mat.rows(); ++i)
  117. mat(i,j) = uniform(rng);
  118. gttoc_(basicTime);
  119. tictoc_getNode(basicTimeNode, basicTime);
  120. basicTime = basicTimeNode->secs();
  121. gtsam::tictoc_reset_();
  122. cout << format(" Basic: %1% mus/element") % double(1000000 * basicTime / double(mat.rows()*mat.cols()*nReps)) << endl;
  123. gttic_(fullTime);
  124. for(size_t rep=0; rep<nReps; ++rep)
  125. for(size_t j=0; j<(size_t)full.cols(); ++j)
  126. for(size_t i=0; i<(size_t)full.rows(); ++i)
  127. full(i,j) = uniform(rng);
  128. gttoc_(fullTime);
  129. tictoc_getNode(fullTimeNode, fullTime);
  130. fullTime = fullTimeNode->secs();
  131. gtsam::tictoc_reset_();
  132. cout << format(" Full: %1% mus/element") % double(1000000 * fullTime / double(full.rows()*full.cols()*nReps)) << endl;
  133. gttic_(topTime);
  134. for(size_t rep=0; rep<nReps; ++rep)
  135. for(size_t j=0; j<(size_t)top.cols(); ++j)
  136. for(size_t i=0; i<(size_t)top.rows(); ++i)
  137. top(i,j) = uniform(rng);
  138. gttoc_(topTime);
  139. tictoc_getNode(topTimeNode, topTime);
  140. topTime = topTimeNode->secs();
  141. gtsam::tictoc_reset_();
  142. cout << format(" Top: %1% mus/element") % double(1000000 * topTime / double(top.rows()*top.cols()*nReps)) << endl;
  143. gttic_(blockTime);
  144. for(size_t rep=0; rep<nReps; ++rep)
  145. for(size_t j=0; j<(size_t)block.cols(); ++j)
  146. for(size_t i=0; i<(size_t)block.rows(); ++i)
  147. block(i,j) = uniform(rng);
  148. gttoc_(blockTime);
  149. tictoc_getNode(blockTimeNode, blockTime);
  150. blockTime = blockTimeNode->secs();
  151. gtsam::tictoc_reset_();
  152. cout << format(" Block: %1% mus/element") % double(1000000 * blockTime / double(block.rows()*block.cols()*nReps)) << endl;
  153. cout << endl;
  154. }
  155. {
  156. double basicTime, fullTime, topTime, blockTime;
  157. typedef pair<size_t,size_t> ij_t;
  158. vector<ij_t> ijs(100000);
  159. cout << "Row-major matrix, random assignment:" << endl;
  160. // Do a few initial assignments to let any cache effects stabilize
  161. for_each(ijs.begin(), ijs.end(), _1 = make_pair(uniform_i(rng),uniform_j(rng)));
  162. for(size_t rep=0; rep<1000; ++rep)
  163. for(const ij_t& ij: ijs) { mat(ij.first, ij.second) = uniform(rng); }
  164. gttic_(basicTime);
  165. for_each(ijs.begin(), ijs.end(), _1 = make_pair(uniform_i(rng),uniform_j(rng)));
  166. for(size_t rep=0; rep<1000; ++rep)
  167. for(const ij_t& ij: ijs) { mat(ij.first, ij.second) = uniform(rng); }
  168. gttoc_(basicTime);
  169. tictoc_getNode(basicTimeNode, basicTime);
  170. basicTime = basicTimeNode->secs();
  171. gtsam::tictoc_reset_();
  172. cout << format(" Basic: %1% mus/element") % double(1000000 * basicTime / double(ijs.size()*nReps)) << endl;
  173. gttic_(fullTime);
  174. for_each(ijs.begin(), ijs.end(), _1 = make_pair(uniform_i(rng),uniform_j(rng)));
  175. for(size_t rep=0; rep<1000; ++rep)
  176. for(const ij_t& ij: ijs) { full(ij.first, ij.second) = uniform(rng); }
  177. gttoc_(fullTime);
  178. tictoc_getNode(fullTimeNode, fullTime);
  179. fullTime = fullTimeNode->secs();
  180. gtsam::tictoc_reset_();
  181. cout << format(" Full: %1% mus/element") % double(1000000 * fullTime / double(ijs.size()*nReps)) << endl;
  182. gttic_(topTime);
  183. for_each(ijs.begin(), ijs.end(), _1 = make_pair(uniform_i(rng)%top.rows(),uniform_j(rng)));
  184. for(size_t rep=0; rep<1000; ++rep)
  185. for(const ij_t& ij: ijs) { top(ij.first, ij.second) = uniform(rng); }
  186. gttoc_(topTime);
  187. tictoc_getNode(topTimeNode, topTime);
  188. topTime = topTimeNode->secs();
  189. gtsam::tictoc_reset_();
  190. cout << format(" Top: %1% mus/element") % double(1000000 * topTime / double(ijs.size()*nReps)) << endl;
  191. gttic_(blockTime);
  192. for_each(ijs.begin(), ijs.end(), _1 = make_pair(uniform_i(rng)%block.rows(),uniform_j(rng)%block.cols()));
  193. for(size_t rep=0; rep<1000; ++rep)
  194. for(const ij_t& ij: ijs) { block(ij.first, ij.second) = uniform(rng); }
  195. gttoc_(blockTime);
  196. tictoc_getNode(blockTimeNode, blockTime);
  197. blockTime = blockTimeNode->secs();
  198. gtsam::tictoc_reset_();
  199. cout << format(" Block: %1% mus/element") % double(1000000 * blockTime / double(ijs.size()*nReps)) << endl;
  200. cout << endl;
  201. }
  202. }
  203. // if(true) {
  204. // cout << "\nTesting square triangular matrices:" << endl;
  205. //
  206. //// typedef triangular_matrix<double, ublas::upper, ublas::column_major> triangular;
  207. //// typedef ublas::matrix<double, ublas::column_major> matrix;
  208. // typedef MatrixXd matrix; // default col major
  209. //
  210. //// triangular tri(5,5);
  211. //
  212. // matrix mat(5,5);
  213. // for(size_t j=0; j<(size_t)mat.cols(); ++j)
  214. // for(size_t i=0; i<(size_t)mat.rows(); ++i)
  215. // mat(i,j) = uniform(rng);
  216. //
  217. // tri = ublas::triangular_adaptor<matrix, ublas::upper>(mat);
  218. // cout << " Assigned from triangular adapter: " << tri << endl;
  219. //
  220. // cout << " Triangular adapter of mat: " << ublas::triangular_adaptor<matrix, ublas::upper>(mat) << endl;
  221. //
  222. // for(size_t j=0; j<(size_t)mat.cols(); ++j)
  223. // for(size_t i=0; i<(size_t)mat.rows(); ++i)
  224. // mat(i,j) = uniform(rng);
  225. // mat = tri;
  226. // cout << " Assign matrix from triangular: " << mat << endl;
  227. //
  228. // for(size_t j=0; j<(size_t)mat.cols(); ++j)
  229. // for(size_t i=0; i<(size_t)mat.rows(); ++i)
  230. // mat(i,j) = uniform(rng);
  231. // (ublas::triangular_adaptor<matrix, ublas::upper>(mat)) = tri;
  232. // cout << " Assign triangular adaptor from triangular: " << mat << endl;
  233. // }
  234. // {
  235. // cout << "\nTesting wide triangular matrices:" << endl;
  236. //
  237. // typedef triangular_matrix<double, ublas::upper, ublas::column_major> triangular;
  238. // typedef ublas::matrix<double, ublas::column_major> matrix;
  239. //
  240. // triangular tri(5,7);
  241. //
  242. // matrix mat(5,7);
  243. // for(size_t j=0; j<(size_t)mat.cols(); ++j)
  244. // for(size_t i=0; i<(size_t)mat.rows(); ++i)
  245. // mat(i,j) = uniform(rng);
  246. //
  247. // tri = ublas::triangular_adaptor<matrix, ublas::upper>(mat);
  248. // cout << " Assigned from triangular adapter: " << tri << endl;
  249. //
  250. // cout << " Triangular adapter of mat: " << ublas::triangular_adaptor<matrix, ublas::upper>(mat) << endl;
  251. //
  252. // for(size_t j=0; j<(size_t)mat.cols(); ++j)
  253. // for(size_t i=0; i<(size_t)mat.rows(); ++i)
  254. // mat(i,j) = uniform(rng);
  255. // mat = tri;
  256. // cout << " Assign matrix from triangular: " << mat << endl;
  257. //
  258. // for(size_t j=0; j<(size_t)mat.cols(); ++j)
  259. // for(size_t i=0; i<(size_t)mat.rows(); ++i)
  260. // mat(i,j) = uniform(rng);
  261. // mat = ublas::triangular_adaptor<matrix, ublas::upper>(mat);
  262. // cout << " Assign matrix from triangular adaptor of self: " << mat << endl;
  263. // }
  264. // {
  265. // cout << "\nTesting subvectors:" << endl;
  266. //
  267. // typedef MatrixXd matrix;
  268. // matrix mat(4,4);
  269. //
  270. // for(size_t j=0; j<(size_t)mat.cols(); ++j)
  271. // for(size_t i=0; i<(size_t)mat.rows(); ++i)
  272. // mat(i,j) = i*mat.rows() + j;
  273. // cout << " mat = " << mat;
  274. //
  275. // cout << " vec(1:4, 2:2) = " << mat.block(1,2, ), ublas::range(1,4), ublas::range(2,2));
  276. //
  277. // }
  278. return 0;
  279. }