我一直在分析TCP延迟(特别是write
从一个小消息的用户空间到内核空间),以便对a的延迟有一些直觉write
(确认这可能是特定于上下文的).我注意到测试之间存在很大的不一致,这对我来说似乎很相似,而且我很想知道差异来自何处.我知道微基准测试可能会有问题,但我仍然觉得我缺少一些基本的理解(因为延迟差异是~10倍).
设置是我有一个C++ TCP服务器接受一个客户端连接(来自同一CPU上的另一个进程),并且在与客户端连接时write
,对套接字进行20次系统调用,一次发送一个字节.服务器的完整代码将在本文末尾复制.这是每次write
使用的输出boost/timer
(增加~1 mic的噪音):
$ clang++ -std=c++11 -stdlib=libc++ tcpServerStove.cpp -O3; ./a.out
18 mics
3 mics
3 mics
4 mics
3 mics
3 mics
4 mics
3 mics
5 mics
3 mics
...
Run Code Online (Sandbox Code Playgroud)
我可靠地发现第一个write
明显慢于其他人.如果我write
在计时器中包装10,000个呼叫,平均每个2微秒write
,但第一个呼叫总是15个以上的话筒.为什么会出现这种"变暖"现象?
相关地,我运行了一个实验,在每个write
调用之间我做一些阻止CPU工作(计算一个大的素数).这会导致所有的write
调用是缓慢的:
$ clang++ -std=c++11 -stdlib=libc++ tcpServerStove.cpp -O3; ./a.out
20 mics
23 mics
23 mics
30 mics
23 mics
21 mics
21 mics
22 mics
22 …
Run Code Online (Sandbox Code Playgroud) 我在尝试使用 torch.multiprocessing 实现 Hogwild 时遇到了一个神秘的错误。特别是,代码的一个版本运行良好,但是当我在多处理步骤之前添加看似无关的代码位时,这会在多处理步骤中以某种方式导致错误:RuntimeError: Unable to handle autograd's threading in combination with fork-based multiprocessing. See https://github.com/pytorch/pytorch/wiki/Autograd-and-Fork
我在下面粘贴的最小代码示例中重现了错误。如果我注释掉m0 = Model(); train(m0)
在单独的模型实例上执行非并行训练的两行代码,那么一切运行正常。我无法弄清楚这些行是如何导致问题的。
我在 Linux 机器上运行 PyTorch 1.5.1 和 Python 3.7.6,仅在 CPU 上进行训练。
import torch
import torch.multiprocessing as mp
from torch import nn
def train(model):
opt = torch.optim.Adam(model.parameters(), lr=1e-5)
for _ in range(10000):
opt.zero_grad()
# We train the model to output the value 4 (arbitrarily)
loss = (model(0) - 4)**2
loss.backward()
opt.step()
# Toy model with one parameter tensor …
Run Code Online (Sandbox Code Playgroud) python machine-learning multiprocessing deep-learning pytorch
在各种情况下,我观察到链表迭代在C++中始终比在Go中慢10-15%.我在Stack Overflow上解决这个谜团的第一次尝试就在这里.我编码的例子有问题,因为:
1)由于堆分配,内存访问是不可预测的,并且
2)因为没有实际工作,一些人的编译器正在优化主循环.
为解决这些问题,我有一个新程序,包含C++和Go中的实现.C++版本需要1.75秒,而Go版本需要1.48秒.这次,我在计时开始之前做了一个大的堆分配,并用它来操作一个对象池,我从该对象池中释放并获取链表的节点.这样,内存访问应该在两个实现之间完全类似.
希望这使得神秘更具可重复性!
C++:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <boost/timer.hpp>
using namespace std;
struct Node {
Node *next; // 8 bytes
int age; // 4 bytes
};
// Object pool, where every free slot points to the previous free slot
template<typename T, int n>
struct ObjPool
{
typedef T* pointer;
typedef pointer* metapointer;
ObjPool() :
_top(NULL),
_size(0)
{
pointer chunks = new T[n];
for (int i=0; i < n; …
Run Code Online (Sandbox Code Playgroud) 有一个开放的Git问题,请求使用道具来对齐菜单项.与此同时,将一些Navbar项目(例如登录,注销)移动到右侧的正确方法是什么?
这里有一个菜单的示例代码,其中所有菜单项都在左侧.
import { Menu, Icon } from 'antd';
const SubMenu = Menu.SubMenu;
const MenuItemGroup = Menu.ItemGroup;
class App extends React.Component {
state = {
current: 'mail',
}
handleClick = (e) => {
console.log('click ', e);
this.setState({
current: e.key,
});
}
render() {
return (
<Menu
onClick={this.handleClick}
selectedKeys={[this.state.current]}
mode="horizontal"
>
<Menu.Item key="mail">
<Icon type="mail" />Navigation One
</Menu.Item>
<Menu.Item key="app" disabled>
<Icon type="appstore" />Navigation Two
</Menu.Item>
<SubMenu title={<span><Icon type="setting" />Navigation Three - Submenu</span>}>
<MenuItemGroup title="Item 1">
<Menu.Item key="setting:1">Option 1</Menu.Item> …
Run Code Online (Sandbox Code Playgroud) 我有一个用于EC2 HTTP服务器的CloudFront分发版.我使用WAF为我的CloudFront分配创建了速率限制.理论上,任何IP地址都不能在任何5分钟内发送超过2,000个请求.但这似乎不起作用.我在<1分钟内从我的笔记本电脑(使用Go程序)发出10,000个并发请求,所有这些请求都通过了.我知道他们正在达到EC2原点,因为我的HTTP服务器保留了一个请求计数器.
奇怪的是,WAF仪表板甚至可以识别出流量超过了5分钟的限制:
我的EC2服务器注册了所有10,000次点击.
我错过了一些配置的细微之处吗?或者,在CloudFront注册流量峰值和实施IP块之间是否存在长时间延迟?
当我键入一个左括号后跟一个换行符时,我希望光标自动缩进一个制表符值 - 与打开大括号或左方括号的方式相同。出于某种原因,它缩进了两个制表符值。
我对让它对 .dart 文件正常工作特别感兴趣。
这是我的 .vimrc:
set tabstop=2
set softtabstop=2
set shiftwidth=2
set autoindent
set expandtab
Run Code Online (Sandbox Code Playgroud)
我错过了什么?谢谢你。
编辑:在得到一些反馈后,我创建了一个新的例子,它应该更具可重复性.
我一直在用C++编写一个涉及大量链表迭代的项目.为了获得基准,我在Go中重写了代码.令人惊讶的是,我发现即使将-O标志传递给clang ++之后,Go实现仍然以大约10%的速度运行.可能我只是错过了C++中的一些明显的优化,但是我一直在用一些调整来敲打墙壁.
这是一个简化版本,在C++和Go中具有相同的实现,其中Go程序运行得更快.它所做的只是创建一个包含3000个节点的链表,然后计算在此列表上迭代1,000,000次所需的时间(在C++中为7.5秒,在Go中为6.8).
C++:
#include <iostream>
#include <chrono>
using namespace std;
using ms = chrono::milliseconds;
struct Node {
Node *next;
double age;
};
// Global linked list of nodes
Node *nodes = nullptr;
void iterateAndPlace(double age) {
Node *node = nodes;
Node *prev = nullptr;
while (node != nullptr) {
// Just to make sure that age field is accessed
if (node->age > 99999) {
break;
}
prev = node;
node = node->next;
}
// Arbitrary action …
Run Code Online (Sandbox Code Playgroud) 假设我正在存储一个对象的链接列表,每个对象都是一个大小为 64 字节的结构,这也是我的缓存行的大小。随着时间的推移,我将在链接列表上进行延迟敏感的添加、删除和迭代。据我所知,性能主要取决于对象是否保存在缓存中,因此 RAM 访问的访问量约为 1 纳秒,而不是 > 50 纳秒。
通常建议通过空间局部性来实现这一点,最好将对象存储在连续的内存块中。这很有用,因为每当我访问内存地址时,处理器实际上都会提取缓存行的数据;我们希望这些附加数据成为其他有用的对象,因此我们将所有对象放在一个连续的块中。
我可能会误解,但如果对象大小 >= 缓存行大小,我们似乎不会从这种效果中受益。一次只能将一个对象放入缓存中。
我有一个函数,它接受一个函数指针作为参数。令人惊讶的是,我可以传入一个函数指针和一个普通函数:
#include <iostream>
#include <functional>
int triple(int a) {
return 3*a;
}
int apply(int (*f)(int), int n) {
return f(n);
}
int main() {
std::cout << apply(triple, 7) << "\n";
std::cout << apply(&triple, 7) << "\n";
}
Run Code Online (Sandbox Code Playgroud)
我很困惑为什么这有效。是否存在从函数到函数指针的隐式转换?
I am trying to implement truncated backpropagation through time in PyTorch, for the simple case where K1=K2
. I have an implementation below that produces reasonable output, but I just want to make sure it is correct. When I look online for PyTorch examples of TBTT, they do inconsistent things around detaching the hidden state and zeroing out the gradient, and the ordering of these operations. Please let me know if I have made a mistake.
在下面的代码中,H
维护当前隐藏状态,并model(weights, …
c++ ×4
optimization ×3
go ×2
pytorch ×2
antd ×1
auto-indent ×1
c ×1
cpu-cache ×1
function ×1
linux-kernel ×1
performance ×1
python ×1
reactjs ×1
tcp ×1
vim ×1