[dpdk-dev] [PATCH v3 01/18] eal: add max SIMD bitwidth

Power, Ciara ciara.power at intel.com
Thu Oct 8 16:26:58 CEST 2020


Hi Bruce, Konstantin,


>-----Original Message-----
>From: Bruce Richardson <bruce.richardson at intel.com>
>Sent: Thursday 8 October 2020 15:18
>To: Ananyev, Konstantin <konstantin.ananyev at intel.com>
>Cc: Power, Ciara <ciara.power at intel.com>; dev at dpdk.org; Ray Kinsella
><mdr at ashroe.eu>; Neil Horman <nhorman at tuxdriver.com>
>Subject: Re: [dpdk-dev] [PATCH v3 01/18] eal: add max SIMD bitwidth
>
>On Thu, Oct 08, 2020 at 03:07:54PM +0100, Ananyev, Konstantin wrote:
>>
>> > On Thu, Oct 08, 2020 at 01:07:26PM +0000, Ananyev, Konstantin wrote:
>> > >
>> > > > This patch adds a max SIMD bitwidth EAL configuration. The API
>> > > > allows for an app to set this value. It can also be set using
>> > > > EAL argument --force-max-simd-bitwidth, which will lock the
>> > > > value and override any modifications made by the app.
>> > > >
>> > > > Signed-off-by: Ciara Power <ciara.power at intel.com>
>> > > >
>> > > > ---
>> > > > v3:
>> > > >   - Added enum value to essentially disable using max SIMD to choose
>> > > >     paths, intended for use by ARM SVE.
>> > > >   - Fixed parsing bitwidth argument to return an error for values
>> > > >     greater than uint16_t.
>> > > > v2: Added to Doxygen comment for API.
>> > > > ---
>> > > >  lib/librte_eal/common/eal_common_options.c | 64
>++++++++++++++++++++++
>> > > >  lib/librte_eal/common/eal_internal_cfg.h   |  8 +++
>> > > >  lib/librte_eal/common/eal_options.h        |  2 +
>> > > >  lib/librte_eal/include/rte_eal.h           | 33 +++++++++++
>> > > >  lib/librte_eal/rte_eal_version.map         |  4 ++
>> > > >  5 files changed, 111 insertions(+)
>> > > >
>> > > > diff --git a/lib/librte_eal/common/eal_common_options.c
>> > > > b/lib/librte_eal/common/eal_common_options.c
>> > > > index a5426e1234..e9117a96af 100644
>> > > > --- a/lib/librte_eal/common/eal_common_options.c
>> > > > +++ b/lib/librte_eal/common/eal_common_options.c
>> > > > @@ -102,6 +102,7 @@ eal_long_options[] = {
>> > > > {OPT_MATCH_ALLOCATIONS, 0, NULL,
>OPT_MATCH_ALLOCATIONS_NUM},
>> > > >  {OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
>> > > >  {OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
>> > > > +{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL,
>> > > > +OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
>> > > >  {0,                     0, NULL, 0                        }
>> > > >  };
>> > > >
>> > > > @@ -1309,6 +1310,34 @@ eal_parse_iova_mode(const char *name)
>> > > > return 0;  }
>> > > >
>> > > > +static int
>> > > > +eal_parse_simd_bitwidth(const char *arg, bool locked) { char
>> > > > +*end; unsigned long bitwidth; int ret; struct internal_config
>> > > > +*internal_conf = eal_get_internal_configuration();
>> > > > +
>> > > > +if (arg == NULL || arg[0] == '\0') return -1;
>> > > > +
>> > > > +errno = 0;
>> > > > +bitwidth = strtoul(arg, &end, 0);
>> > > > +
>> > > > +/* check for errors */
>> > > > +if (bitwidth > UINT16_MAX || errno != 0 || end == NULL || *end
>> > > > +!= '\0') return -1;
>> > > > +
>> > > > +if (bitwidth == 0)
>> > > > +bitwidth = UINT16_MAX;
>> > > > +ret = rte_set_max_simd_bitwidth(bitwidth);
>> > > > +if (ret < 0)
>> > > > +return -1;
>> > > > +internal_conf->max_simd_bitwidth.locked = locked; return 0; }
>> > > > +
>> > > >  static int
>> > > >  eal_parse_base_virtaddr(const char *arg)  { @@ -1707,6 +1736,13
>> > > > @@ eal_parse_common_option(int opt, const char *optarg,  case
>> > > > OPT_NO_TELEMETRY_NUM:
>> > > >  conf->no_telemetry = 1;
>> > > >  break;
>> > > > +case OPT_FORCE_MAX_SIMD_BITWIDTH_NUM:
>> > > > +if (eal_parse_simd_bitwidth(optarg, 1) < 0) { RTE_LOG(ERR, EAL,
>> > > > +"invalid parameter for --"
>> > > > +OPT_FORCE_MAX_SIMD_BITWIDTH "\n"); return -1; } break;
>> > > >
>> > > >  /* don't know what to do, leave this to caller */
>> > > >  default:
>> > > > @@ -1903,6 +1939,33 @@ eal_check_common_options(struct
>> > > > internal_config *internal_cfg)  return 0;  }
>> > > >
>> > > > +uint16_t
>> > > > +rte_get_max_simd_bitwidth(void) { const struct internal_config
>> > > > +*internal_conf = eal_get_internal_configuration(); return
>> > > > +internal_conf->max_simd_bitwidth.bitwidth;
>> > > > +}
>> > > > +
>> > > > +int
>> > > > +rte_set_max_simd_bitwidth(uint16_t bitwidth) { struct
>> > > > +internal_config *internal_conf =
>> > > > +eal_get_internal_configuration();
>> > > > +if (internal_conf->max_simd_bitwidth.locked) { RTE_LOG(NOTICE,
>> > > > +EAL, "Cannot set max SIMD bitwidth - user runtime override
>> > > > +enabled"); return -EPERM; }
>> > > > +
>> > > > +if (bitwidth != RTE_MAX_SIMD_DISABLE && (bitwidth <
>RTE_NO_SIMD
>> > > > +||
>> > > > +!rte_is_power_of_2(bitwidth))) { RTE_LOG(ERR, EAL, "Invalid
>> > > > +bitwidth value!\n"); return -EINVAL; }
>> > > > +internal_conf->max_simd_bitwidth.bitwidth = bitwidth; return 0;
>> > > > +}
>> > > > +
>> > > >  void
>> > > >  eal_common_usage(void)
>> > > >  {
>> > > > @@ -1981,6 +2044,7 @@ eal_common_usage(void)
>> > > >         "  --"OPT_BASE_VIRTADDR"     Base virtual address\n"
>> > > >         "  --"OPT_TELEMETRY"   Enable telemetry support (on by
>default)\n"
>> > > >         "  --"OPT_NO_TELEMETRY"   Disable telemetry support\n"
>> > > > +       "  --"OPT_FORCE_MAX_SIMD_BITWIDTH" Force the max SIMD
>bitwidth\n"
>> > > >         "\nEAL options for DEBUG use only:\n"
>> > > >         "  --"OPT_HUGE_UNLINK"       Unlink hugepage files after init\n"
>> > > >         "  --"OPT_NO_HUGE"           Use malloc instead of hugetlbfs\n"
>> > > > diff --git a/lib/librte_eal/common/eal_internal_cfg.h
>b/lib/librte_eal/common/eal_internal_cfg.h
>> > > > index 13f93388a7..367e0cc19e 100644
>> > > > --- a/lib/librte_eal/common/eal_internal_cfg.h
>> > > > +++ b/lib/librte_eal/common/eal_internal_cfg.h
>> > > > @@ -33,6 +33,12 @@ struct hugepage_info {
>> > > >  int lock_descriptor;    /**< file descriptor for hugepage dir */
>> > > >  };
>> > > >
>> > > > +struct simd_bitwidth {
>> > > > +/**< flag indicating if bitwidth is locked from further modification */
>> > > > +bool locked;
>> > > > +uint16_t bitwidth; /**< bitwidth value */
>> > > > +};
>> > > > +
>> > > >  /**
>> > > >   * internal configuration
>> > > >   */
>> > > > @@ -85,6 +91,8 @@ struct internal_config {
>> > > >  volatile unsigned int init_complete;
>> > > >  /**< indicates whether EAL has completed initialization */
>> > > >  unsigned int no_telemetry; /**< true to disable Telemetry */
>> > > > +/** max simd bitwidth path to use */
>> > > > +struct simd_bitwidth max_simd_bitwidth;
>> > > >  };
>> > > >
>> > > >  void eal_reset_internal_config(struct internal_config *internal_cfg);
>> > > > diff --git a/lib/librte_eal/common/eal_options.h
>b/lib/librte_eal/common/eal_options.h
>> > > > index 89769d48b4..ef33979664 100644
>> > > > --- a/lib/librte_eal/common/eal_options.h
>> > > > +++ b/lib/librte_eal/common/eal_options.h
>> > > > @@ -85,6 +85,8 @@ enum {
>> > > >  OPT_TELEMETRY_NUM,
>> > > >  #define OPT_NO_TELEMETRY      "no-telemetry"
>> > > >  OPT_NO_TELEMETRY_NUM,
>> > > > +#define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-
>bitwidth"
>> > > > +OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
>> > > >  OPT_LONG_MAX_NUM
>> > > >  };
>> > > >
>> > > > diff --git a/lib/librte_eal/include/rte_eal.h
>b/lib/librte_eal/include/rte_eal.h
>> > > > index ddcf6a2e7a..fb739f3474 100644
>> > > > --- a/lib/librte_eal/include/rte_eal.h
>> > > > +++ b/lib/librte_eal/include/rte_eal.h
>> > > > @@ -43,6 +43,14 @@ enum rte_proc_type_t {
>> > > >  RTE_PROC_INVALID
>> > > >  };
>> > > >
>> > > > +enum rte_max_simd_t {
>> > > > +RTE_NO_SIMD = 64,
>> > >
>> > > While I do understand the idea of having that value from consistency
>point of view,
>> > > I wonder do we really need to allow user to specify values smaller then
>128.
>> > > At least on x86 we always have 128 bit SIMD enabled, even for -
>Dmachine=default.
>> > > So seems no much point to forbid libraries using SSE code-path when
>compiler
>> > > is free to insert SSE instructions on its own will.
>> > >
>> >
>> > The reason to support this is for testing purposes, as it allows an easy
>> > way for a tester to check out any scalar code paths - which are often
>> > common across architectures.
>>
>> If it is just for testing things in a consistent way, then it is  probably ok.
>> The thing that worries me - later in this series there are patches
>> that insert extra checks into inline functions that use SSE instincts:
>> https://patches.dpdk.org/patch/79355/ (lpm: choose vector path at
>runtime).
>> Which seems like a total overkill for me.
>>
>> >
>> > > > +RTE_MAX_128_SIMD = 128,
>> > > > +RTE_MAX_256_SIMD = 256,
>> > > > +RTE_MAX_512_SIMD = 512,
>> > > > +RTE_MAX_SIMD_DISABLE = UINT16_MAX,
>> > >
>> > > As a nit, I think it is safe enough to have this last value
>> > > (RTE_MAX_SIMD_DISABLE or RTE_MAX_SIMD_MAX) equal to
>(INT16_MAX + 1).
>> > > That would be big enough to probably never hit actual HW limit,
>> > > while it still remains power of two, as other values.
>> > >
>> >
>> > I actually think it's probably clearer as-is, because the fact of the rest
>> > being powers of 2 is irrelevant since we just check greater than or less
>> > than.
>>
>> Well, rte_set_max_simd_bitwidth() does accept only power of two values
>> _AND_ this special one (UINT16_MAX).
>> By changing it to 2^15, we can remove that special value test.
>>
>> > If we did change it, then we need to put in a comment explaining why
>> > the plus-one,
>>
>> I don't think it is that big deal to put a comment,
>> plus for UINT16_MAX we do need some explanation too, right?
>>
>I'm ok either way. Ciara, what do you think?

Either is fine with me, I can change it to (INT16_MAX + 1) if that is preferred, and remove the extra special case check in the rte_set_max_simd_bitwidth()

Thanks,
Ciara


More information about the dev mailing list