c / c++ : is it end of era ?

D

Dave Vandervies

jacob navia said:
GREAT DAVE!!!
1) You are a genius.

No, I'm just somebody who cares about correctness and knows how to drive
a compiler[1].
You can even correct warnings that you yourself
provoked! Impressing.

I corrected warnings that the compiler gave me when I asked it to warn
me about departures from correct C and constructs that were likely to
cause trouble; this is not impressive or even noteworthy. The habit of
cleaning up these problems (or, better, writing code that doesn't have
them in the first place) should be part of every programmer's toolkit.

2) I explicitely disabled optimizations. Apparently you don't. Then,
you got waht you want. ASTOUNDING.

The command I used to compile it was:I don't see any optimization in there. If you do, please tell me where
it is so I can take it out and try again.

1) thompson asks me if I have data for any difference between strchr and
memchr.
2) I take the effort to do it. I provide the data.
3) You start by correcting pedantic warnings. Sure being a pedant like
your mentors you stop there.

I started by making sure I was working with a correct C program.
If you consider this inappropriate, you're posting to the wrong newsgroup.


dave

[1] The obvious comment about frames of reference is Left As An Exercise
For The Reader.
 
S

Stephen Sprunk

jacob navia said:
Instead of strcat Strcat, etc. That's why operator overloading comes
handy since it allows ...

C does not have operator (or any other type of) overloading. You appear
to have, yet again, gotten lost on your way to comp.lang.c++.

<OT> C++ even has a standard "string" object, which does all of the nice
things you're advocating here, and is typically implemented with counted
strings. </OT>

S
 
J

jacob navia

Dave Vandervies a écrit :
[snip]
I started by making sure I was working with a correct C program.
If you consider this inappropriate, you're posting to the wrong newsgroup.


dave

[1] The obvious comment about frames of reference is Left As An Exercise
For The Reader.
root@ubuntu:/tmp# gcc tmemchr.c
root@ubuntu:/tmp# ./a.out
Time for strchr=51
Time for memchr=27
root@ubuntu:/tmp# uname -a
Linux ubuntu 2.6.12-10-386 #1 Fri Sep 15 16:31:49 UTC 2006 i686 GNU/Linux
root@ubuntu:/tmp# cat /proc/cpuinfo
processor : 0
vendor_id : AuthenticAMD
cpu family : 6
model : 8
model name : AMD Sempron(tm) 2500+
stepping : 1
cpu MHz : 1756.400
cache size : 256 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge
mca cmov pat pse36 mmx fxsr sse syscall mp mmxext 3dnowext 3dnow
bogomips : 3489.79

How I did that?
This is Left As An Exercise For The Reader.

In any case it proves my point
strchr is slower by more than 30 % compared to memchr under libc/linux
 
J

jacob navia

Stephen Sprunk a écrit :
C does not have operator (or any other type of) overloading. You appear
to have, yet again, gotten lost on your way to comp.lang.c++.

<OT> C++ even has a standard "string" object, which does all of the nice
things you're advocating here, and is typically implemented with counted
strings. </OT>

S

I have implemented operator overloading in the lcc-win32
coimpiler system. I think it is an improvement to C, without
incurring with all the associated costs of C++.
 
K

Keith Thompson

jacob navia said:
Dave Vandervies a écrit :
[snip]
I started by making sure I was working with a correct C program.
If you consider this inappropriate, you're posting to the wrong newsgroup.
dave
[1] The obvious comment about frames of reference is Left As An
Exercise
For The Reader.
root@ubuntu:/tmp# gcc tmemchr.c

By default, gcc doesn't bother to complain about a lot of things that
it probably should. Try compiling with "-ansi -pedantic -Wall -W".
root@ubuntu:/tmp# ./a.out
Time for strchr=51
Time for memchr=27 [snip]
In any case it proves my point
strchr is slower by more than 30 % compared to memchr under libc/linux

On an x86 platform. I asked whether you had tested it on multiple
platforms. Optimizations that work only on x86 systems are only
slightly interesting.
 
K

Keith Thompson

jacob navia said:
I have implemented operator overloading in the lcc-win32
coimpiler system. I think it is an improvement to C, without
incurring with all the associated costs of C++.

But it isn't C. Do you understand that?
 
