@@ -1384,192 +1384,19 @@ Status QnnBackendManager::CreateHtpPowerCfgId(uint32_t device_id, uint32_t core_
13841384 return Status::OK ();
13851385}
13861386
1387- Status QnnBackendManager::SetHtpPowerConfig (uint32_t htp_power_config_client_id,
1388- HtpPerformanceMode htp_performance_mode) {
1387+ Status QnnBackendManager::SetHtpPowerConfigs (uint32_t htp_power_config_client_id,
1388+ HtpPerformanceMode htp_performance_mode,
1389+ uint32_t rpc_polling_time,
1390+ uint32_t rpc_control_latency) {
13891391 // This function is called in QNN EP's OnRunStart() even if QNN backend setup failed and the model is assigned
13901392 // to a different EP. Therefore, we have to check that backend setup actually completed before trying to
13911393 // set an HTP power config ID. Otherwise, this causes a segfault because the QNN backend lib is unloaded.
13921394 ORT_RETURN_IF_NOT (backend_setup_completed_, " Cannot set HTP power config ID if backend setup is not complete." );
1393- QnnDevice_Infrastructure_t qnn_device_infra = nullptr ;
1394- auto status = qnn_interface_.deviceGetInfrastructure (&qnn_device_infra);
1395- ORT_RETURN_IF (QNN_SUCCESS != status, " backendGetPerfInfrastructure failed." );
1396-
1397- auto * htp_infra = static_cast <QnnHtpDevice_Infrastructure_t*>(qnn_device_infra);
1398- ORT_RETURN_IF (QNN_HTP_DEVICE_INFRASTRUCTURE_TYPE_PERF != htp_infra->infraType ,
1399- " HTP infra type = " , htp_infra->infraType , " , which is not perf infra type." );
1400- QnnHtpDevice_PerfInfrastructure_t& htp_perf_infra = htp_infra->perfInfra ;
14011395
1402- constexpr const int kNumConfigs = 1 ;
1403- std::vector<QnnHtpPerfInfrastructure_PowerConfig_t> power_configs (
1404- kNumConfigs );
1405- QnnHtpPerfInfrastructure_PowerConfig_t& dcvs_config = power_configs[0 ];
1406- dcvs_config.option = QNN_HTP_PERF_INFRASTRUCTURE_POWER_CONFIGOPTION_DCVS_V3 ;
1407- QnnHtpPerfInfrastructure_DcvsV3_t& dcvs_v3 = dcvs_config.dcvsV3Config ;
1408- dcvs_v3.contextId = htp_power_config_client_id;
1409- dcvs_v3.setSleepDisable = 0 ;
1410- dcvs_v3.sleepDisable = 0 ;
1411- dcvs_v3.setDcvsEnable = 1 ;
1412- dcvs_v3.powerMode = QNN_HTP_PERF_INFRASTRUCTURE_POWERMODE_PERFORMANCE_MODE ;
1413- // choose performance mode
1414- switch (htp_performance_mode) {
1415- case HtpPerformanceMode::kHtpBurst :
1416- case HtpPerformanceMode::kHtpSustainedHighPerformance :
1417- dcvs_v3.setSleepLatency = 1 ; // true
1418- dcvs_v3.sleepLatency = kSleepMinLatency ;
1419- dcvs_v3.dcvsEnable = kDcvsDisable ;
1420- dcvs_v3.setBusParams = 1 ;
1421- dcvs_v3.busVoltageCornerMin = DCVS_VOLTAGE_VCORNER_MAX_VOLTAGE_CORNER ;
1422- dcvs_v3.busVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_MAX_VOLTAGE_CORNER ;
1423- dcvs_v3.busVoltageCornerMax = DCVS_VOLTAGE_VCORNER_MAX_VOLTAGE_CORNER ;
1424- dcvs_v3.setCoreParams = 1 ;
1425- dcvs_v3.coreVoltageCornerMin = DCVS_VOLTAGE_VCORNER_MAX_VOLTAGE_CORNER ;
1426- dcvs_v3.coreVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_MAX_VOLTAGE_CORNER ;
1427- dcvs_v3.coreVoltageCornerMax = DCVS_VOLTAGE_VCORNER_MAX_VOLTAGE_CORNER ;
1428- break ;
1429- case HtpPerformanceMode::kHtpHighPerformance :
1430- dcvs_v3.setSleepLatency = 1 ; // true
1431- dcvs_v3.sleepLatency = kSleepLowLatency ;
1432- dcvs_v3.dcvsEnable = kDcvsDisable ;
1433- dcvs_v3.setBusParams = 1 ;
1434- dcvs_v3.busVoltageCornerMin = DCVS_VOLTAGE_VCORNER_TURBO ;
1435- dcvs_v3.busVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_TURBO ;
1436- dcvs_v3.busVoltageCornerMax = DCVS_VOLTAGE_VCORNER_TURBO ;
1437- dcvs_v3.setCoreParams = 1 ;
1438- dcvs_v3.coreVoltageCornerMin = DCVS_VOLTAGE_VCORNER_TURBO ;
1439- dcvs_v3.coreVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_TURBO ;
1440- dcvs_v3.coreVoltageCornerMax = DCVS_VOLTAGE_VCORNER_TURBO ;
1441- break ;
1442- case HtpPerformanceMode::kHtpBalanced :
1443- dcvs_v3.setSleepLatency = 1 ; // true
1444- dcvs_v3.sleepLatency = kSleepMediumLatency ;
1445- dcvs_v3.dcvsEnable = kDcvsEnable ;
1446- dcvs_v3.setBusParams = 1 ;
1447- dcvs_v3.busVoltageCornerMin = DCVS_VOLTAGE_VCORNER_NOM_PLUS ;
1448- dcvs_v3.busVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_NOM_PLUS ;
1449- dcvs_v3.busVoltageCornerMax = DCVS_VOLTAGE_VCORNER_NOM_PLUS ;
1450- dcvs_v3.setCoreParams = 1 ;
1451- dcvs_v3.coreVoltageCornerMin = DCVS_VOLTAGE_VCORNER_NOM_PLUS ;
1452- dcvs_v3.coreVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_NOM_PLUS ;
1453- dcvs_v3.coreVoltageCornerMax = DCVS_VOLTAGE_VCORNER_NOM_PLUS ;
1454- break ;
1455- case HtpPerformanceMode::kHtpLowBalanced :
1456- dcvs_v3.setSleepLatency = 1 ; // true
1457- dcvs_v3.sleepLatency = kSleepMediumLatency ;
1458- dcvs_v3.dcvsEnable = kDcvsEnable ;
1459- dcvs_v3.setBusParams = 1 ;
1460- dcvs_v3.busVoltageCornerMin = DCVS_VOLTAGE_VCORNER_NOM ;
1461- dcvs_v3.busVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_NOM ;
1462- dcvs_v3.busVoltageCornerMax = DCVS_VOLTAGE_VCORNER_NOM ;
1463- dcvs_v3.setCoreParams = 1 ;
1464- dcvs_v3.coreVoltageCornerMin = DCVS_VOLTAGE_VCORNER_NOM ;
1465- dcvs_v3.coreVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_NOM ;
1466- dcvs_v3.coreVoltageCornerMax = DCVS_VOLTAGE_VCORNER_NOM ;
1467- break ;
1468- case HtpPerformanceMode::kHtpHighPowerSaver :
1469- dcvs_v3.setSleepLatency = 1 ; // true
1470- dcvs_v3.sleepLatency = kSleepMediumLatency ;
1471- dcvs_v3.dcvsEnable = kDcvsEnable ;
1472- dcvs_v3.setBusParams = 1 ;
1473- dcvs_v3.busVoltageCornerMin = DCVS_VOLTAGE_VCORNER_SVS_PLUS ;
1474- dcvs_v3.busVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_SVS_PLUS ;
1475- dcvs_v3.busVoltageCornerMax = DCVS_VOLTAGE_VCORNER_SVS_PLUS ;
1476- dcvs_v3.setCoreParams = 1 ;
1477- dcvs_v3.coreVoltageCornerMin = DCVS_VOLTAGE_VCORNER_SVS_PLUS ;
1478- dcvs_v3.coreVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_SVS_PLUS ;
1479- dcvs_v3.coreVoltageCornerMax = DCVS_VOLTAGE_VCORNER_SVS_PLUS ;
1480- break ;
1481- case HtpPerformanceMode::kHtpPowerSaver :
1482- dcvs_v3.setSleepLatency = 1 ; // true
1483- dcvs_v3.sleepLatency = kSleepMediumLatency ;
1484- dcvs_v3.dcvsEnable = kDcvsEnable ;
1485- dcvs_v3.setBusParams = 1 ;
1486- dcvs_v3.busVoltageCornerMin = DCVS_VOLTAGE_VCORNER_SVS ;
1487- dcvs_v3.busVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_SVS ;
1488- dcvs_v3.busVoltageCornerMax = DCVS_VOLTAGE_VCORNER_SVS ;
1489- dcvs_v3.setCoreParams = 1 ;
1490- dcvs_v3.coreVoltageCornerMin = DCVS_VOLTAGE_VCORNER_SVS ;
1491- dcvs_v3.coreVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_SVS ;
1492- dcvs_v3.coreVoltageCornerMax = DCVS_VOLTAGE_VCORNER_SVS ;
1493- break ;
1494- case HtpPerformanceMode::kHtpLowPowerSaver :
1495- dcvs_v3.setSleepLatency = 1 ; // true
1496- dcvs_v3.sleepLatency = kSleepMediumLatency ;
1497- dcvs_v3.dcvsEnable = kDcvsEnable ;
1498- dcvs_v3.setBusParams = 1 ;
1499- dcvs_v3.busVoltageCornerMin = DCVS_VOLTAGE_VCORNER_SVS2 ;
1500- dcvs_v3.busVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_SVS2 ;
1501- dcvs_v3.busVoltageCornerMax = DCVS_VOLTAGE_VCORNER_SVS2 ;
1502- dcvs_v3.setCoreParams = 1 ;
1503- dcvs_v3.coreVoltageCornerMin = DCVS_VOLTAGE_VCORNER_SVS2 ;
1504- dcvs_v3.coreVoltageCornerTarget = DCVS_VOLTAGE_VCORNER_SVS2 ;
1505- dcvs_v3.coreVoltageCornerMax = DCVS_VOLTAGE_VCORNER_SVS2 ;
1506- break ;
1507- case HtpPerformanceMode::kHtpExtremePowerSaver :
1508- dcvs_v3.powerMode = QNN_HTP_PERF_INFRASTRUCTURE_POWERMODE_POWER_SAVER_MODE ;
1509- dcvs_v3.setSleepLatency = 1 ; // true
1510- dcvs_v3.sleepLatency = kSleepMediumLatency ;
1511- dcvs_v3.dcvsEnable = kDcvsEnable ;
1512- dcvs_v3.setBusParams = 1 ;
1513- dcvs_v3.busVoltageCornerMin = DCVS_VOLTAGE_CORNER_DISABLE ;
1514- dcvs_v3.busVoltageCornerTarget = DCVS_VOLTAGE_CORNER_DISABLE ;
1515- dcvs_v3.busVoltageCornerMax = DCVS_VOLTAGE_CORNER_DISABLE ;
1516- dcvs_v3.setCoreParams = 1 ;
1517- dcvs_v3.coreVoltageCornerMin = DCVS_VOLTAGE_CORNER_DISABLE ;
1518- dcvs_v3.coreVoltageCornerTarget = DCVS_VOLTAGE_CORNER_DISABLE ;
1519- dcvs_v3.coreVoltageCornerMax = DCVS_VOLTAGE_CORNER_DISABLE ;
1520- break ;
1521- default :
1522- ORT_THROW (" Invalid performance profile %d" , static_cast <int >(htp_performance_mode));
1523- break ;
1524- }
1525- std::vector<const QnnHtpPerfInfrastructure_PowerConfig_t*> perf_power_configs_ptr = ObtainNullTermPtrVector (power_configs);
1526- status = htp_perf_infra.setPowerConfig (htp_power_config_client_id, perf_power_configs_ptr.data ());
1527- ORT_RETURN_IF (QNN_SUCCESS != status, " setPowerConfig failed for HTP performance mode." );
1528-
1529- return Status::OK ();
1530- }
1531-
1532- Status QnnBackendManager::SetRpcPowerConfigs (uint32_t htp_power_config_client_id,
1533- uint32_t rpc_control_latency,
1534- uint32_t rpc_polling_time) {
1535- // This function is called in QNN EP's OnRunStart() even if QNN backend setup failed and the model is assigned
1536- // to a different EP. Therefore, we have to check that backend setup actually completed before trying to
1537- // set RPC control latency. Otherwise, this causes a segfault because the QNN backend library is unloaded.
1538- ORT_RETURN_IF_NOT (backend_setup_completed_, " Cannot set HTP RPC control latency if backend setup is not complete." );
1539-
1540- constexpr int kNumRpcPollingPowerConfigs = 2 ;
1541- std::vector<QnnHtpPerfInfrastructure_PowerConfig_t> rpc_power_configs;
1542- rpc_power_configs.reserve (kNumRpcPollingPowerConfigs );
1543-
1544- // Set rpc control latency here
1545- if (rpc_control_latency != 0 ) {
1546- auto & rpc_control_latency_cfg = rpc_power_configs.emplace_back ();
1547- rpc_control_latency_cfg.option = QNN_HTP_PERF_INFRASTRUCTURE_POWER_CONFIGOPTION_RPC_CONTROL_LATENCY ;
1548- rpc_control_latency_cfg.rpcControlLatencyConfig = rpc_control_latency;
1549- }
1550-
1551- // Note: v68 does not support rpc polling mode
1552- if (rpc_polling_time != 0 ) {
1553- auto & rpc_polling_time_cfg = rpc_power_configs.emplace_back ();
1554- rpc_polling_time_cfg.option = QNN_HTP_PERF_INFRASTRUCTURE_POWER_CONFIGOPTION_RPC_POLLING_TIME ;
1555- rpc_polling_time_cfg.rpcPollingTimeConfig = rpc_polling_time;
1556- }
1557-
1558- if (rpc_power_configs.size () > 0 ) {
1559- QnnDevice_Infrastructure_t qnn_device_infra = nullptr ;
1560- auto status = qnn_interface_.deviceGetInfrastructure (&qnn_device_infra);
1561- ORT_RETURN_IF (QNN_SUCCESS != status, " backendGetPerfInfrastructure failed." );
1562-
1563- auto * htp_infra = static_cast <QnnHtpDevice_Infrastructure_t*>(qnn_device_infra);
1564- ORT_RETURN_IF (QNN_HTP_DEVICE_INFRASTRUCTURE_TYPE_PERF != htp_infra->infraType ,
1565- " HTP infra type = " , htp_infra->infraType , " , which is not perf infra type." );
1566- QnnHtpDevice_PerfInfrastructure_t& htp_perf_infra = htp_infra->perfInfra ;
1567-
1568- std::vector<const QnnHtpPerfInfrastructure_PowerConfig_t*> perf_power_configs_ptr =
1569- ObtainNullTermPtrVector (rpc_power_configs);
1570- status = htp_perf_infra.setPowerConfig (htp_power_config_client_id, perf_power_configs_ptr.data ());
1571- ORT_RETURN_IF (QNN_SUCCESS != status, " setPowerConfig failed for RPC control latency." );
1572- }
1396+ ORT_RETURN_IF_ERROR (htp_power_config_manager_.AddRpcPollingTime (rpc_polling_time));
1397+ ORT_RETURN_IF_ERROR (htp_power_config_manager_.AddRpcControlLatency (rpc_control_latency));
1398+ ORT_RETURN_IF_ERROR (htp_power_config_manager_.AddHtpPerformanceMode (htp_performance_mode, htp_power_config_client_id));
1399+ ORT_RETURN_IF_ERROR (htp_power_config_manager_.SetPowerConfig (htp_power_config_client_id, GetQnnInterface ()));
15731400
15741401 return Status::OK ();
15751402}
@@ -1583,18 +1410,24 @@ Status QnnBackendManager::SetPerThreadHtpPowerConfigs(const std::thread::id& thr
15831410 auto htp_power_config_id = htp_power_configs.power_config_id ;
15841411 if (pre_run) {
15851412 if (htp_power_configs.pre_run_perf_mode .has_value ()) {
1586- ORT_RETURN_IF_ERROR (SetHtpPowerConfig (htp_power_config_id, *htp_power_configs.pre_run_perf_mode ));
1413+ ORT_RETURN_IF_ERROR (htp_power_config_manager_.AddHtpPerformanceMode (*htp_power_configs.pre_run_perf_mode ,
1414+ htp_power_config_id));
1415+ }
1416+
1417+ if (htp_power_configs.rpc_control_latency .has_value ()) {
1418+ ORT_RETURN_IF_ERROR (htp_power_config_manager_.AddRpcControlLatency (*htp_power_configs.rpc_control_latency ));
15871419 }
15881420
1589- if (htp_power_configs.rpc_configs .has_value ()) {
1590- ORT_RETURN_IF_ERROR (SetRpcPowerConfigs (htp_power_config_id,
1591- htp_power_configs.rpc_configs ->rpc_control_latency ,
1592- htp_power_configs.rpc_configs ->rpc_polling_time ));
1421+ if (htp_power_configs.rpc_polling_time .has_value ()) {
1422+ ORT_RETURN_IF_ERROR (htp_power_config_manager_.AddRpcPollingTime (*htp_power_configs.rpc_polling_time ));
15931423 }
15941424 } else if (htp_power_configs.post_run_perf_mode .has_value ()) {
1595- ORT_RETURN_IF_ERROR (SetHtpPowerConfig (htp_power_config_id, *htp_power_configs.post_run_perf_mode ));
1425+ ORT_RETURN_IF_ERROR (htp_power_config_manager_.AddHtpPerformanceMode (*htp_power_configs.post_run_perf_mode ,
1426+ htp_power_config_id));
15961427 }
15971428
1429+ ORT_RETURN_IF_ERROR (htp_power_config_manager_.SetPowerConfig (htp_power_config_id, GetQnnInterface ()));
1430+
15981431 return Status::OK ();
15991432}
16001433
0 commit comments