@@ -523,25 +523,45 @@ class NeutronBackend final : public PyTorchBackendInterface {
523523 }
524524 }
525525
526+ // Resume (clock-ungate) the NPU immediately before inference and suspend it
527+ // again immediately after, so its clock only runs during compute
528+ #ifdef NEUTRON_NPU_POWER_GATING
529+ NeutronError resumeRC = neutronResume ();
530+ if (resumeRC != ENONE ) {
531+ ET_LOG (Error, " neutronResume failed with error code %ld" , resumeRC);
532+ return Error::InvalidProgram;
533+ }
534+ #endif
535+
526536#ifdef ET_EVENT_TRACER_ENABLED
527537 // Save ticks before neutron compute to measure how much time profiling dump
528538 // takes
529539 et_timestamp_t start_ticks = ::executorch::runtime::pal_current_ticks ();
530540#endif
531541 // Run neutron compute.
532542 NeutronError neutronRC = neutronRunBlocking (cfg->nmh , &cfg->dcfg );
543+ #ifdef ET_EVENT_TRACER_ENABLED
544+ // Save ticks after neutron compute to measure how much time profiling dump
545+ // takes
546+ et_timestamp_t stop_ticks = ::executorch::runtime::pal_current_ticks ();
547+ #endif
548+
549+ #ifdef NEUTRON_NPU_POWER_GATING
550+ // Suspend (clock-gate) the NPU again regardless of the run result; a failed
551+ // suspend only wastes power, so it must not fail the inference.
552+ NeutronError suspendRC = neutronSuspend ();
553+ if (suspendRC != ENONE ) {
554+ ET_LOG (Error, " neutronSuspend failed with error code %ld" , suspendRC);
555+ }
556+ #endif
557+
533558 if (neutronRC != ENONE ) {
534559 ET_LOG (
535560 Error,
536561 " Neutron model evaluation failed with error code %ld" ,
537562 neutronRC);
538563 return Error::InvalidProgram;
539564 }
540- #ifdef ET_EVENT_TRACER_ENABLED
541- // Save ticks after neutron compute to measure how much time profiling dump
542- // takes
543- et_timestamp_t stop_ticks = ::executorch::runtime::pal_current_ticks ();
544- #endif
545565
546566 // Transpose outputs.
547567 for (int i = 0 ; i < cfg->numOutputs ; i++) {
0 commit comments