jahboater
Posts: 5419
Joined: Wed Feb 04, 2015 6:38 pm
Location: West Dorset

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 1:48 pm

DavidS wrote:
Wed Dec 12, 2018 12:42 pm
Actually C can not, not while following the standard. what you are talking about is implementation specific extensions to the language.
Not in the standard yes, but supported by all the tier-1 compilers GCC, CLANG, ARMCC, ICC (intels compiler).

For comparison, say in BBC Basic or whatever, how would you export the NZCV flags for direct use in the surrounding code?
and what would the code look like?
Something like "mov r1,#0; adds r,r,r; movcs r1,#1" then later in the code "cmp r1,#1" and continue? is horrible - an extra three instructions and an extra register used.

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 2:33 pm

jahboater wrote:
Wed Dec 12, 2018 1:48 pm
DavidS wrote:
Wed Dec 12, 2018 12:42 pm
Actually C can not, not while following the standard. what you are talking about is implementation specific extensions to the language.
Not in the standard yes, but supported by all the tier-1 compilers GCC, CLANG, ARMCC, ICC (intels compiler).

For comparison, say in BBC Basic or whatever, how would you export the flags for direct use in the surrounding code?
and what would the code look like?
Something like "mov r1,#0; adds r,r,r; movcs r1,#1" then later in the code "cmp r1,#1" and continue? is horrible - an extra three instructions and an extra register used.
It is only supported by the compilers that try to imitate one another. And I would not bother trying to mix assembly in that way so I do not know how it would be in BBC BASIC V (though I do remember reading in one of the manuals that there is a way to do it without having to store the flags). Assembly should really be entire functions if used in an HLL.

If I am going to write inline assembly I will write entire functions/procedures in assembly (any language). When using compilers of the gcc style inline assembly I do not do inline, I write the assembly in a separate assembly source assemble and link.

I truly do miss the C compilers that were common that implemented the asm keyword as a function modifier, thus making an entire function assembly (without any quoted listing strings), as that is the way to do assembly mixed into C. For examples see Pure C (68K versions), AHCC, and if memory serves !EasyC, the first two are 68K, and !EasyC is ARM targeting (PureC Amiga/Atari ST series/Sinclair QL, AHCC Atari ST series, !EasyC RISC OS). Unfortunately now many attempt to imitate the ways of each other making for even more confusion.

I will not use gcc or copycat compilers on anything outside of Linux, not anymore (The last being the attempt earlier this thread to compile Linux target stuff on RISC OS). I never have used gcc or the copycats on Amiga OS/AROS or TOS+MiNT based systems of any kind, preferring more reasonable C compilers.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

ejolson
Posts: 4866
Joined: Tue Mar 18, 2014 11:47 am

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 3:49 pm

Heater wrote:
Wed Dec 12, 2018 10:27 am
Yay!
Good news. It would nice to suppress the leading zeros so only a million digits are printed.

I wonder whether the 60-fold performance difference is from the memory allocations or from using Karatsuba all the way down to 1-digit numbers. As I mentioned in my previous post, using the efficient algorithm in the asymptotic regime is an important part of understanding it. Maybe switching to the O(n^2) algorithm when numbers are less than 10 or 100 digits would make up most of the loss. Perhaps someone can profile your code like they did mine.

User avatar
Paeryn
Posts: 2900
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 4:01 pm

DavidS wrote:
Wed Dec 12, 2018 2:33 pm
I will not use gcc or copycat compilers on anything outside of Linux, not anymore (The last being the attempt earlier this thread to compile Linux target stuff on RISC OS). I never have used gcc or the copycats on Amiga OS/AROS or TOS+MiNT based systems of any kind, preferring more reasonable C compilers.
What do you find unreasonable about GCC? The only downside I have with it is that you can't build a single version that lets you choose the target CPU other than variants of a family, but that just means you need separate builds for cross compiling. Other than that it has standards compliant C and C++ compilers that can be built for many different CPUs including targetting a different CPU than the host. Not to mention the other languages GCC supports (e.g. Objective-C/C++, Fortran, Ada and Go, the next version will have a D compiler also).

