---
title: 注意处理器差异
description: "除了架构差异之外，在锁的移植过程中还要注意处理器的差异。x86架构下大部分处理器L3 cache的Cacheline大小一般为64字节，而鲲鹏920处理器的L3 cache Cacheline大小为128字节，所以在设计锁的数据结构时要格外注意，尽量避免多线程相互独立修改的变量共享同一个Cacheline的情况出现，即通常说的“伪共享”现象——这对性能有较大的影响。"
url: https://www.hikunpeng.com/document/detail/zh/kunpenggrf/codeprtr/kunpengtaishanporting_12_0052.html
sourcePath: /source/zh/kunpenggrf/codeprtr/kunpengtaishanporting_12_0052.html
indexId: b2b0f31b4c0045255aa8291bce60f63502f022b9b1f62ff42af00e0d0acfe1e665
---
# 注意处理器差异

除了架构差异之外，在锁的移植过程中还要注意处理器的差异。x86架构下大部分处理器L3 cache的Cacheline大小一般为64字节，而鲲鹏920处理器的L3 cache Cacheline大小为128字节，所以在设计锁的数据结构时要格外注意，尽量避免多线程相互独立修改的变量共享同一个Cacheline的情况出现，即通常说的“伪共享”现象——这对性能有较大的影响。

下面举一个Linux内核中的优化案例进行说明。这是Linux内核iommu驱动中针对ARM平台进行优化的一个补丁（参考链接：https://gitlab.freedesktop.org/drm/msm/commit/14bd9a607f9082e7b5690c27e69072f2aeae0de4(https://gitlab.freedesktop.org/drm/msm/commit/14bd9a607f9082e7b5690c27e69072f2aeae0de4)），优化前的代码如下所示：

```
struct iova_domain {
/* ………… */
struct iova anchor;
struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE];
iova_flush_cb   flush_cb;
iova_entry_dtor entry_dtor;
/* Number of TLB flushes that have been started */
atomic64_t  fq_flush_start_cnt;
/* Number of TLB flushes that have been finished */
atomic64_t  fq_flush_finish_cnt;
struct timer_list fq_timer;
/* 1 when timer is active, 0 when not */
atomic_t fq_timer_on;
};
```

在这个数据结构中，多线程访问的变量主要是原子类型的fq_flush_start_cnt、fq_flush_finish_cnt和atomic_t fq_timer_on。为了避免伪共享现象，我们需要尽量避免这些变量分布在同一个cacheline上。在cacheline为64B的情况下，通过在fq_flush_finish_cnt和fq_timer_on之间插入一个fq_timer变量，就可以达到这个目的。

但是当处理器的cacheline变成128B的情况下，这个处理不足以满足要求，所以我们需要进一步调整数据结构——在原子变量之间插入更多的变量使得fq_flush_finish_cnt和fq_timer_on分布在不同的cacheline上，优化后的代码如下所示：

```
struct iova_domain {
……
/* Number of TLB flushes that have been started */
atomic64_t  fq_flush_start_cnt;
/* Number of TLB flushes that have been finished */
atomic64_t  fq_flush_finish_cnt;
struct iova anchor;
struct iova_rcache rcaches[IOVA_RANGE_CACHE_MAX_SIZE];
iova_flush_cb   flush_cb;
iova_entry_dtor entry_dtor;
struct timer_list fq_timer;
/* 1 when timer is active, 0 when not */
atomic_t fq_timer_on;
};
```
