1 #ifndef GPU_OBJECT_LIFETIME_H 2 #define GPU_OBJECT_LIFETIME_H 3 4 #include <array> 5 #include <stdio.h> 6 #include <string.h> 7 8 namespace Halide { 9 namespace Internal { 10 11 class GpuObjectLifetimeTracker { 12 struct ObjectType { 13 const char *const created; 14 const char *const destroyed; 15 bool const is_global; 16 int total_created; 17 int live_count; 18 19 ObjectType(const char *created, const char *destroyed, bool is_global = false) createdObjectType20 : created(created), destroyed(destroyed), 21 is_global(is_global), total_created(0), live_count(0) { 22 } 23 }; 24 25 std::array<ObjectType, 13> object_types = {{ 26 // OpenCL objects 27 {"clCreateContext", "clReleaseContext", true}, 28 {"clCreateCommandQueue", "clReleaseCommandQueue", true}, 29 // This handles both "clCreateProgramWithSource" and 30 // "clCreateProgramWithBinary". 31 {"clCreateProgram", "clReleaseProgram"}, 32 {"clCreateBuffer", "clReleaseMemObject"}, 33 {"clCreateKernel", "clReleaseKernel"}, 34 35 // CUDA objects 36 {"cuCtxCreate", "cuCtxDestroy", true}, 37 {"cuModuleLoad", "cuModuleUnload"}, 38 {"cuMemAlloc", "cuMemFree"}, 39 40 // Metal objects 41 {"Allocating: MTLCreateSystemDefaultDevice", "Releasing: MTLCreateSystemDefaultDevice", true}, 42 {"Allocating: new_command_queue", "Releasing: new_command_queue"}, 43 {"Allocating: new_library_with_source", "Releasing: new_library_with_source"}, 44 45 // Hexagon objects 46 {"halide_remote_load_library", "halide_remote_release_library"}, 47 {"ion_alloc", "ion_free"}, 48 }}; 49 50 public: 51 // Parse a line of output from gpu_debug and update object counts. record_gpu_debug(const char * str)52 void record_gpu_debug(const char *str) { 53 for (auto &o : object_types) { 54 if (strstr(str, o.created)) { 55 o.total_created++; 56 o.live_count++; 57 } else if (strstr(str, o.destroyed)) { 58 o.live_count--; 59 } 60 } 61 } 62 63 // Check that there are no live objects remaining, and we created at least one object. validate_gpu_object_lifetime(bool allow_globals,bool allow_none,int max_globals)64 int validate_gpu_object_lifetime(bool allow_globals, bool allow_none, int max_globals) { 65 int total = 0; 66 for (auto &o : object_types) { 67 if (o.live_count != 0 && 68 !(allow_globals && o.is_global)) { 69 printf("Error! %d objects created by %s still live\n", 70 o.live_count, o.created); 71 return -1; 72 } 73 if (o.is_global && o.total_created > max_globals) { 74 printf("Error! %d global objects created by %s, max is %d\n", 75 o.total_created, o.created, max_globals); 76 return -1; 77 } 78 79 total += o.total_created; 80 } 81 if (!allow_none && total == 0) { 82 printf("Error! No objects created. Ensure gpu_debug is set, "); 83 printf("and record_gpu_debug is called from halide_print.\n"); 84 return -1; 85 } 86 return 0; 87 } 88 }; 89 90 } // namespace Internal 91 } // namespace Halide 92 93 #endif 94