| | 13 | |
| | 14 | class JacobiCellSimple |
| | 15 | { |
| | 16 | public: |
| | 17 | typedef Stencils::VonNeumann<3, 1> Stencil; |
| | 18 | typedef Topologies::Cube<3>::Topology Topology; |
| | 19 | |
| | 20 | class API : public CellAPITraits::Fixed |
| | 21 | {}; |
| | 22 | |
| | 23 | JacobiCellSimple(double t = 0) : |
| | 24 | temp(t) |
| | 25 | {} |
| | 26 | |
| | 27 | static int nanoSteps() |
| | 28 | { |
| | 29 | return 1; |
| | 30 | } |
| | 31 | |
| | 32 | template<typename NEIGHBORHOOD> |
| | 33 | void update(const NEIGHBORHOOD& hood, int /* nanoStep */) |
| | 34 | { |
| | 35 | temp = (hood[FixedCoord<0, 0, -1>()].temp + |
| | 36 | hood[FixedCoord<0, -1, 0>()].temp + |
| | 37 | hood[FixedCoord<1, 0, 0>()].temp + |
| | 38 | hood[FixedCoord<0, 0, 0>()].temp + |
| | 39 | hood[FixedCoord<1, 0, 0>()].temp + |
| | 40 | hood[FixedCoord<0, 1, 0>()].temp + |
| | 41 | hood[FixedCoord<0, 0, 1>()].temp) * (1.0 / 7.0); |
| | 42 | } |
| | 43 | |
| | 44 | double temp; |
| | 45 | }; |
| | 46 | |
| | 47 | class JacobiCellMagic |
| | 48 | { |
| | 49 | public: |
| | 50 | typedef Stencils::VonNeumann<3, 1> Stencil; |
| | 51 | typedef Topologies::Cube<3>::Topology Topology; |
| | 52 | |
| | 53 | class API : public CellAPITraits::Fixed, public CellAPITraits::Line |
| | 54 | {}; |
| | 55 | |
| | 56 | JacobiCellMagic(double t = 0) : |
| | 57 | temp(t) |
| | 58 | {} |
| | 59 | |
| | 60 | static int nanoSteps() |
| | 61 | { |
| | 62 | return 1; |
| | 63 | } |
| | 64 | |
| | 65 | template<typename NEIGHBORHOOD> |
| | 66 | void update(const NEIGHBORHOOD& hood, int /* nanoStep */) |
| | 67 | { |
| | 68 | temp = (hood[FixedCoord<0, 0, -1>()].temp + |
| | 69 | hood[FixedCoord<0, -1, 0>()].temp + |
| | 70 | hood[FixedCoord<1, 0, 0>()].temp + |
| | 71 | hood[FixedCoord<0, 0, 0>()].temp + |
| | 72 | hood[FixedCoord<1, 0, 0>()].temp + |
| | 73 | hood[FixedCoord<0, 1, 0>()].temp + |
| | 74 | hood[FixedCoord<0, 0, 1>()].temp) * (1.0 / 7.0); |
| | 75 | } |
| | 76 | |
| | 77 | template<typename NEIGHBORHOOD> |
| | 78 | static void updateLine(JacobiCellMagic *target, long *x, long endX, const NEIGHBORHOOD& hood, int /* nanoStep */) |
| | 79 | { |
| | 80 | for (; *x < endX; ++*x) { |
| | 81 | target[*x].update(hood, 0); |
| | 82 | } |
| | 83 | } |
| | 84 | |
| | 85 | double temp; |
| | 86 | }; |
| | 289 | template<class CELL> |
| | 290 | class MonoInitializer : public SimpleInitializer<CELL> |
| | 291 | { |
| | 292 | public: |
| | 293 | MonoInitializer(const Coord<3>& dim, int steps) : SimpleInitializer<CELL>(dim, steps) |
| | 294 | {} |
| | 295 | |
| | 296 | virtual void grid(GridBase<CELL, 3> *ret) |
| | 297 | { |
| | 298 | CoordBox<3> box = ret->boundingBox(); |
| | 299 | for (CoordBox<3>::Iterator i = box.begin(); i != box.end(); ++i) { |
| | 300 | ret->at(*i) = CELL(1.0); |
| | 301 | } |
| | 302 | ret->atEdge() = CELL(0.0); |
| | 303 | } |
| | 304 | }; |
| | 305 | |
| | 306 | template<class CELL> |
| | 307 | double singleBenchmark(Coord<3> dim) |
| | 308 | { |
| | 309 | int repeats = 50.0 * 1000 * 1000 / dim.prod(); |
| | 310 | repeats = std::max(repeats, 10); |
| | 311 | |
| | 312 | SerialSimulator<CELL> sim( |
| | 313 | new MonoInitializer<CELL>(dim, repeats)); |
| | 314 | // sim.addWriter(new TracingWriter<CELL>(500, repeats)); |
| | 315 | |
| | 316 | long long tBegin= Chronometer::timeUSec(); |
| | 317 | sim.run(); |
| | 318 | long long tEnd = Chronometer::timeUSec(); |
| | 319 | |
| | 320 | if (sim.getGrid()->at(Coord<3>(1, 1, 1)).temp == 4711) { |
| | 321 | std::cout << "this statement just serves to prevent the compiler from" |
| | 322 | << "optimizing away the loops above\n"; |
| | 323 | } |
| | 324 | |
| | 325 | double updates = 1.0 * repeats * (dim - Coord<3>::diagonal(2)).prod(); |
| | 326 | double seconds = (tEnd - tBegin) * 10e-6; |
| | 327 | double glups = 10e-9 * updates / seconds; |
| | 328 | |
| | 329 | return glups; |
| | 330 | } |
| | 331 | |
| | 332 | template<class CELL> |
| | 333 | void benchmark(std::string name) |
| | 334 | { |
| | 335 | std::cout << "Benchmarking " << name << "\n"; |
| | 336 | |
| | 337 | std::stringstream fileName; |
| | 338 | fileName << "data." << name << ".txt"; |
| | 339 | std::ofstream outfile(fileName.str().c_str()); |
| | 340 | outfile << "# BENCHMARK_ID MAXTRIX_SIZE GLUPS\n"; |
| | 341 | |
| | 342 | int maxI = 24; |
| | 343 | |
| | 344 | for (int i = 0; i < maxI; ++i) { |
| | 345 | int dim = std::pow(2, 4 + 0.25 * i); |
| | 346 | if (dim % 2) { |
| | 347 | ++dim; |
| | 348 | } |
| | 349 | |
| | 350 | double glups = singleBenchmark<CELL>(Coord<3>::diagonal(dim)); |
| | 351 | outfile << dim << " " << glups << "\n"; |
| | 352 | |
| | 353 | int percent = 100 * i / (maxI - 1); |
| | 354 | std::cout << std::setw(3) << percent << "%, dim = " << std::setw(3) << dim << ", " << glups << " GLUPS "; |
| | 355 | for (int dots = 0; dots < i; ++dots) { |
| | 356 | std::cout << "."; |
| | 357 | } |
| | 358 | std::cout.flush(); |
| | 359 | std::cout << "\r"; |
| | 360 | } |
| | 361 | |
| | 362 | std::cout << "\n"; |
| | 363 | } |
| | 364 | |
| 211 | | std::cout << "gogogo\n"; |
| 212 | | |
| 213 | | Coord<3> dim(128, 128, 128); |
| 214 | | |
| 215 | | { |
| 216 | | typedef Grid<JacobiCellStreakUpdate, JacobiCellStreakUpdate::Topology> GridType; |
| 217 | | GridType gridA(dim, 1.0); |
| 218 | | GridType gridB(dim, 2.0); |
| 219 | | GridType *gridOld = &gridA; |
| 220 | | GridType *gridNew = &gridB; |
| 221 | | |
| 222 | | int maxT = 2000; |
| 223 | | |
| 224 | | CoordBox<3> gridBox = gridA.boundingBox(); |
| 225 | | CoordBox<3> lineStarts = gridA.boundingBox(); |
| 226 | | lineStarts.dimensions.x() = 1; |
| 227 | | |
| 228 | | long long tBegin= Chronometer::timeUSec(); |
| 229 | | |
| 230 | | for (int t = 0; t < maxT; ++t) { |
| 231 | | for (CoordBox<3>::Iterator i = lineStarts.begin(); |
| 232 | | i != lineStarts.end(); |
| 233 | | ++i) { |
| 234 | | Streak<3> streak(*i, dim.x()); |
| 235 | | const JacobiCellStreakUpdate *pointers[JacobiCellStreakUpdate::Stencil::VOLUME]; |
| 236 | | LinePointerAssembly<JacobiCellStreakUpdate::Stencil>()(pointers, streak, *gridOld); |
| 237 | | LinePointerUpdateFunctor<JacobiCellStreakUpdate>()( |
| 238 | | streak, gridBox, pointers, &(*gridNew)[streak.origin], 0); |
| 239 | | } |
| 240 | | |
| 241 | | std::swap(gridOld, gridNew); |
| 242 | | } |
| 243 | | |
| 244 | | long long tEnd = Chronometer::timeUSec(); |
| 245 | | |
| 246 | | if (gridA[Coord<3>(1, 1, 1)].temp == 4711) { |
| 247 | | std::cout << "this statement just serves to prevent the compiler from" |
| 248 | | << "optimizing away the loops above\n"; |
| 249 | | } |
| 250 | | |
| 251 | | double updates = 1.0 * maxT * dim.prod(); |
| 252 | | double seconds = (tEnd - tBegin) * 10e-6; |
| 253 | | double gLUPS = 10e-9 * updates / seconds; |
| 254 | | |
| 255 | | std::cout << "GLUPS: " << gLUPS << "\n"; |
| 256 | | } |
| 257 | | |
| | 367 | benchmark<JacobiCellSimple >("JacobiCellSimple"); |
| | 368 | benchmark<JacobiCellMagic >("JacobiCellMagic"); |
| | 369 | benchmark<JacobiCellStreakUpdate>("JacobiCellStreakUpdate"); |