我在一个系统std::fill上观察到,与常量值或动态值相比,std::vector<int>设置常量值时,大型系统显着且持续地较慢:01
5.8 GiB/s vs 7.5 GiB/s
但是,对于较小的数据大小,结果是不同的,其中fill(0)更快:
对于4个GiB数据大小的多个线程,fill(1)显示更高的斜率,但达到的峰值远低于fill(0)(51 GiB/s对90 GiB/s):
这提出了次要问题,为什么峰值带宽fill(1)要低得多.
测试系统是一个双插槽Intel Xeon CPU E5-2680 v3,设置为2.5 GHz(通道/sys/cpufreq),带有8x16 GiB DDR4-2133.我使用GCC 6.1.0(-O3)和英特尔编译器17.0.1(-fast)进行了测试,结果都相同.GOMP_CPU_AFFINITY=0,12,1,13,2,14,3,15,4,16,5,17,6,18,7,19,8,20,9,21,10,22,11,23被设定了.Strem/add/24个线程在系统上获得85 GiB/s.
我能够在不同的Haswell双插槽服务器系统上重现这种效果,但没有任何其他架构.例如在Sandy Bridge EP上,内存性能是相同的,而在缓存fill(0)中则要快得多.
这是重现的代码:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <omp.h>
#include <vector>
using value = int;
using vector = std::vector<value>;
constexpr size_t write_size = 8ll * 1024 * 1024 * 1024;
constexpr size_t …Run Code Online (Sandbox Code Playgroud) 在Richard Reese所着的"理解和使用C指针"一书中,它在第85页说
Run Code Online (Sandbox Code Playgroud)int vector[5] = {1, 2, 3, 4, 5};生成的代码与生成的代码
vector[i]不同*(vector+i).该表示法vector[i]生成从位置向量开始的机器代码,从该位置移动i位置,并使用其内容.符号*(vector+i)生成的机器代码从位置开始vector,添加i到地址,然后使用该地址的内容.结果相同,生成的机器代码不同.这种差异对大多数程序员来说很少有意义.
你可以在这里看到摘录.这段经文是什么意思?在什么情况下,任何编译器都会为这两个编译器生成不同的 "移动"与基础之间是否存在差异,而"添加"基数是否存在差异?我无法让它在GCC上工作 - 生成不同的机器代码.
一般概念似乎与正确使用的拥有原始指针相比没有时间开销,只要std::unique_ptr有足够的优化.
但是std::unique_ptr,特别是在复合数据结构中使用std::vector<std::unique_ptr<T>>呢?例如,调整矢量的基础数据的大小,这可能发生在push_back.各地要隔离性能,我环路pop_back,shrink_to_fit,emplace_back:
#include <chrono>
#include <vector>
#include <memory>
#include <iostream>
constexpr size_t size = 1000000;
constexpr size_t repeat = 1000;
using my_clock = std::chrono::high_resolution_clock;
template<class T>
auto test(std::vector<T>& v) {
v.reserve(size);
for (size_t i = 0; i < size; i++) {
v.emplace_back(new int());
}
auto t0 = my_clock::now();
for (int i = 0; i < repeat; i++) {
auto back = std::move(v.back()); …Run Code Online (Sandbox Code Playgroud) 是否有可能在bash中拦截一个SIGINT,做一些事情,然后忽略它(保持bash运行).
我知道我可以忽略SIGINT
trap '' SIGINT
Run Code Online (Sandbox Code Playgroud)
我也可以用sigint做点什么
trap handler SIGINT
Run Code Online (Sandbox Code Playgroud)
但是在handler执行之后仍然会停止脚本.例如
#!/bin/bash
handler()
{
kill -s SIGINT $PID
}
program &
PID=$!
trap handler SIGINT
wait $PID
#do some other cleanup with results from program
Run Code Online (Sandbox Code Playgroud)
当我按下ctrl + c时,将发送SIGINT to program,但bash将跳过waitBEFORE程序正确关闭并在其信号处理程序中创建其输出.
使用@suspectus答案我可以wait $PID改为:
while kill -0 $PID > /dev/null 2>&1
do
wait $PID
done
Run Code Online (Sandbox Code Playgroud)
这实际上对我有用我只是不是100%确定这是'干净'还是'肮脏的解决方法'.
当使用std::minmax结构化绑定时,我遇到了一个相当微妙的错误.似乎传递的rvalues并不总是像人们期望的那样被复制.最初我T operator[]() const在自定义容器上使用a ,但它似乎与文字整数相同.
#include <algorithm>
#include <cstdio>
#include <tuple>
int main()
{
auto [amin, amax] = std::minmax(3, 6);
printf("%d,%d\n", amin, amax); // undefined,undefined
int bmin, bmax;
std::tie(bmin, bmax) = std::minmax(3, 6);
printf("%d,%d\n", bmin, bmax); // 3,6
}
Run Code Online (Sandbox Code Playgroud)
使用GCC 8.1.1 -O1 -Wuninitialized将导致0,0打印为第一行,并且:
warning: ‘<anonymous>’ is used uninitialized in this function [-Wuninitialized]
Run Code Online (Sandbox Code Playgroud)
Clang 6.0.1 at -O2也会在没有警告的情况下给出错误的第一个结果.
在-O0GCC给出正确的结果而没有警告.对于clang,结果似乎是正确的-O1或-O0.
在rvalue仍然有效被复制的意义上,第一行和第二行不应该是等价的吗?
另外,为什么这取决于优化级别?特别是我对GCC没有发出任何警告感到惊讶.
需要澄清我对发送类型中给出的isend和issend的理解
我的理解是,一旦发送缓冲区空闲,即所有数据都被释放后,isend将返回.另一方面,Issend仅在收到获取/未获取整个数据的确认时才返回.这就是全部吗?
请考虑以下代码:
namespace foo {
namespace bar {
class foo {};
}
class baz {};
}
using namespace foo::bar;
::foo::baz mybaz;
Run Code Online (Sandbox Code Playgroud)
这段代码有效吗?还是::foo含糊不清?或者::foo指的class foo是,没有::foo::baz.
谈到编译器,gcc 6.1.1似乎认为后者:
scope.cpp:9:8: error: ‘baz’ in ‘class foo::bar::foo’ does not name a type
::foo::baz mybaz;
^~~
Run Code Online (Sandbox Code Playgroud)
另一方面gcc 5.3.1,clang 3.8.0并且intel编译器16.0.3不会产生任何警告或错误.
我怀疑在C++ 14标准的3.4.3.2.2下,这应该是有效的而不是含糊不清的,但我不太确定.
编辑:此外,foo::baz mybaz只有clang报告一个模棱两可的错误.
我有两个Python CLI工具,它们共享一组常用的click.options。目前,通用选项已重复:
@click.command()
@click.option('--foo', is_flag=True)
@click.option('--bar', is_flag=True)
@click.option('--unique-flag-1', is_flag=True)
def command_one():
pass
@click.command()
@click.option('--foo', is_flag=True)
@click.option('--bar', is_flag=True)
@click.option('--unique-flag-2', is_flag=True)
def command_two():
pass
Run Code Online (Sandbox Code Playgroud)
是否可以将通用选项提取到可以应用于每个功能的单个装饰器中?
import unittest
from typing import *
T = TypeVar("T", bound=unittest.TestCase)
def decorate(func: Callable[[T], None]) -> Callable[[T], None]:
def decorated_function(self: T) -> None:
return func(self)
return decorated_function
Run Code Online (Sandbox Code Playgroud)
现在我什至有一个生成器来创建这些装饰器并想要速记这些装饰器。我对存储装饰器的变量使用什么类型(省略生成器的简化示例)。
my_decorate: Callable[[Callable[[T], None]], Callable[[T], None]] = decorate
Run Code Online (Sandbox Code Playgroud)
这可行,但很笨拙。所以问题是:
如何为该类型别名以避免编写完整签名?
不起作用的事情:
TD = Callable[[Callable[[T], None]], Callable[[T], None]]
my_decorate: TD[T] = decorator_variable
Run Code Online (Sandbox Code Playgroud)
给出错误
error: Type variable "mypytest.T" is unbound
note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class)
note: (Hint: Use "T" in function signature …Run Code Online (Sandbox Code Playgroud) 我试图了解linux perf,发现一些非常令人困惑的行为:
我写了一个简单的多线程示例,其中一个线程固定到每个核心; 每个线程在本地运行计算,并且不相互通信(见test.cc下文).我在想这个例子应该有非常低的(如果不是零)上下文切换.但是,使用linux perf来分析示例显示了数千个上下文切换 - 远远超出了我的预期.我进一步分析了linux命令sleep 20以进行比较,显示更少的上下文切换.
此个人资料结果对我没有任何意义.什么导致如此多的上下文切换?
> sudo perf stat -e sched:sched_switch ./test
Performance counter stats for './test':
6,725 sched:sched_switch
20.835 seconds time elapsed
> sudo perf stat -e sched:sched_switch sleep 20
Performance counter stats for 'sleep 20':
1 sched:sched_switch
20.001 seconds time elapsed
Run Code Online (Sandbox Code Playgroud)
要重现结果,请运行以下代码:
perf stat -e context-switches sleep 20
perf stat -e context-switches ./test
Run Code Online (Sandbox Code Playgroud)
要编译源代码,请输入以下代码:
g++ -std=c++11 -pthread -o test test.cc
Run Code Online (Sandbox Code Playgroud)
// test.cc
#include <iostream>
#include <thread>
#include <vector> …Run Code Online (Sandbox Code Playgroud)