DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH v1 0/5] Implementation of revised ML xstats spec
@ 2023-04-23  5:13 Srikanth Yalavarthi
  2023-04-23  5:13 ` [PATCH v1 1/5] mldev: remove xstats APIs from library Srikanth Yalavarthi
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Srikanth Yalavarthi @ 2023-04-23  5:13 UTC (permalink / raw)
  Cc: dev, syalavarthi, sshankarnara, aprabhu, ptakkar

This series of patches introduces revised xstats specification for ML
device. The revised xstats spec is based on eventdev xstats and supports
DEVICE and MODEL modes to get xstats. This enables retrieving xstats for
device and each model separately.


Srikanth Yalavarthi (5):
  mldev: remove xstats APIs from library
  mldev: introduce revised xstats
  mldev: implement xstats library functions
  app/mldev: enable reporting xstats
  ml/cnxk: implement xstats driver functions

 app/test-mldev/meson.build                 |   1 +
 app/test-mldev/ml_common.h                 |  11 +
 app/test-mldev/ml_options.c                |   5 +-
 app/test-mldev/test_common.h               |   3 +
 app/test-mldev/test_inference_common.c     | 113 -----
 app/test-mldev/test_inference_common.h     |   1 -
 app/test-mldev/test_inference_interleave.c |   6 +-
 app/test-mldev/test_inference_ordered.c    |   5 +-
 app/test-mldev/test_model_ops.c            |   3 +
 app/test-mldev/test_stats.c                | 129 +++++
 app/test-mldev/test_stats.h                |  13 +
 doc/guides/mldevs/cnxk.rst                 |  30 +-
 drivers/ml/cnxk/cn10k_ml_dev.h             |  96 +++-
 drivers/ml/cnxk/cn10k_ml_model.h           |  21 -
 drivers/ml/cnxk/cn10k_ml_ops.c             | 520 +++++++++++++++------
 lib/mldev/rte_mldev.c                      |  15 +-
 lib/mldev/rte_mldev.h                      |  97 ++--
 lib/mldev/rte_mldev_core.h                 |  28 +-
 18 files changed, 757 insertions(+), 340 deletions(-)
 create mode 100644 app/test-mldev/test_stats.c
 create mode 100644 app/test-mldev/test_stats.h

--
2.17.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v1 1/5] mldev: remove xstats APIs from library
  2023-04-23  5:13 [PATCH v1 0/5] Implementation of revised ML xstats spec Srikanth Yalavarthi
@ 2023-04-23  5:13 ` Srikanth Yalavarthi
  2023-04-23  5:14 ` [PATCH v1 2/5] mldev: introduce revised xstats Srikanth Yalavarthi
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Srikanth Yalavarthi @ 2023-04-23  5:13 UTC (permalink / raw)
  To: Srikanth Yalavarthi; +Cc: dev, sshankarnara, aprabhu, ptakkar

This change is a preparatoy step for revised xstats APIs.
Revised xstats APIs support reporting device and per model
stats, which is based on eventdev xstats.

Removed xstats APIs from spec and library implementation.
Disabled reporting xstats in test application and disabled
xstats functions in drivers. Renamed stats_get function to
throughput_get.

This change is needed as the revised APIs are not backward
compatible with the current xstats.

Signed-off-by: Srikanth Yalavarthi <syalavarthi@marvell.com>
---
 app/test-mldev/test_inference_common.c     | 55 +------------
 app/test-mldev/test_inference_common.h     |  2 +-
 app/test-mldev/test_inference_interleave.c |  2 +-
 app/test-mldev/test_inference_ordered.c    |  2 +-
 drivers/ml/cnxk/cn10k_ml_ops.c             | 10 +--
 lib/mldev/rte_mldev.c                      | 88 --------------------
 lib/mldev/rte_mldev.h                      | 90 ---------------------
 lib/mldev/rte_mldev_core.h                 | 93 ----------------------
 lib/mldev/version.map                      |  4 -
 9 files changed, 7 insertions(+), 339 deletions(-)

diff --git a/app/test-mldev/test_inference_common.c b/app/test-mldev/test_inference_common.c
index af831fc1bf..1e16608582 100644
--- a/app/test-mldev/test_inference_common.c
+++ b/app/test-mldev/test_inference_common.c
@@ -1029,7 +1029,7 @@ ml_inference_launch_cores(struct ml_test *test, struct ml_options *opt, uint16_t
 }
 
 int
-ml_inference_stats_get(struct ml_test *test, struct ml_options *opt)
+ml_inference_throughput_get(struct ml_test *test, struct ml_options *opt)
 {
 	struct test_inference *t = ml_test_priv(test);
 	uint64_t total_cycles = 0;
@@ -1038,56 +1038,10 @@ ml_inference_stats_get(struct ml_test *test, struct ml_options *opt)
 	uint64_t avg_e2e;
 	uint32_t qp_id;
 	uint64_t freq;
-	int ret;
-	int i;
 
 	if (!opt->stats)
 		return 0;
 
-	/* get xstats size */
-	t->xstats_size = rte_ml_dev_xstats_names_get(opt->dev_id, NULL, 0);
-	if (t->xstats_size >= 0) {
-		/* allocate for xstats_map and values */
-		t->xstats_map = rte_malloc(
-			"ml_xstats_map", t->xstats_size * sizeof(struct rte_ml_dev_xstats_map), 0);
-		if (t->xstats_map == NULL) {
-			ret = -ENOMEM;
-			goto error;
-		}
-
-		t->xstats_values =
-			rte_malloc("ml_xstats_values", t->xstats_size * sizeof(uint64_t), 0);
-		if (t->xstats_values == NULL) {
-			ret = -ENOMEM;
-			goto error;
-		}
-
-		ret = rte_ml_dev_xstats_names_get(opt->dev_id, t->xstats_map, t->xstats_size);
-		if (ret != t->xstats_size) {
-			printf("Unable to get xstats names, ret = %d\n", ret);
-			ret = -1;
-			goto error;
-		}
-
-		for (i = 0; i < t->xstats_size; i++)
-			rte_ml_dev_xstats_get(opt->dev_id, &t->xstats_map[i].id,
-					      &t->xstats_values[i], 1);
-	}
-
-	/* print xstats*/
-	printf("\n");
-	print_line(80);
-	printf(" ML Device Extended Statistics\n");
-	print_line(80);
-	for (i = 0; i < t->xstats_size; i++)
-		printf(" %-64s = %" PRIu64 "\n", t->xstats_map[i].name, t->xstats_values[i]);
-	print_line(80);
-
-	/* release buffers */
-	rte_free(t->xstats_map);
-
-	rte_free(t->xstats_values);
-
 	/* print end-to-end stats */
 	freq = rte_get_tsc_hz();
 	for (qp_id = 0; qp_id < RTE_MAX_LCORE; qp_id++)
@@ -1121,11 +1075,4 @@ ml_inference_stats_get(struct ml_test *test, struct ml_options *opt)
 	print_line(80);
 
 	return 0;
-
-error:
-	rte_free(t->xstats_map);
-
-	rte_free(t->xstats_values);
-
-	return ret;
 }
diff --git a/app/test-mldev/test_inference_common.h b/app/test-mldev/test_inference_common.h
index e79344cea4..0a9b930788 100644
--- a/app/test-mldev/test_inference_common.h
+++ b/app/test-mldev/test_inference_common.h
@@ -70,6 +70,6 @@ void ml_inference_mem_destroy(struct ml_test *test, struct ml_options *opt);
 int ml_inference_result(struct ml_test *test, struct ml_options *opt, uint16_t fid);
 int ml_inference_launch_cores(struct ml_test *test, struct ml_options *opt, uint16_t start_fid,
 			      uint16_t end_fid);
-int ml_inference_stats_get(struct ml_test *test, struct ml_options *opt);
+int ml_inference_throughput_get(struct ml_test *test, struct ml_options *opt);
 
 #endif /* TEST_INFERENCE_COMMON_H */
diff --git a/app/test-mldev/test_inference_interleave.c b/app/test-mldev/test_inference_interleave.c
index bd2c286737..23b8efe4f0 100644
--- a/app/test-mldev/test_inference_interleave.c
+++ b/app/test-mldev/test_inference_interleave.c
@@ -58,7 +58,7 @@ test_inference_interleave_driver(struct ml_test *test, struct ml_options *opt)
 		ml_inference_iomem_destroy(test, opt, fid);
 	}
 
-	ml_inference_stats_get(test, opt);
+	ml_inference_throughput_get(test, opt);
 
 	for (fid = 0; fid < opt->nb_filelist; fid++) {
 		ret = ml_model_stop(test, opt, &t->model[fid], fid);
diff --git a/app/test-mldev/test_inference_ordered.c b/app/test-mldev/test_inference_ordered.c
index 8992358936..f49810c152 100644
--- a/app/test-mldev/test_inference_ordered.c
+++ b/app/test-mldev/test_inference_ordered.c
@@ -54,7 +54,7 @@ test_inference_ordered_driver(struct ml_test *test, struct ml_options *opt)
 		goto error;
 
 	ml_inference_iomem_destroy(test, opt, fid);
-	ml_inference_stats_get(test, opt);
+	ml_inference_throughput_get(test, opt);
 
 	/* stop model */
 	ret = ml_model_stop(test, opt, &t->model[fid], fid);
diff --git a/drivers/ml/cnxk/cn10k_ml_ops.c b/drivers/ml/cnxk/cn10k_ml_ops.c
index b5eaa24e83..521bad4eea 100644
--- a/drivers/ml/cnxk/cn10k_ml_ops.c
+++ b/drivers/ml/cnxk/cn10k_ml_ops.c
@@ -1089,7 +1089,7 @@ cn10k_ml_dev_xstats_names_get(struct rte_ml_dev *dev, struct rte_ml_dev_xstats_m
 	return count;
 }
 
-static int
+static int __rte_unused
 cn10k_ml_dev_xstats_by_name_get(struct rte_ml_dev *dev, const char *name, uint16_t *stat_id,
 				uint64_t *value)
 {
@@ -1136,7 +1136,7 @@ cn10k_ml_dev_xstats_by_name_get(struct rte_ml_dev *dev, const char *name, uint16
 	return 0;
 }
 
-static int
+static int __rte_unused
 cn10k_ml_dev_xstats_get(struct rte_ml_dev *dev, const uint16_t *stat_ids, uint64_t *values,
 			uint16_t nb_ids)
 {
@@ -1167,7 +1167,7 @@ cn10k_ml_dev_xstats_get(struct rte_ml_dev *dev, const uint16_t *stat_ids, uint64
 	return count;
 }
 
-static int
+static int __rte_unused
 cn10k_ml_dev_xstats_reset(struct rte_ml_dev *dev, const uint16_t *stat_ids, uint16_t nb_ids)
 {
 	struct rte_ml_dev_info dev_info;
@@ -2308,10 +2308,6 @@ struct rte_ml_dev_ops cn10k_ml_ops = {
 	/* Stats ops */
 	.dev_stats_get = cn10k_ml_dev_stats_get,
 	.dev_stats_reset = cn10k_ml_dev_stats_reset,
-	.dev_xstats_names_get = cn10k_ml_dev_xstats_names_get,
-	.dev_xstats_by_name_get = cn10k_ml_dev_xstats_by_name_get,
-	.dev_xstats_get = cn10k_ml_dev_xstats_get,
-	.dev_xstats_reset = cn10k_ml_dev_xstats_reset,
 
 	/* Model ops */
 	.model_load = cn10k_ml_model_load,
diff --git a/lib/mldev/rte_mldev.c b/lib/mldev/rte_mldev.c
index f5904a0d4a..72d4d7a165 100644
--- a/lib/mldev/rte_mldev.c
+++ b/lib/mldev/rte_mldev.c
@@ -438,94 +438,6 @@ rte_ml_dev_stats_reset(int16_t dev_id)
 	(*dev->dev_ops->dev_stats_reset)(dev);
 }
 
-int
-rte_ml_dev_xstats_names_get(int16_t dev_id, struct rte_ml_dev_xstats_map *xstats_map, uint32_t size)
-{
-	struct rte_ml_dev *dev;
-
-	if (!rte_ml_dev_is_valid_dev(dev_id)) {
-		RTE_MLDEV_LOG(ERR, "Invalid dev_id = %d\n", dev_id);
-		return -EINVAL;
-	}
-
-	dev = rte_ml_dev_pmd_get_dev(dev_id);
-	if (*dev->dev_ops->dev_xstats_names_get == NULL)
-		return -ENOTSUP;
-
-	return (*dev->dev_ops->dev_xstats_names_get)(dev, xstats_map, size);
-}
-
-int
-rte_ml_dev_xstats_by_name_get(int16_t dev_id, const char *name, uint16_t *stat_id, uint64_t *value)
-{
-	struct rte_ml_dev *dev;
-
-	if (!rte_ml_dev_is_valid_dev(dev_id)) {
-		RTE_MLDEV_LOG(ERR, "Invalid dev_id = %d\n", dev_id);
-		return -EINVAL;
-	}
-
-	dev = rte_ml_dev_pmd_get_dev(dev_id);
-	if (*dev->dev_ops->dev_xstats_by_name_get == NULL)
-		return -ENOTSUP;
-
-	if (name == NULL) {
-		RTE_MLDEV_LOG(ERR, "Dev %d, name cannot be NULL\n", dev_id);
-		return -EINVAL;
-	}
-
-	if (value == NULL) {
-		RTE_MLDEV_LOG(ERR, "Dev %d, value cannot be NULL\n", dev_id);
-		return -EINVAL;
-	}
-
-	return (*dev->dev_ops->dev_xstats_by_name_get)(dev, name, stat_id, value);
-}
-
-int
-rte_ml_dev_xstats_get(int16_t dev_id, const uint16_t *stat_ids, uint64_t *values, uint16_t nb_ids)
-{
-	struct rte_ml_dev *dev;
-
-	if (!rte_ml_dev_is_valid_dev(dev_id)) {
-		RTE_MLDEV_LOG(ERR, "Invalid dev_id = %d\n", dev_id);
-		return -EINVAL;
-	}
-
-	dev = rte_ml_dev_pmd_get_dev(dev_id);
-	if (*dev->dev_ops->dev_xstats_get == NULL)
-		return -ENOTSUP;
-
-	if (stat_ids == NULL) {
-		RTE_MLDEV_LOG(ERR, "Dev %d, stat_ids cannot be NULL\n", dev_id);
-		return -EINVAL;
-	}
-
-	if (values == NULL) {
-		RTE_MLDEV_LOG(ERR, "Dev %d, values cannot be NULL\n", dev_id);
-		return -EINVAL;
-	}
-
-	return (*dev->dev_ops->dev_xstats_get)(dev, stat_ids, values, nb_ids);
-}
-
-int
-rte_ml_dev_xstats_reset(int16_t dev_id, const uint16_t *stat_ids, uint16_t nb_ids)
-{
-	struct rte_ml_dev *dev;
-
-	if (!rte_ml_dev_is_valid_dev(dev_id)) {
-		RTE_MLDEV_LOG(ERR, "Invalid dev_id = %d\n", dev_id);
-		return -EINVAL;
-	}
-
-	dev = rte_ml_dev_pmd_get_dev(dev_id);
-	if (*dev->dev_ops->dev_xstats_reset == NULL)
-		return -ENOTSUP;
-
-	return (*dev->dev_ops->dev_xstats_reset)(dev, stat_ids, nb_ids);
-}
-
 int
 rte_ml_dev_dump(int16_t dev_id, FILE *fd)
 {
diff --git a/lib/mldev/rte_mldev.h b/lib/mldev/rte_mldev.h
index b22234730d..1e967a7c2a 100644
--- a/lib/mldev/rte_mldev.h
+++ b/lib/mldev/rte_mldev.h
@@ -605,96 +605,6 @@ struct rte_ml_dev_xstats_map {
 	/**< xstat name */
 };
 
-/**
- * Retrieve names of extended statistics of an ML device.
- *
- * @param dev_id
- *   The identifier of the device.
- * @param[out] xstats_map
- *   Block of memory to insert id and names into. Must be at least size in capacity.
- * If set to NULL, function returns required capacity.
- * @param size
- *   Capacity of xstats_map (number of name-id maps).
- *
- * @return
- *   - Positive value on success:
- *      - The return value is the number of entries filled in the stats map.
- *      - If xstats_map set to NULL then required capacity for xstats_map.
- *   - Negative value on error:
- *      - -ENODEV: for invalid *dev_id*.
- *      - -ENOTSUP: if the device doesn't support this function.
- */
-__rte_experimental
-int
-rte_ml_dev_xstats_names_get(int16_t dev_id, struct rte_ml_dev_xstats_map *xstats_map,
-			    uint32_t size);
-
-/**
- * Retrieve the value of a single stat by requesting it by name.
- *
- * @param dev_id
- *   The identifier of the device.
- * @param name
- *   The stat name to retrieve.
- * @param stat_id
- *   If non-NULL, the numerical id of the stat will be returned, so that further requests for
- * the stat can be got using rte_ml_dev_xstats_get, which will be faster as it doesn't need to
- * scan a list of names for the stat.
- * @param[out] value
- *   Must be non-NULL, retrieved xstat value will be stored in this address.
- *
- * @return
- *   - 0: Successfully retrieved xstat value.
- *   - -EINVAL: invalid parameters.
- *   - -ENOTSUP: if not supported.
- */
-__rte_experimental
-int
-rte_ml_dev_xstats_by_name_get(int16_t dev_id, const char *name, uint16_t *stat_id, uint64_t *value);
-
-/**
- * Retrieve extended statistics of an ML device.
- *
- * @param dev_id
- *   The identifier of the device.
- * @param stat_ids
- *   The id numbers of the stats to get. The ids can be fetched from the stat position in the
- * stat list from rte_ml_dev_xstats_names_get(), or by using rte_ml_dev_xstats_by_name_get().
- * @param values
- *   The values for each stats request by ID.
- * @param nb_ids
- *   The number of stats requested.
- * @return
- *   - Positive value: number of stat entries filled into the values array
- *   - Negative value on error:
- *      - -ENODEV: for invalid *dev_id*.
- *      - -ENOTSUP: if the device doesn't support this function.
- */
-__rte_experimental
-int
-rte_ml_dev_xstats_get(int16_t dev_id, const uint16_t *stat_ids, uint64_t *values, uint16_t nb_ids);
-
-/**
- * Reset the values of the xstats of the selected component in the device.
- *
- * @param dev_id
- *   The identifier of the device.
- * @param stat_ids
- *   Selects specific statistics to be reset. When NULL, all statistics will be reset.
- * If non-NULL, must point to array of at least *nb_ids* size.
- * @param nb_ids
- *   The number of ids available from the *ids* array. Ignored when ids is NULL.
- * @return
- *   - 0: Successfully reset the statistics to zero.
- *   - -EINVAL: invalid parameters.
- *   - -ENOTSUP: if not supported.
- */
-__rte_experimental
-int
-rte_ml_dev_xstats_reset(int16_t dev_id, const uint16_t *stat_ids, uint16_t nb_ids);
-
-/* Utility operations */
-
 /**
  * Dump internal information about *dev_id* to the FILE* provided in *fd*.
  *
diff --git a/lib/mldev/rte_mldev_core.h b/lib/mldev/rte_mldev_core.h
index e3c1b2cc2c..926a652397 100644
--- a/lib/mldev/rte_mldev_core.h
+++ b/lib/mldev/rte_mldev_core.h
@@ -236,87 +236,6 @@ typedef int (*mldev_stats_get_t)(struct rte_ml_dev *dev, struct rte_ml_dev_stats
  */
 typedef void (*mldev_stats_reset_t)(struct rte_ml_dev *dev);
 
-/**
- * @internal
- *
- * Function used to get names of extended stats.
- *
- * @param dev
- *	ML device pointer.
- * @param xstats_map
- *	Array to insert id and names into.
- * @param size
- *	Size of xstats_map array.
- *
- * @return
- *	- >= 0 and <= size on success.
- *	- > size, error. Returns the size of xstats_map array required.
- *	- < 0, error code on failure.
- */
-typedef int (*mldev_xstats_names_get_t)(struct rte_ml_dev *dev,
-					struct rte_ml_dev_xstats_map *xstats_map, uint32_t size);
-
-/**
- * @internal
- *
- * Function used to get a single extended stat by name.
- *
- * @param dev
- *	ML device pointer.
- * @param name
- *	Name of the stat to retrieve.
- * @param stat_id
- *	ID of the stat to be returned.
- * @param value
- *	Value of the stat to be returned.
- *
- * @return
- *	- >= 0 stat value.
- *	- < 0, error code on failure.
- */
-typedef int (*mldev_xstats_by_name_get_t)(struct rte_ml_dev *dev, const char *name,
-					  uint16_t *stat_id, uint64_t *value);
-
-/**
- * @internal
- *
- * Function used to retrieve extended stats of a device.
- *
- * @param dev
- *	ML device pointer.
- * @param stat_ids
- *	Array of ID numbers of the stats to be retrieved.
- * @param values
- *	Values of the stats requested by the ID.
- * @param nb_ids
- *	Number of stats requested.
- *
- * @return
- *	- >= 0, number of entries filled into the values array.
- *	- < 0, error code on failure.
- */
-typedef int (*mldev_xstats_get_t)(struct rte_ml_dev *dev, const uint16_t *stat_ids,
-				  uint64_t *values, uint16_t nb_ids);
-
-/**
- * @internal
- *
- * Function used to reset extended stats.
- *
- * @param dev
- *	ML device pointer.
- * @param stat_ids
- *	Array of stats IDs to be reset.
- * @param nb_ids
- *	Number of IDs in the stat_ids array.
- *
- * @return
- *	- 0 on success.
- *	- < 0, error code on failure.
- */
-typedef int (*mldev_xstats_reset_t)(struct rte_ml_dev *dev, const uint16_t *stat_ids,
-				    uint16_t nb_ids);
-
 /**
  * @internal
  *
@@ -579,18 +498,6 @@ struct rte_ml_dev_ops {
 	/** Reset device statistics. */
 	mldev_stats_reset_t dev_stats_reset;
 
-	/** Get names of extended stats. */
-	mldev_xstats_names_get_t dev_xstats_names_get;
-
-	/** Get value of a single extended stat. */
-	mldev_xstats_by_name_get_t dev_xstats_by_name_get;
-
-	/** Get extended stats of a device. */
-	mldev_xstats_get_t dev_xstats_get;
-
-	/** Reset extended stats of the device. */
-	mldev_xstats_reset_t dev_xstats_reset;
-
 	/** Dump ML device debug info. */
 	mldev_dump_t dev_dump;
 
diff --git a/lib/mldev/version.map b/lib/mldev/version.map
index 0706b565be..c774a87a5e 100644
--- a/lib/mldev/version.map
+++ b/lib/mldev/version.map
@@ -17,10 +17,6 @@ EXPERIMENTAL {
 	rte_ml_dev_stats_get;
 	rte_ml_dev_stats_reset;
 	rte_ml_dev_stop;
-	rte_ml_dev_xstats_by_name_get;
-	rte_ml_dev_xstats_get;
-	rte_ml_dev_xstats_names_get;
-	rte_ml_dev_xstats_reset;
 	rte_ml_enqueue_burst;
 	rte_ml_io_dequantize;
 	rte_ml_io_input_size_get;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v1 2/5] mldev: introduce revised xstats
  2023-04-23  5:13 [PATCH v1 0/5] Implementation of revised ML xstats spec Srikanth Yalavarthi
  2023-04-23  5:13 ` [PATCH v1 1/5] mldev: remove xstats APIs from library Srikanth Yalavarthi