C

Chris Torek

Ok, but apart from code that is explicitly non-reentrant (because it
allocates data with limited scoop in a statical fashion), C code will be
reentrant, meaning that any function can call any function, including
itself, without having the functions' "instances" conflicting with each
other...

Using that definition of "re-entrant", yes. That is not the meaning
I usually associate with the word, though. "My" meaning is more
general, and implies that the underlying system (which will use
languages other than C) can switch between processes and/or threads
that share the code, in ways that "see through" things the compiler
has done. For instance, a subroutine call in C is atomic -- nothing
can get between the call in the caller and the start of the callee[%]
-- but at the OS level, it generally is not atomic.

Using this version of "reentrant", C code need not be, and at least
historically often was, not reentrant. Specifically, code like:

struct foo func(struct bar x) {
struct foo val;
...
return val;
}

could, if you thread-switched out from the middle of a call or
return, corrupt the parameters and/or return value. The compilers
would emit "non-reentrant" code -- code that worked OK with
C-compiler-generated recursion, but not with general thread-style
re-entering at arbitrary instruction points -- for handling structure
arguments and/or return values.

[% The exception, sort of, to this claim has to do with signals.
But C's signals are (a) not guaranteed to really work like the
hardware interrupts, e.g., the C system could hold off signals
around subroutine calls, and (b) remove many of the guarantees that
C makes that give it the kind of "C level re-entrancy" you describe
above. In particular, a signal handler can only work with variables
of type "sig_atomic_t" if those variable are also accessed from
outside the handler.]
 
D

Dave Vandervies

jacob navia said:
root@ubuntu:/tmp# gcc tmemchr.c
root@ubuntu:/tmp# ./a.out
Time for strchr=51
Time for memchr=27
[...]

How I did that?
This is Left As An Exercise For The Reader.

I don't think I'll bother. Since you don't seem to be inclined to be
cooperative, it's Highly Unlikely to be worth my time and energy to
figure out why you're claiming results that can't be replicated here.


dave
 
D

Dave Vandervies

root@ubuntu:/tmp# ./a.out
Time for strchr=51
Time for memchr=27 [snip]
In any case it proves my point
strchr is slower by more than 30 % compared to memchr under libc/linux

On an x86 platform.

On his particular x86 system. I couldn't replicate his results on any
of the three x86 systems I tried it on (all run the entire test program
in no more than a few tenths of a second), and nobody else seems to have
though it was worth trying it and posting the results. (On the slowest
of the bunch (the only I tried to find an actual difference on rather
than just re-running the test that navia posted), four billion calls to
either function took a little bit over 200 seconds, with the differences
between them smaller than the error bound on the measurement.)
I asked whether you had tested it on multiple
platforms. Optimizations that work only on x86 systems are only
slightly interesting.

....and optimizations that work only on the x86 system used by the person
claiming the optimization is useful are even less interesting.


dave
 
J

jacob navia

Dave Vandervies a écrit :
root@ubuntu:/tmp# gcc tmemchr.c
root@ubuntu:/tmp# ./a.out
Time for strchr=51
Time for memchr=27

[...]


How I did that?
This is Left As An Exercise For The Reader.


I don't think I'll bother. Since you don't seem to be inclined to be
cooperative, it's Highly Unlikely to be worth my time and energy to
figure out why you're claiming results that can't be replicated here.


dave

#include <stdio.h>
#include <time.h>
#include <string.h>
#define MAXITER 10000000
int main(void){
char s[4096];
int i,c=0;
time_t t,tStrchr,tMemchr;

for (i=0; i<sizeof(s)-1;i++) {
s = 'a';
}
s[sizeof(s)-1] = 0;
t = time(NULL);
for (i=0; i<MAXITER;i++) {
if (strchr(s,'1'))
c++;
}
tStrchr= time(NULL) - t;
printf("Time for strchr=%d\n",tStrchr);
t = time(NULL);
for (i=0; i<MAXITER;i++) {
if (memchr(s,'1',sizeof(s)))
c++;
}
tMemchr=time(NULL)-t;
printf("Time for memchr=%d\n",tMemchr);
return c;
}
 
J

jacob navia

Dave Vandervies a écrit :
Keith Thompson said:
root@ubuntu:/tmp# ./a.out
Time for strchr=51
Time for memchr=27
[snip]

