我为谓词palindrom字符串做了一个dll库plnd.dll:
let IsPalindromLib (str:string)=
let rec fn(a,b)=a>b||str.[a]=str.[b]&&fn(a+1,b-1)
fn(0,str.Length-1)
检查速度:
#time
#r "c:/libs/plnd.dll"
open Plnd
let IsPalindrom (str:string)= //equal library function
let rec fn(a,b)=a>b||str.[a]=str.[b]&&fn(a+1,b-1)
fn(0,str.Length-1)
let lst=[1..10000000]|>List.map string
let _ = lst|>List.filter IsPalindrom //from this code
// CPU time = 0.250 (+-20)
let _ = lst|>List.filter (IsPalindromLib) //from library
// CPU time = 0.500 (+-20)
let _ = lst|>List.filter (IsPalindromLib>>not>>not) //from library>>not>>not
// CPU time = 0.250 (+-20)
调用此代码中定义的函数比调用库中的函数更快,这是正常的。但在调用外部函数时使用组合谓词not>>not
(布尔值) - SPEEDS UP ???
答案 0 :(得分:1)
我在这方面做了一些研究,必须说这确实发生了。这种行为背后的原因是什么?显然它是由优化器引起的。我担心我没有足够的知识来描述代码优化器的原因,所以我可能只是猜测。这是我使用过的代码:
open plnd
let lst=[1..10000000]|>List.map string
let inline fn a = x.IsPalindromLib a
let fn2 = x.IsPalindromLib
然后我测试了几种不同情况的时间:调试/发布配置,方法IsPalindromLib在模块中定义为内联/非内联,FSI标志优化器开/关。以下是每个查询的结果。执行时间。
//debug config, optimizer is on, library has the method as non-inline
let _ = lst|>List.filter (x.IsPalindromLib >> not >> not);; //0.98 - 1.01
let _ = lst|>List.filter (x.IsPalindromLib);; //1.13 - 1.16
let _ = lst|>List.filter (fn);; //1.13 - 1.16
let _ = lst|>List.filter (fn>>not >> not);; //1.14 - 1.18
let _ = lst|>List.filter (fn2);; //1.14 - 1.16
let _ = lst|>List.filter (fn2>>not >> not);; //0.96 - 0.99
//debug config, optimizer is on, library has the method as inline
let _ = lst|>List.filter (x.IsPalindromLib >> not >> not);; //0.82 - 0.84
let _ = lst|>List.filter (x.IsPalindromLib);; //0.82 - 0.84
let _ = lst|>List.filter (fn);; //0.81 - 0.85
let _ = lst|>List.filter (fn>>not >> not);; //0.81 - 0.85
let _ = lst|>List.filter (fn2);; //0.18 - 0.22
let _ = lst|>List.filter (fn2>>not >> not);; //0.18 - 0.22
//debug config, optimizer is off, library has the method as inline
let _ = lst|>List.filter (x.IsPalindromLib >> not >> not);; //1.63-1.67
let _ = lst|>List.filter (x.IsPalindromLib);; //1.15 - 1.17
let _ = lst|>List.filter (fn);; //1.15 - 1.17
let _ = lst|>List.filter (fn>>not >> not);; //1.63 - 1.67
let _ = lst|>List.filter (fn2);; //1.14 - 1.16
let _ = lst|>List.filter (fn2>>not >> not);; //1.63-1.67
//debug config, optimizer is off, library has the method as not inline
let _ = lst|>List.filter (x.IsPalindromLib >> not >> not);; //1.66 - 1.68
let _ = lst|>List.filter (x.IsPalindromLib);; //1.15 - 1.18
let _ = lst|>List.filter (fn);; //1.13 - 1.17
let _ = lst|>List.filter (fn>>not >> not);; //1.66 - 1.68
let _ = lst|>List.filter (fn2);; //1.17 - 1.18
let _ = lst|>List.filter (fn2>>not >> not);; //1.66 - 1.68
//release config, optimize is off in FSI, library has the method as inline
let _ = lst|>List.filter (x.IsPalindromLib >> not >> not);; //1.63-1.67
let _ = lst|>List.filter (x.IsPalindromLib);; //1.15 - 1.17
let _ = lst|>List.filter (fn);; //1.15 - 1.17
let _ = lst|>List.filter (fn>>not >> not);; //1.63 - 1.67
let _ = lst|>List.filter (fn2);; //1.14 - 1.16
let _ = lst|>List.filter (fn2>>not >> not);; //1.63-1.67
//release config, optimize is off in FSI, library has the method as not inline
let _ = lst|>List.filter (x.IsPalindromLib >> not >> not);; //0.83-0.85
let _ = lst|>List.filter (x.IsPalindromLib);; //0.34 - 0.37
let _ = lst|>List.filter (fn);; //0.35 - 0.50
let _ = lst|>List.filter (fn>>not >> not);; //0.81 - 0.87
let _ = lst|>List.filter (fn2);; //0.37 - 0.45
let _ = lst|>List.filter (fn2>>not >> not);; //0.82 - 0.88
从这些测量中,我们可以说调用x.IsPalindromLib >> not >>not
比调用它更快的事实是由优化器引起的。
答案 1 :(得分:0)
可能只是解释器在第一次调用时加载库函数。尝试颠倒最后两个语句的顺序:
let _ = lst|>List.filter (IsPalindromLib>>not>>not) //from library>>not>>not
let _ = lst|>List.filter (IsPalindromLib) //from lirary
看看哪一个更快。如果这次没有>> not>>的呼叫不是更快,你可能只是在看一些函数加载或结果缓存的解释器问题或类似的东西。