github.com/wzzhu/tensor@v0.9.24/perf.go (about)

     1  package tensor
     2  
     3  import (
     4  	"runtime"
     5  	"sync"
     6  
     7  	"github.com/wzzhu/tensor/internal/storage"
     8  )
     9  
    10  var habbo sync.Mutex
    11  var usePool = true
    12  
    13  // tensorPool is a pool of *Tensor grouped by size. It's guarded by poolsClosed
    14  
    15  const (
    16  	maxAPDims = 8
    17  	maxDims   = 8
    18  	PoolSize  = 4096
    19  )
    20  
    21  // UsePool enables the use of a pool of *Tensors as provided in the package. This is the default option
    22  func UsePool() {
    23  	habbo.Lock()
    24  	usePool = true
    25  	habbo.Unlock()
    26  }
    27  
    28  // DontUsePool makes sure the functions don't use the tensor pool provided.
    29  // This is useful as certain applications don't lend themselves well to use of the pool.
    30  // Examples of such applications would be one where many tensors of wildly different sizes are created all the time.
    31  func DontUsePool() {
    32  	habbo.Lock()
    33  	usePool = false
    34  	habbo.Unlock()
    35  }
    36  
    37  // headerPool should ever only be used by scalarToHeader
    38  var headerPool = make(chan *storage.Header, PoolSize)
    39  
    40  func borrowHeader() *storage.Header {
    41  	select {
    42  	case hdr := <-headerPool:
    43  		return hdr
    44  	default:
    45  		hdr := new(storage.Header)
    46  		runtime.SetFinalizer(hdr, destroyHeader)
    47  		return hdr
    48  	}
    49  }
    50  
    51  func returnHeader(hdr *storage.Header) {
    52  	destroyHeader(hdr)
    53  	if len(headerPool) < cap(headerPool) {
    54  		headerPool <- hdr
    55  	}
    56  }
    57  
    58  func destroyHeader(hdr *storage.Header) {
    59  	hdr.Raw = nil
    60  }
    61  
    62  var densePool = make(chan *Dense, PoolSize)
    63  
    64  func borrowDense() *Dense {
    65  	select {
    66  	case t := <-densePool:
    67  		return t
    68  	default:
    69  		t := new(Dense)
    70  		t.e = StdEng{}
    71  		// t.oe = StdEng{}
    72  		return t
    73  	}
    74  	// return densePool.Get().(*Dense)
    75  }
    76  
    77  // ReturnTensor returns a Tensor to their respective pools. USE WITH CAUTION
    78  func ReturnTensor(t Tensor) {
    79  	if !usePool {
    80  		return
    81  	}
    82  	switch tt := t.(type) {
    83  	case *Dense:
    84  		tt.AP.zero()
    85  
    86  		if tt.transposeWith != nil {
    87  			ReturnInts(tt.transposeWith)
    88  			tt.transposeWith = nil
    89  		}
    90  
    91  		// array reset
    92  		tt.t = Dtype{}
    93  		tt.array.Header.Raw = nil
    94  
    95  		// engine and flag reset
    96  		tt.e = StdEng{}
    97  		tt.oe = nil
    98  		tt.flag = 0
    99  
   100  		// other reset
   101  		tt.old.zero()
   102  		tt.viewOf = 0
   103  		tt.transposeWith = nil
   104  
   105  		// mask related stuff - TODO: deprecate
   106  		tt.mask = nil
   107  		tt.maskIsSoft = false
   108  
   109  		// densePool.Put(tt)
   110  		if len(densePool) < cap(densePool) {
   111  			densePool <- tt
   112  		}
   113  	}
   114  }
   115  
   116  /* ----------------------------------------------------------------
   117  ------------------ Create Pools
   118  ------------------------------------------------------------------*/
   119  
   120  /* APLIST POOL */
   121  
   122  // Init function
   123  func init() {
   124  
   125  	for i := range intsPool {
   126  		size := i
   127  		intsPool[i].New = func() interface{} { return make([]int, size) }
   128  	}
   129  
   130  	// for i := range boolsPool {
   131  	// 	size := i
   132  	// 	boolsPool[i].New = func() interface{} { return make([]bool, size) }
   133  	// }
   134  }
   135  
   136  /* INTS POOL */
   137  
   138  var intsPool [maxDims + 1]sync.Pool
   139  
   140  // var intsPool = make(chan []int, PoolSize)
   141  
   142  /* BOOLS POOL */
   143  var boolsPool = make(chan []bool, PoolSize)
   144  
   145  // var boolsPool [PoolSize]sync.Pool
   146  
   147  // BorrowInts borrows a slice of ints from the pool. USE WITH CAUTION.
   148  func BorrowInts(size int) []int {
   149  	if size > maxDims {
   150  		return make([]int, size, size)
   151  	}
   152  
   153  	// select {
   154  	// case ints := <-intsPool:
   155  	// 	ints = ints[:size]
   156  	// 	return ints
   157  	// default:
   158  	// 	ints := make([]int, size, 8)
   159  	// 	return ints
   160  	// }
   161  	retVal := intsPool[size].Get()
   162  	if retVal == nil {
   163  		return make([]int, size)
   164  	}
   165  	// log.Printf("Borrowing %p. Called by %v", retVal, string(debug.Stack()))
   166  	return retVal.([]int)[:size]
   167  }
   168  
   169  // ReturnInts returns a slice from the pool. USE WITH CAUTION.
   170  func ReturnInts(is []int) {
   171  	// log.Printf("Returning %p. Called by %v", is, string(debug.Stack()))
   172  	if is == nil {
   173  		return
   174  	}
   175  	// if len(is) == 2 && is[0] == 52 && is[1] == 10 {
   176  	// 	log.Printf("ints %v", is)
   177  	// 	pc, _, _, _ := runtime.Caller(3)
   178  	// 	log.Printf("Called: %v", runtime.FuncForPC(pc).Name())
   179  	// }
   180  	size := cap(is)
   181  	if size > maxDims {
   182  		return
   183  	}
   184  	is = is[:cap(is)]
   185  	for i := range is {
   186  		is[i] = 0
   187  	}
   188  
   189  	// if len(intsPool) < cap(intsPool) {
   190  	// 	intsPool <- is
   191  	// }
   192  
   193  	intsPool[size].Put(is)
   194  }
   195  
   196  // BorrowBools borrows a slice of bools from the pool. USE WITH CAUTION.
   197  func BorrowBools(size int) []bool {
   198  	if size >= 8 {
   199  		return make([]bool, size)
   200  	}
   201  
   202  	select {
   203  	case bools := <-boolsPool:
   204  		return bools
   205  	default:
   206  		bools := make([]bool, 8)
   207  		bools = bools[:size]
   208  		return bools
   209  	}
   210  
   211  	// retVal := boolsPool[size].Get()
   212  	// if retVal == nil {
   213  	// 	return make([]bool, size)
   214  	// }
   215  	// return retVal.([]bool)
   216  }
   217  
   218  // ReturnBools returns a slice from the pool. USE WITH CAUTION.
   219  func ReturnBools(is []bool) {
   220  	if is == nil {
   221  		return
   222  	}
   223  	size := cap(is)
   224  	if size >= 8 {
   225  		return
   226  	}
   227  	is = is[:cap(is)]
   228  	for i := range is {
   229  		is[i] = false
   230  	}
   231  
   232  	if len(boolsPool) < cap(boolsPool) {
   233  		boolsPool <- is
   234  	}
   235  	// boolsPool[size].Put(is)
   236  }
   237  
   238  // var optPool = make(chan *OpOpt, PoolSize)
   239  // var optPool = newRingbuffer(PoolSize)
   240  var optPool = &sync.Pool{
   241  	New: func() interface{} { return new(OpOpt) },
   242  }
   243  
   244  func borrowOpOpt() *OpOpt {
   245  	// select {
   246  	// case fo := <-optPool:
   247  	// 	return fo
   248  	// default:
   249  	// 	return new(OpOpt)
   250  	// }
   251  
   252  	return optPool.Get().(*OpOpt)
   253  
   254  	// if fo, err := optPool.Get(); err == nil {
   255  	// 	return (*OpOpt)(fo)
   256  	// }
   257  	// return new(OpOpt)
   258  }
   259  
   260  func returnOpOpt(oo *OpOpt) {
   261  	oo.reuse = nil
   262  	oo.incr = nil
   263  	oo.unsafe = false
   264  	oo.same = false
   265  	oo.t = Dtype{}
   266  	// if len(optPool) < cap(optPool) {
   267  	// 	optPool <- oo
   268  	// }
   269  
   270  	optPool.Put(oo)
   271  
   272  	// optPool.Put(unsafe.Pointer(oo))
   273  }