小编Ale*_*iev的帖子

我可以用“using”声明类型 [[nodiscard]] 吗?

您可以使用该属性声明一个类[[nodiscard]]。当您从此类的语义中知道每当它从函数返回时,它必须用于某些用途时,它可能会很有用。[[nodiscard]]我正是遇到这种情况,用它来标记类而不是返回它的每个单独的函数会非常方便。然而,有一个复杂的问题。这是我需要制作的类型[[nodiscard]]:

using ConnectionStruct = std::pair<std::shared_ptr<CMutex>, std::shared_ptr<SignalFunction>>;
Run Code Online (Sandbox Code Playgroud)

是否有语法将 my 标记ConnectionStruct为[[nodiscard]]?

c++ c++17 nodiscard

4
推荐指数
1
解决办法
485
查看次数

是否可以调试英特尔 TSX?

我想利用 Intel TSX 来编写无锁代码。

xbegin
my_inst1
my_inst2
xend
Run Code Online (Sandbox Code Playgroud)

但是,由于某些原因,我在 TSX 执行 TSX 中的一条指令中止。

我想知道哪条指令产生了错误并使 TSX 中止。

有没有办法知道哪个指令产生了错误?

我的第一次尝试是在 TSX 区域中执行每条指令后增加全局计数器。但是,当故障发生时,对计数器的更新也会回滚,因为它会回滚 TSX 区域中的每次写入。

有什么技巧可以调试 TSX 执行吗?

debugging x86 assembly intel intel-tsx

4
推荐指数
1
解决办法
179
查看次数

创建线程安全原子计数器

我在我的一个项目中有一个特定的要求,即保持某些操作的“计数”,并最终定期“读取”+“重置”这些计数器(例如24小时)。

操作将是:

  • 工作线程 -> 递增计数器(随机)
  • 计时器线程(例如 24 小时)-> 读取计数 -> 执行某些操作 -> 重置计数器

我感兴趣的平台是Windows,但是如果这个可以跨平台就更好了。我正在使用 Visual Studio,目标 Windows 架构仅是 x64。

我不确定结果是否“ok”以及我的实施是否正确。坦率地说,我从未使用过太多 std 包装器,而且我的 C++ 知识非常有限。

结果是:

12272 Current: 2
12272 After: 0
12272 Current: 18
12272 After: 0
12272 Current: 20
12272 After: 0
12272 Current: 20
12272 After: 0
12272 Current: 20
12272 After: 0
Run Code Online (Sandbox Code Playgroud)

下面是一个完全复制/粘贴的可重现示例:

12272 Current: 2
12272 After: 0
12272 Current: 18
12272 After: 0
12272 Current: 20
12272 After: 0
12272 Current: 20
12272 …
Run Code Online (Sandbox Code Playgroud)

c++ windows

4
推荐指数
1
解决办法
2278
查看次数

为什么错误共享仍然影响非原子,但远小于原子?

考虑以下证明错误共享存在的示例:

\n\n
using type = std::atomic<std::int64_t>;\n\nstruct alignas(128) shared_t\n{\n  type  a;\n  type  b;\n} sh;\n\nstruct not_shared_t\n{\n  alignas(128) type a;\n  alignas(128) type b;\n} not_sh;\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

一个线程a以 1 为步长递增,另一个线程以 1 为步长递增b。增量编译为lock xaddMSVC,即使结果未使用。

\n\n

a对于和分开的结构b,几秒钟内累积的值大约是 的not_shared_t十倍shared_t。

\n\n

到目前为止的预期结果:单独的缓存行在 L1d 缓存中保持热状态,增加lock xadd吞吐量瓶颈,错误共享是缓存行乒乓球的性能灾难。(编者注:更高版本的 MSVClock inc在启用优化时使用。这可能会扩大竞争与非竞争之间的差距。)

\n\n
\n\n

现在我using type = std::atomic<std::int64_t>;用普通的替换std::int64_t

\n\n

(非原子增量编译为inc QWORD PTR [rcx]。循环中的原子加载恰好阻止编译器将计数器保留在寄存器中,直到循环退出。)

\n\n

达到的计数not_shared_t仍大于 的计数shared_t,但现在少于两倍。 …

c++ x86 cpu-architecture cpu-cache false-sharing

3
推荐指数
1
解决办法
481
查看次数

英特尔 JCC 勘误表 - 真的应该单独对待 JCC 吗?

英特尔推送微码更新以修复名为“跳转条件代码 (JCC) 勘误表”的错误。由于在某些条件下禁用将代码放入 ICache,更新微码导致某些操作效率低下。

