在tcl中使用一个大EXPR而不是几个小EXPR是否更快

时间:2013-09-13 14:46:11

标签: performance tcl

我有一个处理器被执行了几十万次:

proc ::TsaiWu { x_all_comp x_all_tens y_all_comp y_all_tens s_allow x_stress y_stress s_stress } {

        set FX  [ expr { 1 / $x_all_tens - 1 / $x_all_tens } ]
        set FY  [ expr { 1 / $y_all_tens - 1 / $y_all_tens } ] 
        set FXX [ expr { 1 / ( $x_all_tens * $x_all_comp ) } ]
        set FYY [ expr { 1 / ( $y_all_tens * $y_all_comp ) } ]
        set IXY [ expr { -0.5 * sqrt( ( $y_all_tens * $y_all_comp) / ( $x_all_tens * $x_all_comp) ) } ]
        set FXY [ expr { $IXY / sqrt( $x_all_tens * $x_all_comp * $y_all_tens * $y_all_comp ) } ]
        set FSS [ expr { 1 / pow($s_allow,2) } ]
        set a   [ expr { $FXX * pow($x_stress,2) + $FYY * pow($y_stress,2) + 2 * $FXY * $x_stress * $y_stress + $FSS * pow($s_stress,2) } ]
        set b   [ expr { $FX * $x_stress + $FY * $y_stress } ]
        set TW  [ expr { $a + $b } ]
        set SR  [ expr { ( -2 + sqrt( pow($b,2) + 4 * $a) ) / ( 2 * $a ) } ]

        set result [ list $TW $SR ] 

    return $result

 }

我有什么可能加快速度?我在表达式中添加了大括号,这确实有很大帮助。将单个方程式重写为两个(一个用于TW,一个用于SR)是否更快? 然后我只需要两次调用expr。如果我用c ++编写这段代码并以某种方式在我的tcl脚本中使用它会更快吗? sqrt和pow(x,0.5)之间有速度差吗?欢迎任何关于如何加快这个过程的提示! 在最终版本中,我将使用upvar或全局变量,所以我不必将结果作为列表副本移交(它是否慢得多?)如果我不将这些行放在proc中,代码运行得更快itselv,insted将它“内联”到需要它的代码中?据我所知,TCI中的触发速度更快......

2 个答案:

答案 0 :(得分:2)

如果使用tcl :: unsupported :: disassemble来检查字节码 在proc中,你会看到一个[expr] vs许多[expr]没有 完全不同。

当你[时间]确保测试大量的迭代时 您测量运行时间,而不是编译到字节码时间 这只发生一次。

您对返回“列表副本”的担忧是没有根据的。那不是 Tcl是如何工作的。用[upvar]来解决你遇到的“问题” 实际上并不是你想要走的路。

使用全局 变量会减慢你的过程,可能是可测量的。你要 你在proc中的[expr]会话,以便他们可以在当地的vars上运行, 字节码的速度增益最大的地方。

答案 1 :(得分:2)

如果你大括号你的表达式(重要!)并且只使用局部变量,它就会产生很小的差别。读取和写入局部变量的成本是最小的,不仅仅是在C中读取和写入变量。执行的实际成本主要在于算术运算和函数调用;这是你应该最小化的(当然,保留正确性)。

具体问题:您可能会发现使用$b**2$b*$bpow($b,2)便宜。 sqrt()电话可能很昂贵;你能减少你做的数量吗? (请注意,pow(…,0.5)不太可能更好,并且在数值准确性方面可能更差。)

一般问题:改变Tcl的构建会产生很大的影响。几个星期前我发现从8.5.9的系统版本切换到我自己的版本(用最新的LLVM / Clang编写),对速度进行了实质性的改进,但源代码相同且相同脚本。有趣的是这些事情......

如果你真的伤到时间,试着写一点C代码来实现数学。这可能会更快(并允许您使用float而不是被迫使用double,这是Tcl内部用于浮点数的原因)但我不知道速度有多快。如果您这样做,您会发现API调用Tcl_GetDoubleFromObjTcl_NewDoubleObj非常有用。