AVX512 block copy performance?
Morten Brørup <[email protected]>
| Newsgroups | org.dpdk.dev |
|---|---|
| Message-ID | <[email protected]> |
> From: dev [mailto:[email protected]] On Behalf Of Leyi Rong > Sent: Thursday, 14 January 2021 07.40 > > Optimize Tx path by using AVX512 instructions and vectorize the > tx free bufs process. > > Signed-off-by: Leyi Rong <[email protected]> > Signed-off-by: Bruce Richardson <[email protected]> > --- [...] > +static __rte_always_inline int > +i40e_tx_free_bufs_avx512(struct i40e_tx_queue *txq) > +{ > + struct i40e_vec_tx_entry *txep; > + uint32_t n; > + uint32_t i; > + int nb_free = 0; > + struct rte_mbuf *m, *free[RTE_I40E_TX_MAX_FREE_BUF_SZ]; > + > + /* check DD bits on threshold descriptor */ > + if ((txq->tx_ring[txq->tx_next_dd].cmd_type_offset_bsz & > + rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) != > + rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE)) > + return 0; > + > + n = txq->tx_rs_thresh; > + > + /* first buffer to free from S/W ring is at index > + * tx_next_dd - (tx_rs_thresh-1) > + */ > + txep = (void *)txq->sw_ring; > + txep += txq->tx_next_dd - (n - 1); > + > + if (txq->offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE && (n & 31) == > 0) { > + struct rte_mempool *mp = txep[0].mbuf->pool; > + void **cache_objs; > + struct rte_mempool_cache *cache = > rte_mempool_default_cache(mp, > + rte_lcore_id()); > + > + if (!cache || cache->len == 0) > + goto normal; > + > + cache_objs = &cache->objs[cache->len]; > + > + if (n > RTE_MEMPOOL_CACHE_MAX_SIZE) { > + rte_mempool_ops_enqueue_bulk(mp, (void *)txep, n); > + goto done; > + } > + > + /* The cache follows the following algorithm > + * 1. Add the objects to the cache > + * 2. Anything greater than the cache min value (if it > + * crosses the cache flush threshold) is flushed to the > ring. > + */ > + /* Add elements back into the cache */ > + uint32_t copied = 0; > + /* n is multiple of 32 */ > + while (copied < n) { > + const __m512i a = _mm512_load_si512(&txep[copied]); > + const __m512i b = _mm512_load_si512(&txep[copied + > 8]); > + const __m512i c = _mm512_load_si512(&txep[copied + > 16]); > + const __m512i d = _mm512_load_si512(&txep[copied + > 24]); > + > + _mm512_storeu_si512(&cache_objs[copied], a); > + _mm512_storeu_si512(&cache_objs[copied + 8], b); > + _mm512_storeu_si512(&cache_objs[copied + 16], c); > + _mm512_storeu_si512(&cache_objs[copied + 24], d); > + copied += 32; > + } Do you have any indications about how this copy loop performs, compared to e.g. the 64-byte block copy in rte_memcpy() [1]? [1]: https://github.com/DPDK/dpdk/blob/v26.07-rc4/lib/eal/x86/include/rte_memcpy.h#L657 I'm wondering if it would be worth adding something similar to the mempool library, for speeding up mbuf alloc/free. > + cache->len += n; > + > + if (cache->len >= cache->flushthresh) { > + rte_mempool_ops_enqueue_bulk > + (mp, &cache->objs[cache->size], > + cache->len - cache->size); > + cache->len = cache->size; > + } > + goto done; > + } > + > +normal: