lib/idxd: only select idxd device that are on the same socket

Prior a regular round robin could result in strange performance
if an idxd device from another socket was used.

Signed-off-by: peluse <peluse@localhost.localdomain>
Signed-off-by: Ziye Yang <ziye.yang@intel.com>
Change-Id: Id863c79067beabe73ef89d92b3fb3c436821b97a
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9367
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: Monica Kenguva <monica.kenguva@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
peluse 2021-09-01 16:17:46 -04:00 committed by Tomasz Zawadzki
parent 17199cdc8f
commit 504bf59148
9 changed files with 45 additions and 2 deletions

View File

@ -2,6 +2,11 @@
## v21.10: (Upcoming Release)
### idxd
Added `spdk_idxd_get_socket` to query the socket that the idxd device
is on.
### nvmf
Added `oncs` to `struct spdk_nvmf_ctrlr_data` so that the transport layer

View File

@ -86,6 +86,15 @@ of service parameters on the work queues that are not currently utilized by
the module. Specialized use of DSA may require different configurations that
can be added to the module as needed.
When a new channel starts, a DSA device will be assigned to the channel. The accel
idxd module has been tuned for the most likely best performance case. The result
is that there is a limited number of channels that can be supported based on the
number of DSA devices in the system. Additionally, for best performance, the accel
idxd module will only use DSA devices on the same socket as the requesting
channel/thread. If an error occurs on initialization indicating that there are no
more DSA devices available either try fewer threads or, if on a 2 socket system,
try spreading threads across cores if possible.
### Software Module {#accel_sw}
The software module is enabled by default. If no hardware engine is explicitly

View File

@ -61,6 +61,14 @@ struct spdk_idxd_device;
*/
struct idxd_batch;
/**
* Get the socket that this device is on
*
* \param idxd device to query
* \return socket number.
*/
uint32_t spdk_idxd_get_socket(struct spdk_idxd_device *idxd);
/**
* Signature for configuring a channel
*

View File

@ -81,6 +81,12 @@ struct device_config g_dev_cfg1 = {
.total_engines = 4,
};
uint32_t
spdk_idxd_get_socket(struct spdk_idxd_device *idxd)
{
return idxd->socket_id;
}
static inline void
_submit_to_hw(struct spdk_idxd_io_channel *chan, struct idxd_ops *op)
{

View File

@ -168,6 +168,7 @@ struct spdk_idxd_impl {
struct spdk_idxd_device {
struct spdk_idxd_impl *impl;
void *portals;
uint32_t socket_id;
int wq_id;
uint32_t num_channels;
uint32_t total_wq_size;

View File

@ -140,6 +140,7 @@ dsa_setup_single_wq(struct spdk_kernel_idxd_device *kernel_idxd, struct accfg_wq
/* Update the active_wq_num of the kernel device */
kernel_idxd->wq_active_num++;
kernel_idxd->idxd.total_wq_size += wq_ctx->wq_size;
kernel_idxd->idxd.socket_id = accfg_device_get_numa_node(dev);
return 0;
}

View File

@ -567,6 +567,7 @@ idxd_attach(struct spdk_pci_device *device)
idxd = &user_idxd->idxd;
user_idxd->device = device;
idxd->impl = &g_user_idxd_impl;
idxd->socket_id = device->socket_id;
pthread_mutex_init(&idxd->num_channels_lock, NULL);
/* Enable PCI busmaster. */

View File

@ -16,6 +16,7 @@
spdk_idxd_batch_create;
spdk_idxd_batch_cancel;
spdk_idxd_batch_get_max;
spdk_idxd_get_socket;
spdk_idxd_set_config;
spdk_idxd_submit_compare;
spdk_idxd_submit_crc32c;

View File

@ -85,6 +85,7 @@ idxd_select_device(struct idxd_io_channel *chan)
{
uint32_t count = 0;
struct idxd_device *dev;
uint32_t socket_id = spdk_env_get_socket_id(spdk_env_get_current_core());
/*
* We allow channels to share underlying devices,
@ -101,6 +102,10 @@ idxd_select_device(struct idxd_io_channel *chan)
dev = g_next_dev;
pthread_mutex_unlock(&g_dev_lock);
if (socket_id != spdk_idxd_get_socket(dev->idxd)) {
continue;
}
/*
* Now see if a channel is available on this one. We only
* allow a specific number of channels to share a device
@ -109,12 +114,18 @@ idxd_select_device(struct idxd_io_channel *chan)
chan->chan = spdk_idxd_get_channel(dev->idxd);
if (chan->chan != NULL) {
chan->max_outstanding = spdk_idxd_chan_get_max_operations(chan->chan);
SPDK_DEBUGLOG(accel_idxd, "On socket %d using device on socket %d\n",
socket_id, spdk_idxd_get_socket(dev->idxd));
return dev;
}
} while (count++ < g_num_devices);
/* we are out of available channels and devices. */
SPDK_ERRLOG("No more DSA devices available!\n");
/* We are out of available channels and/or devices for the local socket. We fix the number
* of channels that we allocate per device and only allocate devices on the same socket
* that the current thread is on. If on a 2 socket system it may be possible to avoid
* this situation by spreading threads across the sockets.
*/
SPDK_ERRLOG("No more DSA devices available on the local socket.\n");
return NULL;
}