* power: remove experimental empty poll API @ 2022-12-20 12:56 David Hunt 2022-12-20 12:56 ` [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt ` (2 more replies) 0 siblings, 3 replies; 14+ messages in thread From: David Hunt @ 2022-12-20 12:56 UTC (permalink / raw) To: dev; +Cc: david.hunt The empty poll mechanism was an experimental API added in commit id 450f0791312c. It aimed to allow power saving depending on the traffic profile. However, it required a training phase and required the user to adjust magic numbers depending on their workload. A new and improved mechanism was added in commit id 682a645438c5, also based on empty polls, implemented a callback mechanism which added 'monitor', 'pause' and 'scale' modes in l3fwd-power. This was and easier mechanism to use, so the original empty poll mechanism is no longer needed. This patch set removes the experimental empty poll API, the empty poll mode from l3fwd-power, and related documentation. This is based on a deprecation notice in the previous release. [1/3] examples/power: remove empty poll mode from [2/3] libs/power: remove experimental empty poll API [3/3] doc/power: remove empty poll documentation ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power 2022-12-20 12:56 power: remove experimental empty poll API David Hunt @ 2022-12-20 12:56 ` David Hunt 2022-12-20 13:26 ` Hunt, David ` (2 more replies) 2022-12-20 12:56 ` [PATCH v1 2/3] libs/power: " David Hunt 2022-12-20 12:56 ` [PATCH v1 3/3] doc/power: remove empty poll documentation David Hunt 2 siblings, 3 replies; 14+ messages in thread From: David Hunt @ 2022-12-20 12:56 UTC (permalink / raw) To: dev; +Cc: david.hunt Remove calls to the experimental empty poll API. l3fwd-power is the only app that uses this. This API is no longer needed as it is superceded by the monitor/pause/scale callback mechanism. Signed-off-by: David Hunt <david.hunt@intel.com> --- examples/l3fwd-power/main.c | 266 +----------------------------------- 1 file changed, 5 insertions(+), 261 deletions(-) diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c index fd3ade330f..015e7b9197 100644 --- a/examples/l3fwd-power/main.c +++ b/examples/l3fwd-power/main.c @@ -43,7 +43,6 @@ #include <rte_timer.h> #include <rte_power.h> #include <rte_spinlock.h> -#include <rte_power_empty_poll.h> #include <rte_metrics.h> #include <rte_telemetry.h> #include <rte_power_pmd_mgmt.h> @@ -125,14 +124,6 @@ #define RX_DESC_DEFAULT 1024 #define TX_DESC_DEFAULT 1024 -/* - * These two thresholds were decided on by running the training algorithm on - * a 2.5GHz Xeon. These defaults can be overridden by supplying non-zero values - * for the med_threshold and high_threshold parameters on the command line. - */ -#define EMPTY_POLL_MED_THRESHOLD 350000UL -#define EMPTY_POLL_HGH_THRESHOLD 580000UL - #define NUM_TELSTATS RTE_DIM(telstats_strings) static uint16_t nb_rxd = RX_DESC_DEFAULT; @@ -150,12 +141,7 @@ static uint32_t enabled_port_mask = 0; static int promiscuous_on = 0; /* NUMA is enabled by default. */ static int numa_on = 1; -static bool empty_poll_stop; -static bool empty_poll_train; volatile bool quit_signal; -static struct ep_params *ep_params; -static struct ep_policy policy; -static long ep_med_edpi, ep_hgh_edpi; /* timer to update telemetry every 500ms */ static struct rte_timer telemetry_timer; @@ -207,7 +193,6 @@ static int parse_ptype; /**< Parse packet type using rx callback, and */ enum appmode { APP_MODE_DEFAULT = 0, APP_MODE_LEGACY, - APP_MODE_EMPTY_POLL, APP_MODE_TELEMETRY, APP_MODE_INTERRUPT, APP_MODE_PMD_MGMT @@ -423,14 +408,6 @@ static inline uint32_t power_idle_heuristic(uint32_t zero_rx_packet_count); static inline enum freq_scale_hint_t power_freq_scaleup_heuristic( \ unsigned int lcore_id, uint16_t port_id, uint16_t queue_id); - -/* - * These defaults are using the max frequency index (1), a medium index (9) - * and a typical low frequency index (14). These can be adjusted to use - * different indexes using the relevant command line parameters. - */ -static uint8_t freq_tlb[] = {14, 9, 1}; - static int is_done(void) { return quit_signal; @@ -1217,110 +1194,7 @@ main_telemetry_loop(__rte_unused void *dummy) return 0; } -/* main processing loop */ -static int -main_empty_poll_loop(__rte_unused void *dummy) -{ - struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; - unsigned int lcore_id; - uint64_t prev_tsc, diff_tsc, cur_tsc; - int i, j, nb_rx; - uint8_t queueid; - uint16_t portid; - struct lcore_conf *qconf; - struct lcore_rx_queue *rx_queue; - - const uint64_t drain_tsc = - (rte_get_tsc_hz() + US_PER_S - 1) / - US_PER_S * BURST_TX_DRAIN_US; - - prev_tsc = 0; - - lcore_id = rte_lcore_id(); - qconf = &lcore_conf[lcore_id]; - - if (qconf->n_rx_queue == 0) { - RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", - lcore_id); - return 0; - } - - for (i = 0; i < qconf->n_rx_queue; i++) { - portid = qconf->rx_queue_list[i].port_id; - queueid = qconf->rx_queue_list[i].queue_id; - RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%u " - "rxqueueid=%hhu\n", lcore_id, portid, queueid); - } - - while (!is_done()) { - stats[lcore_id].nb_iteration_looped++; - - cur_tsc = rte_rdtsc(); - /* - * TX burst queue drain - */ - diff_tsc = cur_tsc - prev_tsc; - if (unlikely(diff_tsc > drain_tsc)) { - for (i = 0; i < qconf->n_tx_port; ++i) { - portid = qconf->tx_port_id[i]; - rte_eth_tx_buffer_flush(portid, - qconf->tx_queue_id[portid], - qconf->tx_buffer[portid]); - } - prev_tsc = cur_tsc; - } - - /* - * Read packet from RX queues - */ - for (i = 0; i < qconf->n_rx_queue; ++i) { - rx_queue = &(qconf->rx_queue_list[i]); - rx_queue->idle_hint = 0; - portid = rx_queue->port_id; - queueid = rx_queue->queue_id; - - nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, - MAX_PKT_BURST); - - stats[lcore_id].nb_rx_processed += nb_rx; - - if (nb_rx == 0) { - - rte_power_empty_poll_stat_update(lcore_id); - - continue; - } else { - rte_power_poll_stat_update(lcore_id, nb_rx); - } - - - /* Prefetch first packets */ - for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { - rte_prefetch0(rte_pktmbuf_mtod( - pkts_burst[j], void *)); - } - - /* Prefetch and forward already prefetched packets */ - for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { - rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ - j + PREFETCH_OFFSET], - void *)); - l3fwd_simple_forward(pkts_burst[j], portid, - qconf); - } - - /* Forward remaining prefetched packets */ - for (; j < nb_rx; j++) { - l3fwd_simple_forward(pkts_burst[j], portid, - qconf); - } - - } - } - - return 0; -} /* main processing loop */ static int main_legacy_loop(__rte_unused void *dummy) @@ -1853,58 +1727,8 @@ parse_pmd_mgmt_config(const char *name) return -1; } -static int -parse_ep_config(const char *q_arg) -{ - char s[256]; - const char *p = q_arg; - char *end; - int num_arg; - - char *str_fld[3]; - - int training_flag; - int med_edpi; - int hgh_edpi; - - ep_med_edpi = EMPTY_POLL_MED_THRESHOLD; - ep_hgh_edpi = EMPTY_POLL_HGH_THRESHOLD; - - strlcpy(s, p, sizeof(s)); - - num_arg = rte_strsplit(s, sizeof(s), str_fld, 3, ','); - - empty_poll_train = false; - - if (num_arg == 0) - return 0; - - if (num_arg == 3) { - - training_flag = strtoul(str_fld[0], &end, 0); - med_edpi = strtoul(str_fld[1], &end, 0); - hgh_edpi = strtoul(str_fld[2], &end, 0); - - if (training_flag == 1) - empty_poll_train = true; - - if (med_edpi > 0) - ep_med_edpi = med_edpi; - - if (hgh_edpi > 0) - ep_hgh_edpi = hgh_edpi; - - } else { - - return -1; - } - - return 0; - -} #define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype" #define CMD_LINE_OPT_LEGACY "legacy" -#define CMD_LINE_OPT_EMPTY_POLL "empty-poll" #define CMD_LINE_OPT_INTERRUPT_ONLY "interrupt-only" #define CMD_LINE_OPT_TELEMETRY "telemetry" #define CMD_LINE_OPT_PMD_MGMT "pmd-mgmt" @@ -1921,7 +1745,6 @@ parse_args(int argc, char **argv) int opt, ret; char **argvopt; int option_index; - uint32_t limit; char *prgname = argv[0]; static struct option lgopts[] = { {"config", 1, 0, 0}, @@ -1929,7 +1752,6 @@ parse_args(int argc, char **argv) {"high-perf-cores", 1, 0, 0}, {"no-numa", 0, 0, 0}, {CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, 0}, - {CMD_LINE_OPT_EMPTY_POLL, 1, 0, 0}, {CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0}, {CMD_LINE_OPT_LEGACY, 0, 0, 0}, {CMD_LINE_OPT_TELEMETRY, 0, 0, 0}, @@ -1944,7 +1766,7 @@ parse_args(int argc, char **argv) argvopt = argv; - while ((opt = getopt_long(argc, argvopt, "p:l:m:h:PuUi:", + while ((opt = getopt_long(argc, argvopt, "p:PuUi:", lgopts, &option_index)) != EOF) { switch (opt) { @@ -1961,18 +1783,6 @@ parse_args(int argc, char **argv) printf("Promiscuous mode selected\n"); promiscuous_on = 1; break; - case 'l': - limit = parse_max_pkt_len(optarg); - freq_tlb[LOW] = limit; - break; - case 'm': - limit = parse_max_pkt_len(optarg); - freq_tlb[MED] = limit; - break; - case 'h': - limit = parse_max_pkt_len(optarg); - freq_tlb[HGH] = limit; - break; case 'u': enabled_uncore = parse_uncore_options(UNCORE_MIN, NULL); if (enabled_uncore < 0) { @@ -2042,23 +1852,6 @@ parse_args(int argc, char **argv) printf("legacy mode is enabled\n"); } - if (!strncmp(lgopts[option_index].name, - CMD_LINE_OPT_EMPTY_POLL, 10)) { - if (app_mode != APP_MODE_DEFAULT) { - printf(" empty-poll mode is mutually exclusive with other modes\n"); - return -1; - } - app_mode = APP_MODE_EMPTY_POLL; - ret = parse_ep_config(optarg); - - if (ret) { - printf("invalid empty poll config\n"); - print_usage(prgname); - return -1; - } - printf("empty-poll is enabled\n"); - } - if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_TELEMETRY, sizeof(CMD_LINE_OPT_TELEMETRY))) { @@ -2575,24 +2368,7 @@ telemetry_setup_timer(void) update_telemetry, NULL); } -static void -empty_poll_setup_timer(void) -{ - int lcore_id = rte_lcore_id(); - uint64_t hz = rte_get_timer_hz(); - - struct ep_params *ep_ptr = ep_params; - - ep_ptr->interval_ticks = hz / INTERVALS_PER_SECOND; - rte_timer_reset_sync(&ep_ptr->timer0, - ep_ptr->interval_ticks, - PERIODICAL, - lcore_id, - rte_empty_poll_detection, - (void *)ep_ptr); - -} static int launch_timer(unsigned int lcore_id) { @@ -2609,10 +2385,7 @@ launch_timer(unsigned int lcore_id) RTE_LOG(INFO, POWER, "Bring up the Timer\n"); - if (app_mode == APP_MODE_EMPTY_POLL) - empty_poll_setup_timer(); - else - telemetry_setup_timer(); + telemetry_setup_timer(); cycles_10ms = rte_get_timer_hz() / 100; @@ -2657,8 +2430,6 @@ mode_to_str(enum appmode mode) switch (mode) { case APP_MODE_LEGACY: return "legacy"; - case APP_MODE_EMPTY_POLL: - return "empty poll"; case APP_MODE_TELEMETRY: return "telemetry"; case APP_MODE_INTERRUPT: @@ -2751,8 +2522,7 @@ main(int argc, char **argv) mode_to_str(app_mode)); /* only legacy and empty poll mode rely on power library */ - if ((app_mode == APP_MODE_LEGACY || app_mode == APP_MODE_EMPTY_POLL) && - init_power_library()) + if ((app_mode == APP_MODE_LEGACY) && init_power_library()) rte_exit(EXIT_FAILURE, "init_power_library failed\n"); if (update_lcore_params() < 0) @@ -3054,31 +2824,9 @@ main(int argc, char **argv) check_all_ports_link_status(enabled_port_mask); - if (app_mode == APP_MODE_EMPTY_POLL) { - - if (empty_poll_train) { - policy.state = TRAINING; - } else { - policy.state = MED_NORMAL; - policy.med_base_edpi = ep_med_edpi; - policy.hgh_base_edpi = ep_hgh_edpi; - } - - ret = rte_power_empty_poll_stat_init(&ep_params, - freq_tlb, - &policy); - if (ret < 0) - rte_exit(EXIT_FAILURE, "empty poll init failed"); - } - - /* launch per-lcore init on every lcore */ if (app_mode == APP_MODE_LEGACY) { rte_eal_mp_remote_launch(main_legacy_loop, NULL, CALL_MAIN); - } else if (app_mode == APP_MODE_EMPTY_POLL) { - empty_poll_stop = false; - rte_eal_mp_remote_launch(main_empty_poll_loop, NULL, - SKIP_MAIN); } else if (app_mode == APP_MODE_TELEMETRY) { unsigned int i; @@ -3110,7 +2858,7 @@ main(int argc, char **argv) rte_eal_mp_remote_launch(main_telemetry_loop, NULL, CALL_MAIN); } - if (app_mode == APP_MODE_EMPTY_POLL || app_mode == APP_MODE_TELEMETRY) + if (app_mode == APP_MODE_TELEMETRY) launch_timer(rte_lcore_id()); RTE_LCORE_FOREACH_WORKER(lcore_id) { @@ -3146,11 +2894,7 @@ main(int argc, char **argv) rte_eth_dev_close(portid); } - if (app_mode == APP_MODE_EMPTY_POLL) - rte_power_empty_poll_stat_free(); - - if ((app_mode == APP_MODE_LEGACY || app_mode == APP_MODE_EMPTY_POLL) && - deinit_power_library()) + if ((app_mode == APP_MODE_LEGACY) && deinit_power_library()) rte_exit(EXIT_FAILURE, "deinit_power_library failed\n"); if (rte_eal_cleanup() < 0) -- 2.17.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power 2022-12-20 12:56 ` [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt @ 2022-12-20 13:26 ` Hunt, David 2023-02-07 10:47 ` Pattan, Reshma 2023-02-08 10:48 ` [PATCH v2 0/3] power: remove experimental empty poll API David Hunt 2 siblings, 0 replies; 14+ messages in thread From: Hunt, David @ 2022-12-20 13:26 UTC (permalink / raw) To: dev On 20/12/2022 12:56, David Hunt wrote: > Remove calls to the experimental empty poll API. l3fwd-power > is the only app that uses this. > > This API is no longer needed as it is superceded by the > monitor/pause/scale callback mechanism. > I did check the spelling against my spellchecker with checkpatch, and it was clean. Too bad my dictionary uses a disputed spelling... From https://www.merriam-webster.com/dictionary/supercede: "Supercede has occurred as a spelling variant of supersede since the 17th century, and it is common in current published writing. It continues, however, to be widely regarded as an error." I'll fix in the next patch revision. Rgds, Dave. ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power 2022-12-20 12:56 ` [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt 2022-12-20 13:26 ` Hunt, David @ 2023-02-07 10:47 ` Pattan, Reshma 2023-02-08 10:48 ` [PATCH v2 0/3] power: remove experimental empty poll API David Hunt 2 siblings, 0 replies; 14+ messages in thread From: Pattan, Reshma @ 2023-02-07 10:47 UTC (permalink / raw) To: Hunt, David, dev; +Cc: Hunt, David > -----Original Message----- > From: David Hunt <david.hunt@intel.com> > /* only legacy and empty poll mode rely on power library */ You can remove empty poll mode reference in above comment. <snip> Can we check, inside print_usage() function , we need to remove below lines " --empty-poll: enable empty poll detection" " follow (training_flag, high_threshold, med_threshold)\n" ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 0/3] power: remove experimental empty poll API 2022-12-20 12:56 ` [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt 2022-12-20 13:26 ` Hunt, David 2023-02-07 10:47 ` Pattan, Reshma @ 2023-02-08 10:48 ` David Hunt 2023-02-08 10:48 ` [PATCH v2 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt ` (3 more replies) 2 siblings, 4 replies; 14+ messages in thread From: David Hunt @ 2023-02-08 10:48 UTC (permalink / raw) To: dev; +Cc: reshma.pattan, david.hunt The empty poll mechanism was an experimental API added in commit id 450f0791312c. It aimed to allow power saving depending on the traffic profile. However, it required a training phase and required the user to adjust magic numbers depending on their workload. A new and improved mechanism was added in commit id 682a645438c5, also based on empty polls, implemented a callback mechanism which added 'monitor', 'pause' and 'scale' modes in l3fwd-power. This was and easier mechanism to use, so the original empty poll mechanism is no longer needed. This patch set removes the experimental empty poll API, the empty poll mode from l3fwd-power, and related documentation. This is based on a deprecation notice in the previous release. [1/3] examples/power: remove empty poll mode from [2/3] libs/power: remove experimental empty poll API [3/3] doc/power: remove empty poll documentation ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 1/3] examples/power: remove empty poll mode from l3fwd-power 2023-02-08 10:48 ` [PATCH v2 0/3] power: remove experimental empty poll API David Hunt @ 2023-02-08 10:48 ` David Hunt 2023-02-08 11:11 ` Pattan, Reshma 2023-02-08 10:48 ` [PATCH v2 2/3] libs/power: remove experimental empty poll API David Hunt ` (2 subsequent siblings) 3 siblings, 1 reply; 14+ messages in thread From: David Hunt @ 2023-02-08 10:48 UTC (permalink / raw) To: dev; +Cc: reshma.pattan, david.hunt Remove calls to the experimental empty poll API. l3fwd-power is the only app that uses this. This API is no longer needed as it is superseded by the monitor/pause/scale callback mechanism. Signed-off-by: David Hunt <david.hunt@intel.com> --- examples/l3fwd-power/main.c | 270 +----------------------------------- 1 file changed, 6 insertions(+), 264 deletions(-) diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c index fd3ade330f..bd2110c878 100644 --- a/examples/l3fwd-power/main.c +++ b/examples/l3fwd-power/main.c @@ -43,7 +43,6 @@ #include <rte_timer.h> #include <rte_power.h> #include <rte_spinlock.h> -#include <rte_power_empty_poll.h> #include <rte_metrics.h> #include <rte_telemetry.h> #include <rte_power_pmd_mgmt.h> @@ -125,14 +124,6 @@ #define RX_DESC_DEFAULT 1024 #define TX_DESC_DEFAULT 1024 -/* - * These two thresholds were decided on by running the training algorithm on - * a 2.5GHz Xeon. These defaults can be overridden by supplying non-zero values - * for the med_threshold and high_threshold parameters on the command line. - */ -#define EMPTY_POLL_MED_THRESHOLD 350000UL -#define EMPTY_POLL_HGH_THRESHOLD 580000UL - #define NUM_TELSTATS RTE_DIM(telstats_strings) static uint16_t nb_rxd = RX_DESC_DEFAULT; @@ -150,12 +141,7 @@ static uint32_t enabled_port_mask = 0; static int promiscuous_on = 0; /* NUMA is enabled by default. */ static int numa_on = 1; -static bool empty_poll_stop; -static bool empty_poll_train; volatile bool quit_signal; -static struct ep_params *ep_params; -static struct ep_policy policy; -static long ep_med_edpi, ep_hgh_edpi; /* timer to update telemetry every 500ms */ static struct rte_timer telemetry_timer; @@ -207,7 +193,6 @@ static int parse_ptype; /**< Parse packet type using rx callback, and */ enum appmode { APP_MODE_DEFAULT = 0, APP_MODE_LEGACY, - APP_MODE_EMPTY_POLL, APP_MODE_TELEMETRY, APP_MODE_INTERRUPT, APP_MODE_PMD_MGMT @@ -423,14 +408,6 @@ static inline uint32_t power_idle_heuristic(uint32_t zero_rx_packet_count); static inline enum freq_scale_hint_t power_freq_scaleup_heuristic( \ unsigned int lcore_id, uint16_t port_id, uint16_t queue_id); - -/* - * These defaults are using the max frequency index (1), a medium index (9) - * and a typical low frequency index (14). These can be adjusted to use - * different indexes using the relevant command line parameters. - */ -static uint8_t freq_tlb[] = {14, 9, 1}; - static int is_done(void) { return quit_signal; @@ -1217,110 +1194,7 @@ main_telemetry_loop(__rte_unused void *dummy) return 0; } -/* main processing loop */ -static int -main_empty_poll_loop(__rte_unused void *dummy) -{ - struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; - unsigned int lcore_id; - uint64_t prev_tsc, diff_tsc, cur_tsc; - int i, j, nb_rx; - uint8_t queueid; - uint16_t portid; - struct lcore_conf *qconf; - struct lcore_rx_queue *rx_queue; - - const uint64_t drain_tsc = - (rte_get_tsc_hz() + US_PER_S - 1) / - US_PER_S * BURST_TX_DRAIN_US; - - prev_tsc = 0; - - lcore_id = rte_lcore_id(); - qconf = &lcore_conf[lcore_id]; - - if (qconf->n_rx_queue == 0) { - RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", - lcore_id); - return 0; - } - - for (i = 0; i < qconf->n_rx_queue; i++) { - portid = qconf->rx_queue_list[i].port_id; - queueid = qconf->rx_queue_list[i].queue_id; - RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%u " - "rxqueueid=%hhu\n", lcore_id, portid, queueid); - } - - while (!is_done()) { - stats[lcore_id].nb_iteration_looped++; - - cur_tsc = rte_rdtsc(); - /* - * TX burst queue drain - */ - diff_tsc = cur_tsc - prev_tsc; - if (unlikely(diff_tsc > drain_tsc)) { - for (i = 0; i < qconf->n_tx_port; ++i) { - portid = qconf->tx_port_id[i]; - rte_eth_tx_buffer_flush(portid, - qconf->tx_queue_id[portid], - qconf->tx_buffer[portid]); - } - prev_tsc = cur_tsc; - } - - /* - * Read packet from RX queues - */ - for (i = 0; i < qconf->n_rx_queue; ++i) { - rx_queue = &(qconf->rx_queue_list[i]); - rx_queue->idle_hint = 0; - portid = rx_queue->port_id; - queueid = rx_queue->queue_id; - - nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, - MAX_PKT_BURST); - - stats[lcore_id].nb_rx_processed += nb_rx; - - if (nb_rx == 0) { - - rte_power_empty_poll_stat_update(lcore_id); - - continue; - } else { - rte_power_poll_stat_update(lcore_id, nb_rx); - } - - - /* Prefetch first packets */ - for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { - rte_prefetch0(rte_pktmbuf_mtod( - pkts_burst[j], void *)); - } - - /* Prefetch and forward already prefetched packets */ - for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { - rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ - j + PREFETCH_OFFSET], - void *)); - l3fwd_simple_forward(pkts_burst[j], portid, - qconf); - } - - /* Forward remaining prefetched packets */ - for (; j < nb_rx; j++) { - l3fwd_simple_forward(pkts_burst[j], portid, - qconf); - } - - } - } - - return 0; -} /* main processing loop */ static int main_legacy_loop(__rte_unused void *dummy) @@ -1636,8 +1510,6 @@ print_usage(const char *prgname) " --max-pkt-len PKTLEN: maximum packet length in decimal (64-9600)\n" " --parse-ptype: parse packet type by software\n" " --legacy: use legacy interrupt-based scaling\n" - " --empty-poll: enable empty poll detection" - " follow (training_flag, high_threshold, med_threshold)\n" " --telemetry: enable telemetry mode, to update" " empty polls, full polls, and core busyness to telemetry\n" " --interrupt-only: enable interrupt-only mode\n" @@ -1853,58 +1725,8 @@ parse_pmd_mgmt_config(const char *name) return -1; } -static int -parse_ep_config(const char *q_arg) -{ - char s[256]; - const char *p = q_arg; - char *end; - int num_arg; - - char *str_fld[3]; - - int training_flag; - int med_edpi; - int hgh_edpi; - - ep_med_edpi = EMPTY_POLL_MED_THRESHOLD; - ep_hgh_edpi = EMPTY_POLL_HGH_THRESHOLD; - - strlcpy(s, p, sizeof(s)); - - num_arg = rte_strsplit(s, sizeof(s), str_fld, 3, ','); - - empty_poll_train = false; - - if (num_arg == 0) - return 0; - - if (num_arg == 3) { - - training_flag = strtoul(str_fld[0], &end, 0); - med_edpi = strtoul(str_fld[1], &end, 0); - hgh_edpi = strtoul(str_fld[2], &end, 0); - - if (training_flag == 1) - empty_poll_train = true; - - if (med_edpi > 0) - ep_med_edpi = med_edpi; - - if (hgh_edpi > 0) - ep_hgh_edpi = hgh_edpi; - - } else { - - return -1; - } - - return 0; - -} #define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype" #define CMD_LINE_OPT_LEGACY "legacy" -#define CMD_LINE_OPT_EMPTY_POLL "empty-poll" #define CMD_LINE_OPT_INTERRUPT_ONLY "interrupt-only" #define CMD_LINE_OPT_TELEMETRY "telemetry" #define CMD_LINE_OPT_PMD_MGMT "pmd-mgmt" @@ -1921,7 +1743,6 @@ parse_args(int argc, char **argv) int opt, ret; char **argvopt; int option_index; - uint32_t limit; char *prgname = argv[0]; static struct option lgopts[] = { {"config", 1, 0, 0}, @@ -1929,7 +1750,6 @@ parse_args(int argc, char **argv) {"high-perf-cores", 1, 0, 0}, {"no-numa", 0, 0, 0}, {CMD_LINE_OPT_MAX_PKT_LEN, 1, 0, 0}, - {CMD_LINE_OPT_EMPTY_POLL, 1, 0, 0}, {CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0}, {CMD_LINE_OPT_LEGACY, 0, 0, 0}, {CMD_LINE_OPT_TELEMETRY, 0, 0, 0}, @@ -1944,7 +1764,7 @@ parse_args(int argc, char **argv) argvopt = argv; - while ((opt = getopt_long(argc, argvopt, "p:l:m:h:PuUi:", + while ((opt = getopt_long(argc, argvopt, "p:PuUi:", lgopts, &option_index)) != EOF) { switch (opt) { @@ -1961,18 +1781,6 @@ parse_args(int argc, char **argv) printf("Promiscuous mode selected\n"); promiscuous_on = 1; break; - case 'l': - limit = parse_max_pkt_len(optarg); - freq_tlb[LOW] = limit; - break; - case 'm': - limit = parse_max_pkt_len(optarg); - freq_tlb[MED] = limit; - break; - case 'h': - limit = parse_max_pkt_len(optarg); - freq_tlb[HGH] = limit; - break; case 'u': enabled_uncore = parse_uncore_options(UNCORE_MIN, NULL); if (enabled_uncore < 0) { @@ -2042,23 +1850,6 @@ parse_args(int argc, char **argv) printf("legacy mode is enabled\n"); } - if (!strncmp(lgopts[option_index].name, - CMD_LINE_OPT_EMPTY_POLL, 10)) { - if (app_mode != APP_MODE_DEFAULT) { - printf(" empty-poll mode is mutually exclusive with other modes\n"); - return -1; - } - app_mode = APP_MODE_EMPTY_POLL; - ret = parse_ep_config(optarg); - - if (ret) { - printf("invalid empty poll config\n"); - print_usage(prgname); - return -1; - } - printf("empty-poll is enabled\n"); - } - if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_TELEMETRY, sizeof(CMD_LINE_OPT_TELEMETRY))) { @@ -2575,24 +2366,7 @@ telemetry_setup_timer(void) update_telemetry, NULL); } -static void -empty_poll_setup_timer(void) -{ - int lcore_id = rte_lcore_id(); - uint64_t hz = rte_get_timer_hz(); - - struct ep_params *ep_ptr = ep_params; - - ep_ptr->interval_ticks = hz / INTERVALS_PER_SECOND; - rte_timer_reset_sync(&ep_ptr->timer0, - ep_ptr->interval_ticks, - PERIODICAL, - lcore_id, - rte_empty_poll_detection, - (void *)ep_ptr); - -} static int launch_timer(unsigned int lcore_id) { @@ -2609,10 +2383,7 @@ launch_timer(unsigned int lcore_id) RTE_LOG(INFO, POWER, "Bring up the Timer\n"); - if (app_mode == APP_MODE_EMPTY_POLL) - empty_poll_setup_timer(); - else - telemetry_setup_timer(); + telemetry_setup_timer(); cycles_10ms = rte_get_timer_hz() / 100; @@ -2657,8 +2428,6 @@ mode_to_str(enum appmode mode) switch (mode) { case APP_MODE_LEGACY: return "legacy"; - case APP_MODE_EMPTY_POLL: - return "empty poll"; case APP_MODE_TELEMETRY: return "telemetry"; case APP_MODE_INTERRUPT: @@ -2750,9 +2519,8 @@ main(int argc, char **argv) RTE_LOG(INFO, L3FWD_POWER, "Selected operation mode: %s\n", mode_to_str(app_mode)); - /* only legacy and empty poll mode rely on power library */ - if ((app_mode == APP_MODE_LEGACY || app_mode == APP_MODE_EMPTY_POLL) && - init_power_library()) + /* only legacy mode relies on power library */ + if ((app_mode == APP_MODE_LEGACY) && init_power_library()) rte_exit(EXIT_FAILURE, "init_power_library failed\n"); if (update_lcore_params() < 0) @@ -3054,31 +2822,9 @@ main(int argc, char **argv) check_all_ports_link_status(enabled_port_mask); - if (app_mode == APP_MODE_EMPTY_POLL) { - - if (empty_poll_train) { - policy.state = TRAINING; - } else { - policy.state = MED_NORMAL; - policy.med_base_edpi = ep_med_edpi; - policy.hgh_base_edpi = ep_hgh_edpi; - } - - ret = rte_power_empty_poll_stat_init(&ep_params, - freq_tlb, - &policy); - if (ret < 0) - rte_exit(EXIT_FAILURE, "empty poll init failed"); - } - - /* launch per-lcore init on every lcore */ if (app_mode == APP_MODE_LEGACY) { rte_eal_mp_remote_launch(main_legacy_loop, NULL, CALL_MAIN); - } else if (app_mode == APP_MODE_EMPTY_POLL) { - empty_poll_stop = false; - rte_eal_mp_remote_launch(main_empty_poll_loop, NULL, - SKIP_MAIN); } else if (app_mode == APP_MODE_TELEMETRY) { unsigned int i; @@ -3110,7 +2856,7 @@ main(int argc, char **argv) rte_eal_mp_remote_launch(main_telemetry_loop, NULL, CALL_MAIN); } - if (app_mode == APP_MODE_EMPTY_POLL || app_mode == APP_MODE_TELEMETRY) + if (app_mode == APP_MODE_TELEMETRY) launch_timer(rte_lcore_id()); RTE_LCORE_FOREACH_WORKER(lcore_id) { @@ -3146,11 +2892,7 @@ main(int argc, char **argv) rte_eth_dev_close(portid); } - if (app_mode == APP_MODE_EMPTY_POLL) - rte_power_empty_poll_stat_free(); - - if ((app_mode == APP_MODE_LEGACY || app_mode == APP_MODE_EMPTY_POLL) && - deinit_power_library()) + if ((app_mode == APP_MODE_LEGACY) && deinit_power_library()) rte_exit(EXIT_FAILURE, "deinit_power_library failed\n"); if (rte_eal_cleanup() < 0) -- 2.17.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH v2 1/3] examples/power: remove empty poll mode from l3fwd-power 2023-02-08 10:48 ` [PATCH v2 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt @ 2023-02-08 11:11 ` Pattan, Reshma 0 siblings, 0 replies; 14+ messages in thread From: Pattan, Reshma @ 2023-02-08 11:11 UTC (permalink / raw) To: Hunt, David, dev > -----Original Message----- > From: Hunt, David <david.hunt@intel.com> > > Signed-off-by: David Hunt <david.hunt@intel.com> > --- Acked-By: Reshma Pattan <reshma.pattan@intel.com> ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 2/3] libs/power: remove experimental empty poll API 2023-02-08 10:48 ` [PATCH v2 0/3] power: remove experimental empty poll API David Hunt 2023-02-08 10:48 ` [PATCH v2 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt @ 2023-02-08 10:48 ` David Hunt 2023-02-08 10:48 ` [PATCH v2 3/3] doc/power: remove empty poll documentation David Hunt 2023-02-19 23:53 ` [PATCH v2 0/3] power: remove experimental empty poll API Thomas Monjalon 3 siblings, 0 replies; 14+ messages in thread From: David Hunt @ 2023-02-08 10:48 UTC (permalink / raw) To: dev; +Cc: reshma.pattan, david.hunt This patchset removes the empty poll experimental API, which has been in an experimental state since it was added. This API is no longer needed as it is superseded by the PMD Power Management monitor/pause/scale callback mechanism. Signed-off-by: David Hunt <david.hunt@intel.com> Acked-by: Reshma Pattan <reshma.pattan@intel.com> --- lib/power/meson.build | 2 - lib/power/rte_power_empty_poll.c | 529 ------------------------------- lib/power/rte_power_empty_poll.h | 223 ------------- lib/power/version.map | 7 - 4 files changed, 761 deletions(-) delete mode 100644 lib/power/rte_power_empty_poll.c delete mode 100644 lib/power/rte_power_empty_poll.h diff --git a/lib/power/meson.build b/lib/power/meson.build index 49a805391f..1ce8b7c07d 100644 --- a/lib/power/meson.build +++ b/lib/power/meson.build @@ -19,13 +19,11 @@ sources = files( 'power_kvm_vm.c', 'power_pstate_cpufreq.c', 'rte_power.c', - 'rte_power_empty_poll.c', 'rte_power_intel_uncore.c', 'rte_power_pmd_mgmt.c', ) headers = files( 'rte_power.h', - 'rte_power_empty_poll.h', 'rte_power_intel_uncore.h', 'rte_power_pmd_mgmt.h', 'rte_power_guest_channel.h', diff --git a/lib/power/rte_power_empty_poll.c b/lib/power/rte_power_empty_poll.c deleted file mode 100644 index 4a4db51247..0000000000 --- a/lib/power/rte_power_empty_poll.c +++ /dev/null @@ -1,529 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2018 Intel Corporation - */ - -#include <string.h> - -#include <rte_lcore.h> -#include <rte_malloc.h> -#include <inttypes.h> - -#include "rte_power.h" -#include "rte_power_empty_poll.h" - -#define INTERVALS_PER_SECOND 100 /* (10ms) */ -#define SECONDS_TO_TRAIN_FOR 2 -#define DEFAULT_MED_TO_HIGH_PERCENT_THRESHOLD 70 -#define DEFAULT_HIGH_TO_MED_PERCENT_THRESHOLD 30 -#define DEFAULT_CYCLES_PER_PACKET 800 - -static struct ep_params *ep_params; -static uint32_t med_to_high_threshold = DEFAULT_MED_TO_HIGH_PERCENT_THRESHOLD; -static uint32_t high_to_med_threshold = DEFAULT_HIGH_TO_MED_PERCENT_THRESHOLD; - -static uint32_t avail_freqs[RTE_MAX_LCORE][NUM_FREQS]; - -static uint32_t total_avail_freqs[RTE_MAX_LCORE]; - -static uint32_t freq_index[NUM_FREQ]; - -static uint32_t -get_freq_index(enum freq_val index) -{ - return freq_index[index]; -} - - -static int -set_power_freq(int lcore_id, enum freq_val freq, bool specific_freq) -{ - int err = 0; - uint32_t power_freq_index; - if (!specific_freq) - power_freq_index = get_freq_index(freq); - else - power_freq_index = freq; - - err = rte_power_set_freq(lcore_id, power_freq_index); - - return err; -} - - -static __rte_always_inline void -exit_training_state(struct priority_worker *poll_stats) -{ - RTE_SET_USED(poll_stats); -} - -static __rte_always_inline void -enter_training_state(struct priority_worker *poll_stats) -{ - poll_stats->iter_counter = 0; - poll_stats->cur_freq = LOW; - poll_stats->queue_state = TRAINING; -} - -static __rte_always_inline void -enter_normal_state(struct priority_worker *poll_stats) -{ - /* Clear the averages arrays and strs */ - memset(poll_stats->edpi_av, 0, sizeof(poll_stats->edpi_av)); - poll_stats->ec = 0; - - poll_stats->cur_freq = MED; - poll_stats->iter_counter = 0; - poll_stats->threshold_ctr = 0; - poll_stats->queue_state = MED_NORMAL; - RTE_LOG(INFO, POWER, "Set the power freq to MED\n"); - set_power_freq(poll_stats->lcore_id, MED, false); - - poll_stats->thresh[MED].threshold_percent = med_to_high_threshold; - poll_stats->thresh[HGH].threshold_percent = high_to_med_threshold; -} - -static __rte_always_inline void -enter_busy_state(struct priority_worker *poll_stats) -{ - memset(poll_stats->edpi_av, 0, sizeof(poll_stats->edpi_av)); - poll_stats->ec = 0; - - poll_stats->cur_freq = HGH; - poll_stats->iter_counter = 0; - poll_stats->threshold_ctr = 0; - poll_stats->queue_state = HGH_BUSY; - set_power_freq(poll_stats->lcore_id, HGH, false); -} - -static __rte_always_inline void -enter_purge_state(struct priority_worker *poll_stats) -{ - poll_stats->iter_counter = 0; - poll_stats->queue_state = LOW_PURGE; -} - -static __rte_always_inline void -set_state(struct priority_worker *poll_stats, - enum queue_state new_state) -{ - enum queue_state old_state = poll_stats->queue_state; - if (old_state != new_state) { - - /* Call any old state exit functions */ - if (old_state == TRAINING) - exit_training_state(poll_stats); - - /* Call any new state entry functions */ - if (new_state == TRAINING) - enter_training_state(poll_stats); - if (new_state == MED_NORMAL) - enter_normal_state(poll_stats); - if (new_state == HGH_BUSY) - enter_busy_state(poll_stats); - if (new_state == LOW_PURGE) - enter_purge_state(poll_stats); - } -} - -static __rte_always_inline void -set_policy(struct priority_worker *poll_stats, - struct ep_policy *policy) -{ - set_state(poll_stats, policy->state); - - if (policy->state == TRAINING) - return; - - poll_stats->thresh[MED_NORMAL].base_edpi = policy->med_base_edpi; - poll_stats->thresh[HGH_BUSY].base_edpi = policy->hgh_base_edpi; - - poll_stats->thresh[MED_NORMAL].trained = true; - poll_stats->thresh[HGH_BUSY].trained = true; - -} - -static void -update_training_stats(struct priority_worker *poll_stats, - uint32_t freq, - bool specific_freq, - uint32_t max_train_iter) -{ - RTE_SET_USED(specific_freq); - - uint64_t p0_empty_deq; - - if (poll_stats->cur_freq == freq && - poll_stats->thresh[freq].trained == false) { - if (poll_stats->thresh[freq].cur_train_iter == 0) { - - set_power_freq(poll_stats->lcore_id, - freq, specific_freq); - - poll_stats->empty_dequeues_prev = - poll_stats->empty_dequeues; - - poll_stats->thresh[freq].cur_train_iter++; - - return; - } else if (poll_stats->thresh[freq].cur_train_iter - <= max_train_iter) { - - p0_empty_deq = poll_stats->empty_dequeues - - poll_stats->empty_dequeues_prev; - - poll_stats->empty_dequeues_prev = - poll_stats->empty_dequeues; - - poll_stats->thresh[freq].base_edpi += p0_empty_deq; - poll_stats->thresh[freq].cur_train_iter++; - - } else { - if (poll_stats->thresh[freq].trained == false) { - poll_stats->thresh[freq].base_edpi = - poll_stats->thresh[freq].base_edpi / - max_train_iter; - - /* Add on a factor of 0.05% - * this should remove any - * false negatives when the system is 0% busy - */ - poll_stats->thresh[freq].base_edpi += - poll_stats->thresh[freq].base_edpi / 2000; - - poll_stats->thresh[freq].trained = true; - poll_stats->cur_freq++; - - } - } - } -} - -static __rte_always_inline uint32_t -update_stats(struct priority_worker *poll_stats) -{ - uint64_t tot_edpi = 0; - uint32_t j, percent; - - struct priority_worker *s = poll_stats; - - uint64_t cur_edpi = s->empty_dequeues - s->empty_dequeues_prev; - - s->empty_dequeues_prev = s->empty_dequeues; - - if (s->thresh[s->cur_freq].base_edpi < cur_edpi) { - - /* edpi mean empty poll counter difference per interval */ - RTE_LOG(DEBUG, POWER, "cur_edpi is too large " - "cur edpi %"PRId64" " - "base edpi %"PRId64"\n", - cur_edpi, - s->thresh[s->cur_freq].base_edpi); - /* Value to make us fail need debug log*/ - return 1000UL; - } - - s->edpi_av[s->ec++ % BINS_AV] = cur_edpi; - - for (j = 0; j < BINS_AV; j++) { - tot_edpi += s->edpi_av[j]; - } - - tot_edpi = tot_edpi / BINS_AV; - - percent = 100 - (uint32_t)(((float)tot_edpi / - (float)s->thresh[s->cur_freq].base_edpi) * 100); - - return (uint32_t)percent; -} - - -static __rte_always_inline void -update_stats_normal(struct priority_worker *poll_stats) -{ - uint32_t percent; - - if (poll_stats->thresh[poll_stats->cur_freq].base_edpi == 0) { - - enum freq_val cur_freq = poll_stats->cur_freq; - - /* edpi mean empty poll counter difference per interval */ - RTE_LOG(DEBUG, POWER, "cure freq is %d, edpi is %"PRIu64"\n", - cur_freq, - poll_stats->thresh[cur_freq].base_edpi); - return; - } - - percent = update_stats(poll_stats); - - if (percent > 100) { - /* edpi mean empty poll counter difference per interval */ - RTE_LOG(DEBUG, POWER, "Edpi is bigger than threshold\n"); - return; - } - - if (poll_stats->cur_freq == LOW) - RTE_LOG(INFO, POWER, "Purge Mode is not currently supported\n"); - else if (poll_stats->cur_freq == MED) { - - if (percent > - poll_stats->thresh[MED].threshold_percent) { - - if (poll_stats->threshold_ctr < INTERVALS_PER_SECOND) - poll_stats->threshold_ctr++; - else { - set_state(poll_stats, HGH_BUSY); - RTE_LOG(INFO, POWER, "MOVE to HGH\n"); - } - - } else { - /* reset */ - poll_stats->threshold_ctr = 0; - } - - } else if (poll_stats->cur_freq == HGH) { - - if (percent < - poll_stats->thresh[HGH].threshold_percent) { - - if (poll_stats->threshold_ctr < INTERVALS_PER_SECOND) - poll_stats->threshold_ctr++; - else { - set_state(poll_stats, MED_NORMAL); - RTE_LOG(INFO, POWER, "MOVE to MED\n"); - } - } else { - /* reset */ - poll_stats->threshold_ctr = 0; - } - - } -} - -static int -empty_poll_training(struct priority_worker *poll_stats, - uint32_t max_train_iter) -{ - - if (poll_stats->iter_counter < INTERVALS_PER_SECOND) { - poll_stats->iter_counter++; - return 0; - } - - - update_training_stats(poll_stats, - LOW, - false, - max_train_iter); - - update_training_stats(poll_stats, - MED, - false, - max_train_iter); - - update_training_stats(poll_stats, - HGH, - false, - max_train_iter); - - - if (poll_stats->thresh[LOW].trained == true - && poll_stats->thresh[MED].trained == true - && poll_stats->thresh[HGH].trained == true) { - - set_state(poll_stats, MED_NORMAL); - - RTE_LOG(INFO, POWER, "LOW threshold is %"PRIu64"\n", - poll_stats->thresh[LOW].base_edpi); - - RTE_LOG(INFO, POWER, "MED threshold is %"PRIu64"\n", - poll_stats->thresh[MED].base_edpi); - - - RTE_LOG(INFO, POWER, "HIGH threshold is %"PRIu64"\n", - poll_stats->thresh[HGH].base_edpi); - - RTE_LOG(INFO, POWER, "Training is Complete for %d\n", - poll_stats->lcore_id); - } - - return 0; -} - -void -rte_empty_poll_detection(struct rte_timer *tim, void *arg) -{ - - uint32_t i; - - struct priority_worker *poll_stats; - - RTE_SET_USED(tim); - - RTE_SET_USED(arg); - - for (i = 0; i < NUM_NODES; i++) { - - poll_stats = &(ep_params->wrk_data.wrk_stats[i]); - - if (rte_lcore_is_enabled(poll_stats->lcore_id) == 0) - continue; - - switch (poll_stats->queue_state) { - case(TRAINING): - empty_poll_training(poll_stats, - ep_params->max_train_iter); - break; - - case(HGH_BUSY): - case(MED_NORMAL): - update_stats_normal(poll_stats); - break; - - case(LOW_PURGE): - break; - default: - break; - - } - - } - -} - -int -rte_power_empty_poll_stat_init(struct ep_params **eptr, uint8_t *freq_tlb, - struct ep_policy *policy) -{ - uint32_t i; - /* Allocate the ep_params structure */ - ep_params = rte_zmalloc_socket(NULL, - sizeof(struct ep_params), - 0, - rte_socket_id()); - - if (!ep_params) - return -1; - - if (freq_tlb == NULL) { - freq_index[LOW] = 14; - freq_index[MED] = 9; - freq_index[HGH] = 1; - } else { - freq_index[LOW] = freq_tlb[LOW]; - freq_index[MED] = freq_tlb[MED]; - freq_index[HGH] = freq_tlb[HGH]; - } - - RTE_LOG(INFO, POWER, "Initialize the Empty Poll\n"); - - /* Train for pre-defined period */ - ep_params->max_train_iter = INTERVALS_PER_SECOND * SECONDS_TO_TRAIN_FOR; - - struct stats_data *w = &ep_params->wrk_data; - - *eptr = ep_params; - - /* initialize all wrk_stats state */ - for (i = 0; i < NUM_NODES; i++) { - - if (rte_lcore_is_enabled(i) == 0) - continue; - /*init the freqs table */ - total_avail_freqs[i] = rte_power_freqs(i, - avail_freqs[i], - NUM_FREQS); - - RTE_LOG(INFO, POWER, "total avail freq is %d , lcoreid %d\n", - total_avail_freqs[i], - i); - - if (get_freq_index(LOW) > total_avail_freqs[i]) - return -1; - - if (rte_get_main_lcore() != i) { - w->wrk_stats[i].lcore_id = i; - set_policy(&w->wrk_stats[i], policy); - } - } - - return 0; -} - -void -rte_power_empty_poll_stat_free(void) -{ - - RTE_LOG(INFO, POWER, "Close the Empty Poll\n"); - - rte_free(ep_params); -} - -int -rte_power_empty_poll_stat_update(unsigned int lcore_id) -{ - struct priority_worker *poll_stats; - - if (lcore_id >= NUM_NODES) - return -1; - - poll_stats = &(ep_params->wrk_data.wrk_stats[lcore_id]); - - if (poll_stats->lcore_id == 0) - poll_stats->lcore_id = lcore_id; - - poll_stats->empty_dequeues++; - - return 0; -} - -int -rte_power_poll_stat_update(unsigned int lcore_id, uint8_t nb_pkt) -{ - - struct priority_worker *poll_stats; - - if (lcore_id >= NUM_NODES) - return -1; - - poll_stats = &(ep_params->wrk_data.wrk_stats[lcore_id]); - - if (poll_stats->lcore_id == 0) - poll_stats->lcore_id = lcore_id; - - poll_stats->num_dequeue_pkts += nb_pkt; - - return 0; -} - - -uint64_t -rte_power_empty_poll_stat_fetch(unsigned int lcore_id) -{ - struct priority_worker *poll_stats; - - if (lcore_id >= NUM_NODES) - return -1; - - poll_stats = &(ep_params->wrk_data.wrk_stats[lcore_id]); - - if (poll_stats->lcore_id == 0) - poll_stats->lcore_id = lcore_id; - - return poll_stats->empty_dequeues; -} - -uint64_t -rte_power_poll_stat_fetch(unsigned int lcore_id) -{ - struct priority_worker *poll_stats; - - if (lcore_id >= NUM_NODES) - return -1; - - poll_stats = &(ep_params->wrk_data.wrk_stats[lcore_id]); - - if (poll_stats->lcore_id == 0) - poll_stats->lcore_id = lcore_id; - - return poll_stats->num_dequeue_pkts; -} diff --git a/lib/power/rte_power_empty_poll.h b/lib/power/rte_power_empty_poll.h deleted file mode 100644 index b9819337e6..0000000000 --- a/lib/power/rte_power_empty_poll.h +++ /dev/null @@ -1,223 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2018 Intel Corporation - */ - -#ifndef _RTE_EMPTY_POLL_H -#define _RTE_EMPTY_POLL_H - -/** - * @file - * RTE Power Management - */ -#include <stdint.h> -#include <stdbool.h> - -#include <rte_compat.h> -#include <rte_common.h> -#include <rte_string_fns.h> -#include <rte_timer.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define NUM_FREQS RTE_MAX_LCORE_FREQS - -#define BINS_AV 4 /* Has to be ^2 */ - -#define DROP (NUM_DIRECTIONS * NUM_DEVICES) - -#define NUM_PRIORITIES 2 - -#define NUM_NODES 256 /* Max core number*/ - -/* Processor Power State */ -enum freq_val { - LOW, - MED, - HGH, - NUM_FREQ = NUM_FREQS -}; - - -/* Queue Polling State */ -enum queue_state { - TRAINING, /* NO TRAFFIC */ - MED_NORMAL, /* MED */ - HGH_BUSY, /* HIGH */ - LOW_PURGE, /* LOW */ -}; - -/* Queue Stats */ -struct freq_threshold { - - uint64_t base_edpi; - bool trained; - uint32_t threshold_percent; - uint32_t cur_train_iter; -}; - -/* Each Worker Thread Empty Poll Stats */ -struct priority_worker { - - /* Current dequeue and throughput counts */ - /* These 2 are written to by the worker threads */ - /* So keep them on their own cache line */ - uint64_t empty_dequeues; - uint64_t num_dequeue_pkts; - - enum queue_state queue_state; - - uint64_t empty_dequeues_prev; - - /* Used for training only */ - struct freq_threshold thresh[NUM_FREQ]; - enum freq_val cur_freq; - - /* bucket arrays to calculate the averages */ - /* edpi mean empty poll counter difference per interval */ - uint64_t edpi_av[BINS_AV]; - /* empty poll counter */ - uint32_t ec; - - uint32_t lcore_id; - uint32_t iter_counter; - uint32_t threshold_ctr; - uint32_t display_ctr; - uint8_t dev_id; - -} __rte_cache_aligned; - - -struct stats_data { - - struct priority_worker wrk_stats[NUM_NODES]; - - /* flag to stop rx threads processing packets until training over */ - bool start_rx; - -}; - -/* Empty Poll Parameters */ -struct ep_params { - - /* Timer related stuff */ - uint64_t interval_ticks; - uint32_t max_train_iter; - - struct rte_timer timer0; - struct stats_data wrk_data; -}; - - -/* Sample App Init information */ -struct ep_policy { - - uint64_t med_base_edpi; - uint64_t hgh_base_edpi; - - enum queue_state state; -}; - - - -/** - * Initialize the power management system. - * - * @param eptr - * the structure of empty poll configuration - * @param freq_tlb - * the power state/frequency mapping table - * @param policy - * the initialization policy from sample app - * - * @return - * - 0 on success. - * - Negative on error. - */ -__rte_experimental -int -rte_power_empty_poll_stat_init(struct ep_params **eptr, uint8_t *freq_tlb, - struct ep_policy *policy); - -/** - * Free the resource hold by power management system. - */ -__rte_experimental -void -rte_power_empty_poll_stat_free(void); - -/** - * Update specific core empty poll counter - * It's not thread safe. - * - * @param lcore_id - * lcore id - * - * @return - * - 0 on success. - * - Negative on error. - */ -__rte_experimental -int -rte_power_empty_poll_stat_update(unsigned int lcore_id); - -/** - * Update specific core valid poll counter, not thread safe. - * - * @param lcore_id - * lcore id. - * @param nb_pkt - * The packet number of one valid poll. - * - * @return - * - 0 on success. - * - Negative on error. - */ -__rte_experimental -int -rte_power_poll_stat_update(unsigned int lcore_id, uint8_t nb_pkt); - -/** - * Fetch specific core empty poll counter. - * - * @param lcore_id - * lcore id - * - * @return - * Current lcore empty poll counter value. - */ -__rte_experimental -uint64_t -rte_power_empty_poll_stat_fetch(unsigned int lcore_id); - -/** - * Fetch specific core valid poll counter. - * - * @param lcore_id - * lcore id - * - * @return - * Current lcore valid poll counter value. - */ -__rte_experimental -uint64_t -rte_power_poll_stat_fetch(unsigned int lcore_id); - -/** - * Empty poll state change detection function - * - * @param tim - * The timer structure - * @param arg - * The customized parameter - */ -__rte_experimental -void -rte_empty_poll_detection(struct rte_timer *tim, void *arg); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/power/version.map b/lib/power/version.map index 8fccbf20f7..05d544e947 100644 --- a/lib/power/version.map +++ b/lib/power/version.map @@ -25,15 +25,8 @@ DPDK_23 { EXPERIMENTAL { global: - rte_empty_poll_detection; rte_power_check_env_supported; - rte_power_empty_poll_stat_fetch; - rte_power_empty_poll_stat_free; - rte_power_empty_poll_stat_init; - rte_power_empty_poll_stat_update; rte_power_guest_channel_receive_msg; - rte_power_poll_stat_fetch; - rte_power_poll_stat_update; # added in 21.02 rte_power_ethdev_pmgmt_queue_disable; -- 2.17.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 3/3] doc/power: remove empty poll documentation 2023-02-08 10:48 ` [PATCH v2 0/3] power: remove experimental empty poll API David Hunt 2023-02-08 10:48 ` [PATCH v2 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt 2023-02-08 10:48 ` [PATCH v2 2/3] libs/power: remove experimental empty poll API David Hunt @ 2023-02-08 10:48 ` David Hunt 2023-02-19 23:53 ` [PATCH v2 0/3] power: remove experimental empty poll API Thomas Monjalon 3 siblings, 0 replies; 14+ messages in thread From: David Hunt @ 2023-02-08 10:48 UTC (permalink / raw) To: dev; +Cc: reshma.pattan, david.hunt Remove the documentation for the removed experimental empty poll API, as it is no longer needed. This API is no longer needed as it is superseded by the PMD Power Management monitor/pause/scale callback mechanism. Signed-off-by: David Hunt <david.hunt@intel.com> Acked-by: Reshma Pattan <reshma.pattan@intel.com> --- doc/guides/prog_guide/power_man.rst | 94 ------------------- doc/guides/rel_notes/release_23_03.rst | 4 + .../sample_app_ug/l3_forward_power_man.rst | 70 -------------- 3 files changed, 4 insertions(+), 164 deletions(-) diff --git a/doc/guides/prog_guide/power_man.rst b/doc/guides/prog_guide/power_man.rst index 68db59bd49..f6674efe2d 100644 --- a/doc/guides/prog_guide/power_man.rst +++ b/doc/guides/prog_guide/power_man.rst @@ -107,100 +107,6 @@ User Cases The power management mechanism is used to save power when performing L3 forwarding. -Empty Poll API --------------- - -Removal Warning -~~~~~~~~~~~~~~~ - -The experimental empty poll API will be removed from the library -in a future DPDK release. -The empty poll mechanism is superseded by the power PMD modes -i.e. monitor, pause and scale. - - -Abstract -~~~~~~~~ - -For packet processing workloads such as DPDK polling is continuous. -This means CPU cores always show 100% busy independent of how much work -those cores are doing. It is critical to accurately determine how busy -a core is hugely important for the following reasons: - - * No indication of overload conditions - * User does not know how much real load is on a system, resulting - in wasted energy as no power management is utilized - -Compared to the original l3fwd-power design, instead of going to sleep -after detecting an empty poll, the new mechanism just lowers the core frequency. -As a result, the application does not stop polling the device, which leads -to improved handling of bursts of traffic. - -When the system become busy, the empty poll mechanism can also increase the core -frequency (including turbo) to do best effort for intensive traffic. This gives -us more flexible and balanced traffic awareness over the standard l3fwd-power -application. - - -Proposed Solution -~~~~~~~~~~~~~~~~~ -The proposed solution focuses on how many times empty polls are executed. -The less the number of empty polls, means current core is busy with processing -workload, therefore, the higher frequency is needed. The high empty poll number -indicates the current core not doing any real work therefore, we can lower the -frequency to safe power. - -In the current implementation, each core has 1 empty-poll counter which assume -1 core is dedicated to 1 queue. This will need to be expanded in the future to -support multiple queues per core. - -Power state definition: -^^^^^^^^^^^^^^^^^^^^^^^ - -* LOW: Not currently used, reserved for future use. - -* MED: the frequency is used to process modest traffic workload. - -* HIGH: the frequency is used to process busy traffic workload. - -There are two phases to establish the power management system: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* Training phase. This phase is used to measure the optimal frequency - change thresholds for a given system. The thresholds will differ from - system to system due to differences in processor micro-architecture, - cache and device configurations. - In this phase, the user must ensure that no traffic can enter the - system so that counts can be measured for empty polls at low, medium - and high frequencies. Each frequency is measured for two seconds. - Once the training phase is complete, the threshold numbers are - displayed, and normal mode resumes, and traffic can be allowed into - the system. These threshold number can be used on the command line - when starting the application in normal mode to avoid re-training - every time. - -* Normal phase. Every 10ms the run-time counters are compared - to the supplied threshold values, and the decision will be made - whether to move to a different power state (by adjusting the - frequency). - -API Overview for Empty Poll Power Management -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* **State Init**: initialize the power management system. - -* **State Free**: free the resource hold by power management system. - -* **Update Empty Poll Counter**: update the empty poll counter. - -* **Update Valid Poll Counter**: update the valid poll counter. - -* **Set the Frequency Index**: update the power state/frequency mapping. - -* **Detect empty poll state change**: empty poll state change detection algorithm then take action. - -User Cases ----------- -The mechanism can applied to any device which is based on polling. e.g. NIC, FPGA. - Ethernet PMD Power Management API --------------------------------- diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst index b8c5b68d6c..bc3395d1ca 100644 --- a/doc/guides/rel_notes/release_23_03.rst +++ b/doc/guides/rel_notes/release_23_03.rst @@ -68,6 +68,10 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= + * Removed the experimental empty poll API from the power library + The empty poll mechanism is superseded by the power PMD modes + i.e. monitor, pause and scale. + API Changes ----------- diff --git a/doc/guides/sample_app_ug/l3_forward_power_man.rst b/doc/guides/sample_app_ug/l3_forward_power_man.rst index fa3ef67c08..4a6f33bf4f 100644 --- a/doc/guides/sample_app_ug/l3_forward_power_man.rst +++ b/doc/guides/sample_app_ug/l3_forward_power_man.rst @@ -109,8 +109,6 @@ where, * --no-numa: optional, disables numa awareness -* --empty-poll: Traffic Aware power management. See below for details - * --telemetry: Telemetry mode. * --pmd-mgmt: PMD power management mode. @@ -238,74 +236,6 @@ If a thread polls multiple Rx queues and different queue returns different sleep the algorithm controls the sleep time in a conservative manner by sleeping for the least possible time in order to avoid a potential performance impact. -Empty Poll Mode -------------------------- -Additionally, there is a traffic aware mode of operation called "Empty -Poll" where the number of empty polls can be monitored to keep track -of how busy the application is. Empty poll mode can be enabled by the -command line option --empty-poll. - -See :doc:`Power Management<../prog_guide/power_man>` chapter in the DPDK Programmer's Guide for empty poll mode details. - -.. code-block:: console - - ./<build_dir>/examples/dpdk-l3fwd-power -l xxx -n 4 -a 0000:xx:00.0 -a 0000:xx:00.1 \ - -- -p 0x3 -P --config="(0,0,xx),(1,0,xx)" --empty-poll="0,0,0" -l 14 -m 9 -h 1 - -Where, - ---empty-poll: Enable the empty poll mode instead of original algorithm - ---empty-poll="training_flag, med_threshold, high_threshold" - -* ``training_flag`` : optional, enable/disable training mode. Default value is 0. If the training_flag is set as 1(true), then the application will start in training mode and print out the trained threshold values. If the training_flag is set as 0(false), the application will start in normal mode, and will use either the default thresholds or those supplied on the command line. The trained threshold values are specific to the user’s system, may give a better power profile when compared to the default threshold values. - -* ``med_threshold`` : optional, sets the empty poll threshold of a modestly busy system state. If this is not supplied, the application will apply the default value of 350000. - -* ``high_threshold`` : optional, sets the empty poll threshold of a busy system state. If this is not supplied, the application will apply the default value of 580000. - -* -l : optional, set up the LOW power state frequency index - -* -m : optional, set up the MED power state frequency index - -* -h : optional, set up the HIGH power state frequency index - -Empty Poll Mode Example Usage -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To initially obtain the ideal thresholds for the system, the training -mode should be run first. This is achieved by running the l3fwd-power -app with the training flag set to “1”, and the other parameters set to -0. - -.. code-block:: console - - ./<build_dir>/examples/dpdk-l3fwd-power -l 1-3 -- -p 0x0f --config="(0,0,2),(0,1,3)" --empty-poll "1,0,0" –P - -This will run the training algorithm for x seconds on each core (cores 2 -and 3), and then print out the recommended threshold values for those -cores. The thresholds should be very similar for each core. - -.. code-block:: console - - POWER: Bring up the Timer - POWER: set the power freq to MED - POWER: Low threshold is 230277 - POWER: MED threshold is 335071 - POWER: HIGH threshold is 523769 - POWER: Training is Complete for 2 - POWER: set the power freq to MED - POWER: Low threshold is 236814 - POWER: MED threshold is 344567 - POWER: HIGH threshold is 538580 - POWER: Training is Complete for 3 - -Once the values have been measured for a particular system, the app can -then be started without the training mode so traffic can start immediately. - -.. code-block:: console - - ./<build_dir>/examples/dpdk-l3fwd-power -l 1-3 -- -p 0x0f --config="(0,0,2),(0,1,3)" --empty-poll "0,340000,540000" –P - Telemetry Mode -------------- -- 2.17.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 0/3] power: remove experimental empty poll API 2023-02-08 10:48 ` [PATCH v2 0/3] power: remove experimental empty poll API David Hunt ` (2 preceding siblings ...) 2023-02-08 10:48 ` [PATCH v2 3/3] doc/power: remove empty poll documentation David Hunt @ 2023-02-19 23:53 ` Thomas Monjalon 3 siblings, 0 replies; 14+ messages in thread From: Thomas Monjalon @ 2023-02-19 23:53 UTC (permalink / raw) To: David Hunt; +Cc: dev, reshma.pattan 08/02/2023 11:48, David Hunt: > The empty poll mechanism was an experimental API added in > commit id 450f0791312c. It aimed to allow power saving depending > on the traffic profile. However, it required a training phase > and required the user to adjust magic numbers depending on > their workload. > > A new and improved mechanism was added in commit id > 682a645438c5, also based on empty polls, implemented a > callback mechanism which added 'monitor', 'pause' and 'scale' > modes in l3fwd-power. This was and easier mechanism to use, > so the original empty poll mechanism is no longer needed. > > This patch set removes the experimental empty poll API, the > empty poll mode from l3fwd-power, and related documentation. > > This is based on a deprecation notice in the previous release. > > [1/3] examples/power: remove empty poll mode from > [2/3] libs/power: remove experimental empty poll API > [3/3] doc/power: remove empty poll documentation Squashed and applied, thanks. ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v1 2/3] libs/power: remove experimental empty poll API 2022-12-20 12:56 power: remove experimental empty poll API David Hunt 2022-12-20 12:56 ` [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt @ 2022-12-20 12:56 ` David Hunt 2023-02-07 11:04 ` Pattan, Reshma 2022-12-20 12:56 ` [PATCH v1 3/3] doc/power: remove empty poll documentation David Hunt 2 siblings, 1 reply; 14+ messages in thread From: David Hunt @ 2022-12-20 12:56 UTC (permalink / raw) To: dev; +Cc: david.hunt This patchset removes the empty poll experimental API, which has been in an experimental state since it was added. This API is no longer needed as it is superceded by the monitor/pause/scale callback mechanism. Signed-off-by: David Hunt <david.hunt@intel.com> --- lib/power/meson.build | 2 - lib/power/rte_power_empty_poll.c | 529 ------------------------------- lib/power/rte_power_empty_poll.h | 223 ------------- lib/power/version.map | 7 - 4 files changed, 761 deletions(-) delete mode 100644 lib/power/rte_power_empty_poll.c delete mode 100644 lib/power/rte_power_empty_poll.h diff --git a/lib/power/meson.build b/lib/power/meson.build index 49a805391f..1ce8b7c07d 100644 --- a/lib/power/meson.build +++ b/lib/power/meson.build @@ -19,13 +19,11 @@ sources = files( 'power_kvm_vm.c', 'power_pstate_cpufreq.c', 'rte_power.c', - 'rte_power_empty_poll.c', 'rte_power_intel_uncore.c', 'rte_power_pmd_mgmt.c', ) headers = files( 'rte_power.h', - 'rte_power_empty_poll.h', 'rte_power_intel_uncore.h', 'rte_power_pmd_mgmt.h', 'rte_power_guest_channel.h', diff --git a/lib/power/rte_power_empty_poll.c b/lib/power/rte_power_empty_poll.c deleted file mode 100644 index 4a4db51247..0000000000 --- a/lib/power/rte_power_empty_poll.c +++ /dev/null @@ -1,529 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2018 Intel Corporation - */ - -#include <string.h> - -#include <rte_lcore.h> -#include <rte_malloc.h> -#include <inttypes.h> - -#include "rte_power.h" -#include "rte_power_empty_poll.h" - -#define INTERVALS_PER_SECOND 100 /* (10ms) */ -#define SECONDS_TO_TRAIN_FOR 2 -#define DEFAULT_MED_TO_HIGH_PERCENT_THRESHOLD 70 -#define DEFAULT_HIGH_TO_MED_PERCENT_THRESHOLD 30 -#define DEFAULT_CYCLES_PER_PACKET 800 - -static struct ep_params *ep_params; -static uint32_t med_to_high_threshold = DEFAULT_MED_TO_HIGH_PERCENT_THRESHOLD; -static uint32_t high_to_med_threshold = DEFAULT_HIGH_TO_MED_PERCENT_THRESHOLD; - -static uint32_t avail_freqs[RTE_MAX_LCORE][NUM_FREQS]; - -static uint32_t total_avail_freqs[RTE_MAX_LCORE]; - -static uint32_t freq_index[NUM_FREQ]; - -static uint32_t -get_freq_index(enum freq_val index) -{ - return freq_index[index]; -} - - -static int -set_power_freq(int lcore_id, enum freq_val freq, bool specific_freq) -{ - int err = 0; - uint32_t power_freq_index; - if (!specific_freq) - power_freq_index = get_freq_index(freq); - else - power_freq_index = freq; - - err = rte_power_set_freq(lcore_id, power_freq_index); - - return err; -} - - -static __rte_always_inline void -exit_training_state(struct priority_worker *poll_stats) -{ - RTE_SET_USED(poll_stats); -} - -static __rte_always_inline void -enter_training_state(struct priority_worker *poll_stats) -{ - poll_stats->iter_counter = 0; - poll_stats->cur_freq = LOW; - poll_stats->queue_state = TRAINING; -} - -static __rte_always_inline void -enter_normal_state(struct priority_worker *poll_stats) -{ - /* Clear the averages arrays and strs */ - memset(poll_stats->edpi_av, 0, sizeof(poll_stats->edpi_av)); - poll_stats->ec = 0; - - poll_stats->cur_freq = MED; - poll_stats->iter_counter = 0; - poll_stats->threshold_ctr = 0; - poll_stats->queue_state = MED_NORMAL; - RTE_LOG(INFO, POWER, "Set the power freq to MED\n"); - set_power_freq(poll_stats->lcore_id, MED, false); - - poll_stats->thresh[MED].threshold_percent = med_to_high_threshold; - poll_stats->thresh[HGH].threshold_percent = high_to_med_threshold; -} - -static __rte_always_inline void -enter_busy_state(struct priority_worker *poll_stats) -{ - memset(poll_stats->edpi_av, 0, sizeof(poll_stats->edpi_av)); - poll_stats->ec = 0; - - poll_stats->cur_freq = HGH; - poll_stats->iter_counter = 0; - poll_stats->threshold_ctr = 0; - poll_stats->queue_state = HGH_BUSY; - set_power_freq(poll_stats->lcore_id, HGH, false); -} - -static __rte_always_inline void -enter_purge_state(struct priority_worker *poll_stats) -{ - poll_stats->iter_counter = 0; - poll_stats->queue_state = LOW_PURGE; -} - -static __rte_always_inline void -set_state(struct priority_worker *poll_stats, - enum queue_state new_state) -{ - enum queue_state old_state = poll_stats->queue_state; - if (old_state != new_state) { - - /* Call any old state exit functions */ - if (old_state == TRAINING) - exit_training_state(poll_stats); - - /* Call any new state entry functions */ - if (new_state == TRAINING) - enter_training_state(poll_stats); - if (new_state == MED_NORMAL) - enter_normal_state(poll_stats); - if (new_state == HGH_BUSY) - enter_busy_state(poll_stats); - if (new_state == LOW_PURGE) - enter_purge_state(poll_stats); - } -} - -static __rte_always_inline void -set_policy(struct priority_worker *poll_stats, - struct ep_policy *policy) -{ - set_state(poll_stats, policy->state); - - if (policy->state == TRAINING) - return; - - poll_stats->thresh[MED_NORMAL].base_edpi = policy->med_base_edpi; - poll_stats->thresh[HGH_BUSY].base_edpi = policy->hgh_base_edpi; - - poll_stats->thresh[MED_NORMAL].trained = true; - poll_stats->thresh[HGH_BUSY].trained = true; - -} - -static void -update_training_stats(struct priority_worker *poll_stats, - uint32_t freq, - bool specific_freq, - uint32_t max_train_iter) -{ - RTE_SET_USED(specific_freq); - - uint64_t p0_empty_deq; - - if (poll_stats->cur_freq == freq && - poll_stats->thresh[freq].trained == false) { - if (poll_stats->thresh[freq].cur_train_iter == 0) { - - set_power_freq(poll_stats->lcore_id, - freq, specific_freq); - - poll_stats->empty_dequeues_prev = - poll_stats->empty_dequeues; - - poll_stats->thresh[freq].cur_train_iter++; - - return; - } else if (poll_stats->thresh[freq].cur_train_iter - <= max_train_iter) { - - p0_empty_deq = poll_stats->empty_dequeues - - poll_stats->empty_dequeues_prev; - - poll_stats->empty_dequeues_prev = - poll_stats->empty_dequeues; - - poll_stats->thresh[freq].base_edpi += p0_empty_deq; - poll_stats->thresh[freq].cur_train_iter++; - - } else { - if (poll_stats->thresh[freq].trained == false) { - poll_stats->thresh[freq].base_edpi = - poll_stats->thresh[freq].base_edpi / - max_train_iter; - - /* Add on a factor of 0.05% - * this should remove any - * false negatives when the system is 0% busy - */ - poll_stats->thresh[freq].base_edpi += - poll_stats->thresh[freq].base_edpi / 2000; - - poll_stats->thresh[freq].trained = true; - poll_stats->cur_freq++; - - } - } - } -} - -static __rte_always_inline uint32_t -update_stats(struct priority_worker *poll_stats) -{ - uint64_t tot_edpi = 0; - uint32_t j, percent; - - struct priority_worker *s = poll_stats; - - uint64_t cur_edpi = s->empty_dequeues - s->empty_dequeues_prev; - - s->empty_dequeues_prev = s->empty_dequeues; - - if (s->thresh[s->cur_freq].base_edpi < cur_edpi) { - - /* edpi mean empty poll counter difference per interval */ - RTE_LOG(DEBUG, POWER, "cur_edpi is too large " - "cur edpi %"PRId64" " - "base edpi %"PRId64"\n", - cur_edpi, - s->thresh[s->cur_freq].base_edpi); - /* Value to make us fail need debug log*/ - return 1000UL; - } - - s->edpi_av[s->ec++ % BINS_AV] = cur_edpi; - - for (j = 0; j < BINS_AV; j++) { - tot_edpi += s->edpi_av[j]; - } - - tot_edpi = tot_edpi / BINS_AV; - - percent = 100 - (uint32_t)(((float)tot_edpi / - (float)s->thresh[s->cur_freq].base_edpi) * 100); - - return (uint32_t)percent; -} - - -static __rte_always_inline void -update_stats_normal(struct priority_worker *poll_stats) -{ - uint32_t percent; - - if (poll_stats->thresh[poll_stats->cur_freq].base_edpi == 0) { - - enum freq_val cur_freq = poll_stats->cur_freq; - - /* edpi mean empty poll counter difference per interval */ - RTE_LOG(DEBUG, POWER, "cure freq is %d, edpi is %"PRIu64"\n", - cur_freq, - poll_stats->thresh[cur_freq].base_edpi); - return; - } - - percent = update_stats(poll_stats); - - if (percent > 100) { - /* edpi mean empty poll counter difference per interval */ - RTE_LOG(DEBUG, POWER, "Edpi is bigger than threshold\n"); - return; - } - - if (poll_stats->cur_freq == LOW) - RTE_LOG(INFO, POWER, "Purge Mode is not currently supported\n"); - else if (poll_stats->cur_freq == MED) { - - if (percent > - poll_stats->thresh[MED].threshold_percent) { - - if (poll_stats->threshold_ctr < INTERVALS_PER_SECOND) - poll_stats->threshold_ctr++; - else { - set_state(poll_stats, HGH_BUSY); - RTE_LOG(INFO, POWER, "MOVE to HGH\n"); - } - - } else { - /* reset */ - poll_stats->threshold_ctr = 0; - } - - } else if (poll_stats->cur_freq == HGH) { - - if (percent < - poll_stats->thresh[HGH].threshold_percent) { - - if (poll_stats->threshold_ctr < INTERVALS_PER_SECOND) - poll_stats->threshold_ctr++; - else { - set_state(poll_stats, MED_NORMAL); - RTE_LOG(INFO, POWER, "MOVE to MED\n"); - } - } else { - /* reset */ - poll_stats->threshold_ctr = 0; - } - - } -} - -static int -empty_poll_training(struct priority_worker *poll_stats, - uint32_t max_train_iter) -{ - - if (poll_stats->iter_counter < INTERVALS_PER_SECOND) { - poll_stats->iter_counter++; - return 0; - } - - - update_training_stats(poll_stats, - LOW, - false, - max_train_iter); - - update_training_stats(poll_stats, - MED, - false, - max_train_iter); - - update_training_stats(poll_stats, - HGH, - false, - max_train_iter); - - - if (poll_stats->thresh[LOW].trained == true - && poll_stats->thresh[MED].trained == true - && poll_stats->thresh[HGH].trained == true) { - - set_state(poll_stats, MED_NORMAL); - - RTE_LOG(INFO, POWER, "LOW threshold is %"PRIu64"\n", - poll_stats->thresh[LOW].base_edpi); - - RTE_LOG(INFO, POWER, "MED threshold is %"PRIu64"\n", - poll_stats->thresh[MED].base_edpi); - - - RTE_LOG(INFO, POWER, "HIGH threshold is %"PRIu64"\n", - poll_stats->thresh[HGH].base_edpi); - - RTE_LOG(INFO, POWER, "Training is Complete for %d\n", - poll_stats->lcore_id); - } - - return 0; -} - -void -rte_empty_poll_detection(struct rte_timer *tim, void *arg) -{ - - uint32_t i; - - struct priority_worker *poll_stats; - - RTE_SET_USED(tim); - - RTE_SET_USED(arg); - - for (i = 0; i < NUM_NODES; i++) { - - poll_stats = &(ep_params->wrk_data.wrk_stats[i]); - - if (rte_lcore_is_enabled(poll_stats->lcore_id) == 0) - continue; - - switch (poll_stats->queue_state) { - case(TRAINING): - empty_poll_training(poll_stats, - ep_params->max_train_iter); - break; - - case(HGH_BUSY): - case(MED_NORMAL): - update_stats_normal(poll_stats); - break; - - case(LOW_PURGE): - break; - default: - break; - - } - - } - -} - -int -rte_power_empty_poll_stat_init(struct ep_params **eptr, uint8_t *freq_tlb, - struct ep_policy *policy) -{ - uint32_t i; - /* Allocate the ep_params structure */ - ep_params = rte_zmalloc_socket(NULL, - sizeof(struct ep_params), - 0, - rte_socket_id()); - - if (!ep_params) - return -1; - - if (freq_tlb == NULL) { - freq_index[LOW] = 14; - freq_index[MED] = 9; - freq_index[HGH] = 1; - } else { - freq_index[LOW] = freq_tlb[LOW]; - freq_index[MED] = freq_tlb[MED]; - freq_index[HGH] = freq_tlb[HGH]; - } - - RTE_LOG(INFO, POWER, "Initialize the Empty Poll\n"); - - /* Train for pre-defined period */ - ep_params->max_train_iter = INTERVALS_PER_SECOND * SECONDS_TO_TRAIN_FOR; - - struct stats_data *w = &ep_params->wrk_data; - - *eptr = ep_params; - - /* initialize all wrk_stats state */ - for (i = 0; i < NUM_NODES; i++) { - - if (rte_lcore_is_enabled(i) == 0) - continue; - /*init the freqs table */ - total_avail_freqs[i] = rte_power_freqs(i, - avail_freqs[i], - NUM_FREQS); - - RTE_LOG(INFO, POWER, "total avail freq is %d , lcoreid %d\n", - total_avail_freqs[i], - i); - - if (get_freq_index(LOW) > total_avail_freqs[i]) - return -1; - - if (rte_get_main_lcore() != i) { - w->wrk_stats[i].lcore_id = i; - set_policy(&w->wrk_stats[i], policy); - } - } - - return 0; -} - -void -rte_power_empty_poll_stat_free(void) -{ - - RTE_LOG(INFO, POWER, "Close the Empty Poll\n"); - - rte_free(ep_params); -} - -int -rte_power_empty_poll_stat_update(unsigned int lcore_id) -{ - struct priority_worker *poll_stats; - - if (lcore_id >= NUM_NODES) - return -1; - - poll_stats = &(ep_params->wrk_data.wrk_stats[lcore_id]); - - if (poll_stats->lcore_id == 0) - poll_stats->lcore_id = lcore_id; - - poll_stats->empty_dequeues++; - - return 0; -} - -int -rte_power_poll_stat_update(unsigned int lcore_id, uint8_t nb_pkt) -{ - - struct priority_worker *poll_stats; - - if (lcore_id >= NUM_NODES) - return -1; - - poll_stats = &(ep_params->wrk_data.wrk_stats[lcore_id]); - - if (poll_stats->lcore_id == 0) - poll_stats->lcore_id = lcore_id; - - poll_stats->num_dequeue_pkts += nb_pkt; - - return 0; -} - - -uint64_t -rte_power_empty_poll_stat_fetch(unsigned int lcore_id) -{ - struct priority_worker *poll_stats; - - if (lcore_id >= NUM_NODES) - return -1; - - poll_stats = &(ep_params->wrk_data.wrk_stats[lcore_id]); - - if (poll_stats->lcore_id == 0) - poll_stats->lcore_id = lcore_id; - - return poll_stats->empty_dequeues; -} - -uint64_t -rte_power_poll_stat_fetch(unsigned int lcore_id) -{ - struct priority_worker *poll_stats; - - if (lcore_id >= NUM_NODES) - return -1; - - poll_stats = &(ep_params->wrk_data.wrk_stats[lcore_id]); - - if (poll_stats->lcore_id == 0) - poll_stats->lcore_id = lcore_id; - - return poll_stats->num_dequeue_pkts; -} diff --git a/lib/power/rte_power_empty_poll.h b/lib/power/rte_power_empty_poll.h deleted file mode 100644 index b9819337e6..0000000000 --- a/lib/power/rte_power_empty_poll.h +++ /dev/null @@ -1,223 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2018 Intel Corporation - */ - -#ifndef _RTE_EMPTY_POLL_H -#define _RTE_EMPTY_POLL_H - -/** - * @file - * RTE Power Management - */ -#include <stdint.h> -#include <stdbool.h> - -#include <rte_compat.h> -#include <rte_common.h> -#include <rte_string_fns.h> -#include <rte_timer.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define NUM_FREQS RTE_MAX_LCORE_FREQS - -#define BINS_AV 4 /* Has to be ^2 */ - -#define DROP (NUM_DIRECTIONS * NUM_DEVICES) - -#define NUM_PRIORITIES 2 - -#define NUM_NODES 256 /* Max core number*/ - -/* Processor Power State */ -enum freq_val { - LOW, - MED, - HGH, - NUM_FREQ = NUM_FREQS -}; - - -/* Queue Polling State */ -enum queue_state { - TRAINING, /* NO TRAFFIC */ - MED_NORMAL, /* MED */ - HGH_BUSY, /* HIGH */ - LOW_PURGE, /* LOW */ -}; - -/* Queue Stats */ -struct freq_threshold { - - uint64_t base_edpi; - bool trained; - uint32_t threshold_percent; - uint32_t cur_train_iter; -}; - -/* Each Worker Thread Empty Poll Stats */ -struct priority_worker { - - /* Current dequeue and throughput counts */ - /* These 2 are written to by the worker threads */ - /* So keep them on their own cache line */ - uint64_t empty_dequeues; - uint64_t num_dequeue_pkts; - - enum queue_state queue_state; - - uint64_t empty_dequeues_prev; - - /* Used for training only */ - struct freq_threshold thresh[NUM_FREQ]; - enum freq_val cur_freq; - - /* bucket arrays to calculate the averages */ - /* edpi mean empty poll counter difference per interval */ - uint64_t edpi_av[BINS_AV]; - /* empty poll counter */ - uint32_t ec; - - uint32_t lcore_id; - uint32_t iter_counter; - uint32_t threshold_ctr; - uint32_t display_ctr; - uint8_t dev_id; - -} __rte_cache_aligned; - - -struct stats_data { - - struct priority_worker wrk_stats[NUM_NODES]; - - /* flag to stop rx threads processing packets until training over */ - bool start_rx; - -}; - -/* Empty Poll Parameters */ -struct ep_params { - - /* Timer related stuff */ - uint64_t interval_ticks; - uint32_t max_train_iter; - - struct rte_timer timer0; - struct stats_data wrk_data; -}; - - -/* Sample App Init information */ -struct ep_policy { - - uint64_t med_base_edpi; - uint64_t hgh_base_edpi; - - enum queue_state state; -}; - - - -/** - * Initialize the power management system. - * - * @param eptr - * the structure of empty poll configuration - * @param freq_tlb - * the power state/frequency mapping table - * @param policy - * the initialization policy from sample app - * - * @return - * - 0 on success. - * - Negative on error. - */ -__rte_experimental -int -rte_power_empty_poll_stat_init(struct ep_params **eptr, uint8_t *freq_tlb, - struct ep_policy *policy); - -/** - * Free the resource hold by power management system. - */ -__rte_experimental -void -rte_power_empty_poll_stat_free(void); - -/** - * Update specific core empty poll counter - * It's not thread safe. - * - * @param lcore_id - * lcore id - * - * @return - * - 0 on success. - * - Negative on error. - */ -__rte_experimental -int -rte_power_empty_poll_stat_update(unsigned int lcore_id); - -/** - * Update specific core valid poll counter, not thread safe. - * - * @param lcore_id - * lcore id. - * @param nb_pkt - * The packet number of one valid poll. - * - * @return - * - 0 on success. - * - Negative on error. - */ -__rte_experimental -int -rte_power_poll_stat_update(unsigned int lcore_id, uint8_t nb_pkt); - -/** - * Fetch specific core empty poll counter. - * - * @param lcore_id - * lcore id - * - * @return - * Current lcore empty poll counter value. - */ -__rte_experimental -uint64_t -rte_power_empty_poll_stat_fetch(unsigned int lcore_id); - -/** - * Fetch specific core valid poll counter. - * - * @param lcore_id - * lcore id - * - * @return - * Current lcore valid poll counter value. - */ -__rte_experimental -uint64_t -rte_power_poll_stat_fetch(unsigned int lcore_id); - -/** - * Empty poll state change detection function - * - * @param tim - * The timer structure - * @param arg - * The customized parameter - */ -__rte_experimental -void -rte_empty_poll_detection(struct rte_timer *tim, void *arg); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/power/version.map b/lib/power/version.map index 8fccbf20f7..05d544e947 100644 --- a/lib/power/version.map +++ b/lib/power/version.map @@ -25,15 +25,8 @@ DPDK_23 { EXPERIMENTAL { global: - rte_empty_poll_detection; rte_power_check_env_supported; - rte_power_empty_poll_stat_fetch; - rte_power_empty_poll_stat_free; - rte_power_empty_poll_stat_init; - rte_power_empty_poll_stat_update; rte_power_guest_channel_receive_msg; - rte_power_poll_stat_fetch; - rte_power_poll_stat_update; # added in 21.02 rte_power_ethdev_pmgmt_queue_disable; -- 2.17.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH v1 2/3] libs/power: remove experimental empty poll API 2022-12-20 12:56 ` [PATCH v1 2/3] libs/power: " David Hunt @ 2023-02-07 11:04 ` Pattan, Reshma 0 siblings, 0 replies; 14+ messages in thread From: Pattan, Reshma @ 2023-02-07 11:04 UTC (permalink / raw) To: Hunt, David, dev; +Cc: Hunt, David > -----Original Message----- > From: David Hunt <david.hunt@intel.com> > Subject: [PATCH v1 2/3] libs/power: remove experimental empty poll API Typo: libs=>lib > This API is no longer needed as it is superceded by the monitor/pause/scale > callback mechanism. monitor/pause/scale => "PMD Power Management Mode monitor/pause/scale" Rest of the changes looks ok. > Signed-off-by: David Hunt <david.hunt@intel.com> Acked-By: Reshma Pattan <reshma.pattan@intel.com> ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v1 3/3] doc/power: remove empty poll documentation 2022-12-20 12:56 power: remove experimental empty poll API David Hunt 2022-12-20 12:56 ` [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt 2022-12-20 12:56 ` [PATCH v1 2/3] libs/power: " David Hunt @ 2022-12-20 12:56 ` David Hunt 2023-02-07 10:06 ` Pattan, Reshma 2 siblings, 1 reply; 14+ messages in thread From: David Hunt @ 2022-12-20 12:56 UTC (permalink / raw) To: dev; +Cc: david.hunt Remove the documentation for the removed experimental empty poll API, as it is no longer needed. This API is no longer needed as it is superceded by the monitor/pause/scale callback mechanism. Signed-off-by: David Hunt <david.hunt@intel.com> --- doc/guides/prog_guide/power_man.rst | 94 ------------------- doc/guides/rel_notes/release_23_03.rst | 4 + .../sample_app_ug/l3_forward_power_man.rst | 70 -------------- 3 files changed, 4 insertions(+), 164 deletions(-) diff --git a/doc/guides/prog_guide/power_man.rst b/doc/guides/prog_guide/power_man.rst index 68db59bd49..f6674efe2d 100644 --- a/doc/guides/prog_guide/power_man.rst +++ b/doc/guides/prog_guide/power_man.rst @@ -107,100 +107,6 @@ User Cases The power management mechanism is used to save power when performing L3 forwarding. -Empty Poll API --------------- - -Removal Warning -~~~~~~~~~~~~~~~ - -The experimental empty poll API will be removed from the library -in a future DPDK release. -The empty poll mechanism is superseded by the power PMD modes -i.e. monitor, pause and scale. - - -Abstract -~~~~~~~~ - -For packet processing workloads such as DPDK polling is continuous. -This means CPU cores always show 100% busy independent of how much work -those cores are doing. It is critical to accurately determine how busy -a core is hugely important for the following reasons: - - * No indication of overload conditions - * User does not know how much real load is on a system, resulting - in wasted energy as no power management is utilized - -Compared to the original l3fwd-power design, instead of going to sleep -after detecting an empty poll, the new mechanism just lowers the core frequency. -As a result, the application does not stop polling the device, which leads -to improved handling of bursts of traffic. - -When the system become busy, the empty poll mechanism can also increase the core -frequency (including turbo) to do best effort for intensive traffic. This gives -us more flexible and balanced traffic awareness over the standard l3fwd-power -application. - - -Proposed Solution -~~~~~~~~~~~~~~~~~ -The proposed solution focuses on how many times empty polls are executed. -The less the number of empty polls, means current core is busy with processing -workload, therefore, the higher frequency is needed. The high empty poll number -indicates the current core not doing any real work therefore, we can lower the -frequency to safe power. - -In the current implementation, each core has 1 empty-poll counter which assume -1 core is dedicated to 1 queue. This will need to be expanded in the future to -support multiple queues per core. - -Power state definition: -^^^^^^^^^^^^^^^^^^^^^^^ - -* LOW: Not currently used, reserved for future use. - -* MED: the frequency is used to process modest traffic workload. - -* HIGH: the frequency is used to process busy traffic workload. - -There are two phases to establish the power management system: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* Training phase. This phase is used to measure the optimal frequency - change thresholds for a given system. The thresholds will differ from - system to system due to differences in processor micro-architecture, - cache and device configurations. - In this phase, the user must ensure that no traffic can enter the - system so that counts can be measured for empty polls at low, medium - and high frequencies. Each frequency is measured for two seconds. - Once the training phase is complete, the threshold numbers are - displayed, and normal mode resumes, and traffic can be allowed into - the system. These threshold number can be used on the command line - when starting the application in normal mode to avoid re-training - every time. - -* Normal phase. Every 10ms the run-time counters are compared - to the supplied threshold values, and the decision will be made - whether to move to a different power state (by adjusting the - frequency). - -API Overview for Empty Poll Power Management -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* **State Init**: initialize the power management system. - -* **State Free**: free the resource hold by power management system. - -* **Update Empty Poll Counter**: update the empty poll counter. - -* **Update Valid Poll Counter**: update the valid poll counter. - -* **Set the Frequency Index**: update the power state/frequency mapping. - -* **Detect empty poll state change**: empty poll state change detection algorithm then take action. - -User Cases ----------- -The mechanism can applied to any device which is based on polling. e.g. NIC, FPGA. - Ethernet PMD Power Management API --------------------------------- diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst index b8c5b68d6c..bc3395d1ca 100644 --- a/doc/guides/rel_notes/release_23_03.rst +++ b/doc/guides/rel_notes/release_23_03.rst @@ -68,6 +68,10 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= + * Removed the experimental empty poll API from the power library + The empty poll mechanism is superseded by the power PMD modes + i.e. monitor, pause and scale. + API Changes ----------- diff --git a/doc/guides/sample_app_ug/l3_forward_power_man.rst b/doc/guides/sample_app_ug/l3_forward_power_man.rst index fa3ef67c08..4a6f33bf4f 100644 --- a/doc/guides/sample_app_ug/l3_forward_power_man.rst +++ b/doc/guides/sample_app_ug/l3_forward_power_man.rst @@ -109,8 +109,6 @@ where, * --no-numa: optional, disables numa awareness -* --empty-poll: Traffic Aware power management. See below for details - * --telemetry: Telemetry mode. * --pmd-mgmt: PMD power management mode. @@ -238,74 +236,6 @@ If a thread polls multiple Rx queues and different queue returns different sleep the algorithm controls the sleep time in a conservative manner by sleeping for the least possible time in order to avoid a potential performance impact. -Empty Poll Mode -------------------------- -Additionally, there is a traffic aware mode of operation called "Empty -Poll" where the number of empty polls can be monitored to keep track -of how busy the application is. Empty poll mode can be enabled by the -command line option --empty-poll. - -See :doc:`Power Management<../prog_guide/power_man>` chapter in the DPDK Programmer's Guide for empty poll mode details. - -.. code-block:: console - - ./<build_dir>/examples/dpdk-l3fwd-power -l xxx -n 4 -a 0000:xx:00.0 -a 0000:xx:00.1 \ - -- -p 0x3 -P --config="(0,0,xx),(1,0,xx)" --empty-poll="0,0,0" -l 14 -m 9 -h 1 - -Where, - ---empty-poll: Enable the empty poll mode instead of original algorithm - ---empty-poll="training_flag, med_threshold, high_threshold" - -* ``training_flag`` : optional, enable/disable training mode. Default value is 0. If the training_flag is set as 1(true), then the application will start in training mode and print out the trained threshold values. If the training_flag is set as 0(false), the application will start in normal mode, and will use either the default thresholds or those supplied on the command line. The trained threshold values are specific to the user’s system, may give a better power profile when compared to the default threshold values. - -* ``med_threshold`` : optional, sets the empty poll threshold of a modestly busy system state. If this is not supplied, the application will apply the default value of 350000. - -* ``high_threshold`` : optional, sets the empty poll threshold of a busy system state. If this is not supplied, the application will apply the default value of 580000. - -* -l : optional, set up the LOW power state frequency index - -* -m : optional, set up the MED power state frequency index - -* -h : optional, set up the HIGH power state frequency index - -Empty Poll Mode Example Usage -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To initially obtain the ideal thresholds for the system, the training -mode should be run first. This is achieved by running the l3fwd-power -app with the training flag set to “1”, and the other parameters set to -0. - -.. code-block:: console - - ./<build_dir>/examples/dpdk-l3fwd-power -l 1-3 -- -p 0x0f --config="(0,0,2),(0,1,3)" --empty-poll "1,0,0" –P - -This will run the training algorithm for x seconds on each core (cores 2 -and 3), and then print out the recommended threshold values for those -cores. The thresholds should be very similar for each core. - -.. code-block:: console - - POWER: Bring up the Timer - POWER: set the power freq to MED - POWER: Low threshold is 230277 - POWER: MED threshold is 335071 - POWER: HIGH threshold is 523769 - POWER: Training is Complete for 2 - POWER: set the power freq to MED - POWER: Low threshold is 236814 - POWER: MED threshold is 344567 - POWER: HIGH threshold is 538580 - POWER: Training is Complete for 3 - -Once the values have been measured for a particular system, the app can -then be started without the training mode so traffic can start immediately. - -.. code-block:: console - - ./<build_dir>/examples/dpdk-l3fwd-power -l 1-3 -- -p 0x0f --config="(0,0,2),(0,1,3)" --empty-poll "0,340000,540000" –P - Telemetry Mode -------------- -- 2.17.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH v1 3/3] doc/power: remove empty poll documentation 2022-12-20 12:56 ` [PATCH v1 3/3] doc/power: remove empty poll documentation David Hunt @ 2023-02-07 10:06 ` Pattan, Reshma 0 siblings, 0 replies; 14+ messages in thread From: Pattan, Reshma @ 2023-02-07 10:06 UTC (permalink / raw) To: Hunt, David, dev; +Cc: Hunt, David > -----Original Message----- > From: David Hunt <david.hunt@intel.com> --snip-- > This API is no longer needed as it is superceded by the monitor/pause/scale Nitpick. monitor/pause/scale => "PMD Power Managment modes monitor/pause/scale" > Signed-off-by: David Hunt <david.hunt@intel.com> Acked-By: Reshma Pattan <reshma.pattan@intel.com> ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2023-02-19 23:53 UTC | newest] Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-12-20 12:56 power: remove experimental empty poll API David Hunt 2022-12-20 12:56 ` [PATCH v1 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt 2022-12-20 13:26 ` Hunt, David 2023-02-07 10:47 ` Pattan, Reshma 2023-02-08 10:48 ` [PATCH v2 0/3] power: remove experimental empty poll API David Hunt 2023-02-08 10:48 ` [PATCH v2 1/3] examples/power: remove empty poll mode from l3fwd-power David Hunt 2023-02-08 11:11 ` Pattan, Reshma 2023-02-08 10:48 ` [PATCH v2 2/3] libs/power: remove experimental empty poll API David Hunt 2023-02-08 10:48 ` [PATCH v2 3/3] doc/power: remove empty poll documentation David Hunt 2023-02-19 23:53 ` [PATCH v2 0/3] power: remove experimental empty poll API Thomas Monjalon 2022-12-20 12:56 ` [PATCH v1 2/3] libs/power: " David Hunt 2023-02-07 11:04 ` Pattan, Reshma 2022-12-20 12:56 ` [PATCH v1 3/3] doc/power: remove empty poll documentation David Hunt 2023-02-07 10:06 ` Pattan, Reshma
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).