Hi, all.
What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)
Hi, all.
What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)
You may also add the detail, if the snipped is within a proc (e.g. Byte compiled) or not.I'm interested in both cases :-).
Hi, all.
What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)
пятница, 27 августа 2021 г. в 17:43:24 UTC+3, Harald Oehlmann:
You may also add the detail, if the snipped is within a proc (e.g. ByteI'm interested in both cases :-).
compiled) or not.
Am 27.08.2021 um 15:50 schrieb oleg:
Hi, all.
What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)
Perhaps:
tcl::mathop::* $n -1
You may also add the detail, if the snipped is within a proc (e.g. Byte compiled) or not. If so, it depends, how often the proc is called, e.g.
if byte compilation is a win or not.
пятница, 27 августа 2021 г. в 17:43:24 UTC+3, Harald Oehlmann:
You may also add the detail, if the snipped is within a proc (e.g. ByteI'm interested in both cases :-).
compiled) or not.
Am 27.08.21 um 17:02 schrieb oleg.o....@gmail.com:
пятница, 27 августа 2021 г. в 17:43:24 UTC+3, Harald Oehlmann:
You may also add the detail, if the snipped is within a proc (e.g. Byte >> compiled) or not.I'm interested in both cases :-).
the -$n expr is about 3 times faster ( @level 0 ):
% set n 4543534534
4543534534
% time {expr {$n * -1}} 100000
0.91321 microseconds per iteration
% time {expr {-$n}} 100000
0.35942 microseconds per iteration
% time {expr {$n * -1}} 100000
0.82213 microseconds per iteration
% time {expr {-$n}} 100000
0.33567 microseconds per iteration
% time {expr {$n * -1}} 100000
0.87075 microseconds per iteration
% time {expr {-$n}} 100000
0.33751 microseconds per iteration
if you wrap it in a proc each
% proc a n {expr {-$n}
}
% proc b n {expr {$n * -1}
}
% time {a $n} 100000
0.7419 microseconds per iteration
% time {b $n} 100000
1.27659 microseconds per iteration
oleg.o....@gmail.com <oleg.o....@gmail.com> wrote:
Hi, all.
What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)Read up on the manpage of Tcl's 'time' command. Using it, you can
answer your own question, on your hardware.
On Friday, August 27, 2021 at 4:43:24 PM UTC+2, Harald Oehlmann wrote:0
Am 27.08.2021 um 15:50 schrieb oleg:
Hi, all.
What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)
Perhaps:
tcl::mathop::* $n -1Funny enough, tcl::mathop::- serves as negative sign operator if called with a single argument. One never stops learning new stuff.
You may also add the detail, if the snipped is within a proc (e.g. Byte compiled) or not. If so, it depends, how often the proc is called, e.g.I am not one of the wizards, but I guess that tcl::mathop and expr (with braces) produce (nearly) identical byte code.
if byte compilation is a win or not.
As others pointed out, we can easily look behind the curtains:
$ proc neg a {expr {-$a}}
$ proc mult a {expr {$a*-1}}
$ proc opneg a {::tcl::mathop::- $a}
$ proc opmult a {::tcl::mathop::* $a -1}
$ ::tcl::unsupported::getbytecode proc neg
literals {} variables {{{scalar arg} a}} exception {} instructions {0 {loadScalar1 %0} 2 uminus 3 done} auxiliary {} commands {{codefrom 0 codeto 2 scriptfrom 0 scriptto 9 script {expr {-$a}}}} script {expr {-$a}} namespace :: stackdepth 1 exceptdepth
$ ::tcl::unsupported::getbytecode proc multstackdepth 2 exceptdepth 0
literals -1 variables {{{scalar arg} a}} exception {} instructions {0 {loadScalar1 %0} 2 {push1 @0} 4 mult 5 done} auxiliary {} commands {{codefrom 0 codeto 4 scriptfrom 0 scriptto 11 script {expr {$a*-1}}}} script {expr {$a*-1}} namespace ::
$ ::tcl::unsupported::getbytecode proc opnegstackdepth 1 exceptdepth 0
literals {} variables {{{scalar arg} a}} exception {} instructions {0 {loadScalar1 %0} 2 uminus 3 done} auxiliary {} commands {{codefrom 0 codeto 2 scriptfrom 0 scriptto 18 script {::tcl::mathop::- $a}}} script {::tcl::mathop::- $a} namespace ::
$ ::tcl::unsupported::getbytecode proc opmultnamespace :: stackdepth 2 exceptdepth 0
literals -1 variables {{{scalar arg} a}} exception {} instructions {0 {loadScalar1 %0} 2 {push1 @0} 4 mult 5 done} auxiliary {} commands {{codefrom 0 codeto 4 scriptfrom 0 scriptto 21 script {::tcl::mathop::* $a -1}}} script {::tcl::mathop::* $a -1}
$ ::tcl::unsupported::getbytecode ;# expects one of {lambda method objmethod proc script}
I'd conclude (from the instructions)
* no diff between expr and mathop
* uminus should be slightly faster
Hm. At C level there is no difference between a = a * -1 and a = -a:
~$ cat t.c
void
main(void)
{
int a = 1;
int i;
for(i = 0; i < 1000000; i++)
a = a * -1;
}
~$ cat tt.c
void
main(void)
{
int a = 1;
int i;
for(i = 0; i < 1000000; i++)
a = -a;
}
~$ gcc -S -c -g t.c
~$ gcc t.s
~$ time ./a.out
real 0m0.012s
user 0m0.010s
sys 0m0.002s
~$ as -alhnd t.s
[CUT]
7:t.c **** for(i = 0; i < 1000000; i++)
18 .loc 1 7 8
19 000b C745FC00 movl $0, -4(%rbp)
19 000000
20 .loc 1 7 2
21 0012 EB07 jmp .L2
22 .L3:
8:t.c **** a = a * -1;
23 .loc 1 8 5 discriminator 3
24 0014 F75DF8 negl -8(%rbp)
[CUT]
~$ gcc -S -c -g tt.c
~$ gcc tt.s
~$ time ./a.out
real 0m0.012s
user 0m0.010s
sys 0m0.002s
~$ as -alhnd tt.s
[CUT]
7:tt.c **** for(i = 0; i < 1000000; i++)
18 .loc 1 7 8
19 000b C745FC00 movl $0, -4(%rbp)
19 000000
20 .loc 1 7 2
21 0012 EB07 jmp .L2
22 .L3:
8:tt.c **** a = -a;
23 .loc 1 8 5 discriminator 3
24 0014 F75DF8 negl -8(%rbp)
[CUT]
The C optimizer is effectively replacing "a * -1" with "-a", because "-1" is a
compile-time constant and the compiler knows that the negation instruction is
faster than a multiply instruction.
so the Tcl code
using expr {$a * -1} is going to be slower than expr {-$a}.
понедельник, 30 августа 2021 г. в 14:53:33 UTC+3, Robert Heller:
The C optimizer is effectively replacing "a * -1" with "-a", because "-1" is a
compile-time constant and the compiler knows that the negation instruction is
faster than a multiply instruction.
Exactly. :-)
so the Tcl code
using expr {$a * -1} is going to be slower than expr {-$a}.
It's would be great if this info will be in expr man page.
понеделÑник, 30 авгÑÑÑа 2021 г. в 14:53:33 UTC+3, Robert Heller:
The C optimizer is effectively replacing "a * -1" with "-a", because "-1" is a
compile-time constant and the compiler knows that the negation instruction is
faster than a multiply instruction.
Exactly. :-)
so the Tcl code
using expr {$a * -1} is going to be slower than expr {-$a}.
It's would be great if this info will be in expr man page.
If you would do the effort to put speed-related information to the
man-page, nobody will stop you. Nevertheless, we are happy to have/get correct man pages on the functional level which is the main aim.
???????, 27 ??????? 2021 ?. ? 21:11:20 UTC+3, Rich:
oleg.o....@gmail.com <oleg.o....@gmail.com> wrote:
Hi, all.Read up on the manpage of Tcl's 'time' command. Using it, you can
What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)
answer your own question, on your hardware.
Thanks, but i already done this step :-).
Time can give a different results on my machine than others, for
example(due various factors).
I'm interested in algorithmic difference(if it exists).
понедельник, 30 августа 2021 г. в 15:57:57 UTC+3, Harald Oehlmann:
If you would do the effort to put speed-related information to the
man-page, nobody will stop you. Nevertheless, we are happy to have/get
correct man pages on the functional level which is the main aim.
Ok. Where to send the patch?
Oleg,
the corresponding man-page is on core.tcl-lang.org/tcl in the folder /doc. You may also look to this wiki page to test the formatting: https://core.tcl-lang.org/tcl/wiki?name=How+to+edit/test+tcl+man+pages&p
The formatting is IMHO difficult.
You may add your changes as path to a ticket.
At Mon, 30 Aug 2021 05:03:15 -0700 (PDT) "oleg.o....@gmail.com" <oleg.o.nemanov@gmail.com> wrote:
????????????????????????????????????????????, 30 ???????????????????????????? 2021 ????. ???? 14:53:33 UTC+3, Robert Heller:
The C optimizer is effectively replacing "a * -1" with "-a", because "-1" is a
compile-time constant and the compiler knows that the negation instruction is
faster than a multiply instruction.
Exactly. :-)
so the Tcl code
using expr {$a * -1} is going to be slower than expr {-$a}.
It's would be great if this info will be in expr man page.
The timing difference between a multiplication instruction and a negation instruction should be well known. On a practical level using "expr {$a * -1}" vs. "expr {-$a}" should be very obvious, when the "-1" is a manifest constant.
This is a trivial hand optimization, one the C compiler implements on its own -- good for lazy C programmers -- Tcl programmers need to be a little more pro-active, but that is always the case for Tcl programming.
The timing difference between a multiplication instruction and a negation instruction should be well known.
On a practical level using "expr {$a * -1}"
vs. "expr {-$a}" should be very obvious, when the "-1" is a manifest constant.
I agree with Robert. The man page is not the place to state well known performance differences.
The manpage should document the
options/syntax the command accepts, but if it starts also documenting obvious performance differences we will have a never ending set of
"tips" to be added.
Placing this on the Wiki, as a discussion on the [expr] page would be reasonable.
Of course. You might have a brand new i7, which will probably be
markedly faster than my 7+ year old Xeon here.
I'm interested in algorithmic difference(if it exists).Which is what time will give you. If you test -$x vs. -1*$x on the
same machine, then you have kept machine differences constant (to the
extent you can keep them constant) and so any differences must be due
to different algorithms used for -$x vs -1*$x.
понеделÑник, 30 авгÑÑÑа 2021 г. в 16:33:23 UTC+3, Robert Heller:
The timing difference between a multiplication instruction and a negation instruction should be well known.
Hm. Why? For example, i have C background and for me this is not "well known".
Moreover in other programming languages this situation may differ. And in tcl docs this case isn't described. So, how it should be well known?
On a practical level using "expr {$a * -1}"
vs. "expr {-$a}" should be very obvious, when the "-1" is a manifest constant.
No. This is not obvious. May be you have big tcl experience and that's why you think so.
But i have no such experience and i say you that this is not obvious.
Modern *compiled* languages do all sorts of "obvious" optimizations, so I guess someone who has not written assembly code or otherwise studied machine-level coding or otherwise learned about low-level CPU ALU implementations, might not know about the timing differences between different
sorts of machine instructions.
понеделÑник, 30 авгÑÑÑа 2021 г. в 18:27:02 UTC+3, Robert Heller:
Modern *compiled* languages do all sorts of "obvious" optimizations, so I guess someone who has not written assembly code or otherwise studied machine-level coding or otherwise learned about low-level CPU ALU implementations, might not know about the timing differences between different
sorts of machine instructions.
Agree. But this is just confirming that it is not obvious and well known, isn't it :-)?
At Mon, 30 Aug 2021 09:39:03 -0700 (PDT) "oleg.o....@gmail.com" <oleg.o.nemanov@gmail.com> wrote:
ÿþýõôõûьýøú, 30 ðòóуÑÂтð 2021 ó. ò 18:27:02 UTC+3, Robert Heller:
Modern *compiled* languages do all sorts of "obvious" optimizations, so I >>> guess someone who has not written assembly code or otherwise studied
machine-level coding or otherwise learned about low-level CPU ALU
implementations, might not know about the timing differences between different
sorts of machine instructions.
Agree. But this is just confirming that it is not obvious and well known,
isn't it :-)?
Maybe, but it is the sort of thing that is (should?) be part of a CompSci 101 course. It does not really belong in the man pages. It IS something that belongs in a CompSci textbook and/or course.
I guess it is something I and probably most programmers of my generation, who started programming with Apple ][s, Commadore 64s, Trash-80s, Kim-1s, etc. learned early on. Even though current generation programmers are learning with modern machines with optimizing compilers on multi-core 64-bit processors, it still makes some sense to teach them about the basics of low-level CPU ALU implementations and instill a sense of what the performance costs of different ways to implement a given computation.
???????????, 30 ??????? 2021 ?. ? 17:08:11 UTC+3, Rich:
I agree with Robert. The man page is not the place to state well known
performance differences.
This is not well known :-).
The manpage should document the
options/syntax the command accepts, but if it starts also documenting
obvious performance differences we will have a never ending set of
"tips" to be added.
Ok. Why this is bad (when a man page collect all needed info for developer)?
Placing this on the Wiki, as a discussion on the [expr] page would be
reasonable.
May be you are right. But why a documentation for some func should be necessarily
spread on different locations? Is this good?
???????????, 30 ??????? 2021 ?. ? 16:33:23 UTC+3, Robert Heller:
The timing difference between a multiplication instruction and a
negation instruction should be well known.
Hm. Why? For example, i have C background and for me this is not
"well known".
Moreover in other programming languages this situation may differ.
And in tcl docs this case isn't described. So, how it should be well
known?
On a practical level using "expr {$a * -1}"
vs. "expr {-$a}" should be very obvious, when the "-1" is a manifest constant.
No. This is not obvious. May be you have big tcl experience and
that's why you think so.
But i have no such experience and i say you that this is not obvious.
On 8/30/2021 11:07 AM, Robert Heller wrote:
At Mon, 30 Aug 2021 09:39:03 -0700 (PDT) "oleg.o....@gmail.com" <oleg.o.nemanov@gmail.com> wrote:
?¿?¾?½?µ?´?µ?»???½?¸?º, 30 ?°?²?³???????° 2021 ?³. ?² 18:27:02 UTC+3, Robert Heller:
Modern *compiled* languages do all sorts of "obvious"
optimizations, so I guess someone who has not written assembly
code or otherwise studied machine-level coding or otherwise
learned about low-level CPU ALU implementations, might not know
about the timing differences between different sorts of machine
instructions.
Agree. But this is just confirming that it is not obvious and well
known, isn't it :-)?
Maybe, but it is the sort of thing that is (should?) be part of a
CompSci 101 course. It does not really belong in the man pages. It
IS something that belongs in a CompSci textbook and/or course.
I guess it is something I and probably most programmers of my
generation, who started programming with Apple ][s, Commadore 64s,
Trash-80s, Kim-1s, etc. learned early on. Even though current
generation programmers are learning with modern machines with
optimizing compilers on multi-core 64-bit processors, it still makes
some sense to teach them about the basics of low-level CPU ALU
implementations and instill a sense of what the performance costs of
different ways to implement a given computation.
I would think that the section on [expr] performance is better left as
is, since it discusses the most important thing for a new tcl programmer
to be aware of, namely braces.
At Mon, 30 Aug 2021 07:25:31 -0700 (PDT) "oleg.o....@gmail.com" <oleg.o.nemanov@gmail.com> wrote:
????????????????????????????????????????????, 30 ???????????????????????????? 2021 ????. ???? 16:33:23 UTC+3, Robert Heller:
The timing difference between a multiplication instruction and a
negation instruction should be well known.
Hm. Why? For example, i have C background and for me this is not
"well known". Moreover in other programming languages this
situation may differ. And in tcl docs this case isn't described.
So, how it should be well known?
Modern *compiled* languages do all sorts of "obvious" optimizations,
so I guess someone who has not written assembly code or otherwise
studied machine-level coding or otherwise learned about low-level CPU
ALU implementations, might not know about the timing differences
between different sorts of machine instructions.
???????????, 30 ??????? 2021 ?. ? 16:55:19 UTC+3, Rich:
Of course. You might have a brand new i7, which will probably be
markedly faster than my 7+ year old Xeon here.
I'm interested in algorithmic difference(if it exists).Which is what time will give you. If you test -$x vs. -1*$x on the
same machine, then you have kept machine differences constant (to the
extent you can keep them constant) and so any differences must be due
to different algorithms used for -$x vs -1*$x.
Not really. I told about situation when some operation/costruct can
be slower/faster on different machine architectures.
oleg.o....@gmail.com <oleg.o.nemanov@gmail.com> wrote:
???????, 27 ??????? 2021 ?. ? 21:11:20 UTC+3, Rich:
oleg.o....@gmail.com <oleg.o....@gmail.com> wrote:
Hi, all.Read up on the manpage of Tcl's 'time' command. Using it, you can
What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)
answer your own question, on your hardware.
Thanks, but i already done this step :-).
You had not indicated so yet in this thread when I posted my reply.
Time can give a different results on my machine than others, for
example(due various factors).
Of course. You might have a brand new i7, which will probably be
markedly faster than my 7+ year old Xeon here.
I'm interested in algorithmic difference(if it exists).
Which is what time will give you. If you test -$x vs. -1*$x on the
same machine, then you have kept machine differences constant (to the
extent you can keep them constant) and so any differences must be due
to different algorithms used for -$x vs -1*$x.
On 8/30/2021 6:55 AM, Rich wrote:
oleg.o....@gmail.com <oleg.o.nemanov@gmail.com> wrote:
???????, 27 ??????? 2021 ?. ? 21:11:20 UTC+3, Rich:
oleg.o....@gmail.com <oleg.o....@gmail.com> wrote:
Hi, all.Read up on the manpage of Tcl's 'time' command. Using it, you can
What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)
answer your own question, on your hardware.
Thanks, but i already done this step :-).
You had not indicated so yet in this thread when I posted my reply.
Time can give a different results on my machine than others, for
example(due various factors).
Of course. You might have a brand new i7, which will probably be
markedly faster than my 7+ year old Xeon here.
I'm interested in algorithmic difference(if it exists).
Which is what time will give you. If you test -$x vs. -1*$x on the
same machine, then you have kept machine differences constant (to the
extent you can keep them constant) and so any differences must be due
to different algorithms used for -$x vs -1*$x.
And [time] can tell you things that can be a surprise; so after I lopped
off the right most digit:
% set n 4543534534
4543534534
% time {expr {$n * -1}} 100000
0.453894 microseconds per iteration
% set n 454353453 ;# w/o the last digit
454353453
% time {expr {$n * -1}} 100000
0.16878700000000002 microseconds per iteration
When I ran my tests with a different number than the OP used, I was
thinking, gee I have a really fast machine!
I'm guessing that the number the OP chose to test with must be larger
than my system can handle as a simple machine word and so something
is going on by tcl behind the scenes that I don't know about. I used
32 bit tcl here, but 64 bit tcl got the same timing.
Maybe the bytecode interpreter overhead is more important than the
actual arithmetic statement that is eventually executed. Is a uminus
going to be that much faster than a mult, or is it that there's an extra
push that's the difference?
At Mon, 30 Aug 2021 09:39:03 -0700 (PDT) "oleg.o....@gmail.com" <oleg.o....@gmail.com> wrote:
понедельник, 30 Ð°Ð²Ð³ÑƒÑ Ñ‚Ð° 2021 г. в 18:27:02 UTC+3, Robert Heller:
Modern *compiled* languages do all sorts of "obvious" optimizations, so I
guess someone who has not written assembly code or otherwise studied machine-level coding or otherwise learned about low-level CPU ALU implementations, might not know about the timing differences between different
sorts of machine instructions.
Agree. But this is just confirming that it is not obvious and well known, isn't it :-)?Maybe, but it is the sort of thing that is (should?) be part of a CompSci 101
course. It does not really belong in the man pages. It IS something that belongs in a CompSci textbook and/or course.
I guess it is something I and probably most programmers of my generation, who
started programming with Apple ][s, Commadore 64s, Trash-80s, Kim-1s, etc. learned early on. Even though current generation programmers are learning with modern machines with optimizing compilers on multi-core 64-bit processors, it still makes some sense to teach them about the basics of low-level CPU ALU implementations and instill a sense of what the performance
costs of different ways to implement a given computation.
% ::tcl::unsupported::disassemble script {expr {-$n}}
Well, in this case it would be bad because it is an obvious issue that should not need mention in the man page. Other than beginners, the
rest of us should already know that a multiplication operation is more computational effort than a negation operation.
The man page should
document the necessary syntax in order to show how to use the command. Adding obvious items merely clutters the man page with information that
all but true beginners have no need to read through.
You could argue that the man page might include a reference to the wiki 'expr' page for further information and/or tips and tricks, that way if someone is unaware of the wiki they would then be made aware.
Then you left an awful lot of information up to one's imagination,
because this:
"What is faster: [expr {$n * -1}] or [expr {-$n}] ? :-)"
Does not suggest to me that you are asking which of those are
faster/slower on different machine architectures.
And with the exception of your "hi", that quoted line above is all that
was in your original posting to which I originally replied to create
this sub-thread.
Experience *does* have a direct impact on what any one individual
considers obvious. In my case, I've known this fact (multiplication is
more work than negation) for at least 34 years, possibly longer.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 300 |
Nodes: | 16 (2 / 14) |
Uptime: | 56:10:14 |
Calls: | 6,712 |
Files: | 12,243 |
Messages: | 5,355,474 |