我正在查看 n4713 C++ 标准中的 8.4.4.1:
void f() {
float x, &r = x;
[=] {
decltype(x) y1; // y1 has type float
decltype((x)) y2 = y1; // y2 has type float const& because this lambda is not mutable and x is an lvalue
decltype(r) r1 = y1; // r1 has type float&
decltype((r)) r2 = y2; // r2 has type float const&
};
}
Run Code Online (Sandbox Code Playgroud)
标准说 r2 有 type float const&,然后我尝试打印出类型:
#include <iostream>
template <class T>
void print_type() {
std::cout …Run Code Online (Sandbox Code Playgroud) 我在 GCC 10.0 和 Clang 10.0 中尝试了以下代码:
template <template <typename> typename>
struct Foo {
Foo() { std::cout << "generic" << std::endl; }
};
template <typename>
struct Bar {};
template <typename T>
using Fake_Bar = Bar<T>;
template <>
struct Foo<Bar> {
Foo() { std::cout << "specialization" << std::endl; }
};
int main() {
Foo<Bar> a;
Foo<Fake_Bar> b;
}
Run Code Online (Sandbox Code Playgroud)
他们给出了不同的输出:
海湾合作委员会:
specialization
specialization
Run Code Online (Sandbox Code Playgroud)
铛:
specialization
generic
Run Code Online (Sandbox Code Playgroud)
根据 C++17 标准,哪一个是正确的?规则是什么?
与此类似帖子,我想创建一个名为共享内存段(通过创建shm_open()+ mmap()特定的NUMA节点(不一定是本地)上的CentOS 7).该帖子建议通过使用来实现numa_move_pages().
我还有几个问题:
如果另一个进程(在不同NUMA的本地核心上运行)稍后启动并且mmap()s到同一个命名的共享内存段,OS是否会决定将命名的共享内存段移动到此进程的本地NUMA?如果是,我该如何预防呢?
是否还有其他情况,在我指定后,命名共享内存段将被移动到另一个NUMA numa_move_pages()?
给定一个命名的共享内存段/shm/dev,如何检查它属于哪个NUMA节点?
我查看了numactl,它的--membind选项是我想要的,但我不确定如果两个不同的进程使用--membind2个不同的节点会产生什么影响.谁赢?如果#3得到解答,我想我可以测试一下.
谢谢!
#include <iostream>
#include <vector>
template<typename Container, typename Index>
decltype(auto)
foo(Container&& c, Index i) {
return std::forward<Container>(c)[i];
}
template<typename Container, typename Index>
decltype(auto)
bar(Container&& c, Index i) {
return c[i];
}
int main() {
std::vector<uint32_t> q{1, 3, 5};
std::vector<uint32_t> r{2, 4, 6};
std::cout << "lvalue" << std::endl;
std::cout << foo(q, 1) << std::endl;
std::cout << bar(q, 1) << std::endl;
std::cout << "rvalue" << std::endl;
std::cout << foo(std::move(q), 1) << std::endl;
std::cout << bar(std::move(r), 1) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
foo()和的返回类型有什么区别bar()? …
我有以下代码:
#include <atomic>
int main () {
std::atomic<uint32_t> value(0);
value.fetch_add(1, std::memory_order::relaxed);
static_assert(std::atomic<uint32_t>::is_always_lock_free);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它可以编译,所以这意味着std::atomic<uint32_t>::is_always_lock_free是真的。
然后,使用 gcc 10 和 的汇编代码如下所示-std=c++20 -O3 -mtune=skylake-avx512 -march=skylake-avx512:
0000000000401050 <main>:
401050: c7 44 24 fc 00 00 00 mov DWORD PTR [rsp-0x4],0x0
401057: 00
401058: f0 ff 44 24 fc lock inc DWORD PTR [rsp-0x4]
40105d: 31 c0 xor eax,eax
40105f: c3 ret
Run Code Online (Sandbox Code Playgroud)
许多帖子指出,读-修改-写操作(fetch_add()此处)不能是没有锁的原子操作。
我的问题是std::atomic::is_always_lock_free存在的true真正含义是什么。
该页面说明Equals true if this atomic type is …
我正在使用 boost 1.63,当我编译包含#include <boost/algorithm/string.hpp>.
海湾合作委员会抱怨:
In file included from /opt/boost/boost/mpl/aux_/na_assert.hpp:23,
from /opt/boost/boost/mpl/arg.hpp:25,
from /opt/boost/boost/mpl/placeholders.hpp:24,
from /opt/boost/boost/iterator/iterator_categories.hpp:17,
from /opt/boost/boost/iterator/iterator_facade.hpp:14,
from /opt/boost/boost/range/iterator_range_core.hpp:27,
from /opt/boost/boost/range/iterator_range.hpp:13,
from /opt/boost/boost/range/as_literal.hpp:22,
from /opt/boost/boost/algorithm/string/trim.hpp:19,
from /opt/boost/boost/algorithm/string.hpp:19,
from [my source that includes <boost/algorithm/string.hpp>]
/opt/boost/boost/mpl/assert.hpp:188:21: warning: unnecessary parentheses in declaration of ‘assert_arg’ [-Wparentheses]
failed ************ (Pred::************
^
/opt/boost/boost/mpl/assert.hpp:193:21: warning: unnecessary parentheses in declaration of ‘assert_not_arg’ [-Wparentheses]
failed ************ (boost::mpl::not_<Pred>::************
^
Run Code Online (Sandbox Code Playgroud)
我查看了来源,抱怨部分是:
template< typename Pred >
failed ************ (Pred::************
assert_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type )
);
template< typename Pred …Run Code Online (Sandbox Code Playgroud) 我阅读了 C++ 标准 (n4713) 的 § 32.6.1 3:
无锁的操作也应该是无地址的。也就是说,通过两个不同地址对同一内存位置的原子操作将进行原子通信。实现不应依赖于任何每个进程的状态。此限制允许通过多次映射到进程的内存和在两个进程之间共享的内存进行通信。
所以听起来可以在同一内存位置执行无锁原子操作。我想知道怎么做。
假设我在 Linux 上有一个命名的共享内存段(通过 shm_open() 和 mmap())。例如,如何对共享内存段的前 4 个字节执行无锁操作?
起初,我以为我可以只reinterpret_cast指向std::atomic<int32_t>*. 但后来我读到了这个。它首先指出 std::atomic 可能没有相同大小的 T 或对齐:
当我们设计 C++11 原子时,我误以为可以使用诸如
int x; reinterpret_cast<atomic<int>&>(x).fetch_add(1);
Run Code Online (Sandbox Code Playgroud)
如果 atomic 和 int 的表示不同,或者它们的对齐方式不同,这显然会失败。但我知道这在我关心的平台上不是问题。而且,在实践中,我可以通过在编译时检查大小和对齐方式匹配来轻松测试问题。
Tho,在这种情况下对我来说很好,因为我在同一台机器上使用共享内存,并且在两个不同的进程中投射指针将“获取”相同的位置。但是,文章指出编译器可能不会将强制转换的指针视为指向原子类型的指针:
然而,这不能保证是可靠的,即使在人们可能期望它工作的平台上,因为它可能会混淆编译器中基于类型的别名分析。编译器可能会假设 int 也不会作为
atomic<int>. (见 3.10,[Basic.lval],最后一段。)
欢迎任何输入!
std::memory_order::relaxed在C ++ Standard 中滥用的示例之一:
std::atomic<int> x{0};
int a[] = {1,2};
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) {
x.fetch_add(1, std::memory_order::relaxed);
// spin wait for another iteration to change the value of x
while (x.load(std::memory_order::relaxed) == 1) { } // incorrect: assumes execution order
});
Run Code Online (Sandbox Code Playgroud)
然后说,
上面的示例取决于迭代的执行顺序,并且如果两个迭代均在同一执行线程上顺序执行,则不会终止。
问题:
注释说:“不正确:假定执行顺序”。什么是“假定执行顺序”?我想念它。
“以上示例取决于迭代的执行顺序”中的“迭代”指的是什么?这是否意味着while循环中的迭代?还是指迭代std::for_each?
如果的迭代std::for_each由不同的线程并行执行,那么迭代/线程之一不会退出仍然不是真的吗?因为x.fetch_add(1, std::memory_order::relaxed)是原子的,所以一个线程将生成x1,另一个线程将生成x2,并且两个线程的x == 1都是不可能的。没有?
uint8_t,uint16_t,uint32_t,uint64_t?如果是,那么定义的行为是什么(来自C++标准的摘录非常感谢)int8_t,int16_t,int32_t,int64_t?(摘自C++标准非常感谢)我看到这篇文章的第一个答案提到我的问题#1,它是用C标准定义的,虽然他没有引用它,我在C++标准中找不到任何东西.
=================
更新1:
因为它是错误的术语而删除了每次"下溢"(感谢@ach).添加了#5来表达我对"下溢"的真正含义(错误)