github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/niterator/iterator_test.go (about)

     1  package niterator
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/egonelbre/exp/niterator/basic"
     7  	"github.com/egonelbre/exp/niterator/instruct"
     8  	"github.com/egonelbre/exp/niterator/onearr"
     9  	"github.com/egonelbre/exp/niterator/onearrpremul"
    10  	"github.com/egonelbre/exp/niterator/onearrrev"
    11  	"github.com/egonelbre/exp/niterator/onearrrevadvance"
    12  	"github.com/egonelbre/exp/niterator/onearrrevspecialize"
    13  	"github.com/egonelbre/exp/niterator/onearrrevspecializeadvance"
    14  	"github.com/egonelbre/exp/niterator/ordone"
    15  	"github.com/egonelbre/exp/niterator/premul"
    16  	"github.com/egonelbre/exp/niterator/shape"
    17  	"github.com/egonelbre/exp/niterator/specialize"
    18  	"github.com/egonelbre/exp/niterator/unroll"
    19  	"github.com/egonelbre/exp/niterator/unrollinreverse"
    20  	"github.com/egonelbre/exp/niterator/unrollinreverseadvance"
    21  	"github.com/egonelbre/exp/niterator/unrollinreversebool"
    22  	"github.com/egonelbre/exp/niterator/unrollinreversehardcode"
    23  	"github.com/egonelbre/exp/niterator/unrollinreverseswitch"
    24  	"github.com/egonelbre/exp/niterator/unrollinverse"
    25  	"github.com/egonelbre/exp/niterator/unrollreverse"
    26  )
    27  
    28  const skipUseless = true
    29  
    30  type TestSize struct {
    31  	Name string
    32  	AP   *shape.AP
    33  }
    34  
    35  var (
    36  	indexOf100x = 5
    37  	testSizes   = []TestSize{
    38  		0: {"3x20x40x24", shape.New(3, 20, 40, 24)},
    39  		1: {"24x20x40x3", shape.New(24, 20, 40, 3)},
    40  		2: {"24x20x40x30", shape.New(24, 20, 40, 30)},
    41  		3: {"5x50x100x150", shape.New(5, 50, 100, 150)},
    42  		4: {"150x100x50x5", shape.New(150, 100, 50, 5)},
    43  		5: {"100x100x100x100", shape.New(100, 100, 100, 100)},
    44  	}
    45  
    46  	verifyIndex = make([][]int, len(testSizes))
    47  )
    48  
    49  func init() {
    50  	for api, testsize := range testSizes {
    51  		ap := testsize.AP
    52  		verify := make([]int, ap.TotalSize())
    53  
    54  		it := basic.NewIterator(ap)
    55  		i := 0
    56  		for index, err := it.Next(); err == nil; index, err = it.Next() {
    57  			i++
    58  			verify[index] = i
    59  		}
    60  		for _, v := range verify {
    61  			if v == 0 {
    62  				panic("invalid iterator")
    63  			}
    64  		}
    65  
    66  		verifyIndex[api] = verify
    67  	}
    68  }
    69  
    70  func testIterator(t *testing.T, newiterator func(ap *shape.AP) Iterator) {
    71  	t.Helper()
    72  	for api, testsize := range testSizes {
    73  		t.Run(testsize.Name, func(t *testing.T) {
    74  			verify := verifyIndex[api]
    75  			ap := testsize.AP
    76  			count := 0
    77  			i := 0
    78  			it := newiterator(ap)
    79  			for index, err := it.Next(); err == nil; index, err = it.Next() {
    80  				count++
    81  				i++
    82  				if verify[index] != i {
    83  					t.Fatalf("invalid at %d", index)
    84  				}
    85  			}
    86  
    87  			if count != ap.TotalSize() {
    88  				t.Fatalf("invalid count: got %d expected %d", count, ap.TotalSize())
    89  			}
    90  		})
    91  	}
    92  }
    93  
    94  func TestBasic(t *testing.T) {
    95  	testIterator(t, func(ap *shape.AP) Iterator { return basic.NewIterator(ap) })
    96  }
    97  
    98  func BenchmarkBasic(b *testing.B) {
    99  	for api, testsize := range testSizes {
   100  		b.Run(testsize.Name, func(b *testing.B) {
   101  			verify := verifyIndex[api]
   102  			ap := testsize.AP
   103  			b.SetBytes(int64(ap.TotalSize()))
   104  			for i := 0; i < b.N; i++ {
   105  				it := basic.NewIterator(ap)
   106  				total := 0
   107  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   108  					total += verify[index] * index
   109  				}
   110  				_ = total
   111  			}
   112  		})
   113  	}
   114  }
   115  
   116  func TestInstruct(t *testing.T) {
   117  	if skipUseless {
   118  		t.Skip("skipping useless approach")
   119  	}
   120  	testIterator(t, func(ap *shape.AP) Iterator { return instruct.NewIterator(ap) })
   121  }
   122  
   123  func BenchmarkInstruct(b *testing.B) {
   124  	if skipUseless {
   125  		b.Skip("skipping useless approach")
   126  	}
   127  	for api, testsize := range testSizes {
   128  		b.Run(testsize.Name, func(b *testing.B) {
   129  			verify := verifyIndex[api]
   130  			ap := testsize.AP
   131  			b.SetBytes(int64(ap.TotalSize()))
   132  			for i := 0; i < b.N; i++ {
   133  				it := instruct.NewIterator(ap)
   134  				total := 0
   135  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   136  					total += verify[index] * index
   137  				}
   138  				_ = total
   139  			}
   140  		})
   141  	}
   142  }
   143  
   144  func TestOrdone(t *testing.T) {
   145  	if skipUseless {
   146  		t.Skip("skipping useless approach")
   147  	}
   148  	testIterator(t, func(ap *shape.AP) Iterator { return ordone.NewIterator(ap) })
   149  }
   150  
   151  func BenchmarkOrdone(b *testing.B) {
   152  	if skipUseless {
   153  		b.Skip("skipping useless approach")
   154  	}
   155  	for api, testsize := range testSizes {
   156  		b.Run(testsize.Name, func(b *testing.B) {
   157  			verify := verifyIndex[api]
   158  			ap := testsize.AP
   159  			b.SetBytes(int64(ap.TotalSize()))
   160  			for i := 0; i < b.N; i++ {
   161  				it := ordone.NewIterator(ap)
   162  				total := 0
   163  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   164  					total += verify[index] * index
   165  				}
   166  				_ = total
   167  			}
   168  		})
   169  	}
   170  }
   171  
   172  func TestPremul(t *testing.T) {
   173  	if skipUseless {
   174  		t.Skip("skipping useless approach")
   175  	}
   176  	testIterator(t, func(ap *shape.AP) Iterator { return premul.NewIterator(ap) })
   177  }
   178  
   179  func BenchmarkPremul(b *testing.B) {
   180  	if skipUseless {
   181  		b.Skip("skipping useless approach")
   182  	}
   183  	for api, testsize := range testSizes {
   184  		b.Run(testsize.Name, func(b *testing.B) {
   185  			verify := verifyIndex[api]
   186  			ap := testsize.AP
   187  			b.SetBytes(int64(ap.TotalSize()))
   188  			for i := 0; i < b.N; i++ {
   189  				it := premul.NewIterator(ap)
   190  				total := 0
   191  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   192  					total += verify[index] * index
   193  				}
   194  				_ = total
   195  			}
   196  		})
   197  	}
   198  }
   199  
   200  func TestOnearr(t *testing.T) {
   201  	testIterator(t, func(ap *shape.AP) Iterator { return onearr.NewIterator(ap) })
   202  }
   203  
   204  func BenchmarkOnearr(b *testing.B) {
   205  	for api, testsize := range testSizes {
   206  		b.Run(testsize.Name, func(b *testing.B) {
   207  			verify := verifyIndex[api]
   208  			ap := testsize.AP
   209  			b.SetBytes(int64(ap.TotalSize()))
   210  			for i := 0; i < b.N; i++ {
   211  				it := onearr.NewIterator(ap)
   212  				total := 0
   213  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   214  					total += verify[index] * index
   215  				}
   216  				_ = total
   217  			}
   218  		})
   219  	}
   220  }
   221  
   222  func TestOnearrRev(t *testing.T) {
   223  	testIterator(t, func(ap *shape.AP) Iterator { return onearrrev.NewIterator(ap) })
   224  }
   225  
   226  func BenchmarkOnearrRev(b *testing.B) {
   227  	for api, testsize := range testSizes {
   228  		b.Run(testsize.Name, func(b *testing.B) {
   229  			verify := verifyIndex[api]
   230  			ap := testsize.AP
   231  			b.SetBytes(int64(ap.TotalSize()))
   232  			for i := 0; i < b.N; i++ {
   233  				it := onearrrev.NewIterator(ap)
   234  				total := 0
   235  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   236  					total += verify[index] * index
   237  				}
   238  				_ = total
   239  			}
   240  		})
   241  	}
   242  }
   243  
   244  func TestOnearrRevAdvance(t *testing.T) {
   245  	testIterator(t, func(ap *shape.AP) Iterator { return onearrrevadvance.NewIterator(ap) })
   246  }
   247  
   248  func BenchmarkOnearrRevAdvance(b *testing.B) {
   249  	for api, testsize := range testSizes {
   250  		b.Run(testsize.Name, func(b *testing.B) {
   251  			verify := verifyIndex[api]
   252  			ap := testsize.AP
   253  			b.SetBytes(int64(ap.TotalSize()))
   254  			for i := 0; i < b.N; i++ {
   255  				it := onearrrevadvance.NewIterator(ap)
   256  				total := 0
   257  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   258  					total += verify[index] * index
   259  				}
   260  				_ = total
   261  			}
   262  		})
   263  	}
   264  }
   265  
   266  func TestOnearrRevSpecialize(t *testing.T) {
   267  	testIterator(t, func(ap *shape.AP) Iterator { return onearrrevspecialize.NewIterator(ap) })
   268  }
   269  
   270  func BenchmarkOnearrRevSpecialize(b *testing.B) {
   271  	for api, testsize := range testSizes {
   272  		b.Run(testsize.Name, func(b *testing.B) {
   273  			verify := verifyIndex[api]
   274  			ap := testsize.AP
   275  			b.SetBytes(int64(ap.TotalSize()))
   276  			for i := 0; i < b.N; i++ {
   277  				it := onearrrevspecialize.NewIterator(ap)
   278  				total := 0
   279  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   280  					total += verify[index] * index
   281  				}
   282  				_ = total
   283  			}
   284  		})
   285  	}
   286  }
   287  
   288  func TestOnearrRevSpecializeAdvance(t *testing.T) {
   289  	testIterator(t, func(ap *shape.AP) Iterator { return onearrrevspecializeadvance.NewIterator(ap) })
   290  }
   291  
   292  func BenchmarkOnearrRevSpecializeAdvance(b *testing.B) {
   293  	for api, testsize := range testSizes {
   294  		b.Run(testsize.Name, func(b *testing.B) {
   295  			verify := verifyIndex[api]
   296  			ap := testsize.AP
   297  			b.SetBytes(int64(ap.TotalSize()))
   298  			for i := 0; i < b.N; i++ {
   299  				it := onearrrevspecializeadvance.NewIterator(ap)
   300  				total := 0
   301  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   302  					total += verify[index] * index
   303  				}
   304  				_ = total
   305  			}
   306  		})
   307  	}
   308  }
   309  
   310  func TestOnearrPremul(t *testing.T) {
   311  	if skipUseless {
   312  		t.Skip("skipping useless approach")
   313  	}
   314  	testIterator(t, func(ap *shape.AP) Iterator { return onearrpremul.NewIterator(ap) })
   315  }
   316  
   317  func BenchmarkOnearrPremul(b *testing.B) {
   318  	if skipUseless {
   319  		b.Skip("skipping useless approach")
   320  	}
   321  	for api, testsize := range testSizes {
   322  		b.Run(testsize.Name, func(b *testing.B) {
   323  			verify := verifyIndex[api]
   324  			ap := testsize.AP
   325  			b.SetBytes(int64(ap.TotalSize()))
   326  			for i := 0; i < b.N; i++ {
   327  				it := onearrpremul.NewIterator(ap)
   328  				total := 0
   329  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   330  					total += verify[index] * index
   331  				}
   332  				_ = total
   333  			}
   334  		})
   335  	}
   336  }
   337  
   338  func TestSpecialize(t *testing.T) {
   339  	testIterator(t, func(ap *shape.AP) Iterator { return specialize.NewIterator(ap) })
   340  }
   341  
   342  func BenchmarkSpecialize(b *testing.B) {
   343  	for api, testsize := range testSizes {
   344  		b.Run(testsize.Name, func(b *testing.B) {
   345  			verify := verifyIndex[api]
   346  			ap := testsize.AP
   347  			b.SetBytes(int64(ap.TotalSize()))
   348  			for i := 0; i < b.N; i++ {
   349  				it := specialize.NewIterator(ap)
   350  				total := 0
   351  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   352  					total += verify[index] * index
   353  				}
   354  				_ = total
   355  			}
   356  		})
   357  	}
   358  }
   359  
   360  func TestUnroll(t *testing.T) {
   361  	testIterator(t, func(ap *shape.AP) Iterator { return unroll.NewIterator(ap) })
   362  }
   363  
   364  func BenchmarkUnroll(b *testing.B) {
   365  	for api, testsize := range testSizes {
   366  		b.Run(testsize.Name, func(b *testing.B) {
   367  			verify := verifyIndex[api]
   368  			ap := testsize.AP
   369  			b.SetBytes(int64(ap.TotalSize()))
   370  			for i := 0; i < b.N; i++ {
   371  				it := unroll.NewIterator(ap)
   372  				total := 0
   373  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   374  					total += verify[index] * index
   375  				}
   376  				_ = total
   377  			}
   378  		})
   379  	}
   380  }
   381  
   382  func TestUnrollReverse(t *testing.T) {
   383  	testIterator(t, func(ap *shape.AP) Iterator { return unrollreverse.NewIterator(ap) })
   384  }
   385  
   386  func BenchmarkUnrollReverse(b *testing.B) {
   387  	for api, testsize := range testSizes {
   388  		b.Run(testsize.Name, func(b *testing.B) {
   389  			verify := verifyIndex[api]
   390  			ap := testsize.AP
   391  			b.SetBytes(int64(ap.TotalSize()))
   392  			for i := 0; i < b.N; i++ {
   393  				it := unrollreverse.NewIterator(ap)
   394  				total := 0
   395  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   396  					total += verify[index] * index
   397  				}
   398  				_ = total
   399  			}
   400  		})
   401  	}
   402  }
   403  
   404  func TestUnrollInverse(t *testing.T) {
   405  	testIterator(t, func(ap *shape.AP) Iterator { return unrollinverse.NewIterator(ap) })
   406  }
   407  
   408  func BenchmarkUnrollInverse(b *testing.B) {
   409  	for api, testsize := range testSizes {
   410  		b.Run(testsize.Name, func(b *testing.B) {
   411  			verify := verifyIndex[api]
   412  			ap := testsize.AP
   413  			b.SetBytes(int64(ap.TotalSize()))
   414  			for i := 0; i < b.N; i++ {
   415  				it := unrollinverse.NewIterator(ap)
   416  				total := 0
   417  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   418  					total += verify[index] * index
   419  				}
   420  				_ = total
   421  			}
   422  		})
   423  	}
   424  }
   425  
   426  func TestUnrollInReverse(t *testing.T) {
   427  	testIterator(t, func(ap *shape.AP) Iterator { return unrollinreverse.NewIterator(ap) })
   428  }
   429  
   430  func BenchmarkUnrollInReverse(b *testing.B) {
   431  	for api, testsize := range testSizes {
   432  		b.Run(testsize.Name, func(b *testing.B) {
   433  			verify := verifyIndex[api]
   434  			ap := testsize.AP
   435  			b.SetBytes(int64(ap.TotalSize()))
   436  			for i := 0; i < b.N; i++ {
   437  				it := unrollinreverse.NewIterator(ap)
   438  				total := 0
   439  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   440  					total += verify[index] * index
   441  				}
   442  				_ = total
   443  			}
   444  		})
   445  	}
   446  }
   447  
   448  func TestUnrollInReverseAdvance(t *testing.T) {
   449  	testIterator(t, func(ap *shape.AP) Iterator { return unrollinreverseadvance.NewIterator(ap) })
   450  }
   451  
   452  func BenchmarkUnrollInReverseAdvance(b *testing.B) {
   453  	for api, testsize := range testSizes {
   454  		b.Run(testsize.Name, func(b *testing.B) {
   455  			verify := verifyIndex[api]
   456  			ap := testsize.AP
   457  			b.SetBytes(int64(ap.TotalSize()))
   458  			for i := 0; i < b.N; i++ {
   459  				it := unrollinreverseadvance.NewIterator(ap)
   460  				total := 0
   461  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   462  					total += verify[index] * index
   463  				}
   464  				_ = total
   465  			}
   466  		})
   467  	}
   468  }
   469  
   470  func TestUnrollInReverseSwitch(t *testing.T) {
   471  	testIterator(t, func(ap *shape.AP) Iterator { return unrollinreverseswitch.NewIterator(ap) })
   472  }
   473  
   474  func BenchmarkUnrollInReverseSwitch(b *testing.B) {
   475  	for api, testsize := range testSizes {
   476  		b.Run(testsize.Name, func(b *testing.B) {
   477  			verify := verifyIndex[api]
   478  			ap := testsize.AP
   479  			b.SetBytes(int64(ap.TotalSize()))
   480  			for i := 0; i < b.N; i++ {
   481  				it := unrollinreverseswitch.NewIterator(ap)
   482  				total := 0
   483  				for index, err := it.Next(); err == nil; index, err = it.Next() {
   484  					total += verify[index] * index
   485  				}
   486  				_ = total
   487  			}
   488  		})
   489  	}
   490  }
   491  
   492  func BenchmarkUnrollInReverseBool(b *testing.B) {
   493  	for api, testsize := range testSizes {
   494  		b.Run(testsize.Name, func(b *testing.B) {
   495  			verify := verifyIndex[api]
   496  			ap := testsize.AP
   497  			b.SetBytes(int64(ap.TotalSize()))
   498  			for i := 0; i < b.N; i++ {
   499  				it := unrollinreversebool.NewIterator(ap)
   500  				total := 0
   501  				for index, done := it.Next(); !done; index, done = it.Next() {
   502  					total += verify[index] * index
   503  				}
   504  				_ = total
   505  			}
   506  		})
   507  	}
   508  }
   509  
   510  // special
   511  // func TestUnrollInReverseHardcode(t *testing.T) {
   512  // 	testIterator(t, unrollinreversehardcode.NewIterator(shape.New(100, 100, 100, 100)))
   513  // }
   514  
   515  func BenchmarkUnrollInReverseHardcode(b *testing.B) {
   516  	b.Run("100x100x100x100", func(b *testing.B) {
   517  		verify := verifyIndex[indexOf100x]
   518  		ap := shape.New(100, 100, 100, 100)
   519  		b.SetBytes(int64(ap.TotalSize()))
   520  		for i := 0; i < b.N; i++ {
   521  			it := unrollinreversehardcode.NewIterator(ap)
   522  			total := 0
   523  			for index, err := it.Next(); err == nil; index, err = it.Next() {
   524  				total += verify[index] * index
   525  			}
   526  			_ = total
   527  		}
   528  	})
   529  }