已发布的文档,标题为跳转条件代码勘误的缓解措施不仅列出了JCC,还列出了:无条件跳转、条件跳转、宏融合条件跳转、调用和返回。

MSVC 开关/QIntel-jcc-erratum文档提到:

在 /QIntel-jcc-erratum 下,编译器检测跨越或结束于 32 字节边界的跳转和宏融合跳转指令。

问题是:

  • 是否有理由将 JCC 与其他跳转分开处理?
  • 是否有理由将宏融合 JCC 与其他 JCC 分开处理?

x86 assembly intel cpu-architecture micro-architecture

3
推荐指数
1
解决办法
363
查看次数

除了提供必要的保证外,硬件内存屏障是否可以更快地了解原子操作?

TL;DR:在生产者-消费者队列中,放置一个不必要的(从 C++ 内存模型的角度来看)内存栅栏或不必要的强内存顺序是否有必要以牺牲可能更差的吞吐量为代价来获得更好的延迟?


C++ 内存模型是在硬件上执行的,方法是使用某种内存栅栏来实现更强的内存顺序,而不是将它们放在较弱的内存顺序上。

特别是,如果生产者这样做store(memory_order_release),而消费者使用 观察存储的值load(memory_order_acquire),则加载和存储之间没有围栏。在 x86 上根本没有栅栏,在 ARM 上栅栏是在存储之前和加载之后进行放置操作。

没有围栏存储的值最终会被没有围栏的负载观察到(可能在几次不成功的尝试之后)

我想知道在队列的两侧放置围栏是否可以更快地观察到值?如果有围栏和没有围栏,延迟是多少?

我希望只有一个循环load(memory_order_acquire)和pause/yield限制为数千次迭代是最好的选择,因为它无处不在,但想了解原因。

由于这个问题是关于硬件行为的,我希望没有通用的答案。如果是这样,我主要想知道 x86(x64 风格),其次是 ARM。


例子:

T queue[MAX_SIZE]

std::atomic<std::size_t>   shared_producer_index;

void producer()
{
   std::size_t private_producer_index = 0;

   for(;;)
   {
       private_producer_index++;  // Handling rollover and queue full omitted

       /* fill data */;

      shared_producer_index.store(
          private_producer_index, std::memory_order_release);
      // Maybe barrier here or stronger order above?
   }
}


