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 }