我正在研究单个生产者单个消费者环缓冲区实现.我有两个要求:
1)将单个堆分配的环形缓冲区实例与高速缓存行对齐.
2)将环形缓冲区内的字段与高速缓存行对齐(以防止错误共享).
我的班级看起来像:
#define CACHE_LINE_SIZE 64 // To be used later.
template<typename T, uint64_t num_events>
class RingBuffer { // This needs to be aligned to a cache line.
public:
....
private:
std::atomic<int64_t> publisher_sequence_ ;
int64_t cached_consumer_sequence_;
T* events_;
std::atomic<int64_t> consumer_sequence_; // This needs to be aligned to a cache line.
};
Run Code Online (Sandbox Code Playgroud)
让我首先解决第1点,即对齐单个堆分配的类实例.有几种方法:
1)使用c ++ 11 alignas(..)说明符:
template<typename T, uint64_t num_events>
class alignas(CACHE_LINE_SIZE) RingBuffer {
public:
....
private:
// All the private fields.
};
Run Code Online (Sandbox Code Playgroud)
2)使用 …
我想要实现以下目标:
1)我在java端有一个表示图像的字节数组.
2)我需要让我的本机代码访问它.
3)本机代码使用GraphicsMagick解码此图像,并通过调用resize创建一堆缩略图.它还计算图像的感知散列,该散列是矢量或unint8_t数组.
4)一旦我将这些数据返回给Java端,不同的线程就会读取它.缩略图将通过HTTP上传到某些外部存储服务.
我的问题是:
1)将字节从Java传递到我的本机代码的最有效方法是什么?我可以将其作为字节数组访问.我认为将其作为字节缓冲区(包装此字节数组)与字节数组传递在此处没有任何特别的优势.
2)将这些缩略图和感知哈希返回给java代码的最佳方法是什么?我想到了几个选择:
(i)我可以在Java中分配一个字节缓冲区,然后将其传递给我的本机方法.然后,本机方法可以写入并在完成后设置一个限制并返回写入的字节数或一些表示成功的布尔值.然后,我可以对字节缓冲区进行切片和切块,以提取不同的缩略图和感知哈希,并将其传递给将上传缩略图的不同线程.这种方法的问题是我不知道要分配的大小.所需的大小将取决于我提前生成的缩略图的大小和缩略图的数量(我事先知道).
(ii)一旦我知道所需的大小,我也可以在本机代码中分配字节缓冲区.我可以根据自定义打包协议将我的blob记忆到正确的区域并返回此字节缓冲区.(i)和(ii)都很复杂,因为自定义打包协议必须指示每个缩略图的长度和感知散列.
(iii)定义一个具有缩略图字段的Java类:字节缓冲区数组和感知散列字节:字节数组.当我知道所需的确切大小时,我可以在本机代码中分配字节缓冲区.然后,我可以将GraphicsMagick blob中的字节memcpy到每个字节缓冲区的直接地址.我假设还有一些方法来设置写在字节缓冲区上的字节数,以便java代码知道字节缓冲区有多大.设置字节缓冲区后,我可以填写我的Java对象并返回它.与(i)和(ii)相比,我在这里创建了更多的字节缓冲区以及Java对象,但我避免了自定义协议的复杂性.(i),(ii)和(iii)背后的基本原理 - 鉴于我对这些缩略图的唯一做法是上传它们,我希望通过NIO上传它们时保存带字节缓冲区(vs字节数组)的额外副本.
(iv)定义一个Java类,它具有缩略图的字节数组(而不是字节缓冲区)和感知散列的字节数组.我在我的本机代码中创建这些Java数组,并使用SetByteArrayRegion从我的GraphicsMagick blob复制字节.与以前的方法相比,缺点是,当上传它时,将这个字节数组从堆复制到某个直接缓冲区时,现在Java中还会有另一个副本.不确定我是否会在复杂性方面保存任何东西,而不是(iii).
任何建议都会很棒.
编辑:@main提出了一个有趣的解决方案.我正在编辑我的问题以跟进该选项.如果我想像@main建议的那样在DirectBuffer中包装本机内存,我怎么知道何时可以安全地释放本机内存?
我正在写一个有三个优先队列作为私人成员的班级.
class Foo {
...
...
private:
// I am fine with using pointers instead if it helps.
std::priority_queue<int> first; // min heap.
std::priority_queue<int> second; // max heap.
std::priority_queue<int> third; // min heap.
};
Run Code Online (Sandbox Code Playgroud)
现在我需要first并third以a min heaps和seconda 开始max heap.作为我班级功能的一部分,我需要做以下事情:
second到first.理想情况下,这是通过最低的复制量来实现的.应该移动底层矢量.此外first,现在应该表现得像max heap.third到second.这意味着second现在应该表现得像min heap.third已将内容移至second,因此应为空.我想要分配一个新的底层向量或重用first's底层向量(它不再需要它.另外第三个现在应该是一个max heap.我需要执行此循环(max - …
Eclipse scala插件有一个非常好的信息.可以将鼠标悬停在函数定义,val,var,函数调用等上,并获取类型信息.这对我来说非常有用,可以确保类型兼容性,尤其是在我尝试新事物的时候.
IntelliJ Idea 12.1中是否有类似的功能(此评论的最新版本)?
我能找到的最接近的是类型信息设置.在Mac OS 10.7.5上,默认的键绑定对我来说甚至都不起作用.即使经过调整之后,它也无法像在Eclipse中那样普遍使用,它显示了几乎所有内容的类型.有没有人设法让这个工作?我理想的设置是悬停类型信息,就像在Eclipse中一样.
我听说过有关Scala的IntelliJ IDE的很棒的东西,但到目前为止,Eclipse Scala插件已经取得了成功.
我正在编写一个处理图像(大数据)的应用程序服务器.我正在尝试将图像数据发送回客户端时最小化副本.我需要发送给客户的处理过的图像位于从jemalloc获得的缓冲区中.我想到将数据发送回客户端的方法是:
1)简单的写呼叫.
// Allocate buffer buf.
// Store image data in this buffer.
write(socket, buf, len);
Run Code Online (Sandbox Code Playgroud)
2)我通过mmap而不是jemalloc获取缓冲区,虽然我认为jemalloc已经使用mmap创建了缓冲区.然后我做一个简单的写电话.
buf = mmap(file, len); // Imagine proper options.
// Store image data in this buffer.
write(socket, buf, len);
Run Code Online (Sandbox Code Playgroud)
3)我像以前一样通过mmap获取缓冲区.然后我使用sendfile发送数据:
buf = mmap(in_fd, len); // Imagine proper options.
// Store image data in this buffer.
int rc;
rc = sendfile(out_fd, file, &offset, count);
// Deal with rc.
Run Code Online (Sandbox Code Playgroud)
似乎(1)和(2)可能会做同样的事情,因为jemalloc可能首先通过mmap分配内存.但我不确定(3).这真的会带来任何好处吗?本文关于Linux零拷贝方法的图4 表明使用sendfile可以防止进一步的拷贝:
没有数据被复制到套接字缓冲区.相反,只有具有关于数据的下落和长度信息的描述符被附加到套接字缓冲区.DMA引擎将数据直接从内核缓冲区传递到协议引擎,从而消除了剩余的最终副本.
如果一切顺利,这似乎是一场胜利.我不知道我的mmaped缓冲区是否算作内核缓冲区.另外我不知道什么时候重新使用这个缓冲区是安全的.由于fd和length是唯一附加到套接字缓冲区的东西,我假设内核实际上异步地将这些数据写入套接字.如果它执行sendfile的返回表示什么?我怎么知道何时重用这个缓冲区?
所以我的问题是:
在x86处理器上有没有办法将数据从常规写回内存加载到寄存器而不通过缓存层次结构?
我的用例是我有一个很大的查找结构(Hash map或B-Tree).我正在处理大量的数字(比我的L3大得多但适合内存).我想做的很简单:
int result = 0;
for (num : stream_numbers) {
int lookup_result = lookup_using_b_tree(num);
result += do_some_math_that_touches_registers_only(lookup_result);
}
return result;
Run Code Online (Sandbox Code Playgroud)
由于我只访问每个数字一次并且所有数字的总和超过L3大小,我想他们最终会驱逐一些缓存行来保存我的B树的一部分.相反,我理想的是不喜欢这个流命中缓存中的任何数字,因为它们根本没有时间局部性(只读一次).这样我可以最大化我的B树保留在缓存中的机会,并且查找速度更快.
我已经查看了(v)movntdqaSSE 4.1中有关时间负载的说明.这似乎不太合适,因为它似乎只适用于组合内存的不可缓存的写入.英特尔的这篇旧文章声称:
未来几代英特尔处理器可能包含流加载的优化和增强功能,例如增加流加载缓冲区的利用率和支持额外的内存类型,为软件开发人员提供更多机会,以提高其应用程序的性能和能效.
但是我今天没有意识到任何这样的处理器.我已经在其他地方读过,处理器可以选择忽略这个回写内存的提示并使用movdqa替代.那么有什么方法可以实现从常规回写内存加载而不通过x86处理器上的缓存层次结构,即使它只能在Haswell和后来的模型上实现?我还要感谢有关未来是否可能的任何信息?
尝试上传文件时,Google Drive REST API有时会返回500:内部服务器错误.大多数这些错误实际上对应于成功上传.我们会根据Google的推荐重新尝试上传,以便稍后查看重复内容.
处理这些错误的推荐方法是什么?
我正在评估libuv作为我正在编写的C/c ++服务器的库.协议的长度是前缀的,所以只要我能从流中读取32位整数,我就应该知道我应该分配什么大小的缓冲区.文档说可能会多次调用uv_read_start函数.
UV_EXTERN int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
由于我使用长度前缀协议,一旦我知道缓冲区的正确大小,我想分配它并重新使用它进行后续读取,直到我收到所有字节.用libuv有一个简单的方法吗?现在看来,uv_alloc_cb函数必须要处理这个问题.我可以将缓冲区与流对象关联,而不是将其放在地图或其他内容中吗?
由于我使用长度前缀协议,我根本不想在堆上分配缓冲区,直到我可以读取前4个字节(32位).我是否可以在堆栈上分配大小为4的缓冲区并让uv_read_cb函数实际执行堆分配?uv_read_cb函数是否作为uv_read_start函数的一部分同步调用?如果它是,那么当我知道我还没有附加到我的流的缓冲区时,我应该能够在堆栈上进行分配.
编写x86暂停指令的跨平台实现的最佳实践是什么?我打算在C++ 11项目的繁忙旋转循环中使用它.
如果我只使用gcc工具链,那么我可以使用_mm_pause内在函数.即使本机处理器不支持x86暂停指令,这种内在功能是否正确?我也希望我的代码也能用于clang/llvm工具链.
我认为回退可以使用"std :: this_thread :: sleep_for",因为我使用的是C++ 11.但我不确定如何检测处理器功能(支持暂停与不支持)并重新进入休眠状态.
我正在使用cmake来构建我的项目,并且也将始终在同一台机器上构建和部署.所以我很乐意在编译期间检测处理器设置.
示例实现(伪代码)是:
void pause() {
// Not sure how to detect if pause is available on the platform.
#if defined(USE_mm_pause)
__asm__ ( "pause;" );
#else
std::this_thread::sleep_for(std::chrono::seconds(0));
#endif
}
Run Code Online (Sandbox Code Playgroud) 我正在 ARM 板上的旧版本内核上运行 perf record。内核版本为3.18.21-rt19
板上的 perf 版本同样是 perf 版本 3.18.21。
虽然我可以在此性能上记录和使用报告功能,但此版本的报告 TUI 非常糟糕/不存在。它不是可扩展部分(在图形模式下),而是显示为一个巨大的可滚动函数列表,非常难以使用。另外,由于某种原因,我的 C++ 函数名称没有被破坏,因此很难阅读它。
是否有可能以某种方式:
将在此较旧 ARM 内核上创建的 perf.data 导出到运行较新内核和较新版本 perf 的 x86 计算机,并使用该计算机上的 perf 报告。当我尝试这样做时(我在运行 perf 版本 4.4.13 的内核 4.4.0-31-generic 上运行),我丢失了所有符号,即使在 ARM 计算机上运行 perf 报告显示符号很好(C++ 名称仍然被破坏) )。我不确定这是否只是因为这些内核版本之间的 perf.data 格式发生了变化,或者 x86 版本是否完全无法读取 ARM 机器生成的数据。
为我的旧内核构建一个更新的性能版本(至少是前端),它可以进行整理并公开更新的更好的 TUI。
更改 ARM 板上的内核版本对我来说不是一个选择。
我有一个nvidia显卡,并且能够在过去安装cuda.最近我重新安装了linux(ubuntu 12.04)并且一直在尝试使用debian软件包安装cuda.我按照Youtube上的Nvidia cudacast频道(http://www.youtube.com/watch?v=lVzSullC9l8)的说明安装了cuda工具包.
在我开始之后,我sudo-apt-get install cuda收到以下错误:
Setting up nvidia-current (319.37-0ubuntu1) ...
update-alternatives: error: alternative link /usr/bin/nvidia-cuda-mps-server is already managed by x86_64-linux-gnu_nvidia-cuda-mps-server (slave of x86_64-linux-gnu_gl_conf).
dpkg: error processing nvidia-current (--configure):
subprocess installed post-installation script returned error exit status 2
Run Code Online (Sandbox Code Playgroud)
看起来这可能与Ubuntu建议默认安装的以前的Nvidia驱动程序有关.我尝试使用软件中心卸载所有内容,但仍然没有运气.
有帮助吗?