I used to use GCC on the Amiga (just checked the timeline, it would've been back at version 2.5.7 or 2.5.8), though due to memory and disk limitations I had a cross compiler set up on the Uni workstations for anything substantial.
She who travels light — forgot something.

jahboater
Posts: 5419
Joined: Wed Feb 04, 2015 6:38 pm
Location: West Dorset

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 6:20 pm

DavidS wrote:
Wed Dec 12, 2018 2:33 pm
I will not use gcc or copycat compilers on anything outside of Linux, not anymore (The last being the attempt earlier this thread to compile Linux target stuff on RISC OS).
You know that problem was because you were running an ancient version of GCC on RISC OS.

Heater
Posts: 15368
Joined: Tue Jul 17, 2012 3:02 pm

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 7:34 pm

What is all this nonsense about inline assembler and carry flags and other such machine specific things in C ?

There is no such thing in the C language specification. Which is as it should be.

Yes, it's convenient that C compilers have extensions to do this kind of thing when it is needed.

In general, in a cross-platform way it makes no sense. Even if you have the same "asm" syntax you cannot know that the target is of the architecture you have written your asm for. Even if it is a similar architecture, x86, ARM, whatever, you cannot be sure the target actually has the instructions you are using in your "asm" statements. There are many variants in x86, ARM and other worlds.

Heck, some processors don't even have a "carry" or other machine status bits.

If you think you are optimizing your code by using big "asm" blocks you are probably deluded.
Memory in C++ is a leaky abstraction .

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 7:52 pm

Heater wrote:
Wed Dec 12, 2018 7:34 pm
What is all this nonsense about inline assembler and carry flags and other such machine specific things in C ?

There is no such thing in the C language specification. Which is as it should be.

Yes, it's convenient that C compilers have extensions to do this kind of thing when it is needed.

In general, in a cross-platform way it makes no sense. Even if you have the same "asm" syntax you cannot know that the target is of the architecture you have written your asm for. Even if it is a similar architecture, x86, ARM, whatever, you cannot be sure the target actually has the instructions you are using in your "asm" statements. There are many variants in x86, ARM and other worlds.

Heck, some processors don't even have a "carry" or other machine status bits.

If you think you are optimizing your code by using big "asm" blocks you are probably deluded.
There is a place for assembly in C, and I agree with you in that it is not for optimization so much. Though if reading writing CPU/MMU specific registers for things like setting up cahces, setting up the pagetables, etc, you need to have some assembly, and doing so as an entire function is a lot better than the inline crud of gcc, not to mention that when you have to use assembly in C it should be as clear as it would be in a stand alone Assembly Source, so the strings used in the gcc style asm implementation are kind of useless, just promoting the usage of stand alone assembler sources to be assembled to static linkage objects to be linked in after compile (probably the better way around it anyway).

Though I agree with you again that it is not in the Standard (the point I made above) on how the asm keyword is to be implemented, or even if it is to be implemented (it is one of two keywords that are optional and implementation defined according to the standard).
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 7:57 pm

Heater wrote:
Wed Dec 12, 2018 10:27 am
Yay!

The fibo kartasuba in C++ finally works. Yabba dabba dodda!

Code: Select all

$ g++ -Wall -O3 -o fibo_karatsba fibo_karatsba.cpp bint.cpp -I.
$ time ./fibo_karatsba | head  -c 32
00000000107273956418004772293648
real    1m37.786s
user    1m37.531s
sys     0m0.047s

$ time ./fibo_karatsba | tail  -c 32
4856539211500699706378405156269

real    1m37.490s
user    1m37.313s
sys     0m0.078s
Here is the top level code:

Code: Select all

#include <bint.h>
#include <time.h> 

bint zero = "0";
bint one = "1";
bint two = "2";

bint memo[] = {zero, one, one};

int isEven(int n)
{
    return (n & 1) == 0;
}

bint fibo (int n)
{
    if (n <= 2)
    {
        return memo[n];
    }
    else
    {
        int k = (n / 2);
        bint fk = fibo(k);
        bint fk1 = fibo(k + 1);
        if (isEven(n))
        {
            return fk * (fk1 * two - fk);
        }
        return (fk * fk) + (fk1 * fk1);
    }
}

int main (int argc, char* argv[])
{
    bint res = fibo(4784969);

    std::cout << res << std::endl;
    return 0;
}
In terms of expressiveness I think it's gorgeous. It spells out the fast fibo algorithm as clearly as the Python or Javascript versions. DavidS should be happy, it looks just like C does it not? Except for that mysterious "bint" data type.

Same expressiveness is holds for the karatsuba multiply algorithm. Which closely resembles the pseudo code on Wikipedia:

Code: Select all

bint bint::mul (const bint& b)
{
    // The base case(s), only one element in value, just do the multiply
    if (width == 1)
    {
        return b.simpleMul(value[0]);
    }
    if (b.width == 1)
    {
        return simpleMul(b.value[0]);
    }
    // Calculates the size of the numbers
    int m = (this->width);
    int m2 = m / 2;

    // Split the numbers in the middle
    bint high1 = this->high(m2);
    bint low1 = this->low(m2);
    bint high2 = b.high(m2);
    bint low2 = b.low(m2);

    // Do da karatsaba shuffle, yabba dabba do.
    bint z0 = low1 * low2;
    bint z1 = (low1 + high1) * (low2 + high2);
    bint z2 = high1 * high2;

    bint s1 = z1 - z2;
    bint s2 = s1 - z0;

    return  z2.shift(m2 * 2) + s2.shift(m2) + z0;
}
Of course... things are a bit more involved under the hood of that mysterious bint type. The code is here: https://github.com/ZiCog/fibo_4784969/b ... B/bint.cpp for your perusal and comment.
Sorry I missed this earlier when you posted it.

Nice work, and this looks like the version to convert to object oriented FreeBASIC, so off I go for starting on this conversion. Sorry if I am a bit off today, I just got home from the dentist a few minutes ago, having had a root canal done.

Though how did you get any version to run in under 1min 40 seconds on an RPi? Which must be the quoted times, as that is a specific part of this whole thing.
But what about performance?

Well, it sucks. On this PC it's about 60 times slower than ejolson's C version. On the other hand it's over 3 times faster than the karatsuba in javascript version and uses 10 times less memory!

Hardly surprising seeing as I'm naively new'ing and free'ing all over the space for intermediate big integer values and there is a lot of array copying going on. I have to see what I can do about that.

Interestingly my C++ version is only a few source lines more than ejolson's C version, 261 vs 289. So much for DavidS' claims about C++ requiring a lot more lines of code.
Now now, I said C++ makes it easy to add more lines of code, and encourages such. Not that it has to add more lines of code.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

Heater
Posts: 15368
Joined: Tue Jul 17, 2012 3:02 pm

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 8:16 pm

DavidS,
Nice work, ...
Thank you. It was a struggle...
...looks like the version to convert to object oriented FreeBASIC...
Perhaps. Or perhaps there is a better way to do it.
...so off I go for starting on this conversion.
Wait... I thought you agreed previously to do it the easy way, in ARM assembler.
Now now, I said C++ makes it easy to add more lines of code, and encourages such. Not that it has to add more lines of code.
Still not true though. Or no more so than any other language.
Memory in C++ is a leaky abstraction .

User avatar
Paeryn
Posts: 2900
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 8:17 pm

Heater wrote:
Wed Dec 12, 2018 10:27 am
Yay!

The fibo kartasuba in C++ finally works. Yabba dabba dodda!

Code: Select all

$ g++ -Wall -O3 -o fibo_karatsba fibo_karatsba.cpp bint.cpp -I.
$ time ./fibo_karatsba | head  -c 32
00000000107273956418004772293648
real    1m37.786s
user    1m37.531s
sys     0m0.047s
I take it that's not on an RPi? I just realised I'm timing it with profiling but it's already taken 15 minutes <addendum: it finished in 22m 36s>.

You have a strange way of including bint.h, normally <bint.h> is used for a system header (or at least a globally installed header) and "bint.h" is used for a local header. The standard sort of says so but leaves it up to the implementation to define what the default search paths for both. GCC doesn't look in the current directory with <bint.h> for a reason (so you can't accidentally override a system header with a local header). I didn't originally see that you overrode the behaviour by forcibly including the current directory in both search paths, by using "bint.h" you don't need the -I. at the end of your compile command.
C++ spec wrote: Although an implementation may provide a mechanism for making arbitrary source files available to the < > search, in general programmers should use the < > form for headers provided with the implementation, and the " " form for sources outside the control of the implementation.
She who travels light — forgot something.

