Performance 在tcl中使用一个大型EXPR比使用几个小型EXPR快吗

Performance 在tcl中使用一个大型EXPR比使用几个小型EXPR快吗,performance,tcl,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 } ]

我有一个执行数十万次的程序:

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或全局变量,这样我就不必将结果作为列表副本提交(速度慢得多吗?)如果我不将这些行放在itselv的进程中,并将其放在需要的代码“内联”位置,代码运行会更快吗?据我所知,如果您使用TCl::unsupported::discomble来检查字节码,那么TCl中的进程会更快…

在这个过程中,您将看到一个[expr]与多个[expr]之间没有任何区别 完全不同

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

您对返回时“列表副本”的担心是没有根据的。那不是 Tcl是如何工作的。玩弄[upvar]来解决您所做的“问题” 不是你想要走的路

使用全局 变量将减慢您的进程,可能是可测量的。你想要 您的[expr]在进程中,以便他们可以在本地VAR上操作,
字节码的速度增益最大。

如果使用tcl::unsupported::discomble检查字节码 在这个过程中,您将看到一个[expr]与多个[expr]之间没有任何区别 完全不同

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

您对返回时“列表副本”的担心是没有根据的。那不是 Tcl是如何工作的。玩弄[upvar]来解决您所做的“问题” 不是你想要走的路

使用全局 变量将减慢您的进程,可能是可测量的。你想要 您的[expr]在进程中,以便他们可以在本地VAR上操作, 字节码的速度增益最大。

如果您使用表达式(重要!)并仅使用局部变量,则差异很小。读写局部变量的成本很低,不比读写C中的变量高多少。执行的实际成本主要是算术运算和函数调用;这是您应该最小化的(当然,在保持正确性的同时)

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

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

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

如果您将表达式(重要!)放在大括号内,并且只使用局部变量,则差别很小。读写局部变量的成本很低,不比读写C中的变量高多少。执行的实际成本主要是算术运算和函数调用;这是您应该最小化的(当然,在保持正确性的同时)

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

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


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

一些建议:为什么不同时尝试这两种方法并计时?FX和FY始终为零。如果您经常调用这个过程,我建议您使用C重写它,并将其公开为Tcl扩展。嘿,今晚有件事要为我做。(我从未编写过Tcl扩展,但听起来并不难。)我只是对它们进行了计时:减少expr调用将执行时间从3000微秒减少到2000微秒,减少了1/3。将过程编译为*.tbc将每次执行的时间减少到117微秒;-)一些建议:你为什么不两个都试一下,然后计时呢?外汇和财政年度