gpt4 book ai didi

c++ - 同时使用非原子和原子操作

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:08:27 25 4
gpt4 key购买 nike

我有一个线程池,每个线程都包含一个计数器(基本上是 TLS)。

主线程需要通过计算所有线程本地计数器的总和来频繁更新。

大多数时候,每个线程都会递增自己的计数器,因此不需要同步。

但是在主线程更新的时候,我当然需要某种同步。

我想出了 MSVS 内在函数(_InterlockedXXX 函数),它表现出了出色的性能(在我的测试中大约 0.8 秒)但是,它将我的代码限制在 MSVC 编译器和 X86/AMD64 平台上,但是是否有一种 C++ 可移植的方法来做到这一点?

  • 我尝试将 int 类型更改为 std::atomic<int>对于柜台,使用 std::memory_order_relaxed对于增量,但这个解决方案非常慢! (~ 4 秒)

  • 使用基础成员时std::atomic<T>::_My_val ,该值是按我希望的那样以非原子方式访问的,但它也不可移植,所以问题是一样的......

  • 使用单个 std::atomic<int>由于竞争激烈(~ 10 秒),所有线程共享甚至更慢

你有什么想法吗?也许我应该使用图书馆(提升)?还是编写我自己的类?

最佳答案

std::atomic<int>::fetch_add(1, std::memory_order_relaxed)_InterlockedIncrement 一样快.

Visual Studio 将前者编译为 lock add $1 (或等同物),后者为 lock inc ,但执行时间没有区别;在我的系统(Core i5 @3.30 GHz)上,每个都需要 5630 ps/op,大约 18.5 个周期。

使用 Benchpress 的微基准测试:

#define BENCHPRESS_CONFIG_MAIN
#include "benchpress/benchpress.hpp"
#include <atomic>
#include <intrin.h>

std::atomic<long> counter;
void f1(std::atomic<long>& counter) { counter.fetch_add(1, std::memory_order_relaxed); }
void f2(std::atomic<long>& counter) { _InterlockedIncrement((long*)&counter); }
BENCHMARK("fetch_add_1", [](benchpress::context* ctx) {
auto& c = counter; for (size_t i = 0; i < ctx->num_iterations(); ++i) { f1(c); }
})
BENCHMARK("intrin", [](benchpress::context* ctx) {
auto& c = counter; for (size_t i = 0; i < ctx->num_iterations(); ++i) { f2(c); }
})

输出:

fetch_add_1                           200000000        5634 ps/op
intrin 200000000 5637 ps/op

关于c++ - 同时使用非原子和原子操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36544855/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com