In any case it proves my point
strchr is slower by more than 30 % compared to memchr under libc/linux

On an x86 platform.


On his particular x86 system. I couldn't replicate his results on any
of the three x86 systems I tried it on (all run the entire test program
in no more than a few tenths of a second), and nobody else seems to have
though it was worth trying it and posting the results. (On the slowest
of the bunch (the only I tried to find an actual difference on rather
than just re-running the test that navia posted), four billion calls to
either function took a little bit over 200 seconds, with the differences
between them smaller than the error bound on the measurement.)

I asked whether you had tested it on multiple
platforms. Optimizations that work only on x86 systems are only
slightly interesting.


...and optimizations that work only on the x86 system used by the person
claiming the optimization is useful are even less interesting.


dave

I have sent you elsethread the corrected program.
Since now gcc optimizes even when it is not told
to do that, you have to trick it into generating code
for the program you wrote, not for the program gcc
think you should have written.

#include <stdio.h>
#include <time.h>
#include <string.h>
#define MAXITER 10000000
int main(void){
char s[4096];
int i;
time_t t,tStrchr,tMemchr;

for (i=0; i<sizeof(s)-1;i++) {
s = 'a';
}
s[sizeof(s)-1] = 0;
t = time(NULL);
for (i=0; i<MAXITER;i++) {
strchr(s,'1');
}
tStrchr= time(NULL) - t;
printf("Time for strchr=%d\n",tStrchr);
t = time(NULL);
for (i=0; i<MAXITER;i++) {
memchr(s,'1',sizeof(s));
}
tMemchr=time(NULL)-t;
printf("Time for memchr=%d\n",tMemchr);
}
 
J

jacob navia

DAMM!!!!!
I sent you the wrong one.

Here is the one with the necessary corrections for gcc.

1) new variable c, is incremented at
each function call. Then the compiler
cab't optimize the call away.

To avoid that the variable is discarded
main returns that value


jacob navia a écrit :
I have sent you elsethread the corrected program.
Since now gcc optimizes even when it is not told
to do that, you have to trick it into generating code
for the program you wrote, not for the program gcc
think you should have written.

