可能导致性能瓶颈的原因
- 缓存争用:多个线程频繁访问和修改同一个原子变量,导致CPU缓存一致性协议开销增大,例如MESI协议下频繁的缓存无效化操作。
- 总线竞争:原子操作需要通过系统总线进行同步,高并发时总线成为瓶颈,因为同一时刻只能有一个CPU核心对共享内存进行写操作。
优化原子操作性能的方法
- 减少原子操作频率:将多个小的原子操作合并为一个大的原子操作,减少同步开销。
- 使用无锁数据结构:例如无锁队列、无锁哈希表等,通过更细粒度的控制避免全局锁带来的性能损耗。
- 基于线程本地存储(TLS):每个线程维护自己的本地计数器,最后再汇总到全局原子变量,减少对原子变量的竞争。
基于线程本地存储(TLS)优化的代码示例(以C++为例)
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
std::atomic<size_t> totalProcessedBytes(0);
// 线程本地存储计数器
thread_local size_t localProcessedBytes = 0;
void processFilePart(size_t start, size_t end) {
// 模拟处理文件部分内容
for (size_t i = start; i < end; ++i) {
localProcessedBytes++;
}
// 将线程本地计数器的值累加到全局原子变量
totalProcessedBytes += localProcessedBytes;
}
int main() {
const size_t numThreads = 4;
const size_t fileSize = 1000000;
const size_t partSize = fileSize / numThreads;
std::vector<std::thread> threads;
for (size_t i = 0; i < numThreads; ++i) {
size_t start = i * partSize;
size_t end = (i == numThreads - 1)? fileSize : (i + 1) * partSize;
threads.emplace_back(processFilePart, start, end);
}
for (auto& thread : threads) {
thread.join();
}
std::cout << "Total processed bytes: " << totalProcessedBytes << std::endl;
return 0;
}