@ 2023-04-23  5:14 ` Srikanth Yalavarthi
  2023-04-23  5:14 ` [PATCH v1 3/5] mldev: implement xstats library functions Srikanth Yalavarthi
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Srikanth Yalavarthi @ 2023-04-23  5:14 UTC (permalink / raw)
  To: Srikanth Yalavarthi; +Cc: dev, sshankarnara, aprabhu, ptakkar

Introduce revised xstats APIs to support reporting device and
per-model xstats. Stat type is selected through mode parameter.
Support modes include device and model.

Signed-off-by: Srikanth Yalavarthi <syalavarthi@marvell.com>
---
 lib/mldev/rte_mldev.h | 113 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/lib/mldev/rte_mldev.h b/lib/mldev/rte_mldev.h
index 1e967a7c2a..222ecbdbe1 100644
--- a/lib/mldev/rte_mldev.h
+++ b/lib/mldev/rte_mldev.h
@@ -593,6 +593,16 @@ __rte_experimental
 void
 rte_ml_dev_stats_reset(int16_t dev_id);
 
+/**
+ * Selects the component of the mldev to retrieve statistics from.
+ */
+enum rte_ml_dev_xstats_mode {
+	RTE_ML_DEV_XSTATS_DEVICE,
+	/**< Device xstats */
+	RTE_ML_DEV_XSTATS_MODEL,
+	/**< Model xstats */
+};
+
 /**
  * A name-key lookup element for extended statistics.
  *
@@ -605,6 +615,109 @@ struct rte_ml_dev_xstats_map {
 	/**< xstat name */
 };
 
