GCC Code Coverage Report
Directory: . Exec Total Coverage
File: frame/base/View.hpp Lines: 0 164 0.0 %
Date: 2019-01-14 Branches: 0 350 0.0 %

Line Exec Source
1
/**
2
 *  HMLP (High-Performance Machine Learning Primitives)
3
 *
4
 *  Copyright (C) 2014-2017, The University of Texas at Austin
5
 *
6
 *  This program is free software: you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation, either version 3 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program. If not, see the LICENSE file.
18
 *
19
 **/
20
21
22
23
24
#ifndef VIEW_HPP
25
#define VIEW_HPP
26
27
#include <Data.hpp>
28
29
using namespace std;
30
using namespace hmlp;
31
32
namespace hmlp
33
{
34
35
typedef enum { TRANSPOSE, NOTRANSPOSE } TransposeType;
36
/** 1x2, 2x1, 1x3, 3x1 */
37
typedef enum { LEFT, RIGHT, BOTTOM, TOP } SideType;
38
/** 2x2, 3x3 */
39
typedef enum { TOPLEFT, TOPRIGHT, BOTTOMLEFT, BOTTOMRIGHT } QuadrantType;
40
41
42
template<typename T>
43
class View : public ReadWrite
44
{
45
  public:
46
47
    /** empty constructor */
48
    View() {};
49
50
    /** constructor for the buffer */
51
    View( Data<T> &buff ) { Set( buff ); };
52
53
    View( bool TRANS, Data<T> &buff ) { Set( TRANS, buff ); };
54
55
56
    /** destructor */
57
    //~View() { printf( "~View()\n" ); fflush( stdout ); };
58
59
    /** base case setup */
60
    void Set( bool TRANS, Data<T> &buff )
61
    {
62
      this->trans = TRANS;
63
      if ( trans )
64
      {
65
        /** Data<T> is stored in column major */
66
        this->m = buff.col();
67
        this->n = buff.row();
68
      }
69
      else
70
      {
71
        this->m = buff.row();
72
        this->n = buff.col();
73
      }
74
      this->offm  = 0;
75
      this->offn  = 0;
76
      this->base  = this;
77
      this->buff  = &buff;
78
    };
79
80
    /** (Default) is none transpose. */
81
    void Set( Data<T> &buff ) { Set( false, buff ); };
82
83
    /** non-base case setup */
84
    void Set( size_t m, size_t n, size_t offm, size_t offn, View<T> *base )
85
    {
86
      this->trans = base->trans;
87
      if ( trans )
88
      {
89
        assert( offm <= base->buff->col() );
90
        assert( offn <= base->buff->row() );
91
      }
92
      else
93
      {
94
        assert( offm <= base->buff->row() );
95
        assert( offn <= base->buff->col() );
96
      }
97
      this->m     = m;
98
      this->n     = n;
99
      this->offm  = offm;
100
      this->offn  = offn;
101
      this->base  = base;
102
      this->buff  = base->buff;
103
    };
104
105
    /** subview operator */
106
    template<typename TINDEX>
107
    T & operator () ( TINDEX i, TINDEX j )
108
    {
109
      size_t offset = 0;
110
      if ( trans )
111
      {
112
        assert( offm + i < buff->col() );
113
        assert( offn + j < buff->row() );
114
        offset = i * ld() + j;
115
      }
116
      else
117
      {
118
        assert( offm + i < buff->row() );
119
        assert( offn + j < buff->col() );
120
        offset = j * ld() + i;
121
      }
122
      return *( data() + offset );
123
    };
124
125
    void CopyValuesFrom( View<T> & A )
126
    {
127
      if ( !m || !n ) return;
128
      assert( A.row() == m && A.col() == n );
129
      for ( size_t j = 0; j < n; j ++ )
130
        for ( size_t i = 0; i < m; i ++ )
131
          (*this)( i, j ) = A( i, j );
132
    };
133
134
    void CopyValuesFrom( Data<T> & A )
135
    {
136
      if ( !m || !n ) return;
137
      assert( A.row() == m && A.col() == n );
138
      for ( size_t j = 0; j < n; j ++ )
139
        for ( size_t i = 0; i < m; i ++ )
140
          (*this)( i, j ) = A( i, j );
141
    };
142
143
    /** Return a data copy of the subview */
144
    Data<T> toData()
145
    {
146
      Data<T> A( m, n );
147
      for ( size_t j = 0; j < n; j ++ )
148
        for ( size_t i = 0; i < m; i ++ )
149
          A( i, j ) = (*this)( i, j );
150
      return A;
151
    };
152
153
    /** [ A1;   = A
154
     *    A2; ]     */
155
    void Partition2x1( View<T> &A1,
156
                       View<T> &A2, size_t mb, SideType side )
157
    {
158
      /** readjust mb */
159
      if ( mb > m ) mb = m;
160
      if ( side == BOTTOM ) mb = m - mb;
161
      /** setup A1 */
162
      A1.Set(     mb, this->n, this->offm,      this->offn, this->base );
163
      /** setup A2 */
164
      A2.Set( m - mb, this->n, this->offm + mb, this->offn, this->base );
165
    };
166
167
168
    /** A = [ A1;
169
     *        A2; ] */
170
    void ContinueWith2x1( View<T> &A1,
171
                          View<T> &A2 )
172
    {
173
      if ( A1.row() && A2.row() ) assert( A1.col() == A2.col() );
174
      (*this) = A1;
175
      assert( A2.HasTheSameBuffer( this->buff ) );
176
      this->m = A1.row() + A2.row();
177
    };
178
179
    /** [ A1, A2; ] = A */
180
    void Partition1x2( View<T> &A1, View<T> &A2, size_t nb, SideType side )
181
    {
182
      /** readjust mb */
183
      if ( nb > n ) nb = n;
184
      if ( side == RIGHT ) nb = n - nb;
185
      /** setup A1 */
186
      A1.Set( this->m,     nb, this->offm, this->offn,      this->base );
187
      /** setup A2 */
188
      A2.Set( this->m, n - nb, this->offm, this->offn + nb, this->base );
189
    };
190
191
    /** A = [ A1, A2; ] */
192
    void ContinueWith1x2( View<T> &A1, View<T> &A2 )
193
    {
194
      if ( A1.col() && A2.col() ) assert( A1.row() == A2.row() );
195
      (*this) = A1;
196
      assert( A2.HasTheSameBuffer( this->buff ) );
197
      this->n = A1.col() + A2.col();
198
    };
199
200
    /** A = [ A11, A12; A21, A22; ]; */
201
    void Partition2x2 ( View<T> &A11, View<T> &A12,
202
                        View<T> &A21, View<T> &A22,
203
                        size_t mb, size_t nb, QuadrantType quadrant )
204
    {
205
      if ( mb > m ) mb = m;
206
      if ( nb > n ) nb = n;
207
208
      switch ( quadrant )
209
      {
210
        case TOPLEFT:
211
        {
212
          break;
213
        }
214
        case TOPRIGHT:
215
        {
216
          nb = n - nb;
217
          break;
218
        }
219
        case BOTTOMLEFT:
220
        {
221
          mb = m - mb;
222
          break;
223
        }
224
        case BOTTOMRIGHT:
225
        {
226
          mb = m - mb;
227
          nb = n - nb;
228
          break;
229
        }
230
        default:
231
        {
232
          printf( "invalid quadrant\n" );
233
          break;
234
        }
235
      }
236
237
      /** setup A11 */
238
      A11.Set(     mb,     nb, offm     , offn     , this->base );
239
      /** setup A12 */
240
      A12.Set(     mb, n - nb, offm     , offn + nb, this->base );
241
      /** setup A21 */
242
      A21.Set( m - mb,     nb, offm + mb, offn     , this->base );
243
      /** setup A22 */
244
      A22.Set( m - mb, n - nb, offm + mb, offn + nb, this->base );
245
246
    };
247
248
249
    void ContinueWith2x2( View<T> &A11, View<T> &A12,
250
                          View<T> &A21, View<T> &A22 )
251
    {
252
       assert( A11.row() == A12.row() );
253
       assert( A11.col() == A21.col() );
254
       assert( A22.row() == A21.row() );
255
       assert( A22.col() == A12.col() );
256
       (*this) = A11;
257
       this->m = A11.row() + A21.row();
258
       this->n = A11.col() + A12.col();
259
    };
260
261
    bool IsTransposed() { return trans; };
262
263
    bool HasTheSameBuffer( Data<T> *target ) { return ( target == buff ); };
264
265
    bool HasUniformBlockSize() { return has_uniform_block_size; };
266
267
    void CreateLeafMatrixBlocks( size_t mb, size_t nb )
268
    {
269
      /** only the base view can have leaf r/w blocks */
270
      if ( base == this )
271
      {
272
        if ( !rwblocks.HasBeenSetup() )
273
        {
274
          this->mb = mb;
275
          this->nb = nb;
276
          rwblocks.Setup(
277
              (size_t)std::ceil( (double)m / mb ),
278
              (size_t)std::ceil( (double)n / nb ) );
279
        }
280
        assert( this->mb == mb );
281
        assert( this->nb == nb );
282
      }
283
      else
284
      {
285
        base->CreateLeafMatrixBlocks( mb, nb );
286
      }
287
    };
288
289
    size_t GetRowBlockSize()
290
    {
291
      if ( base == this ) return mb;
292
      else                return base->GetRowBlockSize();
293
    };
294
295
    size_t GetColumnBlockSize()
296
    {
297
      if ( base == this ) return nb;
298
      else                return base->GetColumnBlockSize();
299
    };
300
301
    bool HasLeafReadWriteBlocks()
302
    {
303
      if ( base == this ) return rwblocks.HasBeenSetup();
304
      else                return base->HasLeafReadWriteBlocks();
305
    };
306
307
    /**
308
     *  @brief  If leaf r/w blocks were created, then the r/w dependency
309
     *          applies to all leaf r/w blocks covered by this view.
310
     *          Otherwise, the r/w dependency only applies to this view.
311
     */
312
    void DependencyAnalysis( ReadWriteType type, Task *task )
313
    {
314
      if ( HasLeafReadWriteBlocks() )
315
      {
316
        for ( size_t j = 0; j < n; j += GetColumnBlockSize() )
317
          for ( size_t i = 0; i < m; i += GetRowBlockSize() )
318
            DependencyAnalysis( offm + i, offn + j, type, task );
319
      }
320
      else
321
      {
322
        ReadWrite::DependencyAnalysis( type, task );
323
      }
324
    };
325
326
    void DependencyAnalysis( size_t i, size_t j, ReadWriteType type, Task *task )
327
    {
328
      if ( base == this )
329
      {
330
        rwblocks.DependencyAnalysis( i / mb, j / nb, type, task );
331
      }
332
      else
333
      {
334
        base->DependencyAnalysis( i, j, type, task );
335
      }
336
    };
337
338
    void DependencyCleanUp()
339
    {
340
      if ( base == this ) rwblocks.DependencyCleanUp();
341
      else base->DependencyCleanUp();
342
    };
343
344
    /** return the row size of the current view */
345
    size_t row() { return m; };
346
347
    /** return the col size of the current view */
348
    size_t col() { return n; };
349
350
    /** return leading dimension of the buffer */
351
    size_t ld()  { return buff->row(); };
352
353
    /** return the pointer of the current view in the buffer */
354
    T *data()
355
    {
356
      assert( buff );
357
      size_t offset;
358
      if ( trans ) offset = offm * ld() + offn;
359
      else         offset = offn * ld() + offm;
360
      return ( buff->data() + offset );
361
    };
362
363
    /** print out all information */
364
    void Print()
365
    {
366
      if ( trans )
367
      {
368
        printf( "[ %5lu+%5lu:%5lu ][ %5lu+%5lu:%5lu ]\n",
369
            offm, m, buff->col(), offn, n, buff->row() );
370
      }
371
      else
372
      {
373
        printf( "[ %5lu+%5lu:%5lu ][ %5lu+%5lu:%5lu ]\n",
374
            offm, m, buff->row(), offn, n, buff->col() );
375
      }
376
    };
377
378
  private:
379
380
    /** whether this is a transpose view? */
381
    bool trans = false;
382
383
    size_t m = 0;
384
385
    size_t n = 0;
386
387
    size_t offm = 0;
388
389
    size_t offn = 0;
390
391
    View<T> *base = NULL;
392
393
    Data<T> *buff = NULL;
394
395
    /** we can only have one kind of mb and nb */
396
    size_t mb = 0;
397
398
    size_t nb = 0;
399
400
    bool has_uniform_block_size = true;
401
402
    MatrixReadWrite rwblocks;
403
404
}; /** end class View */
405
406
407
/**
408
 *  @brief
409
 */
410
template<typename T>
411
void Partition1x2
412
(
413
  View<T> &A, View<T> &A1, View<T> &A2,
414
  size_t nb, SideType side
415
)
416
{
417
  A.Partition1x2( A1, A2, nb, side );
418
}; /** end Partition1x2() */
419
420
421
/**
422
 *  @brief
423
 */
424
template<typename T>
425
void Partition2x1
426
(
427
  View<T> &A, View<T> &A1,
428
              View<T> &A2,
429
  size_t mb, SideType side
430
)
431
{
432
  A.Partition2x1( A1,
433
                  A2, mb, side );
434
}; /** end Partition2x1() */
435
436
437
/**
438
 *  @brief
439
 */
440
template<typename T>
441
void Partition2x2
442
(
443
  View<T> &A, View<T> &A11, View<T> &A12,
444
              View<T> &A21, View<T> &A22,
445
  size_t mb, size_t nb, QuadrantType quadrant
446
)
447
{
448
  A.Partition2x2( A11, A12,
449
                  A21, A22, mb, nb, quadrant );
450
}; /** end Partition2x2() */
451
452
453
/**
454
 *  @brief
455
 */
456
template<typename T>
457
void Repartition1x2To1x3
458
(
459
  View<T> &AL,              View<T> &AR,
460
  View<T> &A0, View<T> &A1, View<T> &A2,
461
  size_t nb, SideType side
462
)
463
{
464
  switch ( side )
465
  {
466
    case LEFT:
467
    {
468
      AL.Partition1x2( A0, A1, nb, RIGHT );
469
      A2 = AR;
470
      break;
471
    }
472
    case RIGHT:
473
    {
474
      A0 = AL;
475
      AR.Partition1x2( A1, A2, nb, LEFT );
476
      break;
477
    }
478
    default:
479
    {
480
      printf( "invalid side\n" );
481
      break;
482
    }
483
  }
484
485
}; /** end Repartition1x2To1x3()*/
486
487
488
template<typename T>
489
void ContinueWith1x3To1x2
490
(
491
  View<T> &AL,              View<T> &AR,
492
  View<T> &A0, View<T> &A1, View<T> &A2,
493
  SideType side
494
)
495
{
496
  switch ( side )
497
  {
498
    case LEFT:
499
    {
500
      AL.ContinueWith1x2( A0, A1 );
501
      AR = A2;
502
      break;
503
    }
504
    case RIGHT:
505
    {
506
      AL = A0;
507
      AR.ContinueWith1x2( A1, A2 );
508
      break;
509
    }
510
    default:
511
    {
512
      printf( "invalid side\n" );
513
      break;
514
    }
515
  }
516
}; /** end ContinueWith1x3To1x2() */
517
518
519
520
521
template<typename T>
522
void Repartition2x1To3x1
523
(
524
  View<T> &AT, View<T> &A0,
525
               View<T> &A1,
526
  View<T> &AB, View<T> &A2,
527
  size_t mb, SideType side
528
)
529
{
530
  switch ( side )
531
  {
532
    case TOP:
533
    {
534
      AT.Partition2x1( A0,
535
                       A1, mb, BOTTOM );
536
      A2 = AB;
537
      break;
538
    }
539
    case BOTTOM:
540
    {
541
      A0 = AT;
542
      AB.Partition2x1( A1,
543
                       A2, mb, TOP );
544
      break;
545
    }
546
    default:
547
    {
548
      printf( "invalid side\n" );
549
      break;
550
    }
551
  }
552
}; /** end Repartition2x1To3x1()*/
553
554
555
template<typename T>
556
void ContinueWith3x1To2x1
557
(
558
  View<T> &AT, View<T> &A0,
559
               View<T> &A1,
560
  View<T> &AB, View<T> &A2,
561
  SideType side
562
)
563
{
564
  switch ( side )
565
  {
566
    case TOP:
567
    {
568
      AT.ContinueWith2x1( A0,
569
                          A1 );
570
      AB = A2;
571
      break;
572
    }
573
    case BOTTOM:
574
    {
575
      AT = A0;
576
      AB.ContinueWith2x1( A1,
577
                          A2 );
578
      break;
579
    }
580
    default:
581
    {
582
      printf( "invalid side\n" );
583
      break;
584
    }
585
  }
586
}; /** end ContinueWith3x1To2x1() */
587
588
589
/**
590
 *  @brief
591
 */
592
template<typename T>
593
void Repartition2x2To3x3
594
(
595
  View<T> &ATL, View<T> &ATR, View<T> &A00, View<T> &A01, View<T> &A02,
596
                              View<T> &A10, View<T> &A11, View<T> &A12,
597
  View<T> &ABL, View<T> &ABR, View<T> &A20, View<T> &A21, View<T> &A22,
598
  size_t mb, size_t nb, QuadrantType quadrant
599
)
600
{
601
  switch ( quadrant )
602
  {
603
    case TOPLEFT:
604
    {
605
      ATL.Partition2x2( A00, A01,
606
                        A10, A11, mb, nb, BOTTOMRIGHT );
607
      ATR.Partition2x1( A02,
608
                        A12,      mb,     BOTTOM      );
609
      ABL.Partition1x2( A20, A21,     nb,       RIGHT );
610
      A22 = ABR;
611
      break;
612
    }
613
    case TOPRIGHT:
614
    {
615
      ATL.Partition2x1( A00,
616
                        A10,      mb,     BOTTOM     );
617
      ATR.Partition2x2( A01, A02,
618
                        A11, A12, mb, nb, BOTTOMLEFT );
619
      A20 = ABL;
620
      ABR.Partition1x2( A21, A22,     nb,       LEFT );
621
      break;
622
    }
623
    case BOTTOMLEFT:
624
    {
625
      ATL.Partition1x2( A00, A01,     nb,    RIGHT );
626
      A02 = ATR;
627
      ABL.Partition2x2( A10, A11,
628
                        A20, A21, mb, nb, TOPRIGHT );
629
      ABR.Partition2x1( A12,
630
                        A22,      mb,     TOP      );
631
      break;
632
    }
633
    case BOTTOMRIGHT:
634
    {
635
      A00 = ATL;
636
      ATR.Partition1x2( A01, A02,     nb,    LEFT );
637
      ABL.Partition2x1( A10,
638
                        A20,      mb,     TOP     );
639
      ABR.Partition2x2( A11, A12,
640
                        A21, A22, mb, nb, TOPLEFT );
641
      break;
642
    }
643
    default:
644
    {
645
      printf( "invalid quadrant\n" );
646
      break;
647
    }
648
  }
649
}; /** end Repartition2x2To3x3() */
650
651
652
653
/**
654
 *  @brief
655
 */
656
template<typename T>
657
void ContinueWith3x3To2x2
658
(
659
  View<T> &ATL, View<T> &ATR, View<T> &A00, View<T> &A01, View<T> &A02,
660
                              View<T> &A10, View<T> &A11, View<T> &A12,
661
  View<T> &ABL, View<T> &ABR, View<T> &A20, View<T> &A21, View<T> &A22,
662
  QuadrantType quadrant
663
)
664
{
665
  switch ( quadrant )
666
  {
667
    case TOPLEFT:
668
    {
669
      ATL.ContinueWith2x2( A00, A01,
670
                           A10, A11 );
671
      ATR.ContinueWith2x1( A02,
672
                           A12      );
673
      ABL.ContinueWith1x2( A20, A21 );
674
      ABR = A22;
675
      break;
676
    }
677
    case TOPRIGHT:
678
    {
679
      ATL.ContinueWith2x1( A00,
680
                           A10      );
681
      ATR.ContinueWith2x2( A01, A02,
682
                           A11, A12 );
683
      ABL = A20;
684
      ABR.ContinueWith1x2( A21, A22 );
685
      break;
686
    }
687
    case BOTTOMLEFT:
688
    {
689
      ATL.ContinueWith1x2( A00, A01 );
690
      ATR = A02;
691
      ABL.ContinueWith2x2( A10, A11,
692
                           A20, A21 );
693
      ABR.ContinueWith2x1( A12,
694
                           A22      );
695
      break;
696
    }
697
    case BOTTOMRIGHT:
698
    {
699
      ATL = A00;
700
      ATR.ContinueWith1x2( A01, A02 );
701
      ABL.ContinueWith2x1( A10,
702
                           A20      );
703
      ABR.ContinueWith2x2( A11, A12,
704
                           A21, A22 );
705
      break;
706
    }
707
    default:
708
    {
709
      printf( "invalid quadrant\n" );
710
      break;
711
    }
712
  }
713
}; /** end ContinueWith3x3To2x2() */
714
715
716
717
}; /** end namespace hmlp */
718
719
#endif /** define VIEW_HPP */