小编cru*_*ahl的帖子

为什么memmove比memcpy更快?

我正在研究应用程序中的性能热点,它将50%的时间花在memmove(3)上.应用程序将数百万个4字节整数插入到已排序的数组中,并使用memmove将数据"向右"移位,以便为插入的值腾出空间.

我的期望是复制内存非常快,我很惊讶在memmove上花了这么多时间.但后来我认为memmove很慢,因为它正在移动重叠区域,这必须在紧密的循环中实现,而不是复制大页面的内存.我写了一个小的微基准测试,以确定memcpy和memmove之间是否存在性能差异,期望memcpy能够取胜.

我在两台机器(核心i5,核心i7)上运行我的基准测试,看到memmove实际上比memcpy更快,在旧核心i7上甚至快了两倍!现在我正在寻找解释.

这是我的基准.它用memcpy复制100 mb,然后用memmove移动大约100 mb; 来源和目的地重叠.尝试了源和目的地的各种"距离".每次测试运行10次,打印平均时间.

https://gist.github.com/cruppstahl/78a57cdf937bca3d062c

以下是Core i5的结果(Linux 3.5.0-54-generic#81~precision1-Ubuntu SMP x86_64 GNU/Linux,gcc是4.6.3(Ubuntu/Linaro 4.6.3-1ubuntu5).括号中的数字是源和目的地之间的距离(间隙大小):

memcpy        0.0140074
memmove (002) 0.0106168
memmove (004) 0.01065
memmove (008) 0.0107917
memmove (016) 0.0107319
memmove (032) 0.0106724
memmove (064) 0.0106821
memmove (128) 0.0110633
Run Code Online (Sandbox Code Playgroud)

Memmove实现为SSE优化的汇编代码,从后到前复制.它使用硬件预取将数据加载到缓存中,并将128个字节复制到XMM寄存器,然后将它们存储在目标中.

(memcpy-ssse3-back.S,第1650行)

L(gobble_ll_loop):
    prefetchnta -0x1c0(%rsi)
    prefetchnta -0x280(%rsi)
    prefetchnta -0x1c0(%rdi)
    prefetchnta -0x280(%rdi)
    sub $0x80, %rdx
    movdqu  -0x10(%rsi), %xmm1
    movdqu  -0x20(%rsi), %xmm2
    movdqu  -0x30(%rsi), %xmm3
    movdqu  -0x40(%rsi), %xmm4
    movdqu  -0x50(%rsi), %xmm5
    movdqu  -0x60(%rsi), %xmm6
    movdqu  -0x70(%rsi), %xmm7
    movdqu  -0x80(%rsi), %xmm8
    movdqa  %xmm1, …
Run Code Online (Sandbox Code Playgroud)

c c++ memory performance

88
推荐指数
3
解决办法
2万
查看次数

Spark:将InputFormat作为singleton运行

我正在尝试将一个键值数据库集成到Spark并提出一些问题.我是Spark初学者,已经阅读了很多并运行了一些样本,但没有太复杂.

场景:

我正在使用一个小型hdfs集群将传入的消息存储在数据库中.群集有5个节点,数据分为5个分区.每个分区都存储在单独的数据库文件中.因此,每个节点都可以处理自己的数据分区.

问题:

数据库软件的接口基于JNI,数据库本身以C实现.由于技术原因,数据库软件一次只能维护一个活动连接.只能有一个JVM进程连接到数据库.

由于此限制,读取和写入数据库必须经过相同的JVM过程.

(背景信息:数据库嵌入到进程中.它是基于文件的,一次只能打开一个进程.我可以让它在一个单独的进程中运行,但由于IPC开销,这会慢一点.我的应用程序将执行许多全表扫描.其他写入将被批处理并且不是时间关键的.)

解决方案:

我在脑海中有一些想法如何解决这个问题,但我不知道它们是否适用于Spark.

  • 也许有可能神奇地将Spark配置为每个节点只有一个我专有的InputFormat实例.

  • 如果我的InputFormat第一次使用,它会启动一个单独的线程来创建数据库连接.然后,该线程将继续作为守护进程,并且只要JVM存在,它就会存在.这仅在每个节点只有一个JVM时才有效.如果Spark在同一节点上启动多个JVM,那么每个JVM都会启动自己的数据库线程,这不起作用.

  • 将我的数据库连接移动到每个节点的单独JVM进程,然后我的InputFormat使用IPC连接到此进程.正如我所说,我想避免这种情况.

  • 或者也许你有另一个更好的主意?

我最喜欢的解决方案是#1,紧接着是#2.

感谢您的任何评论和回答!

database hadoop apache-spark

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

boost :: python:编译失败,因为复制构造函数是私有的

我使用boost :: python来包装一个C++类.这个类不允许复制构造函数,但python模块总是想创建一个.

C++类看起来像这样(简化)

class Foo {
  public:
    Foo(const char *name); // constructor

  private:
    ByteArray m_bytearray;
};
Run Code Online (Sandbox Code Playgroud)

ByteArray类继承自boost :: noncopyable,因此Foo没有复制构造函数.

这是Python模块存根:

BOOST_PYTHON_MODULE(Foo)
{   
  class_<Foo>("Foo", init<const char *>())
  ;
}
Run Code Online (Sandbox Code Playgroud)

在编译boost :: python模块时,我得到的错误是无法创建Foo的复制构造函数,因为ByteArray继承自boost :: noncopyable.

如何在我的python模块中禁用复制构造函数?

谢谢Christoph

c++ python

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

在同一端口上运行websocket和http服务器(Rust,hyper)

我想用Rust,Hyper和websocket-rs编写一个Web服务器.Web服务器必须能够在同一端口上处理http请求和websocket请求.我使用官方样本(async-server.rs:https://github.com/cyderize/rust-websocket/blob/master/examples/async-server.rs)并尝试修改它.我的想法是改变错误处理.如果客户端的请求是一个简单的http请求,那么不会返回错误,而是产生一个处理请求的未来.

基于另一个SO问题(如何在使用rust-websocket时处理错误,以便只有那个连接失败而不是整个程序?)我改变了样本中的错误处理.

这是旧代码:

.map_err(|InvalidConnection {error, ..}| {
    println!("Error:{:?}",error);
    return error;
})
Run Code Online (Sandbox Code Playgroud)

这是我的新代码:

.map(Some).or_else(|_| -> Result<_, ()> {
    // SPAWN THE FUTURE
    Ok(None)
})
Run Code Online (Sandbox Code Playgroud)

这是我被困的地方.示例代码调用一个函数spawn_future,该函数需要一个upgrade.reject()在我的代码中不可用的parameter(),因为我无法访问upgrade结构.我尝试了一些其他的东西(即调用handle.spawn_fn),但编译器从不喜欢我做的事情.(我可以粘贴一些编译器错误,但我认为它们不会提高我帖子的质量.)

这是我的问题:编写可以在同一端口上处理http请求和websocket请求的异步服务器的推荐方法是什么?如果我的方法是正确的:你能帮我填一下SPAWN THE FUTURE吗?

附加上下文(如果你还没有注意到):我是一个完整的Rust初学者.

websocket rust hyper

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

在哈希中存储哈希

我在使用Perl脚本时遇到了麻烦.我尝试在哈希中存储哈希.脚本很简单:

use Data::Dumper;

my %h1=();
$h1{name}="parent";
my %h2=();
$h2{name}="child";

$h1{nested}=%h2; # store hash h2 in hash h1

print "h2:\n";
print Dumper(%h2); # works
print "h1{nested}:\n";
print Dumper($h1{nested}); # fails
Run Code Online (Sandbox Code Playgroud)

结果:

h2:
$VAR1 = 'name';
$VAR2 = 'child';
h1{nested}:
$VAR1 = '1/8';
Run Code Online (Sandbox Code Playgroud)

为什么$ h1 {nested}没有作为哈希转储,而是作为某种奇怪的标量(1/8)?

PS:即使这个问题听起来微不足道 - 我搜索了SO,但没有发现它之前被问过.PPS:我的Perl是为x86_64-linux-gnu-thread-multi构建的v5.10.1(*)(有53个已注册的补丁,有关详细信息,请参阅perl -V)

perl hash

5
推荐指数
3
解决办法
3651
查看次数

使用SSE通过uint64 []进行线性搜索

我正在尝试使用SSE指令通过uint64数组实现线性搜索。我为uint16和uint32工作,但我得到uint64代码的编译器错误(linux,gcc-请参见最后的规格)。

我正在尝试比较2x2 64位数字,然后以某种方式将结果转换为数组的索引。这可以与uint32一起很好地工作(学分请访问 http://schani.wordpress.com/2010/04/30/linear-vs-binary-search/):

#include <xmmintrin.h>
#include <smmintrin.h>

typedef ham_u64_t vec2uint64 __attribute__ ((vector_size (16)));
typedef ham_u32_t vec4uint32 __attribute__ ((vector_size (16)));
typedef float     vec4float  __attribute__ ((vector_size (16)));
typedef ham_u16_t vec8uint16 __attribute__ ((vector_size (16)));
typedef ham_u8_t  vec16uint8 __attribute__ ((vector_size (16)));

// ...

vec4uint32 v1 = _mm_loadu_si128((const __m128i *)&data[start + i + 0]);
vec4uint32 v2 = _mm_loadu_si128((const __m128i *)&data[start + i + 4]);
vec4uint32 v3 = _mm_loadu_si128((const __m128i *)&data[start + i + 8]);
vec4uint32 v4 = _mm_loadu_si128((const __m128i *)&data[start + i + …
Run Code Online (Sandbox Code Playgroud)

c c++ search sse linear-search

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

标签 统计

c++ ×3

c ×2

apache-spark ×1

database ×1

hadoop ×1

hash ×1

hyper ×1

linear-search ×1

memory ×1

performance ×1

perl ×1

python ×1

rust ×1

search ×1

sse ×1

websocket ×1