DPDK 缓存预取

318 阅读1分钟

简介

简单来说,为了加速CPU访问内存的速度,于是有了访问更快的缓存结构,一般包括L1、L2、L3。 image.png

示例

通常在进行数据包处理时会先对数据包进行预取操作,dpdk中触发CPU预取的指令如下:

  • rte_prefetch0 预取数据到所有级别的缓存
  • rte_prefetch1 预取数据到所有级别的缓存,除L0外。
  • rte_prefetch2 预取数据到所有级别的缓存,除L0和L1外。
  • rte_prefetch_non_temporal 预取数据到非临时性的缓存,即只将数据预取到较低级别的缓存中,比如L2或L3缓存。这可以防止预取数据污染顶级缓存。

以下为dpdk中ipv4_multicast示例代码,采用的是rte_prefetch0,考虑缓存大小不一次全部预取(防止预取数据污染)。

  • 首先循环预取PREFETCH_OFFSET三个数据包到所有级别缓存。
  • 再循环预取一个新的数据包,同时处理一个已经预取的数据包。
  • 最后循环处理剩下预取的数据包。
while (1) {

		/*
		 * Read packet from RX queues
		 */
		for (i = 0; i < qconf->n_rx_queue; i++) {

			portid = qconf->rx_queue_list[i];
			nb_rx = rte_eth_rx_burst(portid, 0, pkts_burst,
						 MAX_PKT_BURST);

			/* Prefetch first packets */
			for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) {
				rte_prefetch0(rte_pktmbuf_mtod(
						pkts_burst[j], void *));
			}

			/* Prefetch and forward already prefetched packets */
			for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
				rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
						j + PREFETCH_OFFSET], void *));
				mcast_forward(pkts_burst[j], qconf);
			}

			/* Forward remaining prefetched packets */
			for (; j < nb_rx; j++) {
				mcast_forward(pkts_burst[j], qconf);
			}
		}

		/* Send out packets from TX queues */
		send_timeout_burst(qconf);
	}