Heater
Posts: 15368
Joined: Tue Jul 17, 2012 3:02 pm

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 8:19 pm

DavidS,

Sorry, forgot, about the run time.

I'm doing all this on my PC. I don't have a Pi to hand to test on. I suspect that it will be an order of magnitude slower on the Pi.
Memory in C++ is a leaky abstraction .

jahboater
Posts: 5419
Joined: Wed Feb 04, 2015 6:38 pm
Location: West Dorset

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 8:28 pm

Heater wrote:
Wed Dec 12, 2018 7:34 pm
In general, in a cross-platform way it makes no sense. Even if you have the same "asm" syntax you cannot know that the target is of the architecture you have written your asm for. Even if it is a similar architecture, x86, ARM, whatever, you cannot be sure the target actually has the instructions you are using in your "asm" statements. There are many variants in x86, ARM and other worlds.
You can do that. There are countless target specific definitions, so with simple conditional compilation it becomes portable.
#ifdef __AVX__
something fast that's Intel AVX specific
#else
something slow thats 100% portable
#endif
Works fine and if its an old PC that only has SSE, or some other non-x86 platform, or some other compiler even, it will compile the slow stuff.
Heater wrote:
Wed Dec 12, 2018 7:34 pm
Heck, some processors don't even have a "carry" or other machine status bits.
You mean RISC V :(
Heater wrote:
Wed Dec 12, 2018 7:34 pm
If you think you are optimizing your code by using big "asm" blocks you are probably deluded.
Yes, agreed. Keep it to the bare minimum. One line max to exploit some hardware feature for the rare cases the compiler didn't do it itself or didn't provide an intrinsic. And always provide a portable, standards compliant, alternative, that's automatically selected.
Last edited by jahboater on Wed Dec 12, 2018 8:37 pm, edited 1 time in total.

Heater
Posts: 15368
Joined: Tue Jul 17, 2012 3:02 pm

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 8:37 pm

Paeryn,

Thanks for taking a look. I appreciate it.
I take it that's not on an RPi?
Sorry, yes, I should have made that clear. See my last post.
You have a strange way of including bint.h, normally <bint.h> is used for a system heade
Good point. Thanks. Not what I normally do. I will fix it.
I just realised I'm timing it with profiling but it's already taken 15 minute...
Ha!. Time for a funny story...

As I was hacking on this I compiled it with address sanitizer enabled. Like so:

Code: Select all

$ g++ -Wall -O0 -ggdb -fsanitize=address -fno-omit-frame-pointer -o bint_test bint_test.cpp bint.cpp -I.
After all, who would not want to know about "use after free" and memory leak errors as they develop stuff. C++ is so crazy you need those kind of tools to stay sane.

Well, when it was running well enough to calculate fibo(20000) I let it rip on fibo(4784969). It was taking some time so I left it and went to sleep.

Many hours later I return to find it is still running! It is using all my memory and thrashing swap space very heavily.

Then I realize my mistake. I forgot to compile without address sanitizer enabled.

So... that thing had been hammering on my SSD all night. No doubt shortening it's life by years.
Memory in C++ is a leaky abstraction .

jahboater
Posts: 5419
Joined: Wed Feb 04, 2015 6:38 pm
Location: West Dorset

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 8:42 pm

Heater wrote:
Wed Dec 12, 2018 8:37 pm
Well, when it was running well enough to calculate fibo(20000) I let it rip on fibo(4784969). It was taking some time so I left it and went to sleep.

Many hours later I return to find it is still running! It is using all my memory and thrashing swap space very heavily.

Then I realize my mistake. I forgot to compile without address sanitizer enabled.
I've been looking at translating fibo.c to D. But first I have tidied up the C stuff a bit because there is much the D doesnt like. Fibo.c runs in 1.4 seconds and with valgrind 44.5 seconds.

Now that's strange because valgrind is far far slower than the address sanitizer.

What is taking all night???

Heater
Posts: 15368
Joined: Tue Jul 17, 2012 3:02 pm

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 8:58 pm

jahboater,
You can do that. There are countless target specific definitions, so with simple conditional compilation it becomes portable.
Simple?

Some years ago I was involved in a project that had to run on Windows, Mac and Linux such that the various developers could work on it and exercise it. As part of a simulation it was expected to run on those platforms as a finished product.

But it was also the core of embedded system control. As such it had to run on old PSOS and VxWorks embedded operating systems, as well as the new Linux based embedded systems.

Which also meant it had to run on old Motorola 68000 and PowerPC based hardware. Then x86 and ARM based hardware.

That soup of "simple conditional compilation" grew into a nightmare of nested #define and #ifdef all around the code that became very hard to maintain correctly.

At some point we have to say "f'it". We have to say "I am the programmer, this is my program, you as a language compiler/run time creator or OS creator or hardware creator only have one job in life, make my program run. As it is writen."

So far, after decades of development and billions of dollars spent the closest we have come to that is Python and Javascript.

Makes you think does it not?
Memory in C++ is a leaky abstraction .

Heater
Posts: 15368
Joined: Tue Jul 17, 2012 3:02 pm

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 9:11 pm

jahboater,
Now that's strange because valgrind is far far slower than the address sanitizer.

What is taking all night???
That is a good question.

In the past I have seen that valgrind was very slow.

Recently I was happy to see the sanitizers are much faster.

So what is going on there?

Well, not often have I been using such tools on programs that relied on millions and millions of new's and delete's. Mostly I have used them on small test cases.

Then this is running on the Linux Subsystem for Windows. I have no idea how well that handles memory allocation.

I don't know...
Memory in C++ is a leaky abstraction .

Heater
Posts: 15368
Joined: Tue Jul 17, 2012 3:02 pm

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 9:15 pm

ejolson,
Good news. It would nice to suppress the leading zeros so only a million digits are printed
Dang! You spotted the bug there. I'll fix it.
I wonder whether the 60-fold performance difference is from the memory allocations or from using Karatsuba all the way down to 1-digit numbers.
I wonder too.

My gut tells me that just now most of the time is going to all those allocs and frees and memcpy's that happen as all those temporary values come and go.

For example: Every time we split the operands of karatsuba by two there are four allocations and memcpys going on. Which is redundant, there is no need to make copies of the low and high halves of a number, just reference the low and high halves of the original number arrays somehow.

In general when there is an "a = b + c" if b or c are never used again why not just do the addition into there and call the result "a". No need to alloc a new space and add into that.

I'm sure the cut off between "karatsuba" and "schoolboy" multiplication has a big effect. I have no feel for how just yet.

I'd love it if someone would profile this thing.

In the mean time I have some ideas to tweak around with "new" and "delete". We don't need to use those, we can put whatever memory allocation we like in there. I can imagine a stack allocator used the the right places would have a huge effect.

The question in my mind now is: How far can one optimize things under the hood, whilst keeping the top level code mostly the same?
Memory in C++ is a leaky abstraction .

jahboater
Posts: 5419
Joined: Wed Feb 04, 2015 6:38 pm
Location: West Dorset

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 9:33 pm

Heater wrote:
Wed Dec 12, 2018 9:11 pm
Well, not often have I been using such tools on programs that relied on millions and millions of new's and delete's.
That could be it. The sanitizers and valgrind have to record the result of each malloc call (usually a private version of malloc that leaves fences around the memory block). Every memory access must be checked against them. I can imagine that's slow.

Maybe you have run out of memory and its been swapping all night? :( :(

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Why Avoid BASIC on RPi?

Wed Dec 12, 2018 10:19 pm

Heater wrote:
Wed Dec 12, 2018 8:16 pm
Wait... I thought you agreed previously to do it the easy way, in ARM assembler.
You are of course correct. I did say I had just gotten home from the dentist, and now the numb is wearing off.
DavidS wrote: Now now, I said C++ makes it easy to add more lines of code, and encourages such. Not that it has to add more lines of code.
Still not true though. Or no more so than any other language.
I do not know, I very often see C++ code done using way more lines of code than the same thing implemented in another language, often even by the same person, Noting that your source spans 3 files and is over 340 lines (not sure how many lines of code, have not taken the time to strip and count yet), while the C version is under 300 lines (and only 262 lines of code) should say something.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

User avatar
Paeryn
Posts: 2900
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: Why Avoid BASIC on RPi?

Thu Dec 13, 2018 12:22 am

Heater, quick profile of your code. It doesn't count time spent in external code (e.g. memory allocations) which is probably why it says it executes in 212 seconds even though it was more like 1320 seconds. I had optimisations at -O3 but disabled inlining to get better accounts of which function the samples were taken in (100 samples per second).

Code: Select all

  %   cumulative   self              self     total
 time   seconds   seconds    calls  us/call  us/call  name
 30.00     63.72    63.72 566907180     0.11     0.13  bint::sum(bint const&)
 19.40    104.94    41.22   7472782     5.52    28.30  bint::mul(bint const&)
 13.69    134.03    29.09 1987010609    0.01     0.01  bint::bint(unsigned int)
 13.21    162.09    28.06 283601255     0.10     0.11  bint::sub(bint const&)
  9.31    181.86    19.77 289730130     0.07     0.11  bint::simpleMul(unsigned long long) const
  4.63    191.70     9.84 311499166     0.03     0.03  bint::grow()
  3.42    198.97     7.27 282257348     0.03     0.04  bint::high(int) const
  3.08    205.51     6.54 282257348     0.02     0.04  bint::low(int) const
  3.03    211.94     6.43 282257348     0.02     0.04  bint::shift(int)
  0.12    212.19     0.25                              fibo(int)
  0.06    212.32     0.13  14945566     0.01     0.01  bint::~bint()
  0.05    212.42     0.10   3736392     0.03     0.03  bint::bint(bint const&)
  0.00    212.43     0.01                              operator<<(std::ostream&, bint const&)
She who travels light — forgot something.

User avatar
Paeryn
Posts: 2900
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: Why Avoid BASIC on RPi?

Thu Dec 13, 2018 4:12 am

Oh... I was replying to ejolson's question about why __udivmoddi4 wasn't listed only to get a message that their post didn't exist, lost what I'd written.
Anyway, long story short, it was down to it being in a shared library this time which gprof doesn't report (I assume C++ is linking libgcc dynamically whereas C was linking it statically). I've re-run it with static linkage, edited some of the library calls out that aren't relevant to the main working of fibo

Code: Select all

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total
 time   seconds   seconds    calls  us/call  us/call  name
 21.12    193.61   193.61                             _int_free
 17.25    351.77   158.16                             malloc
 15.06    489.78   138.01                             _int_malloc
  7.50    558.52    68.74                             memset
  7.16    624.11    65.59 566907180     0.12     0.12  bint::sum(bint const&)
  5.96    678.79    54.68                             memcpy
  4.31    718.28    39.49                             cfree
  4.02    755.16    36.88  7472782     4.93    22.38  bint::mul(bint const&)
  2.91    781.87    26.71 283601255     0.09     0.09  bint::sub(bint const&)
  2.76    807.14    25.27 289730130     0.09     0.09  bint::simpleMul(unsigned long long) const
  2.39    851.24    21.88                             operator new(unsigned int)
  1.96    869.24    18.00                             __udivmoddi4
  0.73    875.97     6.73 282257348     0.02     0.02  bint::high(int) const
  0.71    882.44     6.47 282257348     0.02     0.02  bint::low(int) const
  0.54    887.39     4.95                             __aeabi_uldivmod
  0.31    890.22     2.83                             _mid_memalign
  0.30    892.96     2.74                             munmap_chunk
  0.25    895.21     2.25                             operator delete(void*)
  0.24    897.39     2.18                             malloc_set_state
  0.22    899.42     2.03                             sysmalloc
  0.14    907.57     1.29                             memmove
  0.14    908.83     1.26                             malloc_consolidate
  0.13    910.05     1.22                             operator delete[](void*)
  0.10    914.49     0.95                             operator new[](unsigned int)
  0.07    915.17     0.68                             __aeabi_ldiv0
  0.03    915.82     0.26                             memcmp
  0.02    916.01     0.19                             fibo(int)
  0.02    916.16     0.15 14945570     0.01     0.01  bint::~bint()
  0.01    916.29     0.14                             bint::grow()
  0.01    916.53     0.12                             bint::shift(int)
  0.01    916.60     0.07  3736392     0.02     0.02  bint::bint(bint const&)
  0.00    916.68     0.01                             bint::operator=(char const*)
  0.00    916.70     0.01                             isEven(int)
  0.00    916.70     0.00        1     0.00     0.00  main
She who travels light — forgot something.

ejolson
Posts: 4866
Joined: Tue Mar 18, 2014 11:47 am

Re: Why Avoid BASIC on RPi?

Thu Dec 13, 2018 6:54 am

Paeryn wrote:
Thu Dec 13, 2018 4:12 am
Oh... I was replying to ejolson's question about why __udivmoddi4 wasn't listed only to get a message that their post didn't exist, lost what I'd written.
Sorry, I finally realized what you meant by
It doesn't count time spent in external code
and retracted my question. I didn't know your reply would get lost.

Heater
Posts: 15368
Joined: Tue Jul 17, 2012 3:02 pm

Re: Why Avoid BASIC on RPi?

Thu Dec 13, 2018 7:29 am

DavidS,
Noting that your source spans 3 files...
That is somewhat irelavent. It normal practice in both C and C++ to have header and source files and to organize related functionality into different source files.
...and is over 340 lines (not sure how many lines of code, have not taken the time to strip and count yet), while the C version is under 300 lines (and only 262 lines of code)...
A common tool to count source lines of code is cloc which results in the following for the c and c++ solutions:

Code: Select all

$ cloc c++/bint.cpp  c++/bint.h c++/fibo_karatsba.cpp
       3 text files.
       3 unique files.
       0 files ignored.

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C++                              2             50             14            289
C/C++ Header                     1             20              0             45
-------------------------------------------------------------------------------
SUM:                             3             70             14            334
-------------------------------------------------------------------------------

$ cloc c/fibonacci.c
       1 text file.
       1 unique file.
       0 files ignored.

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C                                1             23             15            261
-------------------------------------------------------------------------------
... should say something.
Yes. It says your claims are unsubstantiated.
Memory in C++ is a leaky abstraction .

Heater
Posts: 15368
Joined: Tue Jul 17, 2012 3:02 pm

Re: Why Avoid BASIC on RPi?

Thu Dec 13, 2018 7:31 am

jahboater,
Maybe you have run out of memory and its been swapping all night?
That is exactly what happens. Running under the Linux Subsystem for Windows the Task Manager shows it consumes about 5GB of my 8GB RAM and then is showing a lot of disk activity.

I'm now worried how much life that took off my SSD having been doing it all night.
Memory in C++ is a leaky abstraction .

jahboater
Posts: 5419
Joined: Wed Feb 04, 2015 6:38 pm
Location: West Dorset

Re: Why Avoid BASIC on RPi?

Thu Dec 13, 2018 9:06 am

Heater wrote:
Thu Dec 13, 2018 7:29 am
A common tool to count source lines of code is cloc which results in the following for the c and c++ solutions:
The two sources are written in an entirely different style.
The C code is terse with multiple statements on some lines.
I have simplified it a little, and spread the lines out.

Code: Select all

$ cloc fibo.c
       1 text file.
       1 unique file.                              
       0 files ignored.

http://cloc.sourceforge.net v 1.60  T=0.01 s (169.5 files/s, 55942.1 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C                                1             28             22            280
-------------------------------------------------------------------------------

Return to “Off topic discussion”