#include <stdio.h>
#include <time.h>
#include <string.h>
#define MAXITER 10000000
int main(void){
char s[4096];
int i,c=0;
time_t t,tStrchr,tMemchr;

for (i=0; i<sizeof(s)-1;i++) {
s = 'a';
}
s[sizeof(s)-1] = 0;
t = time(NULL);
for (i=0; i<MAXITER;i++) {
if (strchr(s,'1'))

c++;
;
}
tStrchr= time(NULL) - t;
printf("Time for strchr=%d\n",tStrchr);
t = time(NULL);
for (i=0; i<MAXITER;i++) {
if( memchr(s,'1',sizeof(s)))
c++;
 
A

Andrew Sidwell

jacob navia wrote:
In any case it proves my point
strchr is slower by more than 30 % compared to memchr under libc/linux

dougal(~/navia) cat chr.c
#include <stdio.h>
#include <string.h>
#define MAXITER 100000000

int main(void)
{
char s[4096];
int i;

memset(&s, 'a', sizeof(s) - 1);
s[sizeof(s)-1] = 0;

for (i = 0; i < MAXITER; i++)
{
#ifdef MEMCHR
memchr(s, '1', sizeof s)
#else
strchr(s, '1')
#endif
}

return 0;
}
dougal(~/navia) gcc -O0 chr.c -o strchr
dougal(~/navia) time ./strchr
real 0m1.403s
user 0m0.990s
sys 0m0.040s
dougal(~/navia) time ./strchr
real 0m1.743s
user 0m1.000s
sys 0m0.050s
dougal(~/navia) time ./strchr
real 0m1.212s
user 0m1.000s
sys 0m0.050s

dougal(~/navia) gcc -O0 chr.c -DMEMCHR -o memchr
dougal(~/navia) time ./memchr
real 0m1.874s
user 0m1.010s
sys 0m0.020s
dougal(~/navia) time ./memchr
real 0m1.485s
user 0m1.030s
sys 0m0.030s
dougal(~/navia) time ./memchr
real 0m1.282s
user 0m0.990s
sys 0m0.020s

I can see no clear pattern in the performance of the two functions, and
believe that your claim is unsubstantiated.

/proc/cpuinfo says that the processor this was run on was a 735Hz VIA
Ezra (x86) processor, with the flags "fpu de tsc msr cx8 mtrr pge mmx
3dnow", and a 64KB cache.


Andrew Sidwell
 
A

Andrew Sidwell

Andrew Sidwell wrote:
#ifdef MEMCHR
memchr(s, '1', sizeof s)
#else
strchr(s, '1')
#endif
<snip>

Ouch. Please pretend I wrote semicolons at the end of the two lines
which don't start with '#'.

Andrew Sidwell
 
J

jacob navia

Andrew Sidwell a écrit :
jacob navia wrote:
In any case it proves my point
strchr is slower by more than 30 % compared to memchr under libc/linux


dougal(~/navia) cat chr.c
#include <stdio.h>
#include <string.h>
#define MAXITER 100000000

int main(void)
{
char s[4096];
int i;

memset(&s, 'a', sizeof(s) - 1);
s[sizeof(s)-1] = 0;

for (i = 0; i < MAXITER; i++)
{
#ifdef MEMCHR
memchr(s, '1', sizeof s)
#else
strchr(s, '1')
#endif
}

return 0;
}
dougal(~/navia) gcc -O0 chr.c -o strchr
dougal(~/navia) time ./strchr
real 0m1.403s
user 0m0.990s
sys 0m0.040s
dougal(~/navia) time ./strchr
real 0m1.743s
user 0m1.000s
sys 0m0.050s
dougal(~/navia) time ./strchr
real 0m1.212s
user 0m1.000s
sys 0m0.050s

dougal(~/navia) gcc -O0 chr.c -DMEMCHR -o memchr
dougal(~/navia) time ./memchr
real 0m1.874s
user 0m1.010s
sys 0m0.020s
dougal(~/navia) time ./memchr
real 0m1.485s
user 0m1.030s
sys 0m0.030s
dougal(~/navia) time ./memchr
real 0m1.282s
user 0m0.990s
sys 0m0.020s

I can see no clear pattern in the performance of the two functions, and
believe that your claim is unsubstantiated.

/proc/cpuinfo says that the processor this was run on was a 735Hz VIA
Ezra (x86) processor, with the flags "fpu de tsc msr cx8 mtrr pge mmx
3dnow", and a 64KB cache.


Andrew Sidwell

Obviously there is something wrong since in a MUCH faster machine
for 100 million iterations I take 84/43 SECONDS and you take not even
a second...

I explicitely said that you should NOT set any optimizations, and you
compiled with O0. O0 DOES some optimizations, so this is quite dangerous
with benchmarks. I would suggest that you use this program without any
optimizations at all:

#include <stdio.h>
#include <time.h>
#include <string.h>
#define MAXITER 10000000
int main(void){
char s[4096];
int i,c=0;
time_t t,tStrchr,tMemchr;

for (i=0; i<sizeof(s)-1;i++) {
s = 'a';
}
s[sizeof(s)-1] = 0;
t = time(NULL);
for (i=0; i<MAXITER;i++) {
if(strchr(s,'1'))
c++;;
}
tStrchr= time(NULL) - t;
printf("Time for strchr=%d\n",tStrchr);
t = time(NULL);
for (i=0; i<MAXITER;i++) {
if(memchr(s,'1',sizeof(s)))
c++;
}
tMemchr=time(NULL)-t;
printf("Time for memchr=%d\n",tMemchr);
return c;
}

The additions to the variable "c" disable any optimization
of the calls away. Besides, main returns that value
and this means that gcc must generate the code as told.

It is very disappointing that compilers optimize when told
not to!!!

jacob
 
R

Randy Howard

Dave Vandervies a écrit :
[snip]
I started by making sure I was working with a correct C program.
If you consider this inappropriate, you're posting to the wrong newsgroup.


dave

[1] The obvious comment about frames of reference is Left As An Exercise
For The Reader.
root@ubuntu:/tmp# gcc tmemchr.c
root@ubuntu:/tmp# ./a.out
Time for strchr=51
Time for memchr=27
root@ubuntu:/tmp# uname -a
Linux ubuntu 2.6.12-10-386 #1 Fri Sep 15 16:31:49 UTC 2006 i686 GNU/Linux [snip]

In any case it proves my point
strchr is slower by more than 30 % compared to memchr under libc/linux

Maybe so, but it takes over 2 minutes to complete on a PPC (dual G5
2.0GHz) system when compiled with gcc. It outputs 0.000000 for the
strchr, and just goes off into the weeds for the memchr portion.

By dividing the iteration count by 10, I get:

Time for strchr=0.000000
Time for memchr=13.000000

So much for any theory that this method is generally applicable.

Even by using -O3 during compilation, it only shaves a second off the
memchr timing.
 
R

Randy Howard

Dave Vandervies a écrit :
Keith Thompson said:
root@ubuntu:/tmp# ./a.out
Time for strchr=51
Time for memchr=27

[snip]

In any case it proves my point
strchr is slower by more than 30 % compared to memchr under libc/linux

On an x86 platform.


On his particular x86 system. I couldn't replicate his results on any
of the three x86 systems I tried it on (all run the entire test program
in no more than a few tenths of a second), and nobody else seems to have
though it was worth trying it and posting the results. (On the slowest
of the bunch (the only I tried to find an actual difference on rather
than just re-running the test that navia posted), four billion calls to
either function took a little bit over 200 seconds, with the differences
between them smaller than the error bound on the measurement.)

I asked whether you had tested it on multiple
platforms. Optimizations that work only on x86 systems are only
slightly interesting.


...and optimizations that work only on the x86 system used by the person
claiming the optimization is useful are even less interesting.


dave

I have sent you elsethread the corrected program.
Since now gcc optimizes even when it is not told
to do that, you have to trick it into generating code
for the program you wrote, not for the program gcc
think you should have written.

#include <stdio.h>
#include <time.h>
#include <string.h>
#define MAXITER 10000000
int main(void){
char s[4096];
int i;
time_t t,tStrchr,tMemchr;

for (i=0; i<sizeof(s)-1;i++) {
s = 'a';
}
s[sizeof(s)-1] = 0;
t = time(NULL);
for (i=0; i<MAXITER;i++) {
strchr(s,'1');
}
tStrchr= time(NULL) - t;
printf("Time for strchr=%d\n",tStrchr);
t = time(NULL);
for (i=0; i<MAXITER;i++) {
memchr(s,'1',sizeof(s));
}
tMemchr=time(NULL)-t;
printf("Time for memchr=%d\n",tMemchr);
}


Same as before on the PPC G5. strchr takes zero time to complete,
memchr takes forever.
 
R

Randy Howard

DAMM!!!!!
I sent you the wrong one.

Here is the one with the necessary corrections for gcc.

1) new variable c, is incremented at
each function call. Then the compiler
cab't optimize the call away.

To avoid that the variable is discarded
main returns that value


jacob navia a écrit :
I have sent you elsethread the corrected program.
Since now gcc optimizes even when it is not told
to do that, you have to trick it into generating code
for the program you wrote, not for the program gcc
think you should have written.

#include <stdio.h>
#include <time.h>
#include <string.h>
#define MAXITER 10000000
int main(void){
char s[4096];
int i,c=0;
time_t t,tStrchr,tMemchr;

for (i=0; i<sizeof(s)-1;i++) {
s = 'a';
}
s[sizeof(s)-1] = 0;
t = time(NULL);
for (i=0; i<MAXITER;i++) {
if (strchr(s,'1')) c++;
;
}
tStrchr= time(NULL) - t;
printf("Time for strchr=%d\n",tStrchr);
t = time(NULL);
for (i=0; i<MAXITER;i++) {

if( memchr(s,'1',sizeof(s)))
c++;
}
tMemchr=time(NULL)-t;
printf("Time for memchr=%d\n",tMemchr); return c;
}




Again, I had to reduce the MAXITER value by dividing it by 10 to get
reasonable run times.

Anyway, here is the output:
Time for strchr=17
Time for memchr=13

Okay, you managed to make gcc on the PPC G5 hate them both now. I'm
not sure what that is supposed to prove. Are we to assume people care
about best performance when compiling with optimization turned off?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,117
Latest member
Matilda564
Top