view.cc 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // -*- mode: c++; coding: utf-8 -*-
  2. // ra-ra/examples - Operations with views, slicing
  3. // Daniel Llorens - 2015
  4. // Adapted from blitz++/examples/array.cpp
  5. // TODO Better traversal...
  6. #include <iomanip>
  7. #include <chrono>
  8. #include "ra/test.hh"
  9. using std::cout, std::endl, std::flush, ra::TestRecorder;
  10. auto now() { return std::chrono::high_resolution_clock::now(); }
  11. template <class DT> auto ms(DT && dt) { return std::chrono::duration_cast<std::chrono::milliseconds>(dt).count(); }
  12. int main()
  13. {
  14. int numIters = 301;
  15. int N = 64;
  16. ra::Big<float, 3> A({N, N, N}, ra::none);
  17. ra::Big<float, 3> B({N, N, N}, ra::none);
  18. auto interior = ra::iota(N/2, N/4);
  19. // Set up initial conditions: +30 C over an interior block, and +22 C elsewhere
  20. A = 22.;
  21. A(interior, interior, interior) = 30.;
  22. // Note that you don't really need separate I, J, K. You could just use I for every subscript.
  23. auto I = ra::iota(N-2, 1);
  24. auto J = ra::iota(N-2, 1);
  25. auto K = ra::iota(N-2, 1);
  26. // The views A(...) can be precomputed, but that's only useful if the subscripts are beatable.
  27. {
  28. std::chrono::duration<float> dt(0);
  29. double c = 1/6.5;
  30. for (int i=0; i<numIters; ++i) {
  31. auto t0 = now();
  32. B(I, J, K) = c * (.5 * A(I, J, K) + A(I+1, J, K) + A(I-1, J, K)
  33. + A(I, J+1, K) + A(I, J-1, K) + A(I, J, K+1) + A(I, J, K-1));
  34. A(I, J, K) = c * (.5 * B(I, J, K) + B(I+1, J, K) + B(I-1, J, K)
  35. + B(I, J+1, K) + B(I, J-1, K) + B(I, J, K+1) + B(I, J, K-1));
  36. dt += (now()-t0);
  37. // Output the result along a line through the centre
  38. std::println(cout, "{:n:.4f}", A(N/2, N/2, ra::iota(8, 0, N/8)));
  39. }
  40. std::println(cout, "{:10f} ms/iter", (ms(dt)/double(numIters)));
  41. }
  42. ra::Big<float, 3> first_A = A;
  43. A = 22.;
  44. A(interior, interior, interior) = 30.;
  45. // These are always beatable, as well as I+1 and I-1.
  46. auto Im = ra::iota(N-2, 0);
  47. auto Ip = ra::iota(N-2, 2);
  48. {
  49. std::chrono::duration<float> dt(0);
  50. double c = 1/6.5;
  51. for (int i=0; i<numIters; ++i) {
  52. auto t0 = now();
  53. B(I, I, I) = c * (.5 * A(I, I, I) + A(Ip, I, I) + A(Im, I, I)
  54. + A(I, Ip, I) + A(I, Im, I) + A(I, I, Ip) + A(I, I, Im));
  55. A(I, I, I) = c * (.5 * B(I, I, I) + B(Ip, I, I) + B(Im, I, I)
  56. + B(I, Ip, I) + B(I, Im, I) + B(I, I, Ip) + B(I, I, Im));
  57. dt += (now()-t0);
  58. // Output the result along a line through the centre
  59. std::println(cout, "{:n:.4f}", A(N/2, N/2, ra::iota(8, 0, N/8)));
  60. }
  61. std::println(cout, "{:10f} ms/iter", (ms(dt)/double(numIters)));
  62. }
  63. TestRecorder tr(std::cout);
  64. tr.quiet().test_rel(first_A, A, 0.);
  65. return tr.summary();
  66. }