docs: @Override
      public PointersPair malloc(AllocationShape shape, AllocationPoint point, AllocationStatus location) {
  
          //log.info("shape onCreate: {}, target: {}", shape, location);
  
          switch (location) {
              case HOST: {
                  long reqMem = AllocationUtils.getRequiredMemory(shape);
  
                  // FIXME: this is WRONG, and directly leads to memleak
                  if (reqMem < 1)
                      reqMem = 1;
  
                  val pointer = nativeOps.mallocHost(reqMem, 0);
                  if (pointer == null)
                      throw new RuntimeException("Can't allocate [HOST] memory: " + reqMem + "; threadId: "
                                      + Thread.currentThread().getId());
  
                  //                log.info("Host allocation, Thread id: {}, ReqMem: {}, Pointer: {}", Thread.currentThread().getId(), reqMem, pointer != null ? pointer.address() : null);
  
                  val hostPointer = new CudaPointer(pointer);
  
                  val devicePointerInfo = new PointersPair();
                  devicePointerInfo.setDevicePointer(new CudaPointer(hostPointer, reqMem));
                  devicePointerInfo.setHostPointer(new CudaPointer(hostPointer, reqMem));
  
                  point.setPointers(devicePointerInfo);
  
                  point.setAllocationStatus(AllocationStatus.HOST);
  
                  MemoryTracker.getInstance().incrementAllocatedHostAmount(reqMem);
  
                  return devicePointerInfo;
              }
              case DEVICE: {
                  // cudaMalloc call
                  val deviceId = AtomicAllocator.getInstance().getDeviceId();
                  long reqMem = AllocationUtils.getRequiredMemory(shape);
  
                  // FIXME: this is WRONG, and directly leads to memleak
                  if (reqMem < 1)
                      reqMem = 1;
  
                  AllocationsTracker.getInstance().markAllocated(AllocationKind.GENERAL, deviceId, reqMem);
                  var pointer = nativeOps.mallocDevice(reqMem, deviceId, 0);
                  if (pointer == null) {
                      // try to purge stuff if we're low on memory
                      purgeCache(deviceId);
  
                      // call for gc
                      Nd4j.getMemoryManager().invokeGc();
  
                      pointer = nativeOps.mallocDevice(reqMem, deviceId, 0);
                      if (pointer == null)
                          return null;
                  }
  
                  val devicePointer = new CudaPointer(pointer);
  
                  var devicePointerInfo = point.getPointers();
                  if (devicePointerInfo == null)
                      devicePointerInfo = new PointersPair();
                  devicePointerInfo.setDevicePointer(new CudaPointer(devicePointer, reqMem));
  
                  point.setAllocationStatus(AllocationStatus.DEVICE);
                  point.setDeviceId(deviceId);
                  MemoryTracker.getInstance().incrementAllocatedAmount(deviceId, reqMem);
                  return devicePointerInfo;
              }
              default:
                  throw new IllegalStateException("Unsupported location for malloc: [" + location + "]");
          }
      }