@@ -309,25 +309,26 @@ ur_adapter_handle_t_::ur_adapter_handle_t_()
309
309
310
310
if (UrL0Debug & UR_L0_DEBUG_BASIC) {
311
311
logger.setLegacySink (std::make_unique<ur_legacy_sink>());
312
- #ifdef UR_ADAPTER_LEVEL_ZERO_V2
313
- setEnvVar (" ZEL_ENABLE_LOADER_LOGGING" , " 1" );
314
- setEnvVar (" ZEL_LOADER_LOGGING_LEVEL" , " trace" );
315
- setEnvVar (" ZEL_LOADER_LOG_CONSOLE" , " 1" );
316
- setEnvVar (" ZE_ENABLE_VALIDATION_LAYER" , " 1" );
317
- #endif
318
312
};
319
313
320
314
if (UrL0Debug & UR_L0_DEBUG_VALIDATION) {
321
315
setEnvVar (" ZE_ENABLE_VALIDATION_LAYER" , " 1" );
322
316
setEnvVar (" ZE_ENABLE_PARAMETER_VALIDATION" , " 1" );
323
317
}
324
318
325
- if (UrL0LeaksDebug) {
326
- setEnvVar (" ZE_ENABLE_VALIDATION_LAYER" , " 1" );
327
- setEnvVar (" ZEL_ENABLE_BASIC_LEAK_CHECKER" , " 1" );
328
- }
329
-
330
319
PlatformCache.Compute = [](Result<PlatformVec> &result) {
320
+ static std::once_flag ZeCallCountInitialized;
321
+ try {
322
+ std::call_once (ZeCallCountInitialized, []() {
323
+ if (UrL0LeaksDebug) {
324
+ ZeCallCount = new std::map<std::string, int >;
325
+ }
326
+ });
327
+ } catch (...) {
328
+ result = exceptionToResult (std::current_exception ());
329
+ return ;
330
+ }
331
+
331
332
uint32_t UserForcedSysManInit = 0 ;
332
333
// Check if the user has disabled the default L0 Env initialization.
333
334
const int UrSysManEnvInitEnabled = [&UserForcedSysManInit] {
@@ -418,17 +419,6 @@ ur_adapter_handle_t_::ur_adapter_handle_t_()
418
419
loader_version.patch >= 2 )) {
419
420
useInitDrivers = true ;
420
421
}
421
-
422
- #ifdef UR_ADAPTER_LEVEL_ZERO_V2
423
- if ((loader_version.major == 1 && loader_version.minor < 21 ) ||
424
- (loader_version.major == 1 && loader_version.minor == 21 &&
425
- loader_version.patch < 2 )) {
426
- UR_LOG (
427
- WARN,
428
- " WARNING: Level Zero Loader version is older than 1.21.2. "
429
- " Please update to the latest version for API logging support.\n " );
430
- }
431
- #endif
432
422
}
433
423
434
424
if (useInitDrivers) {
@@ -545,6 +535,97 @@ void globalAdapterOnDemandCleanup() {
545
535
}
546
536
547
537
ur_result_t adapterStateTeardown () {
538
+ // Print the balance of various create/destroy native calls.
539
+ // The idea is to verify if the number of create(+) and destroy(-) calls are
540
+ // matched.
541
+ if (ZeCallCount && (UrL0LeaksDebug) != 0 ) {
542
+ bool LeakFound = false ;
543
+ // clang-format off
544
+ //
545
+ // The format of this table is such that each row accounts for a
546
+ // specific type of objects, and all elements in the raw except the last
547
+ // one are allocating objects of that type, while the last element is known
548
+ // to deallocate objects of that type.
549
+ //
550
+ std::vector<std::vector<std::string>> CreateDestroySet = {
551
+ {" zeContextCreate" , " zeContextDestroy" },
552
+ {" zeCommandQueueCreate" , " zeCommandQueueDestroy" },
553
+ {" zeModuleCreate" , " zeModuleDestroy" },
554
+ {" zeKernelCreate" , " zeKernelDestroy" },
555
+ {" zeEventPoolCreate" , " zeEventPoolDestroy" },
556
+ {" zeCommandListCreateImmediate" , " zeCommandListCreate" , " zeCommandListDestroy" },
557
+ {" zeEventCreate" , " zeEventDestroy" },
558
+ {" zeFenceCreate" , " zeFenceDestroy" },
559
+ {" zeImageCreate" ," zeImageViewCreateExt" , " zeImageDestroy" },
560
+ {" zeSamplerCreate" , " zeSamplerDestroy" },
561
+ {" zeMemAllocDevice" , " zeMemAllocHost" , " zeMemAllocShared" , " zeMemFree" },
562
+ };
563
+
564
+ // A sample output aimed below is this:
565
+ // ------------------------------------------------------------------------
566
+ // zeContextCreate = 1 \---> zeContextDestroy = 1
567
+ // zeCommandQueueCreate = 1 \---> zeCommandQueueDestroy = 1
568
+ // zeModuleCreate = 1 \---> zeModuleDestroy = 1
569
+ // zeKernelCreate = 1 \---> zeKernelDestroy = 1
570
+ // zeEventPoolCreate = 1 \---> zeEventPoolDestroy = 1
571
+ // zeCommandListCreateImmediate = 1 |
572
+ // zeCommandListCreate = 1 \---> zeCommandListDestroy = 1 ---> LEAK = 1
573
+ // zeEventCreate = 2 \---> zeEventDestroy = 2
574
+ // zeFenceCreate = 1 \---> zeFenceDestroy = 1
575
+ // zeImageCreate = 0 \---> zeImageDestroy = 0
576
+ // zeSamplerCreate = 0 \---> zeSamplerDestroy = 0
577
+ // zeMemAllocDevice = 0 |
578
+ // zeMemAllocHost = 1 |
579
+ // zeMemAllocShared = 0 \---> zeMemFree = 1
580
+ //
581
+ // clang-format on
582
+ // TODO: use logger to print this messages
583
+ std::cerr << " Check balance of create/destroy calls\n " ;
584
+ std::cerr << " ----------------------------------------------------------\n " ;
585
+ std::stringstream ss;
586
+ for (const auto &Row : CreateDestroySet) {
587
+ int diff = 0 ;
588
+ for (auto I = Row.begin (); I != Row.end ();) {
589
+ const char *ZeName = (*I).c_str ();
590
+ const auto &ZeCount = (*ZeCallCount)[*I];
591
+
592
+ bool First = (I == Row.begin ());
593
+ bool Last = (++I == Row.end ());
594
+
595
+ if (Last) {
596
+ ss << " \\ --->" ;
597
+ diff -= ZeCount;
598
+ } else {
599
+ diff += ZeCount;
600
+ if (!First) {
601
+ ss << " | " ;
602
+ std::cerr << ss.str () << " \n " ;
603
+ ss.str (" " );
604
+ ss.clear ();
605
+ }
606
+ }
607
+ ss << std::setw (30 ) << std::right << ZeName;
608
+ ss << " = " ;
609
+ ss << std::setw (5 ) << std::left << ZeCount;
610
+ }
611
+
612
+ if (diff) {
613
+ LeakFound = true ;
614
+ ss << " ---> LEAK = " << diff;
615
+ }
616
+
617
+ std::cerr << ss.str () << ' \n ' ;
618
+ ss.str (" " );
619
+ ss.clear ();
620
+ }
621
+
622
+ ZeCallCount->clear ();
623
+ delete ZeCallCount;
624
+ ZeCallCount = nullptr ;
625
+ if (LeakFound)
626
+ return UR_RESULT_ERROR_INVALID_MEM_OBJECT;
627
+ }
628
+
548
629
// Due to multiple DLLMain definitions with SYCL, register to cleanup the
549
630
// Global Adapter after refcnt is 0
550
631
#if defined(_WIN32)
0 commit comments