void consumer()
{
   std::size_t private_consumer_index = 0;

   for(;;)
   {
       std::size_t observed_producer_index = shared_producer_index.load( …
Run Code Online (Sandbox Code Playgroud)

c++ x86 arm cpu-architecture memory-barriers

2
推荐指数
1
解决办法
192
查看次数

当外部基础类型未按要求对齐时的atomic_ref

我在p0019r8上读到以下内容:

atomic_ref(T& obj);
Run Code Online (Sandbox Code Playgroud)

要求:引用的对象应与 对齐required_alignment。

当未对齐时, cppreference将其解释为 UB:

如果 obj 未与 required_alignment 对齐,则行为未定义。


那么您期望实现如何处理它呢?

并且实现可以检查编译时 alignof,但实际上类型可能比对齐更对齐alignof。实现可以解释指针位并检查运行时对齐,但这是额外的运行时检查。

最终我看到以下选项:

  • 什么都不做 - 以令人不快的方式实现运行时未定义的行为,仅支持正确的使用
  • 检查编译时对齐 ( alignof) 并在错误时发出警告
  • 检查编译时对齐 ( alignof) ,如果错误不正确,则编译时失败,因为实际对齐可能大于静态类型可见的对齐
  • 检查编译时对齐 ( alignof),如果错误不正确,则在运行时失败,因为实际对齐可能大于静态类型可见的对齐
  • 检查编译时对齐 ( alignof) 并在错误时回退到基于锁
  • 检查运行时对齐(指针位),如果错误则在运行时失败
  • 检查运行时对齐(指针位),如果错误则回退到基于锁

c++ memory-alignment undefined-behavior stdatomic c++20

2
推荐指数
1
解决办法
332
查看次数

我需要在 2021 年使用 _mm256_zeroupper 吗?

摘自Agner Fog 的“用 C++ 优化软件”:

在某些 Intel 处理器上混合使用和不使用 AVX 支持编译的代码时会出现问题。由于 YMM 寄存器状态的变化,从 AVX 代码到非 AVX 代码会导致性能下降。在从 AVX 代码到非 AVX 代码的任何转换之前,应该通过调用内部函数 _mm256_zeroupper() 来避免这种惩罚。在以下情况下,这可能是必要的:

• 如果程序的一部分是使用 AVX 支持编译的,而程序的另一部分是在没有 AVX 支持的情况下编译的,则在离开 AVX 部分之前调用 _mm256_zeroupper()。

• 如果使用 CPU 调度在使用和不使用 AVX 的多个版本中编译函数,则在离开 AVX 部分之前调用 _mm256_zeroupper()。

• 如果一段使用AVX 支持编译的代码调用了编译器自带的库以外的库中的函数,而该库没有AVX 支持,则在调用库函数之前先调用_mm256_zeroupper()。

我想知道什么是英特尔处理器。具体来说,是否有过去五年制造的处理器。这样我就知道修复丢失的_mm256_zeroupper()电话是否为时已晚。

c++ sse simd intrinsics avx

2
推荐指数
1
解决办法
137
查看次数

React Native无法连接到Android中的SSE

我正在使用该包: https: //www.npmjs.com/package/react-native-sse

即使我从文档中复制粘贴代码,我也无法设法从 android 中的服务器接收事件。

import EventSource from "react-native-sse";

const es = new EventSource("https://your-sse-server.com/.well-known/mercure");

es.addEventListener("open", (event) => {
  console.log("Open SSE connection.");
});

es.addEventListener("message", (event) => {
  console.log("New message event:", event.data);
});

es.addEventListener("error", (event) => {
  if (event.type === "error") {
    console.error("Connection error:", event.message);
  } else if (event.type === "exception") {
    console.error("Error:", event.message, event.error);
  }
});

es.addEventListener("close", (event) => {
  console.log("Close SSE connection.");
});
Run Code Online (Sandbox Code Playgroud)
  • 反应本机:v0.65.1
  • 反应本机-sse:v1.1.0

我怎样才能让它发挥作用?

react-native

2
推荐指数
1
解决办法
3280
查看次数

分配器命名要求——例外

[分配器.要求.一般]/37

抛出: allocate可能抛出适当的异常。

其他地方暗示的“适当”有什么限制吗?

有效的自定义分配器可以double在任何请求上抛出 a 吗?


上下文:使用分配器的函数的实现noexcept,但具有后备策略,以便在所有分配失败时执行某些操作。

c++ allocator language-lawyer

2
推荐指数
1
解决办法
105
查看次数

C / C++ 错误:函数内指针变量未定义

根据我的 Java 经验,掌握这一点并不难。

一个非常简单的函数:

void update(float * p,float value)
{
    *p = value;
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨identifier p is undefined.

我认为*p会取消引用指针并在其中存储值。

c error-handling pointers function undefined

1
推荐指数
1
解决办法
1万
查看次数

在不同长度的字符串上将字符串编码为其 ASCII 表示形式

我想使用 ASCII 编码在 Go 中对字符串进行编码,就像下面的 C# 函数一样:

public static byte[] StrToByteArray(string str)
        {

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            return encoding.GetBytes(str);
        }
Run Code Online (Sandbox Code Playgroud)

我知道如何使用以下函数来做到这一点:

import (
        "encoding/ascii85"
    "fmt"
)
func main() {
        dst := make([]byte, 25, 25)
        dst2 := make([]byte, 25, 25)
        ascii85.Encode(dst, []byte("Hello, playground"))
        fmt.Println(dst) 
        ascii85.Decode(dst2, dst, false)
        fmt.Println(string(dst2))
}
Run Code Online (Sandbox Code Playgroud)

目前它的长度被硬编码为 25。如何根据字符串的大小调整长度?

go

1
推荐指数
1
解决办法
319
查看次数

内在向量与朴素向量约简结果的差异

我一直在比较 Intrinsics 向量缩减、朴素向量缩减和使用 openmp 编译指示的向量缩减的运行时间。然而,我发现这些场景的结果是不同的。代码如下 - (内在向量归约取自 - Fastest way to dohorizo​​ntal SSE vector sum(或其他归约))

#include <iostream>
#include <chrono>
#include <vector>
#include <numeric>
#include <algorithm>
#include <immintrin.h>


inline float hsum_ps_sse3(__m128 v) {
    __m128 shuf = _mm_movehdup_ps(v);        // broadcast elements 3,1 to 2,0
    __m128 sums = _mm_add_ps(v, shuf);
    shuf        = _mm_movehl_ps(shuf, sums); // high half -> low half
    sums        = _mm_add_ss(sums, shuf);
    return        _mm_cvtss_f32(sums);
}


float hsum256_ps_avx(__m256 v) {
    __m128 vlow  = _mm256_castps256_ps128(v);
    __m128 vhigh = _mm256_extractf128_ps(v, 1); // high …
Run Code Online (Sandbox Code Playgroud)

c++ vector simd intrinsics ieee-754

1
推荐指数
1
解决办法
122
查看次数