0

我有一个执行几十万次的过程:

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) 之间有速度差异吗?欢迎任何有关如何加快此过程 upp 的提示!在最终版本中,我将使用 upvar 或全局变量,因此我不必将结果作为列表副本移交(它会慢得多吗?)如果我不将这些行放在 proc 中,代码会运行得更快吗? itelv,并将其“内联”放置在需要的地方?据我所知,在 TCl 中 procs 更快...

4

2 回答 2

2

如果您使用 tcl::unsupported::disassemble 来检查 proc 的字节码,您会发现一个 [expr] 与多个 [expr] 根本没有区别。

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

您对退货时的“清单副本”的担忧是没有根据的。这不是 Tcl 的工作方式。玩弄 [upvar] 来解决你实际上没有的“问题”不是你想要走的路。

使用全局变量会减慢你的进程,可能是可测量的。您希望您的 [expr] 会话在 proc 中,以便它们可以在本地变量上运行,其中字节码的速度增益最大。

于 2013-09-13T20:53:13.840 回答
2

如果你支持你的表达式(重要!)并且只使用局部变量,它几乎没有什么区别。读取和写入局部变量的成本是最低的,不比在 C 中读取和写入变量高多少。执行的实际成本主要是算术运算和函数调用;这是您应该最小化的那些(当然,在保持正确性的同时)。

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

一般问题:更改 Tcl 的构建会产生相当大的影响。几周前,我发现从 8.5.9 的系统构建切换到我自己的系统构建(使用最新的 LLVM/Clang 构建)对速度有很大的提高,但使用相同的源代码和相同的脚本。有趣的是这些事情是怎么回事……</p>

如果您真的很费时间,请尝试编写一些 C 代码来实现数学运算。这可能会更快(并且允许您使用float而不是被迫使用double,这是 Tcl 内部用于浮点数的),但我不知道快多少。如果您这样做,您会发现 API 调用Tcl_GetDoubleFromObj很有Tcl_NewDoubleObj用。

于 2013-09-15T16:12:33.987 回答