github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/memutils/memory.go (about) 1 // Copyright (c) 2017-2018 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package memutils 16 17 // #cgo LDFLAGS: -L${SRCDIR}/../lib -lmem 18 // #include "memory.h" 19 import "C" 20 import ( 21 "github.com/uber/aresdb/cgoutils" 22 "reflect" 23 "unsafe" 24 ) 25 26 // GetFlags return flags about the memory management. 27 func GetFlags() C.DeviceMemoryFlags { 28 return C.GetFlags() 29 } 30 31 func IsDeviceMemoryImplementation() bool { 32 return (GetFlags() & C.DEVICE_MEMORY_IMPLEMENTATION_FLAG) != 0 33 } 34 35 func IsPooledMemory() bool { 36 return (GetFlags() & C.POOLED_MEMORY_FLAG) != 0 37 } 38 39 // Init will initialize the memory management. 40 func Init() { 41 doCGoCall(func() C.CGoCallResHandle { 42 return C.Init() 43 }) 44 } 45 46 // HostAlloc allocates memory in C. 47 func HostAlloc(bytes int) unsafe.Pointer { 48 return unsafe.Pointer(doCGoCall(func() C.CGoCallResHandle { 49 return C.HostAlloc(C.size_t(bytes)) 50 })) 51 } 52 53 // HostFree frees memory allocated in C. 54 func HostFree(p unsafe.Pointer) { 55 doCGoCall(func() C.CGoCallResHandle { 56 return C.HostFree(p) 57 }) 58 } 59 60 // MakeSliceFromCPtr make a slice that points to data that cptr points to. 61 // cptr must be a c-allocated pointer as the garbage collector will not update 62 // that uintptr's value if the golang object movee. 63 func MakeSliceFromCPtr(cptr uintptr, length int) []byte { 64 h := reflect.SliceHeader{ 65 Data: cptr, 66 Len: length, 67 Cap: length, 68 } 69 return *(*[]byte)(unsafe.Pointer(&h)) 70 } 71 72 // CreateCudaStream creates a Cuda stream. 73 func CreateCudaStream(device int) unsafe.Pointer { 74 return unsafe.Pointer(doCGoCall(func() C.CGoCallResHandle { 75 return C.CreateCudaStream(C.int(device)) 76 })) 77 } 78 79 // WaitForCudaStream block waits until all pending operations are finished on 80 // the specified Cuda stream. 81 func WaitForCudaStream(stream unsafe.Pointer, device int) { 82 if stream != nil { 83 doCGoCall(func() C.CGoCallResHandle { 84 return C.WaitForCudaStream(stream, C.int(device)) 85 }) 86 } 87 } 88 89 // DestroyCudaStream destroys the specified Cuda stream. 90 func DestroyCudaStream(stream unsafe.Pointer, device int) { 91 if stream != nil { 92 doCGoCall(func() C.CGoCallResHandle { 93 return C.DestroyCudaStream(stream, C.int(device)) 94 }) 95 } 96 } 97 98 // DeviceAllocate allocates the specified amount of memory on the device. 99 func DeviceAllocate(bytes, device int) unsafe.Pointer { 100 return unsafe.Pointer(doCGoCall(func() C.CGoCallResHandle { 101 return C.DeviceAllocate(C.size_t(bytes), C.int(device)) 102 })) 103 } 104 105 // DeviceFree frees the specified memory from the device. 106 func DeviceFree(ptr unsafe.Pointer, device int) { 107 doCGoCall(func() C.CGoCallResHandle { 108 return C.DeviceFree(ptr, C.int(device)) 109 }) 110 } 111 112 // AsyncMemCopyFunc is a abstraction of DeviceToDevice, DeviceToHost, HostToDevice memcopy functions 113 type AsyncMemCopyFunc func(dst, src unsafe.Pointer, bytes int, stream unsafe.Pointer, device int) 114 115 // AsyncCopyHostToDevice asynchronously copies the host buffer to the device 116 // buffer on the specified stream. 117 func AsyncCopyHostToDevice( 118 dst, src unsafe.Pointer, bytes int, stream unsafe.Pointer, device int) { 119 doCGoCall(func() C.CGoCallResHandle { 120 return C.AsyncCopyHostToDevice(dst, src, C.size_t(bytes), stream, C.int(device)) 121 }) 122 } 123 124 // AsyncCopyDeviceToDevice asynchronously copies the src device buffer to the 125 // dst device buffer buffer on the specified stream. 126 func AsyncCopyDeviceToDevice( 127 dst, src unsafe.Pointer, bytes int, stream unsafe.Pointer, device int) { 128 doCGoCall(func() C.CGoCallResHandle { 129 return C.AsyncCopyDeviceToDevice(dst, src, C.size_t(bytes), stream, C.int(device)) 130 }) 131 } 132 133 // AsyncCopyDeviceToHost asynchronously copies the device buffer to the host 134 // buffer on the specified stream. 135 func AsyncCopyDeviceToHost( 136 dst, src unsafe.Pointer, bytes int, stream unsafe.Pointer, device int) { 137 doCGoCall(func() C.CGoCallResHandle { 138 return C.AsyncCopyDeviceToHost(dst, src, C.size_t(bytes), stream, C.int(device)) 139 }) 140 } 141 142 // GetDeviceCount returns the number of GPU devices 143 func GetDeviceCount() int { 144 return int(doCGoCall(func() C.CGoCallResHandle { 145 return C.GetDeviceCount() 146 })) 147 } 148 149 // GetDeviceGlobalMemoryInMB returns the total global memory(MB) for a given device 150 func GetDeviceGlobalMemoryInMB(device int) int { 151 return int(doCGoCall(func() C.CGoCallResHandle { 152 return C.GetDeviceGlobalMemoryInMB(C.int(device)) 153 })) 154 } 155 156 // CudaProfilerStart starts/resumes the profiler. 157 func CudaProfilerStart() { 158 doCGoCall(func() C.CGoCallResHandle { 159 return C.CudaProfilerStart() 160 }) 161 } 162 163 // CudaProfilerStop stops/pauses the profiler. 164 func CudaProfilerStop() { 165 doCGoCall(func() C.CGoCallResHandle { 166 return C.CudaProfilerStop() 167 }) 168 } 169 170 // GetDeviceMemoryInfo returns information about total size and free size of device memory in bytes for a specfic 171 // device. 172 func GetDeviceMemoryInfo(device int) (int, int) { 173 var freeSize, totalSize C.size_t 174 doCGoCall(func() C.CGoCallResHandle { 175 return C.GetDeviceMemoryInfo(&freeSize, &totalSize, C.int(device)) 176 }) 177 return int(freeSize), int(totalSize) 178 } 179 180 // doCGoCall does the cgo call by converting CGoCallResHandle to C.int and *C.char and calls doCGoCall. 181 // The reason to have this wrapper is because CGo types are bound to package name, thereby even C.int are different types 182 // under different packages. 183 func doCGoCall(f func() C.CGoCallResHandle) uintptr { 184 return cgoutils.DoCGoCall(func() (uintptr, unsafe.Pointer) { 185 ret := f() 186 return uintptr(ret.res), unsafe.Pointer(ret.pStrErr) 187 }) 188 }