+/**
+ * Retrieve names of extended statistics of an ML device.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param mode
+ *   Mode of statistics to retrieve. Choices include the device statistics and model statistics.
+ * @param model_id
+ *   Used to specify the model number in model mode, and is ignored in device mode.
+ * @param[out] xstats_map
+ *   Block of memory to insert names and ids into. Must be at least size in capacity. If set to
+ * NULL, function returns required capacity. The id values returned can be passed to
+ * *rte_ml_dev_xstats_get* to select statistics.
+ * @param size
+ *   Capacity of xstats_names (number of xstats_map).
+ * @return
+ *   - Positive value lower or equal to size: success. The return value is the number of entries
+ * filled in the stats table.
+ *   - Positive value higher than size: error, the given statistics table is too small. The return
+ * value corresponds to the size that should be given to succeed. The entries in the table are not
+ * valid and shall not be used by the caller.
+ *   - Negative value on error:
+ *        -ENODEV for invalid *dev_id*.
+ *        -EINVAL for invalid mode, model parameters.
+ *        -ENOTSUP if the device doesn't support this function.
+ */
+__rte_experimental
+int
+rte_ml_dev_xstats_names_get(int16_t dev_id, enum rte_ml_dev_xstats_mode mode, int32_t model_id,
+			    struct rte_ml_dev_xstats_map *xstats_map, uint32_t size);
+
+/**
+ * Retrieve the value of a single stat by requesting it by name.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param name
+ *   Name of stat name to retrieve.
+ * @param[out] stat_id
+ *   If non-NULL, the numerical id of the stat will be returned, so that further requests for the
+ * stat can be got using rte_ml_dev_xstats_get, which will be faster as it doesn't need to scan a
+ * list of names for the stat. If the stat cannot be found, the id returned will be (unsigned)-1.
+ * @param[out] value
+ *   Value of the stat to be returned.
+ * @return
+ *   - Zero: No error.
+ *   - Negative value: -EINVAL if stat not found, -ENOTSUP if not supported.
+ */
+__rte_experimental
+int
+rte_ml_dev_xstats_by_name_get(int16_t dev_id, const char *name, uint16_t *stat_id, uint64_t *value);
+
+/**
+ * Retrieve extended statistics of an ML device.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param mode
+ *  Mode of statistics to retrieve. Choices include the device statistics and model statistics.
+ * @param model_id
+ *   Used to specify the model id in model mode, and is ignored in device mode.
+ * @param stat_ids
+ *   ID numbers of the stats to get. The ids can be got from the stat position in the stat list from
+ * rte_ml_dev_xstats_names_get(), or by using rte_ml_dev_xstats_by_name_get().
+ * @param[out] values
+ *   Values for each stats request by ID.
+ * @param nb_ids
+ *   Number of stats requested.
+ * @return
+ *   - Positive value: number of stat entries filled into the values array
+ *   - Negative value on error:
+ *        -ENODEV for invalid *dev_id*.
+ *        -EINVAL for invalid mode, model id or stat id parameters.
+ *        -ENOTSUP if the device doesn't support this function.
+ */
+__rte_experimental
+int
+rte_ml_dev_xstats_get(int16_t dev_id, enum rte_ml_dev_xstats_mode mode, int32_t model_id,
+		      const uint16_t stat_ids[], uint64_t values[], uint16_t nb_ids);
+
+/**
+ * Reset the values of the xstats of the selected component in the device.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param mode
+ *   Mode of the statistics to reset. Choose from device or model.
+ * @param model_id
+ *   Model stats to reset. 0 and positive values select models, while -1 indicates all models.
+ * @param stat_ids
+ *   Selects specific statistics to be reset. When NULL, all statistics selected by *mode* will be
+ * reset. If non-NULL, must point to array of at least *nb_ids* size.
+ * @param nb_ids
+ *   The number of ids available from the *ids* array. Ignored when ids is NULL.
+ * @return
+ *   - Zero: successfully reset the statistics.
+ *   - Negative value: -EINVAL invalid parameters, -ENOTSUP if not supported.
+ */
+__rte_experimental
+int
+rte_ml_dev_xstats_reset(int16_t dev_id, enum rte_ml_dev_xstats_mode mode, int32_t model_id,
+			const uint16_t stat_ids[], uint16_t nb_ids);
+
 /**
  * Dump internal information about *dev_id* to the FILE* provided in *fd*.
  *
-- 
2.17.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v1 3/5] mldev: implement xstats library functions
  2023-04-23  5:13 [PATCH v1 0/5] Implementation of revised ML xstats spec Srikanth Yalavarthi
  2023-04-23  5:13 ` [PATCH v1 1/5] mldev: remove xstats APIs from library Srikanth Yalavarthi
  2023-04-23  5:14 ` [PATCH v1 2/5] mldev: introduce revised xstats Srikanth Yalavarthi
@ 2023-04-23  5:14 ` Srikanth Yalavarthi
  2023-04-23  5:14 ` [PATCH v1 4/5] app/mldev: enable reporting xstats Srikanth Yalavarthi
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Srikanth Yalavarthi @ 2023-04-23  5:14 UTC (permalink / raw)
  To: Srikanth Yalavarthi; +Cc: dev, sshankarnara, aprabhu, ptakkar

Implemented xstats library functions as per revised spec.

Signed-off-by: Srikanth Yalavarthi <syalavarthi@marvell.com>
---
 lib/mldev/rte_mldev.c      |  91 +++++++++++++++++++++++++++++++
 lib/mldev/rte_mldev_core.h | 107 +++++++++++++++++++++++++++++++++++++
 lib/mldev/version.map      |   4 ++
 3 files changed, 202 insertions(+)

diff --git a/lib/mldev/rte_mldev.c b/lib/mldev/rte_mldev.c
index 72d4d7a165..0d8ccd3212 100644
--- a/lib/mldev/rte_mldev.c
+++ b/lib/mldev/rte_mldev.c
@@ -438,6 +438,97 @@ rte_ml_dev_stats_reset(int16_t dev_id)
 	(*dev->dev_ops->dev_stats_reset)(dev);
 }
 
+int
+rte_ml_dev_xstats_names_get(int16_t dev_id, enum rte_ml_dev_xstats_mode mode, int32_t model_id,
+			    struct rte_ml_dev_xstats_map *xstats_map, uint32_t size)
+{
+	struct rte_ml_dev *dev;
+
+	if (!rte_ml_dev_is_valid_dev(dev_id)) {
+		RTE_MLDEV_LOG(ERR, "Invalid dev_id = %d\n", dev_id);
+		return -EINVAL;
+	}
+
+	dev = rte_ml_dev_pmd_get_dev(dev_id);
+	if (*dev->dev_ops->dev_xstats_names_get == NULL)
+		return -ENOTSUP;
+
+	return (*dev->dev_ops->dev_xstats_names_get)(dev, mode, model_id, xstats_map, size);
+}
+
+int
+rte_ml_dev_xstats_by_name_get(int16_t dev_id, const char *name, uint16_t *stat_id, uint64_t *value)
+{
+	struct rte_ml_dev *dev;
+
+	if (!rte_ml_dev_is_valid_dev(dev_id)) {
+		RTE_MLDEV_LOG(ERR, "Invalid dev_id = %d\n", dev_id);
+		return -EINVAL;
+	}
+
+	dev = rte_ml_dev_pmd_get_dev(dev_id);
+	if (*dev->dev_ops->dev_xstats_by_name_get == NULL)
+		return -ENOTSUP;
+
+	if (name == NULL) {
+		RTE_MLDEV_LOG(ERR, "Dev %d, name cannot be NULL\n", dev_id);
+		return -EINVAL;
+	}
+
+	if (value == NULL) {
+		RTE_MLDEV_LOG(ERR, "Dev %d, value cannot be NULL\n", dev_id);
+		return -EINVAL;
+	}
+
+	return (*dev->dev_ops->dev_xstats_by_name_get)(dev, name, stat_id, value);
+}
+
+int
+rte_ml_dev_xstats_get(int16_t dev_id, enum rte_ml_dev_xstats_mode mode, int32_t model_id,
+		      const uint16_t stat_ids[], uint64_t values[], uint16_t nb_ids)
+{
+	struct rte_ml_dev *dev;
+
+	if (!rte_ml_dev_is_valid_dev(dev_id)) {
+		RTE_MLDEV_LOG(ERR, "Invalid dev_id = %d\n", dev_id);
+		return -EINVAL;
+	}
+
+	dev = rte_ml_dev_pmd_get_dev(dev_id);
+	if (*dev->dev_ops->dev_xstats_get == NULL)
+		return -ENOTSUP;
+
+	if (stat_ids == NULL) {
+		RTE_MLDEV_LOG(ERR, "Dev %d, stat_ids cannot be NULL\n", dev_id);
+		return -EINVAL;
+	}
+
+	if (values == NULL) {
+		RTE_MLDEV_LOG(ERR, "Dev %d, values cannot be NULL\n", dev_id);
+		return -EINVAL;
+	}
+
+	return (*dev->dev_ops->dev_xstats_get)(dev, mode, model_id, stat_ids, values, nb_ids);
+}
+
+int
+rte_ml_dev_xstats_reset(int16_t dev_id, enum rte_ml_dev_xstats_mode mode, int32_t model_id,
+			const uint16_t stat_ids[], uint16_t nb_ids)
+{
+	struct rte_ml_dev *dev;
+
+	if (!rte_ml_dev_is_valid_dev(dev_id)) {
+		RTE_MLDEV_LOG(ERR, "Invalid dev_id = %d\n", dev_id);
+		return -EINVAL;
+	}
+
+	dev = rte_ml_dev_pmd_get_dev(dev_id);
+	if (*dev->dev_ops->dev_xstats_reset == NULL)
+		return -ENOTSUP;
+
+	return (*dev->dev_ops->dev_xstats_reset)(dev, mode, model_id, stat_ids, nb_ids);
+}
+
 int
 rte_ml_dev_dump(int16_t dev_id, FILE *fd)
 {
diff --git a/lib/mldev/rte_mldev_core.h b/lib/mldev/rte_mldev_core.h
index 926a652397..78b8b7633d 100644
--- a/lib/mldev/rte_mldev_core.h
+++ b/lib/mldev/rte_mldev_core.h
@@ -236,6 +236,101 @@ typedef int (*mldev_stats_get_t)(struct rte_ml_dev *dev, struct rte_ml_dev_stats
  */
 typedef void (*mldev_stats_reset_t)(struct rte_ml_dev *dev);
 
