
有时会发生意想不到的事情,必须与世界分享……这就是这样的情况。
最近,我开始尝试使用 perl 进行数据科学应用程序的工作流管理和低级代码的高级监督。在这种情况下,我为 perl 保留的一个角色是内存缓冲区的生命周期管理,使用 perl 应用程序“分配”内存缓冲区并在用 c、assembly、fortran 编写的计算组件和最好的隐藏宝石之间穿梭。 perl 世界,perl 数据语言。
perl 至少可以通过 3 种方式来分配内存缓冲区:
生成字节列表并使用 pack 函数将它们转换为字符串。 使用重复运算符 (x) 生成一个长度等于所需缓冲区大小减一的字符串(在 perl 中,字符串通过空字节终止,因此空字节补偿了我的一个 ).通过 inline 或 ffi::platypus 访问外部内存分配器库来分配缓冲区。
以下 perl 代码实现了这三种方法(pack、string 和 c 中的 malloc),并允许尝试不同的缓冲区大小、初始值和结果精度(通过对分配的多次迭代进行平均)惯例)
#!/home/chrisarg/perl5/perlbrew/perls/current/bin/perluse v5.38;use inline ( c => 'data', cc => 'g++', ld => 'g++', inc => q{}, # replace q{} with anything else you need ccflagsex => q{}, # replace q{} with anything else you need lddlflags => join( q{ }, $config::config{lddlflags}, q{ }, # replace q{ } with anything else you need ), libs => join( q{ }, $config::config{libs}, q{ }, # replace q{ } with anything else you need ), myextlib => '');use benchmark qw(cmpthese);use getopt::long;my ($buffer_size, $init_value, $iterations);getoptions( 'buffer_size=i' => $buffer_size, 'init_value=s' => $init_value, 'iterations=i' => $iterations,) or die "usage: $0 --buffer_size --init_value --iterations n";my $init_value_byte = ord($init_value);my %code_snippets = ( 'string' => sub { $init_value x ( $buffer_size - 1 ); }, 'pack' => sub { pack "c*", ( ($init_value_byte) x $buffer_size ); }, 'c' => sub { allocate_and_initialize_array( $buffer_size, $init_value_byte ); },);cmpthese( $iterations, %code_snippets );__data____c__#include #include #include sv* allocate_and_initialize_array(size_t length, short initial_value) { // allocate memory for the array char* array = (char*)malloc(length * sizeof(char)); char initial_value_byte = (char)initial_value; if (array == null) { fprintf(stderr, "memory allocation failedn"); exit(1); } // initialize each element with the initial_value memset(array, initial_value_byte, length); return newsvuv(ptr2uv(array));}
将脚本调用为:
./time_mem_alloc.pl -buffer_size=1000000 -init_value=a -iterations=20000
产生了令人惊讶的结果:
rate pack c stringpack 322/s -- -92% -99%c 4008/s 1144% -- -92%string 50000/s 15417% 1147% --
使用 perl string 方法比 c 的性能高出 10 倍。
不相信巨大的性能提升,并认为我正在处理 inline::c 中的错误,我用纯 c 重新编码了分配(添加命令行处理/计时等的常用修饰):
#include #include #include #include
按照c代码中注释所说的那样调用c程序,
我得到了以下结果:
Time taken to allocate and initialize array: 0.000203 secondsInitializes per second: 4926.108374
实际上执行的数量级与 inline::c malloc/c 方法的等效分配相同。
在进一步研究这个问题后,我发现我所欣赏的 malloc 牺牲了内存分配的速度以换取通用性,并且有大量更快的内存分配器。看来 perl 正在为其字符串使用这样一个分配器,并在分配缓冲区的任务中击败了 c。
以上就是Perl 停滞不前的日子:揭示 C 的隐藏力量的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1457326.html
微信扫一扫
支付宝扫一扫