You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							137 lines
						
					
					
						
							4.2 KiB
						
					
					
				
			
		
		
	
	
							137 lines
						
					
					
						
							4.2 KiB
						
					
					
				/** Error handling macros for CUDA. All cuda routines should be wrapped
 | 
						|
 * in either a CHECK or WARN call; CHECK will print the error and exit on
 | 
						|
 * failure, while WARN will just print the error on failure. PTRINFO is
 | 
						|
 * a convenience routine for debugging data that needs to be moved to
 | 
						|
 * reg storage.
 | 
						|
 *
 | 
						|
 * By default, no checking is done, for maximum performance on production
 | 
						|
 * runs. define "GPU_CHECK_CALLS" to enable checks.
 | 
						|
 *
 | 
						|
 * TODO: add fortran interface
 | 
						|
 * */
 | 
						|
#include "cuda_runtime_api.h"
 | 
						|
#include "cublas_v2.h"
 | 
						|
 | 
						|
 | 
						|
#ifndef GPU_NO_CHECK_CALLS
 | 
						|
#define CHECK(msg, val) __checkCuda(msg, (val), __FILE__, __LINE__, true)
 | 
						|
#define WARN(msg, val) __checkCuda(msg, (val), __FILE__, __LINE__, false)
 | 
						|
#define PTRINFO(msg, ptr) __print_cuda_ptr_info(msg, ptr)
 | 
						|
#define MEMINFO(msg, ptr, size) __print_cuda_mem_info(msg, ptr, size)
 | 
						|
#else
 | 
						|
#define CHECK(msg, val) { int __i = (val); }
 | 
						|
#define WARN(msg, val)  { int __i = (val); }
 | 
						|
#define PTRINFO(msg, ptr) { void *__p = (void *)(ptr); }
 | 
						|
#define MEMINFO(msg, ptr, size)  { void *__p = (void *)(ptr); }
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
inline int __checkCuda(const char *msg, cudaError_t val, const char *fname,
 | 
						|
                        const int line, bool abort=true) {
 | 
						|
  if (val != cudaSuccess) {
 | 
						|
     fprintf(stderr,
 | 
						|
             "%s(%i): CUDA Error (%s) %i: %s\n",
 | 
						|
             fname, line, msg, val, cudaGetErrorString(val));
 | 
						|
     if (abort) {
 | 
						|
       cudaDeviceReset();
 | 
						|
         exit(EXIT_FAILURE);
 | 
						|
     }
 | 
						|
  }
 | 
						|
  return (int)val;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// overload for cublasStatus_t
 | 
						|
inline int __checkCuda(const char *msg, cublasStatus_t val, const char *fname,
 | 
						|
                        const int line, bool abort=true) {
 | 
						|
  if (val != CUBLAS_STATUS_SUCCESS) {
 | 
						|
     const char *err_s = "OTHER";
 | 
						|
     if (val == CUBLAS_STATUS_NOT_INITIALIZED) {
 | 
						|
         err_s = "NOT_INITIALIZED";
 | 
						|
     } else if (val == CUBLAS_STATUS_INVALID_VALUE) {
 | 
						|
         err_s = "INVALID_VALUE";
 | 
						|
     }
 | 
						|
     fprintf(stderr,
 | 
						|
             "%s(%i): CUDA Error (%s) %i: %s\n",
 | 
						|
             fname, line, msg, val, err_s);
 | 
						|
     if (abort) {
 | 
						|
       cudaDeviceReset();
 | 
						|
       exit(EXIT_FAILURE);
 | 
						|
     }
 | 
						|
  }
 | 
						|
  return (int)val;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
inline void __print_cuda_ptr_info(const char *label, void *ptr) {
 | 
						|
  cudaError_t cu_err;
 | 
						|
  cudaPointerAttributes attr;
 | 
						|
  const char *type_name = NULL;
 | 
						|
 | 
						|
  if (ptr == NULL) {
 | 
						|
    printf("CUDA pointer %s (%zx): NULL\n", label, ptr);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  // NB: the 'type' attribute was not added until CUDA 10.0, use memoryType
 | 
						|
  // for better compatibility
 | 
						|
  cu_err = cudaPointerGetAttributes(&attr, ptr);
 | 
						|
  if (cu_err != cudaSuccess) {
 | 
						|
    if (cu_err == cudaErrorInvalidValue) {
 | 
						|
      type_name = "Invalid (non-unified addressing)";
 | 
						|
    } else {
 | 
						|
      WARN("get pointer attr", cu_err);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  } else if (attr.type == cudaMemoryTypeDevice) {
 | 
						|
    type_name = "Device";
 | 
						|
  } else if (attr.type == cudaMemoryTypeManaged) {
 | 
						|
    type_name = "Managed";
 | 
						|
  } else if (attr.type == cudaMemoryTypeHost) {
 | 
						|
    type_name = "Host";
 | 
						|
  } else if (attr.type == cudaMemoryTypeUnregistered) {
 | 
						|
    type_name = "Unregistered";
 | 
						|
  }
 | 
						|
  printf("CUDA pointer %s (%zx): %s\n", label, ptr, type_name);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
inline void __print_cuda_mem_info(const char *label, void *ptr, size_t size) {
 | 
						|
  cudaError_t cu_err;
 | 
						|
  cudaPointerAttributes pointer_attr;
 | 
						|
  int mem_attr = -123;
 | 
						|
  bool is_managed = false;
 | 
						|
 | 
						|
  cu_err = cudaPointerGetAttributes(&pointer_attr, ptr);
 | 
						|
  if (cu_err != cudaSuccess) {
 | 
						|
    if (cu_err == cudaErrorInvalidValue) {
 | 
						|
      printf("CUDA PreferredLocation of '%s' is NOT CUDA\n", label);
 | 
						|
      return;
 | 
						|
    } else {
 | 
						|
      WARN("get pointer attr", cu_err);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  } else if (pointer_attr.type == cudaMemoryTypeManaged) {
 | 
						|
    is_managed = true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!is_managed) {
 | 
						|
    printf("CUDA PreferredLocation of '%s' is UNMANAGED\n", label);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 
 | 
						|
  WARN("get mem range preferred location",
 | 
						|
       cudaMemRangeGetAttribute(&mem_attr, sizeof(mem_attr),
 | 
						|
                                cudaMemRangeAttributePreferredLocation,
 | 
						|
                                ptr, size));
 | 
						|
  if (mem_attr == cudaCpuDeviceId) {
 | 
						|
      printf("CUDA PreferredLocation of '%s' is CPU (%d)\n", label, mem_attr);
 | 
						|
  } else if (mem_attr == cudaInvalidDeviceId) {
 | 
						|
      printf("CUDA PreferredLocation of '%s' is INVALID (%d)\n",
 | 
						|
             label, mem_attr);
 | 
						|
  } else {
 | 
						|
      printf("CUDA PreferredLocation of '%s' is DEVICE (%d)\n",
 | 
						|
             label, mem_attr);
 | 
						|
  }
 | 
						|
}
 |