+/**
+ * @internal
+ *
+ * Function used to get names of extended stats.
+ *
+ * @param dev
+ *	ML device pointer.
+ * @param mode
+ *	Mode of stats to retrieve.
+ * @param model_id
+ *	Used to specify model id in model mode. Ignored in device mode.
+ * @param xstats_map
+ *	Array to insert id and names into.
+ * @param size
+ *	Size of xstats_map array.
+ *
+ * @return
+ *	- >= 0 and <= size on success.
+ *	- > size, error. Returns the size of xstats_map array required.
+ *	- < 0, error code on failure.
+ */
+typedef int (*mldev_xstats_names_get_t)(struct rte_ml_dev *dev, enum rte_ml_dev_xstats_mode mode,
+					int32_t model_id, struct rte_ml_dev_xstats_map *xstats_map,
+					uint32_t size);
+
+/**
+ * @internal
+ *
+ * Function used to get a single extended stat by name.
+ *
+ * @param dev
+ *	ML device pointer.
+ * @param name
+ *	Name of the stat to retrieve.
+ * @param stat_id
+ *	ID of the stat to be returned.
+ * @param value
+ *	Value of the stat to be returned.
+ *
+ * @return
+ *	- = 0 success.
+ *	- < 0, error code on failure.
+ */
+typedef int (*mldev_xstats_by_name_get_t)(struct rte_ml_dev *dev, const char *name,
+					  uint16_t *stat_id, uint64_t *value);
+
+/**
+ * @internal
+ *
+ * Function used to retrieve extended stats of a device.
+ *
+ * @param dev
+ *	ML device pointer.
+ * @param mode
+ *	Mode of stats to retrieve.
+ * @param model_id
+ *	Used to specify model id in model mode. Ignored in device mode.
+ * @param stat_ids
+ *	Array of ID numbers of the stats to be retrieved.
+ * @param values
+ *	Values of the stats requested by the ID.
+ * @param nb_ids
+ *	Number of stats requested.
+ *
+ * @return
+ *	- >= 0, number of entries filled into the values array.
+ *	- < 0, error code on failure.
+ */
+typedef int (*mldev_xstats_get_t)(struct rte_ml_dev *dev, enum rte_ml_dev_xstats_mode mode,
+				  int32_t model_id, const uint16_t stat_ids[], uint64_t values[],
+				  uint16_t nb_ids);
+
+/**
+ * @internal
+ *
+ * Function used to reset extended stats.
+ *
+ * @param dev
+ *	ML device pointer.
+ * @param mode
+ *	Mode of stats to retrieve.
+ * @param model_id
+ *	Used to specify model id in model mode. Ignored in device mode.
+ * @param stat_ids
+ *	Array of stats IDs to be reset.
+ * @param nb_ids
+ *	Number of IDs in the stat_ids array.
+ *
+ * @return
+ *	- 0 on success.
+ *	- < 0, error code on failure.
+ */
+typedef int (*mldev_xstats_reset_t)(struct rte_ml_dev *dev, enum rte_ml_dev_xstats_mode mode,
+				    int32_t model_id, const uint16_t stat_ids[], uint16_t nb_ids);
+
 /**
  * @internal
  *
@@ -498,6 +593,18 @@ struct rte_ml_dev_ops {
 	/** Reset device statistics. */
 	mldev_stats_reset_t dev_stats_reset;
 
+	/** Get names of extended stats. */
+	mldev_xstats_names_get_t dev_xstats_names_get;
+
+	/** Get value of a single extended stat. */
+	mldev_xstats_by_name_get_t dev_xstats_by_name_get;
+
+	/** Get extended stats of a device. */
+	mldev_xstats_get_t dev_xstats_get;
+
+	/** Reset extended stats of the device. */
+	mldev_xstats_reset_t dev_xstats_reset;
+
 	/** Dump ML device debug info. */
 	mldev_dump_t dev_dump;
 
diff --git a/lib/mldev/version.map b/lib/mldev/version.map
index c774a87a5e..0706b565be 100644
--- a/lib/mldev/version.map
+++ b/lib/mldev/version.map
@@ -17,6 +17,10 @@ EXPERIMENTAL {
 	rte_ml_dev_stats_get;
 	rte_ml_dev_stats_reset;
 	rte_ml_dev_stop;
+	rte_ml_dev_xstats_by_name_get;
+	rte_ml_dev_xstats_get;
+	rte_ml_dev_xstats_names_get;
+	rte_ml_dev_xstats_reset;
 	rte_ml_enqueue_burst;
 	rte_ml_io_dequantize;
 	rte_ml_io_input_size_get;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v1 4/5] app/mldev: enable reporting xstats
  2023-04-23  5:13 [PATCH v1 0/5] Implementation of revised ML xstats spec Srikanth Yalavarthi
                   ` (2 preceding siblings ...)
  2023-04-23  5:14 ` [PATCH v1 3/5] mldev: implement xstats library functions Srikanth Yalavarthi
