考虑这个简单的基准
list1 <- as.list(rep(1, 50))
list2 <- as.list(rep(1, 50))
microbenchmark::microbenchmark(
+ map2(list1, list2, sum))
Unit: microseconds
expr min lq mean median uq max neval
map2(list1, list2, sum) 375.31 384.2045 481.8708 407.8115 420.641 7923.58 100
microbenchmark::microbenchmark(
+ mapply(sum, X=list1, Y=list2, SIMPLIFY = FALSE))
Unit: microseconds
expr min lq mean median uq max neval
mapply(sum, X = list1, Y = list2, SIMPLIFY = FALSE) 46.187 50.634 57.45634 53.3715 59.8715 127.27 100
purrr:map2
为什么mapply
几乎比map2
慢<8> 1>}?我的意思是,我只是简单地在两个列表中并排数字。
问题是我在当前代码中使用for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
//grid08(8X8)
Pane p=new Pane();
ImageView im=new ImageView();
Label l=new Label("");
im.fitWidthProperty().bind(p.widthProperty());
im.fitHeightProperty().bind(p.heightProperty());
l.prefWidthProperty().bind(p.widthProperty());
l.prefHeightProperty().bind(p.heightProperty());
p.getChildren().addAll(im,l);
l.setVisible(false);
l.setStyle("-fx-text-fill: #fff; -fx-font-size: 12px");
l.setAlignment(Pos.CENTER);
p.setStyle("-fx-background-color: black;");
grid.add(p,j,i);//grid->instance of gridPane
p.setOnDragOver(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
if(!l.isVisible()){
event.acceptTransferModes(TransferMode.ANY);
}
}
});
p.setOnDragDropped(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
play(im,event.getDragboard().getString());
}
});
}
}
play(ImageView im,String Url){
new Thread(new Runnable(){
frameGrabber = new FFmpegFrameGrabber(Url);
frameGrabber.setVideoOption("preset","ultrafast");
frameGrabber.setOption("rtsp_transport","tcp");
frameGrabber.setOption("stimeout" , "60000");
frameGrabber.setAudioChannels(0);
frameGrabber.setAudioCodec(0);
try {
frameGrabber.start();
start=true;
} catch (Exception e) {
}
JavaFXFrameConverter jconverter=new JavaFXFrameConverter();
while(true){
Frame frame = frameGrabber.grabImage();
Image image=jconverter.convert(frame);
Platform.runlater(new Runnable(){
im.setImage(image);
});
}
}).start();
}
,所以我想了解这里的开销是什么(以及如何修复它)
谢谢!
答案 0 :(得分:3)
正如评论中提到的@ eipi10,当使用大量数据时,有一些函数调用开销变得不那么重要了:
list1 <- as.list(rep(1, 50000))
list2 <- as.list(rep(1, 50000))
microbenchmark(map2(list1, list2, sum), mapply(sum, X=list1, Y=list2, SIMPLIFY = FALSE))
Unit: milliseconds
expr min lq mean median uq max neval cld
map2(list1, list2, sum) 73.84420 78.21917 82.53853 79.48526 81.28048 218.9266 100 b
mapply(sum, X = list1, Y = list2, SIMPLIFY = FALSE) 51.92849 54.66514 61.34755 56.99206 58.67459 204.2119 100 a
mapply
使用.Internal
而purr::map2
使用.Call
来访问执行处理的基础C函数。它们的工作方式存在一些差异,特别是在参数评估方面,以及R搜索底层代码的方式。
.Internal
上的R帮助给出了一个神秘的信息:
.Internal执行对内置代码的调用 R翻译。
只有真正的R向导才应该考虑使用此功能 R开发人员可以添加到内部函数列表中。
然而,R Internals手册解释了:
在构建时编译成R的C代码可以直接调用什么 被称为基元或通过.Internal接口,这是非常的 类似于.External接口,语法除外。更确切地说,R 维护一个R函数名和相应的C函数表 按照惯例,调用都以'do_'开头并返回SEXP。这个 table(文件src / main / names.c中的R_FunTab)也指定了多少 无论是否需要函数的参数都是必需的或允许的 在调用之前要对参数进行求值,以及是否对函数进行求值 是'内部',因为它必须通过.Internal访问 接口,或直接可访问,在这种情况下,它在R中打印为 .Primitive。
和
少数基元是特殊的而不是内置的 他们是以未经评估的论点进入的。这很清楚 语言结构和赋值运算符所必需的 以及&amp;&amp;和||有条件地评估他们的第二个 参数,和〜,。内部,调用,表达,缺失,on.exit,引用 并且替代哪些不评估他们的一些论点。
.Call
笔记的帮助文件:
如果要经常使用其中一个功能,请指定PACKAGE (将搜索限制在单个DLL中)或将.NAME作为其中一个传递 原生符号对象。搜索符号可能需要很长时间, 特别是当加载了很多名称空间时。
这意味着在使用.Call
时,在搜索DLL时需要花费一些时间来查找函数。值得注意的是purr::map2
在使用.Call
时未指定包名称,这样做可能会减少所需的开销。