@ 2023-04-23  5:14 ` Srikanth Yalavarthi
  2023-04-23  5:14 ` [PATCH v1 5/5] ml/cnxk: implement xstats driver functions Srikanth Yalavarthi
  2023-06-06 13:40 ` [PATCH v1 0/5] Implementation of revised ML xstats spec Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Srikanth Yalavarthi @ 2023-04-23  5:14 UTC (permalink / raw)
  To: Srikanth Yalavarthi; +Cc: dev, sshankarnara, aprabhu, ptakkar

Enabled reporting xstats in ML test application. Enabled
stats option for model_ops test case. Added common files
for xstats and throughput functions.

Signed-off-by: Srikanth Yalavarthi <syalavarthi@marvell.com>
---
 app/test-mldev/meson.build                 |   1 +
 app/test-mldev/ml_common.h                 |  11 ++
 app/test-mldev/ml_options.c                |   5 +-
 app/test-mldev/test_common.h               |   3 +
 app/test-mldev/test_inference_common.c     |  60 ----------
 app/test-mldev/test_inference_common.h     |   1 -
 app/test-mldev/test_inference_interleave.c |   6 +-
 app/test-mldev/test_inference_ordered.c    |   5 +-
 app/test-mldev/test_model_ops.c            |   3 +
 app/test-mldev/test_stats.c                | 129 +++++++++++++++++++++
 app/test-mldev/test_stats.h                |  13 +++
 11 files changed, 172 insertions(+), 65 deletions(-)
 create mode 100644 app/test-mldev/test_stats.c
 create mode 100644 app/test-mldev/test_stats.h

diff --git a/app/test-mldev/meson.build b/app/test-mldev/meson.build
index 15db534dc2..18e28f2713 100644
--- a/app/test-mldev/meson.build
+++ b/app/test-mldev/meson.build
@@ -19,6 +19,7 @@ sources = files(
         'test_inference_common.c',
         'test_inference_ordered.c',
         'test_inference_interleave.c',
+        'test_stats.c'
 )
 
 deps += ['mldev', 'hash']
diff --git a/app/test-mldev/ml_common.h b/app/test-mldev/ml_common.h
index 624a5aff50..8d7cc9eeb7 100644
--- a/app/test-mldev/ml_common.h
+++ b/app/test-mldev/ml_common.h
@@ -26,4 +26,15 @@
 
 #define ml_dump_end printf("\b\t}\n\n")
 
+static inline void
+ml_print_line(uint16_t len)
+{
+	uint16_t i;
+
+	for (i = 0; i < len; i++)
+		printf("-");
+
+	printf("\n");
+}
+
 #endif /* ML_COMMON_H */
diff --git a/app/test-mldev/ml_options.c b/app/test-mldev/ml_options.c
index 2efcc3532c..1daa229748 100644
--- a/app/test-mldev/ml_options.c
+++ b/app/test-mldev/ml_options.c
@@ -205,7 +205,8 @@ ml_dump_test_options(const char *testname)
 	}
 
 	if (strcmp(testname, "model_ops") == 0) {
-		printf("\t\t--models           : comma separated list of models\n");
+		printf("\t\t--models           : comma separated list of models\n"
+		       "\t\t--stats            : enable reporting device statistics\n");
 		printf("\n");
 	}
 
@@ -218,7 +219,7 @@ ml_dump_test_options(const char *testname)
 		       "\t\t--queue_size       : size fo queue-pair\n"
 		       "\t\t--batches          : number of batches of input\n"
 		       "\t\t--tolerance        : maximum tolerance (%%) for output validation\n"
-		       "\t\t--stats            : enable reporting performance statistics\n");
+		       "\t\t--stats            : enable reporting device and model statistics\n");
 		printf("\n");
 	}
 }
diff --git a/app/test-mldev/test_common.h b/app/test-mldev/test_common.h
index a7b2ea652a..def108d5b2 100644
--- a/app/test-mldev/test_common.h
+++ b/app/test-mldev/test_common.h
@@ -14,6 +14,9 @@ struct test_common {
 	struct ml_options *opt;
 	enum ml_test_result result;
 	struct rte_ml_dev_info dev_info;
+	struct rte_ml_dev_xstats_map *xstats_map;
+	uint64_t *xstats_values;
+	int xstats_size;
 };
 
 bool ml_test_cap_check(struct ml_options *opt);
diff --git a/app/test-mldev/test_inference_common.c b/app/test-mldev/test_inference_common.c
index 1e16608582..469ed35f6c 100644
--- a/app/test-mldev/test_inference_common.c
+++ b/app/test-mldev/test_inference_common.c
@@ -39,17 +39,6 @@
 		}                                                                                  \
 	} while (0)
 
-static void
-print_line(uint16_t len)
-{
-	uint16_t i;
-
-	for (i = 0; i < len; i++)
-		printf("-");
-
-	printf("\n");
-}
-
 /* Enqueue inference requests with burst size equal to 1 */
 static int
 ml_enqueue_single(void *arg)
@@ -1027,52 +1016,3 @@ ml_inference_launch_cores(struct ml_test *test, struct ml_options *opt, uint16_t
 
 	return 0;
 }
-
-int
-ml_inference_throughput_get(struct ml_test *test, struct ml_options *opt)
-{
-	struct test_inference *t = ml_test_priv(test);
-	uint64_t total_cycles = 0;
-	uint32_t nb_filelist;
-	uint64_t throughput;
-	uint64_t avg_e2e;
-	uint32_t qp_id;
-	uint64_t freq;
-
-	if (!opt->stats)
-		return 0;
-
-	/* print end-to-end stats */
-	freq = rte_get_tsc_hz();
-	for (qp_id = 0; qp_id < RTE_MAX_LCORE; qp_id++)
-		total_cycles += t->args[qp_id].end_cycles - t->args[qp_id].start_cycles;
-	avg_e2e = total_cycles / opt->repetitions;
-
-	if (freq == 0) {
-		avg_e2e = total_cycles / opt->repetitions;
-		printf(" %-64s = %" PRIu64 "\n", "Average End-to-End Latency (cycles)", avg_e2e);
-	} else {
-		avg_e2e = (total_cycles * NS_PER_S) / (opt->repetitions * freq);
-		printf(" %-64s = %" PRIu64 "\n", "Average End-to-End Latency (ns)", avg_e2e);
-	}
-
-	/* print inference throughput */
-	if (strcmp(opt->test_name, "inference_ordered") == 0)
-		nb_filelist = 1;
-	else
-		nb_filelist = opt->nb_filelist;
-
-	if (freq == 0) {
-		throughput = (nb_filelist * t->cmn.opt->repetitions * 1000000) / total_cycles;
-		printf(" %-64s = %" PRIu64 "\n", "Average Throughput (inferences / million cycles)",
-		       throughput);
-	} else {
-		throughput = (nb_filelist * t->cmn.opt->repetitions * freq) / total_cycles;
-		printf(" %-64s = %" PRIu64 "\n", "Average Throughput (inferences / second)",
-		       throughput);
-	}
-
-	print_line(80);
-
-	return 0;
-}
diff --git a/app/test-mldev/test_inference_common.h b/app/test-mldev/test_inference_common.h
index 0a9b930788..8f27af25e4 100644
--- a/app/test-mldev/test_inference_common.h
+++ b/app/test-mldev/test_inference_common.h
@@ -70,6 +70,5 @@ void ml_inference_mem_destroy(struct ml_test *test, struct ml_options *opt);
 int ml_inference_result(struct ml_test *test, struct ml_options *opt, uint16_t fid);
 int ml_inference_launch_cores(struct ml_test *test, struct ml_options *opt, uint16_t start_fid,
 			      uint16_t end_fid);
-int ml_inference_throughput_get(struct ml_test *test, struct ml_options *opt);
 
 #endif /* TEST_INFERENCE_COMMON_H */
diff --git a/app/test-mldev/test_inference_interleave.c b/app/test-mldev/test_inference_interleave.c
index 23b8efe4f0..9503dda042 100644
--- a/app/test-mldev/test_inference_interleave.c
+++ b/app/test-mldev/test_inference_interleave.c
@@ -7,6 +7,7 @@
 
 #include "ml_common.h"
 #include "test_inference_common.h"
+#include "test_stats.h"
 
 static int
 test_inference_interleave_driver(struct ml_test *test, struct ml_options *opt)
@@ -58,7 +59,8 @@ test_inference_interleave_driver(struct ml_test *test, struct ml_options *opt)
 		ml_inference_iomem_destroy(test, opt, fid);
 	}
 
-	ml_inference_throughput_get(test, opt);
+	for (fid = 0; fid < opt->nb_filelist; fid++)
+		ml_stats_get(test, opt, RTE_ML_DEV_XSTATS_MODEL, fid);
 
 	for (fid = 0; fid < opt->nb_filelist; fid++) {
 		ret = ml_model_stop(test, opt, &t->model[fid], fid);
@@ -70,6 +72,8 @@ test_inference_interleave_driver(struct ml_test *test, struct ml_options *opt)
 			goto error;
 	}
 
+	ml_stats_get(test, opt, RTE_ML_DEV_XSTATS_DEVICE, -1);
+	ml_throughput_get(test, opt);
 	ml_inference_mem_destroy(test, opt);
 
 	ret = ml_inference_mldev_destroy(test, opt);
diff --git a/app/test-mldev/test_inference_ordered.c b/app/test-mldev/test_inference_ordered.c
index f49810c152..e0e826d972 100644
--- a/app/test-mldev/test_inference_ordered.c
+++ b/app/test-mldev/test_inference_ordered.c
@@ -7,6 +7,7 @@
 
 #include "ml_common.h"
 #include "test_inference_common.h"
+#include "test_stats.h"
 
 static int
 test_inference_ordered_driver(struct ml_test *test, struct ml_options *opt)
@@ -54,7 +55,8 @@ test_inference_ordered_driver(struct ml_test *test, struct ml_options *opt)
 		goto error;
 
 	ml_inference_iomem_destroy(test, opt, fid);
-	ml_inference_throughput_get(test, opt);
+	ml_stats_get(test, opt, RTE_ML_DEV_XSTATS_MODEL, fid);
+	ml_throughput_get(test, opt);
 
 	/* stop model */
 	ret = ml_model_stop(test, opt, &t->model[fid], fid);
@@ -70,6 +72,7 @@ test_inference_ordered_driver(struct ml_test *test, struct ml_options *opt)
 	if (fid < opt->nb_filelist)
 		goto next_model;
 
+	ml_stats_get(test, opt, RTE_ML_DEV_XSTATS_DEVICE, -1);
 	ml_inference_mem_destroy(test, opt);
 
 	ret = ml_inference_mldev_destroy(test, opt);
diff --git a/app/test-mldev/test_model_ops.c b/app/test-mldev/test_model_ops.c
index 5bbbcb1a6c..b15587a3c5 100644
--- a/app/test-mldev/test_model_ops.c
+++ b/app/test-mldev/test_model_ops.c
@@ -9,6 +9,7 @@
 #include <rte_mldev.h>
 
 #include "test_model_ops.h"
+#include "test_stats.h"
 
 static bool
 test_model_ops_cap_check(struct ml_options *opt)
@@ -384,6 +385,8 @@ test_model_ops_driver(struct ml_test *test, struct ml_options *opt)
 
 	printf("\n");
 
+	ml_stats_get(test, opt, RTE_ML_DEV_XSTATS_DEVICE, -1);
+
 	/* device destroy */
 	ret = test_model_ops_mldev_destroy(test, opt);
 	if (ret != 0)
diff --git a/app/test-mldev/test_stats.c b/app/test-mldev/test_stats.c
new file mode 100644
index 0000000000..ffe24a9b91
--- /dev/null
+++ b/app/test-mldev/test_stats.c
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Marvell.
+ */
+
+#include "test_stats.h"
+#include "test_inference_common.h"
+#include "test_model_ops.h"
+
+int
+ml_stats_get(struct ml_test *test, struct ml_options *opt, enum rte_ml_dev_xstats_mode mode,
+	     int32_t fid)
+{
+	struct test_common *t = ml_test_priv(test);
+	int32_t model_id;
+	int ret;
+	int i;
+
+	if (!opt->stats)
+		return 0;
+
+	if (mode == RTE_ML_DEV_XSTATS_MODEL)
+		model_id = ((struct test_inference *)t)->model[fid].id;
+	else
+		model_id = -1;
+
+	/* get xstats size */
+	t->xstats_size = rte_ml_dev_xstats_names_get(opt->dev_id, mode, model_id, NULL, 0);
+	if (t->xstats_size > 0) {
+		/* allocate for xstats_map and values */
+		t->xstats_map = rte_malloc(
+			"ml_xstats_map", t->xstats_size * sizeof(struct rte_ml_dev_xstats_map), 0);
+		if (t->xstats_map == NULL) {
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		t->xstats_values =
+			rte_malloc("ml_xstats_values", t->xstats_size * sizeof(uint64_t), 0);
+		if (t->xstats_values == NULL) {
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		ret = rte_ml_dev_xstats_names_get(opt->dev_id, mode, model_id, t->xstats_map,
+						  t->xstats_size);
+		if (ret != t->xstats_size) {
+			printf("Unable to get xstats names, ret = %d\n", ret);
+			ret = -1;
+			goto error;
+		}
+
+		for (i = 0; i < t->xstats_size; i++)
+			rte_ml_dev_xstats_get(opt->dev_id, mode, model_id, &t->xstats_map[i].id,
+					      &t->xstats_values[i], 1);
+	}
+
+	/* print xstats*/
+	printf("\n");
+	ml_print_line(80);
+	if (mode == RTE_ML_DEV_XSTATS_MODEL)
+		printf(" Model Statistics: %s\n",
+		       ((struct test_inference *)t)->model[fid].info.name);
+	else
+		printf(" Device Statistics\n");
+	ml_print_line(80);
+	for (i = 0; i < t->xstats_size; i++)
+		printf(" %-64s = %" PRIu64 "\n", t->xstats_map[i].name, t->xstats_values[i]);
+	ml_print_line(80);
+
+	rte_free(t->xstats_map);
+	rte_free(t->xstats_values);
+
+	return 0;
+
+error:
+	rte_free(t->xstats_map);
+	rte_free(t->xstats_values);
+
+	return ret;
+}
+
+int
+ml_throughput_get(struct ml_test *test, struct ml_options *opt)
+{
+	struct test_inference *t = ml_test_priv(test);
+	uint64_t total_cycles = 0;
+	uint32_t nb_filelist;
+	uint64_t throughput;
+	uint64_t avg_e2e;
+	uint32_t qp_id;
+	uint64_t freq;
+
+	if (!opt->stats)
+		return 0;
+
+	/* print inference throughput */
+	if (strcmp(opt->test_name, "inference_ordered") == 0)
+		nb_filelist = 1;
+	else
+		nb_filelist = opt->nb_filelist;
+
+	/* Print model end-to-end latency and throughput */
+	freq = rte_get_tsc_hz();
+	for (qp_id = 0; qp_id < RTE_MAX_LCORE; qp_id++)
+		total_cycles += t->args[qp_id].end_cycles - t->args[qp_id].start_cycles;
+
+	avg_e2e = total_cycles / (opt->repetitions * nb_filelist);
+	if (freq == 0) {
+		printf(" %-64s = %" PRIu64 "\n", "Average End-to-End Latency (cycles)", avg_e2e);
+	} else {
+		avg_e2e = (avg_e2e * NS_PER_S) / freq;
+		printf(" %-64s = %" PRIu64 "\n", "Average End-to-End Latency (ns)", avg_e2e);
+	}
+
+	/* Print model throughput */
+	if (freq == 0) {
+		throughput = 1000000 / avg_e2e;
+		printf(" %-64s = %" PRIu64 "\n", "Average Throughput (inferences / million cycles)",
+		       throughput);
+	} else {
+		throughput = freq / avg_e2e;
+		printf(" %-64s = %" PRIu64 "\n", "Average Throughput (inferences / second)",
+		       throughput);
+	}
+
+	ml_print_line(80);
+
+	return 0;
+}
diff --git a/app/test-mldev/test_stats.h b/app/test-mldev/test_stats.h
new file mode 100644
index 0000000000..89648490fa
--- /dev/null
+++ b/app/test-mldev/test_stats.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Marvell.
+ */
+
+#include <rte_malloc.h>
+#include <rte_mldev.h>
+
+#include "ml_test.h"
+#include "test_inference_common.h"
+
+int ml_stats_get(struct ml_test *test, struct ml_options *opt, enum rte_ml_dev_xstats_mode,
+		 int32_t fid);
+int ml_throughput_get(struct ml_test *test, struct ml_options *opt);
-- 
2.17.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v1 5/5] ml/cnxk: implement xstats driver functions
  2023-04-23  5:13 [PATCH v1 0/5] Implementation of revised ML xstats spec Srikanth Yalavarthi
                   ` (3 preceding siblings ...)
  2023-04-23  5:14 ` [PATCH v1 4/5] app/mldev: enable reporting xstats Srikanth Yalavarthi
@ 2023-04-23  5:14 ` Srikanth Yalavarthi
  2023-06-06 13:40 ` [PATCH v1 0/5] Implementation of revised ML xstats spec Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Srikanth Yalavarthi @ 2023-04-23  5:14 UTC (permalink / raw)
  To: Srikanth Yalavarthi; +Cc: dev, sshankarnara, aprabhu, ptakkar

Added support for revised xstats APIs in cnxk ML driver.

Signed-off-by: Srikanth Yalavarthi <syalavarthi@marvell.com>
---
 doc/guides/mldevs/cnxk.rst       |  30 +-
 drivers/ml/cnxk/cn10k_ml_dev.h   |  96 +++++-
 drivers/ml/cnxk/cn10k_ml_model.h |  21 --
 drivers/ml/cnxk/cn10k_ml_ops.c   | 530 ++++++++++++++++++++++---------
 4 files changed, 502 insertions(+), 175 deletions(-)

diff --git a/doc/guides/mldevs/cnxk.rst b/doc/guides/mldevs/cnxk.rst
index 91e5df095a..2a339451fd 100644
--- a/doc/guides/mldevs/cnxk.rst
+++ b/doc/guides/mldevs/cnxk.rst
@@ -213,14 +213,32 @@ Debugging Options
 Extended stats
 --------------
 
-Marvell cnxk ML PMD supports reporting the inference latencies
-through extended statistics.
-The PMD supports the below list of 6 extended stats types per each model.
-Total number of extended stats would be equal to 6 x number of models loaded.
+Marvell cnxk ML PMD supports reporting the device and model extended statistics.
 
-.. _table_octeon_cnxk_ml_xstats_names:
+PMD supports the below list of 4 device extended stats.
 
-.. table:: OCTEON cnxk ML PMD xstats names
+.. _table_octeon_cnxk_ml_device_xstats_names:
+
+.. table:: OCTEON cnxk ML PMD device xstats names
+
+   +---+---------------------+----------------------------------------------+
+   | # | Type                | Description                                  |
+   +===+=====================+==============================================+
+   | 1 | nb_models_loaded    | Number of models loaded                      |
+   +---+---------------------+----------------------------------------------+
+   | 2 | nb_models_unloaded  | Number of models unloaded                    |
+   +---+---------------------+----------------------------------------------+
+   | 3 | nb_models_started   | Number of models started                     |
+   +---+---------------------+----------------------------------------------+
+   | 4 | nb_models_stopped   | Number of models stopped                     |
+   +---+---------------------+----------------------------------------------+
+
+
+PMD supports the below list of 6 extended stats types per each model.
+
+.. _table_octeon_cnxk_ml_model_xstats_names:
+
+.. table:: OCTEON cnxk ML PMD model xstats names
 
    +---+---------------------+----------------------------------------------+
    | # | Type                | Description                                  |
diff --git a/drivers/ml/cnxk/cn10k_ml_dev.h b/drivers/ml/cnxk/cn10k_ml_dev.h
index b4e46899c0..5a8c8206b2 100644
--- a/drivers/ml/cnxk/cn10k_ml_dev.h
+++ b/drivers/ml/cnxk/cn10k_ml_dev.h
@@ -380,6 +380,89 @@ struct cn10k_ml_fw {
 	struct cn10k_ml_req *req;
 };
 
+/* Extended stats types enum */
+enum cn10k_ml_xstats_type {
+	/* Number of models loaded */
+	nb_models_loaded,
+
+	/* Number of models unloaded */
+	nb_models_unloaded,
+
+	/* Number of models started */
+	nb_models_started,
+
+	/* Number of models stopped */
+	nb_models_stopped,
+
+	/* Average inference hardware latency */
+	avg_hw_latency,
+
+	/* Minimum hardware latency */
+	min_hw_latency,
+
+	/* Maximum hardware latency */
+	max_hw_latency,
+
+	/* Average firmware latency */
+	avg_fw_latency,
+
+	/* Minimum firmware latency */
+	min_fw_latency,
+
+	/* Maximum firmware latency */
+	max_fw_latency,
+};
+
+/* Extended stats function type enum. */
+enum cn10k_ml_xstats_fn_type {
+	/* Device function */
+	CN10K_ML_XSTATS_FN_DEVICE,
+
+	/* Model function */
+	CN10K_ML_XSTATS_FN_MODEL,
+};
+
+/* Function pointer to get xstats for a type */
+typedef uint64_t (*cn10k_ml_xstats_fn)(struct rte_ml_dev *dev, uint16_t obj_idx,
+				       enum cn10k_ml_xstats_type stat);
+
+/* Extended stats entry structure */
+struct cn10k_ml_xstats_entry {
+	/* Name-ID map */
+	struct rte_ml_dev_xstats_map map;
+
+	/* xstats mode, device or model */
+	enum rte_ml_dev_xstats_mode mode;
+
+	/* Type of xstats */
+	enum cn10k_ml_xstats_type type;
+
+	/* xstats function */
+	enum cn10k_ml_xstats_fn_type fn_id;
+
+	/* Object ID, model ID for model stat type */
+	uint16_t obj_idx;
+
+	/* Allowed to reset the stat */
+	uint8_t reset_allowed;
+
+	/* An offset to be taken away to emulate resets */
+	uint64_t reset_value;
+};
+
+/* Extended stats data */
+struct cn10k_ml_xstats {
+	/* Pointer to xstats entries */
+	struct cn10k_ml_xstats_entry *entries;
+
+	/* Store num stats and offset of the stats for each model */
+	uint16_t count_per_model[ML_CN10K_MAX_MODELS];
+	uint16_t offset_for_model[ML_CN10K_MAX_MODELS];
+	uint16_t count_mode_device;
+	uint16_t count_mode_model;
+	uint16_t count;
+};
+
 /* Device private data */
 struct cn10k_ml_dev {
 	/* Device ROC */
@@ -397,8 +480,17 @@ struct cn10k_ml_dev {
 	/* Number of models loaded */
 	uint16_t nb_models_loaded;
 
-	/* xstats status */
-	bool xstats_enabled;
+	/* Number of models unloaded */
+	uint16_t nb_models_unloaded;
+
+	/* Number of models started */
+	uint16_t nb_models_started;
+
+	/* Number of models stopped */
+	uint16_t nb_models_stopped;
+
+	/* Extended stats data */
+	struct cn10k_ml_xstats xstats;
 
 	/* Enable / disable model data caching */
 	int cache_model_data;
diff --git a/drivers/ml/cnxk/cn10k_ml_model.h b/drivers/ml/cnxk/cn10k_ml_model.h
index 1bc748265d..d04c168a53 100644
--- a/drivers/ml/cnxk/cn10k_ml_model.h
+++ b/drivers/ml/cnxk/cn10k_ml_model.h
@@ -399,27 +399,6 @@ struct cn10k_ml_model_addr {
 	uint32_t total_output_sz_d;
 };
 
-/* Extended stats types enum */
-enum cn10k_ml_model_xstats_type {
-	/* Average hardware latency */
-	avg_hw_latency = 0,
-
-	/* Minimum hardware latency */
-	min_hw_latency,
-
-	/* Maximum hardware latency */
-	max_hw_latency,
-
-	/* Average firmware latency */
-	avg_fw_latency,
-
-	/* Minimum firmware latency */
-	min_fw_latency,
-
-	/* Maximum firmware latency */
-	max_fw_latency,
-};
-
 /* Model fast-path stats */
 struct cn10k_ml_model_stats {
 	/* Total hardware latency, sum of all inferences */
diff --git a/drivers/ml/cnxk/cn10k_ml_ops.c b/drivers/ml/cnxk/cn10k_ml_ops.c
index 521bad4eea..456922c56f 100644
--- a/drivers/ml/cnxk/cn10k_ml_ops.c
+++ b/drivers/ml/cnxk/cn10k_ml_ops.c
@@ -436,6 +436,160 @@ cn10k_ml_prep_fp_job_descriptor(struct rte_ml_dev *dev, struct cn10k_ml_req *req
 	req->jd.model_run.num_batches = op->nb_batches;
 }
 
+struct xstat_info {
+	char name[32];
+	enum cn10k_ml_xstats_type type;
+	uint8_t reset_allowed;
+};
+
+/* Note: Device stats are not allowed to be reset. */
+static const struct xstat_info device_stats[] = {
+	{"nb_models_loaded", nb_models_loaded, 0},
+	{"nb_models_unloaded", nb_models_unloaded, 0},
+	{"nb_models_started", nb_models_started, 0},
+	{"nb_models_stopped", nb_models_stopped, 0},
+};
+
+static const struct xstat_info model_stats[] = {
+	{"Avg-HW-Latency", avg_hw_latency, 1}, {"Min-HW-Latency", min_hw_latency, 1},
+	{"Max-HW-Latency", max_hw_latency, 1}, {"Avg-FW-Latency", avg_fw_latency, 1},
+	{"Min-FW-Latency", min_fw_latency, 1}, {"Max-FW-Latency", max_fw_latency, 1},
+};
+
+static int
+cn10k_ml_xstats_init(struct rte_ml_dev *dev)
+{
+	struct cn10k_ml_dev *mldev;
+	uint16_t nb_stats;
+	uint16_t stat_id;
+	uint16_t model;
+	uint16_t i;
+
+	mldev = dev->data->dev_private;
+
+	/* Allocate memory for xstats entries. Don't allocate during reconfigure */
+	nb_stats = RTE_DIM(device_stats) + ML_CN10K_MAX_MODELS * RTE_DIM(model_stats);
+	if (mldev->xstats.entries == NULL)
+		mldev->xstats.entries = rte_zmalloc("cn10k_ml_xstats",
+						    sizeof(struct cn10k_ml_xstats_entry) * nb_stats,
+						    PLT_CACHE_LINE_SIZE);
+
+	if (mldev->xstats.entries == NULL)
+		return -ENOMEM;
+
+	/* Initialize device xstats */
+	stat_id = 0;
+	for (i = 0; i < RTE_DIM(device_stats); i++) {
+		mldev->xstats.entries[stat_id].map.id = stat_id;
+		snprintf(mldev->xstats.entries[stat_id].map.name,
+			 sizeof(mldev->xstats.entries[stat_id].map.name), "%s",
+			 device_stats[i].name);
+
+		mldev->xstats.entries[stat_id].mode = RTE_ML_DEV_XSTATS_DEVICE;
+		mldev->xstats.entries[stat_id].type = device_stats[i].type;
+		mldev->xstats.entries[stat_id].fn_id = CN10K_ML_XSTATS_FN_DEVICE;
+		mldev->xstats.entries[stat_id].obj_idx = 0;
+		mldev->xstats.entries[stat_id].reset_allowed = device_stats[i].reset_allowed;
+		stat_id++;
+	}
+	mldev->xstats.count_mode_device = stat_id;
+
+	/* Initialize model xstats */
+	for (model = 0; model < ML_CN10K_MAX_MODELS; model++) {
+		mldev->xstats.offset_for_model[model] = stat_id;
+
+		for (i = 0; i < RTE_DIM(model_stats); i++) {
+			mldev->xstats.entries[stat_id].map.id = stat_id;
+			mldev->xstats.entries[stat_id].mode = RTE_ML_DEV_XSTATS_MODEL;
+			mldev->xstats.entries[stat_id].type = model_stats[i].type;
+			mldev->xstats.entries[stat_id].fn_id = CN10K_ML_XSTATS_FN_MODEL;
+			mldev->xstats.entries[stat_id].obj_idx = model;
+			mldev->xstats.entries[stat_id].reset_allowed = model_stats[i].reset_allowed;
+
+			/* Name of xstat is updated during model load */
+			snprintf(mldev->xstats.entries[stat_id].map.name,
+				 sizeof(mldev->xstats.entries[stat_id].map.name), "Model-%u-%s",
+				 model, model_stats[i].name);
+
+			stat_id++;
+		}
+
+		mldev->xstats.count_per_model[model] = RTE_DIM(model_stats);
+	}
+
+	mldev->xstats.count_mode_model = stat_id - mldev->xstats.count_mode_device;
+	mldev->xstats.count = stat_id;
+
+	return 0;
+}
+
+static void
+cn10k_ml_xstats_uninit(struct rte_ml_dev *dev)
+{
+	struct cn10k_ml_dev *mldev;
+
+	mldev = dev->data->dev_private;
+
+	rte_free(mldev->xstats.entries);
+	mldev->xstats.entries = NULL;
+
+	mldev->xstats.count = 0;
+}
+
+static void
+cn10k_ml_xstats_model_name_update(struct rte_ml_dev *dev, uint16_t model_id)
+{
+	struct cn10k_ml_model *model;
+	struct cn10k_ml_dev *mldev;
+	uint16_t rclk_freq;
+	uint16_t sclk_freq;
+	uint16_t stat_id;
+	char suffix[8];
+	uint16_t i;
+
+	mldev = dev->data->dev_private;
+	model = dev->data->models[model_id];
+	stat_id = RTE_DIM(device_stats) + model_id * RTE_DIM(model_stats);
+
+	roc_clk_freq_get(&rclk_freq, &sclk_freq);
+	if (sclk_freq == 0)
+		strcpy(suffix, "cycles");
+	else
+		strcpy(suffix, "ns");
+
+	/* Update xstat name based on model name and sclk availability */
+	for (i = 0; i < RTE_DIM(model_stats); i++) {
+		snprintf(mldev->xstats.entries[stat_id].map.name,
+			 sizeof(mldev->xstats.entries[stat_id].map.name), "%s-%s-%s",
+			 model->metadata.model.name, model_stats[i].name, suffix);
+		stat_id++;
+	}
+}
+
+static uint64_t
+cn10k_ml_dev_xstat_get(struct rte_ml_dev *dev, uint16_t obj_idx __rte_unused,
+		       enum cn10k_ml_xstats_type type)
+{
+	struct cn10k_ml_dev *mldev;
+
+	mldev = dev->data->dev_private;
+
+	switch (type) {
+	case nb_models_loaded:
+		return mldev->nb_models_loaded;
+	case nb_models_unloaded:
+		return mldev->nb_models_unloaded;
+	case nb_models_started:
+		return mldev->nb_models_started;
+	case nb_models_stopped:
+		return mldev->nb_models_stopped;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
 #define ML_AVG_FOREACH_QP(dev, model, qp_id, str, value, count)                                    \
 	do {                                                                                       \
 		value = 0;                                                                         \
@@ -473,8 +627,7 @@ cn10k_ml_prep_fp_job_descriptor(struct rte_ml_dev *dev, struct cn10k_ml_req *req
 	} while (0)
 
 static uint64_t
-cn10k_ml_model_xstat_get(struct rte_ml_dev *dev, uint16_t model_id,
-			 enum cn10k_ml_model_xstats_type type)
+cn10k_ml_model_xstat_get(struct rte_ml_dev *dev, uint16_t obj_idx, enum cn10k_ml_xstats_type type)
 {
 	struct cn10k_ml_model *model;
 	uint16_t rclk_freq; /* MHz */
@@ -483,7 +636,7 @@ cn10k_ml_model_xstat_get(struct rte_ml_dev *dev, uint16_t model_id,
 	uint64_t value;
 	uint32_t qp_id;
 
-	model = dev->data->models[model_id];
+	model = dev->data->models[obj_idx];
 	if (model == NULL)
 		return 0;
 
@@ -517,6 +670,41 @@ cn10k_ml_model_xstat_get(struct rte_ml_dev *dev, uint16_t model_id,
 	return value;
 }
 
+static int
+cn10k_ml_device_xstats_reset(struct rte_ml_dev *dev, const uint16_t stat_ids[], uint16_t nb_ids)
+{
+	struct cn10k_ml_xstats_entry *xs;
+	struct cn10k_ml_dev *mldev;
+	uint16_t nb_stats;
+	uint16_t stat_id;
+	uint32_t i;
+
+	mldev = dev->data->dev_private;
+
+	if (stat_ids == NULL)
+		nb_stats = mldev->xstats.count_mode_device;
+	else
+		nb_stats = nb_ids;
+
+	for (i = 0; i < nb_stats; i++) {
+		if (stat_ids == NULL)
+			stat_id = i;
+		else
+			stat_id = stat_ids[i];
+
+		if (stat_id >= mldev->xstats.count_mode_device)
+			return -EINVAL;
+
+		xs = &mldev->xstats.entries[stat_id];
+		if (!xs->reset_allowed)
+			continue;
+
+		xs->reset_value = cn10k_ml_dev_xstat_get(dev, xs->obj_idx, xs->type);
+	}
+
+	return 0;
+}
+
 #define ML_AVG_RESET_FOREACH_QP(dev, model, qp_id, str)                                            \
 	do {                                                                                       \
 		for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {                      \
@@ -539,8 +727,7 @@ cn10k_ml_model_xstat_get(struct rte_ml_dev *dev, uint16_t model_id,
 	} while (0)
 
 static void
-cn10k_ml_model_xstat_reset(struct rte_ml_dev *dev, uint16_t model_id,
-			   enum cn10k_ml_model_xstats_type type)
+cn10k_ml_reset_model_stat(struct rte_ml_dev *dev, uint16_t model_id, enum cn10k_ml_xstats_type type)
 {
 	struct cn10k_ml_model *model;
 	uint32_t qp_id;
@@ -571,6 +758,60 @@ cn10k_ml_model_xstat_reset(struct rte_ml_dev *dev, uint16_t model_id,
 	}
 }
 
+static int
+cn10k_ml_model_xstats_reset(struct rte_ml_dev *dev, int32_t model_id, const uint16_t stat_ids[],
+			    uint16_t nb_ids)
+{
+	struct cn10k_ml_xstats_entry *xs;
+	struct cn10k_ml_model *model;
+	struct cn10k_ml_dev *mldev;
+	int32_t lcl_model_id = 0;
+	uint16_t start_id;
+	uint16_t end_id;
+	int32_t i;
+	int32_t j;
+
+	mldev = dev->data->dev_private;
+	for (i = 0; i < ML_CN10K_MAX_MODELS; i++) {
+		if (model_id == -1) {
+			model = dev->data->models[i];
+			if (model == NULL) /* Skip inactive models */
+				continue;
+		} else {
+			if (model_id != i)
+				continue;
+
+			model = dev->data->models[model_id];
+			if (model == NULL) {
+				plt_err("Invalid model_id = %d\n", model_id);
+				return -EINVAL;
+			}
+		}
+
+		start_id = mldev->xstats.offset_for_model[i];
+		end_id = mldev->xstats.offset_for_model[i] + mldev->xstats.count_per_model[i] - 1;
+
+		if (stat_ids == NULL) {
+			for (j = start_id; j <= end_id; j++) {
+				xs = &mldev->xstats.entries[j];
+				cn10k_ml_reset_model_stat(dev, i, xs->type);
+			}
+		} else {
+			for (j = 0; j < nb_ids; j++) {
+				if (stat_ids[j] < start_id || stat_ids[j] > end_id) {
+					plt_err("Invalid stat_ids[%d] = %d for model_id = %d\n", j,
+						stat_ids[j], lcl_model_id);
+					return -EINVAL;
+				}
+				xs = &mldev->xstats.entries[stat_ids[j]];
+				cn10k_ml_reset_model_stat(dev, i, xs->type);
+			}
+		}
+	}
+
+	return 0;
+}
+
 static int
 cn10k_ml_cache_model_data(struct rte_ml_dev *dev, uint16_t model_id)
 {
@@ -802,12 +1043,12 @@ cn10k_ml_dev_configure(struct rte_ml_dev *dev, const struct rte_ml_dev_config *c
 
 	rte_spinlock_init(&ocm->lock);
 
-	/* Check firmware stats */
-	if ((mldev->fw.req->jd.fw_load.cap.s.hw_stats) &&
-	    (mldev->fw.req->jd.fw_load.cap.s.fw_stats))
-		mldev->xstats_enabled = true;
-	else
-		mldev->xstats_enabled = false;
+	/* Initialize xstats */
+	ret = cn10k_ml_xstats_init(dev);
+	if (ret != 0) {
+		plt_err("Failed to initialize xstats");
+		goto error;
+	}
 
 	/* Set JCMDQ enqueue function */
 	if (mldev->hw_queue_lock == 1)
@@ -840,6 +1081,9 @@ cn10k_ml_dev_configure(struct rte_ml_dev *dev, const struct rte_ml_dev_config *c
 	dev->op_error_get = cn10k_ml_op_error_get;
 
 	mldev->nb_models_loaded = 0;
+	mldev->nb_models_started = 0;
+	mldev->nb_models_stopped = 0;
+	mldev->nb_models_unloaded = 0;
 	mldev->state = ML_CN10K_DEV_STATE_CONFIGURED;
 
 	return 0;
@@ -899,6 +1143,9 @@ cn10k_ml_dev_close(struct rte_ml_dev *dev)
 
 	rte_free(dev->data->queue_pairs);
 
+	/* Un-initialize xstats */
+	cn10k_ml_xstats_uninit(dev);
+
 	/* Unload firmware */
 	cn10k_ml_fw_unload(mldev);
 
@@ -1029,183 +1276,164 @@ cn10k_ml_dev_stats_reset(struct rte_ml_dev *dev)
 	}
 }
 
-/* Model xstats names */
-struct rte_ml_dev_xstats_map cn10k_ml_model_xstats_table[] = {
-	{avg_hw_latency, "Avg-HW-Latency"}, {min_hw_latency, "Min-HW-Latency"},
-	{max_hw_latency, "Max-HW-Latency"}, {avg_fw_latency, "Avg-FW-Latency"},
-	{min_fw_latency, "Min-FW-Latency"}, {max_fw_latency, "Max-FW-Latency"},
-};
-
 static int
-cn10k_ml_dev_xstats_names_get(struct rte_ml_dev *dev, struct rte_ml_dev_xstats_map *xstats_map,
+cn10k_ml_dev_xstats_names_get(struct rte_ml_dev *dev, enum rte_ml_dev_xstats_mode mode,
+			      int32_t model_id, struct rte_ml_dev_xstats_map *xstats_map,
 			      uint32_t size)
 {
-	struct rte_ml_dev_info dev_info;
-	struct cn10k_ml_model *model;
 	struct cn10k_ml_dev *mldev;
-	uint16_t rclk_freq;
-	uint16_t sclk_freq;
-	uint32_t model_id;
-	uint32_t count;
-	uint32_t type;
-	uint32_t id;
+	uint32_t xstats_mode_count;
+	uint32_t idx = 0;
+	uint32_t i;
 
 	mldev = dev->data->dev_private;
-	if (!mldev->xstats_enabled)
-		return 0;
-
-	if (xstats_map == NULL)
-		return PLT_DIM(cn10k_ml_model_xstats_table) * mldev->nb_models_loaded;
 
-	/* Model xstats names */
-	count = 0;
-	cn10k_ml_dev_info_get(dev, &dev_info);
-	roc_clk_freq_get(&rclk_freq, &sclk_freq);
+	xstats_mode_count = 0;
+	switch (mode) {
+	case RTE_ML_DEV_XSTATS_DEVICE:
+		xstats_mode_count = mldev->xstats.count_mode_device;
+		break;
+	case RTE_ML_DEV_XSTATS_MODEL:
+		if (model_id >= ML_CN10K_MAX_MODELS)
+			break;
+		xstats_mode_count = mldev->xstats.count_per_model[model_id];
+		break;
+	default:
+		return -EINVAL;
+	};
 
-	for (id = 0; id < PLT_DIM(cn10k_ml_model_xstats_table) * dev_info.max_models; id++) {
-		model_id = id / PLT_DIM(cn10k_ml_model_xstats_table);
-		model = dev->data->models[model_id];
+	if (xstats_mode_count > size || xstats_map == NULL)
+		return xstats_mode_count;
 
-		if (model == NULL)
+	for (i = 0; i < mldev->xstats.count && idx < size; i++) {
+		if (mldev->xstats.entries[i].mode != mode)
 			continue;
 
-		xstats_map[count].id = id;
-		type = id % PLT_DIM(cn10k_ml_model_xstats_table);
-
-		if (sclk_freq == 0)
-			snprintf(xstats_map[count].name, RTE_ML_STR_MAX, "%s-%s-cycles",
-				 model->metadata.model.name,
-				 cn10k_ml_model_xstats_table[type].name);
-		else
-			snprintf(xstats_map[count].name, RTE_ML_STR_MAX, "%s-%s-ns",
-				 model->metadata.model.name,
-				 cn10k_ml_model_xstats_table[type].name);
+		if (mode != RTE_ML_DEV_XSTATS_DEVICE &&
+		    model_id != mldev->xstats.entries[i].obj_idx)
+			continue;
 
-		count++;
-		if (count == size)
-			break;
+		strncpy(xstats_map[idx].name, mldev->xstats.entries[i].map.name, RTE_ML_STR_MAX);
+		xstats_map[idx].id = mldev->xstats.entries[i].map.id;
+		idx++;
 	}
 
-	return count;
+	return idx;
 }
 
-static int __rte_unused
+static int
 cn10k_ml_dev_xstats_by_name_get(struct rte_ml_dev *dev, const char *name, uint16_t *stat_id,
 				uint64_t *value)
 {
-	struct rte_ml_dev_xstats_map *xstats_map;
-	struct rte_ml_dev_info dev_info;
+	struct cn10k_ml_xstats_entry *xs;
 	struct cn10k_ml_dev *mldev;
-	uint32_t num_xstats;
-	uint32_t model_id;
-	uint32_t type;
-	uint32_t id;
+	cn10k_ml_xstats_fn fn;
+	uint32_t i;
 
 	mldev = dev->data->dev_private;
-	if (!mldev->xstats_enabled)
-		return 0;
-
-	num_xstats = PLT_DIM(cn10k_ml_model_xstats_table) * mldev->nb_models_loaded;
-	xstats_map = rte_zmalloc("cn10k_ml_xstats_map",
-				 sizeof(struct rte_ml_dev_xstats_map) * num_xstats, 0);
-	if (xstats_map == NULL) {
-		plt_err("Unable to allocate memory for cn10k_ml_xstats_map");
-		return -ENOMEM;
-	}
+	for (i = 0; i < mldev->xstats.count; i++) {
+		xs = &mldev->xstats.entries[i];
+		if (strncmp(xs->map.name, name, RTE_ML_STR_MAX) == 0) {
+			if (stat_id != NULL)
+				*stat_id = xs->map.id;
+
+			switch (xs->fn_id) {
+			case CN10K_ML_XSTATS_FN_DEVICE:
+				fn = cn10k_ml_dev_xstat_get;
+				break;
+			case CN10K_ML_XSTATS_FN_MODEL:
+				fn = cn10k_ml_model_xstat_get;
+				break;
+			default:
+				plt_err("Unexpected xstat fn_id = %d", xs->fn_id);
+				return -EINVAL;
+			}
 
-	cn10k_ml_dev_xstats_names_get(dev, xstats_map, num_xstats);
+			*value = fn(dev, xs->obj_idx, xs->type) - xs->reset_value;
 
-	cn10k_ml_dev_info_get(dev, &dev_info);
-	for (id = 0; id < PLT_DIM(cn10k_ml_model_xstats_table) * dev_info.max_models; id++) {
-		if (strncmp(name, xstats_map[id].name, strlen(name)) == 0) {
-			*stat_id = id;
-			rte_free(xstats_map);
-			break;
+			return 0;
 		}
 	}
 
-	if (id == PLT_DIM(cn10k_ml_model_xstats_table) * dev_info.max_models) {
-		rte_free(xstats_map);
-		return -EINVAL;
-	}
-
-	model_id = id / PLT_DIM(cn10k_ml_model_xstats_table);
-	type = id % PLT_DIM(cn10k_ml_model_xstats_table);
-	*value = cn10k_ml_model_xstat_get(dev, model_id, type);
+	if (stat_id != NULL)
+		*stat_id = (uint16_t)-1;
 
-	return 0;
+	return -EINVAL;
 }
 
-static int __rte_unused
-cn10k_ml_dev_xstats_get(struct rte_ml_dev *dev, const uint16_t *stat_ids, uint64_t *values,
-			uint16_t nb_ids)
+static int
+cn10k_ml_dev_xstats_get(struct rte_ml_dev *dev, enum rte_ml_dev_xstats_mode mode, int32_t model_id,
+			const uint16_t stat_ids[], uint64_t values[], uint16_t nb_ids)
 {
-	struct cn10k_ml_model *model;
+	struct cn10k_ml_xstats_entry *xs;
 	struct cn10k_ml_dev *mldev;
-	uint32_t model_id;
-	uint32_t count;
-	uint32_t type;
+	uint32_t xstats_mode_count;
+	cn10k_ml_xstats_fn fn;
+	uint64_t val;
+	uint32_t idx;
 	uint32_t i;
 
 	mldev = dev->data->dev_private;
-	if (!mldev->xstats_enabled)
-		return 0;
+	xstats_mode_count = 0;
 
-	count = 0;
-	for (i = 0; i < nb_ids; i++) {
-		model_id = stat_ids[i] / PLT_DIM(cn10k_ml_model_xstats_table);
-		model = dev->data->models[model_id];
+	switch (mode) {
+	case RTE_ML_DEV_XSTATS_DEVICE:
+		xstats_mode_count = mldev->xstats.count_mode_device;
+		break;
+	case RTE_ML_DEV_XSTATS_MODEL:
+		if (model_id >= ML_CN10K_MAX_MODELS)
+			return -EINVAL;
+		xstats_mode_count = mldev->xstats.count_per_model[model_id];
+		break;
+	default:
+		return -EINVAL;
+	};
 
-		if (model == NULL)
+	idx = 0;
+	for (i = 0; i < nb_ids && idx < xstats_mode_count; i++) {
+		xs = &mldev->xstats.entries[stat_ids[i]];
+		if (stat_ids[i] > mldev->xstats.count || xs->mode != mode)
 			continue;
 
-		type = stat_ids[i] % PLT_DIM(cn10k_ml_model_xstats_table);
-		values[i] = cn10k_ml_model_xstat_get(dev, model_id, type);
-		count++;
-	}
-
-	return count;
-}
-
-static int __rte_unused
-cn10k_ml_dev_xstats_reset(struct rte_ml_dev *dev, const uint16_t *stat_ids, uint16_t nb_ids)
-{
-	struct rte_ml_dev_info dev_info;
-	struct cn10k_ml_model *model;
-	struct cn10k_ml_dev *mldev;
-	uint32_t model_id;
-	uint32_t type;
-	uint32_t i;
-
-	mldev = dev->data->dev_private;
-	if (!mldev->xstats_enabled)
-		return 0;
-
-	cn10k_ml_dev_info_get(dev, &dev_info);
-	if (stat_ids == NULL) {
-		for (i = 0; i < PLT_DIM(cn10k_ml_model_xstats_table) * dev_info.max_models; i++) {
-			model_id = i / PLT_DIM(cn10k_ml_model_xstats_table);
-			model = dev->data->models[model_id];
-
-			if (model == NULL)
-				continue;
+		if (mode == RTE_ML_DEV_XSTATS_MODEL && model_id != xs->obj_idx) {
+			plt_err("Invalid stats_id[%d] = %d for model_id = %d\n", i, stat_ids[i],
+				model_id);
+			return -EINVAL;
+		}
 
-			type = i % PLT_DIM(cn10k_ml_model_xstats_table);
-			cn10k_ml_model_xstat_reset(dev, model_id, type);
+		switch (xs->fn_id) {
+		case CN10K_ML_XSTATS_FN_DEVICE:
+			fn = cn10k_ml_dev_xstat_get;
+			break;
+		case CN10K_ML_XSTATS_FN_MODEL:
+			fn = cn10k_ml_model_xstat_get;
+			break;
+		default:
+			plt_err("Unexpected xstat fn_id = %d", xs->fn_id);
+			return -EINVAL;
 		}
-	} else {
-		for (i = 0; i < nb_ids; i++) {
-			model_id = stat_ids[i] / PLT_DIM(cn10k_ml_model_xstats_table);
-			model = dev->data->models[model_id];
 
-			if (model == NULL)
-				continue;
+		val = fn(dev, xs->obj_idx, xs->type);
+		if (values)
+			values[idx] = val;
 
-			type = stat_ids[i] % PLT_DIM(cn10k_ml_model_xstats_table);
-			cn10k_ml_model_xstat_reset(dev, model_id, type);
-		}
+		idx++;
 	}
 
+	return idx;
+}
+
+static int
+cn10k_ml_dev_xstats_reset(struct rte_ml_dev *dev, enum rte_ml_dev_xstats_mode mode,
+			  int32_t model_id, const uint16_t stat_ids[], uint16_t nb_ids)
+{
+	switch (mode) {
+	case RTE_ML_DEV_XSTATS_DEVICE:
+		return cn10k_ml_device_xstats_reset(dev, stat_ids, nb_ids);
+	case RTE_ML_DEV_XSTATS_MODEL:
+		return cn10k_ml_model_xstats_reset(dev, model_id, stat_ids, nb_ids);
+	};
+
 	return 0;
 }
 
@@ -1471,6 +1699,9 @@ cn10k_ml_model_load(struct rte_ml_dev *dev, struct rte_ml_model_params *params,
 	dev->data->models[idx] = model;
 	mldev->nb_models_loaded++;
 
+	/* Update xstats names */
+	cn10k_ml_xstats_model_name_update(dev, idx);
+
 	*model_id = idx;
 
 	return 0;
@@ -1497,7 +1728,7 @@ cn10k_ml_model_unload(struct rte_ml_dev *dev, uint16_t model_id)
 	}
 
 	dev->data->models[model_id] = NULL;
-	mldev->nb_models_loaded--;
+	mldev->nb_models_unloaded++;
 
 	snprintf(str, RTE_MEMZONE_NAMESIZE, "%s_%u", CN10K_ML_MODEL_MEMZONE_NAME, model_id);
 	return plt_memzone_free(plt_memzone_lookup(str));
@@ -1627,10 +1858,12 @@ cn10k_ml_model_start(struct rte_ml_dev *dev, uint16_t model_id)
 	locked = false;
 	while (!locked) {
 		if (plt_spinlock_trylock(&model->lock) != 0) {
-			if (ret == 0)
+			if (ret == 0) {
 				model->state = ML_CN10K_MODEL_STATE_STARTED;
-			else
+				mldev->nb_models_started++;
+			} else {
 				model->state = ML_CN10K_MODEL_STATE_UNKNOWN;
+			}
 
 			plt_spinlock_unlock(&model->lock);
 			locked = true;
@@ -1751,6 +1984,7 @@ cn10k_ml_model_stop(struct rte_ml_dev *dev, uint16_t model_id)
 	locked = false;
 	while (!locked) {
 		if (plt_spinlock_trylock(&model->lock) != 0) {
+			mldev->nb_models_stopped++;
 			model->state = ML_CN10K_MODEL_STATE_LOADED;
 			plt_spinlock_unlock(&model->lock);
 			locked = true;
@@ -2308,6 +2542,10 @@ struct rte_ml_dev_ops cn10k_ml_ops = {
 	/* Stats ops */
 	.dev_stats_get = cn10k_ml_dev_stats_get,
 	.dev_stats_reset = cn10k_ml_dev_stats_reset,
+	.dev_xstats_names_get = cn10k_ml_dev_xstats_names_get,
+	.dev_xstats_by_name_get = cn10k_ml_dev_xstats_by_name_get,
+	.dev_xstats_get = cn10k_ml_dev_xstats_get,
+	.dev_xstats_reset = cn10k_ml_dev_xstats_reset,
 
 	/* Model ops */
 	.model_load = cn10k_ml_model_load,
-- 
2.17.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v1 0/5] Implementation of revised ML xstats spec
  2023-04-23  5:13 [PATCH v1 0/5] Implementation of revised ML xstats spec Srikanth Yalavarthi
                   ` (4 preceding siblings ...)
  2023-04-23  5:14 ` [PATCH v1 5/5] ml/cnxk: implement xstats driver functions Srikanth Yalavarthi
@ 2023-06-06 13:40 ` Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Monjalon @ 2023-06-06 13:40 UTC (permalink / raw)
  To: Srikanth Yalavarthi; +Cc: dev, syalavarthi, sshankarnara, aprabhu, ptakkar

23/04/2023 07:13, Srikanth Yalavarthi:
> This series of patches introduces revised xstats specification for ML
> device. The revised xstats spec is based on eventdev xstats and supports
> DEVICE and MODEL modes to get xstats. This enables retrieving xstats for
> device and each model separately.
> 
> 
> Srikanth Yalavarthi (5):
>   mldev: remove xstats APIs from library
>   mldev: introduce revised xstats
>   mldev: implement xstats library functions
>   app/mldev: enable reporting xstats
>   ml/cnxk: implement xstats driver functions

Applied, thanks.

Note: did one small fix in a meson file and squashed implem with API




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-06-06 13:40 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-23  5:13 [PATCH v1 0/5] Implementation of revised ML xstats spec Srikanth Yalavarthi
2023-04-23  5:13 ` [PATCH v1 1/5] mldev: remove xstats APIs from library Srikanth Yalavarthi
2023-04-23  5:14 ` [PATCH v1 2/5] mldev: introduce revised xstats Srikanth Yalavarthi
2023-04-23  5:14 ` [PATCH v1 3/5] mldev: implement xstats library functions Srikanth Yalavarthi
2023-04-23  5:14 ` [PATCH v1 4/5] app/mldev: enable reporting xstats Srikanth Yalavarthi
2023-04-23  5:14 ` [PATCH v1 5/5] ml/cnxk: implement xstats driver functions Srikanth Yalavarthi
2023-06-06 13:40 ` [PATCH v1 0/5] Implementation of revised ML xstats spec Thomas Monjalon

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).