DSPRelated.com
Forums

Thoughts on the C/Assembly Debate

Started by Randy Yates July 28, 2007
On Jul 29, 10:19 am, Randy Yates <ya...@ieee.org> wrote:
> Phil Carmody <thefatphil_demun...@yahoo.co.uk> writes: > > [...] > > But of course that's the programmer taking control. > > To some extent it is, but if you need to "take control," and > you must delve into architecture specifics and write non-portable > C code (at least C code that won't run _fast_ on multiple platforms),
A far cry from non-portable code.
> then assembly provides the ultimate "control."
True. But you have yet to show that it offers more control than a high level language. Yes, an assembler langauge programmer can exploit the fact that he knows that the real and complex arrays are interleaved, but so can the compiler. Yes, changing the data structure (or for that matter the algorithm) may make the processing more efficient, but a C programmer can make the same change for the same reasons, this has to do with machine architecture, not with assembly programming (yes an assembly programmer may know more about the details of the machine architecture, and optimizing performance for a specific machine requires knowing the details of the machine architecture, however, there is no reason that a C programmer cannot know about the machine architecture). What you can do with C and cannot do with assembly is write a limited number of routines, such that for any processor one of the routines will run quickly (and indeed the choice can be make part of the start up).
> > > It appears that that concept offends you when it comes to high level > > languages. > > I wouldn't use the word "offend" - I consider it an abuse of the > high level language.
Why? There is no reason that you should not write a routine tuned to a specific processor in a high level language. Even if the routine will only run at acceptable speed on the one processor (unlikely) there are many reasons to use a high level language in any case (not the least is that you may be able to take advantage of new features in new versions of the processor without having to recode).
> Hey People, this is ludicrous. All these arguments treat assembly > as if it were the ultimate evil. It ain't that bad, folks. Honest.
No, but why give up the advantages of a high level language when you do not have to? Yes there are times when a good assembly programmer can beat a good compiler in terms of speed, and situations where it matters, however it seems that both such situations and good assembly programmers are rare. - William Hughes
On Jul 29, 10:19 am, Randy Yates <ya...@ieee.org> wrote:
> Phil Carmody <thefatphil_demun...@yahoo.co.uk> writes: > > [...] > > But of course that's the programmer taking control. > > To some extent it is, but if you need to "take control," and > you must delve into architecture specifics and write non-portable > C code (at least C code that won't run _fast_ on multiple platforms),
A far cry from non-portable code.
> then assembly provides the ultimate "control."
True. But you have yet to show that it offers more control than a high level language. Yes, an assembler langauge programmer can exploit the fact that he knows that the real and complex arrays are interleaved, but so can the compiler. Yes, changing the data structure (or for that matter the algorithm) may make the processing more efficient, but a C programmer can make the same change for the same reasons, this has to do with machine architecture, not with assembly programming (yes an assembly programmer may know more about the details of the machine architecture, and optimizing performance for a specific machine requires knowing the details of the machine architecture, however, there is no reason that a C programmer cannot know about the machine architecture). What you can do with C and cannot do with assembly is write a limited number of routines, such that for any processor one of the routines will run quickly (and indeed the choice can be make part of the start up).
> > > It appears that that concept offends you when it comes to high level > > languages. > > I wouldn't use the word "offend" - I consider it an abuse of the > high level language.
Why? There is no reason that you should not write a routine tuned to a specific processor in a high level language. Even if the routine will only run at acceptable speed on the one processor (unlikely) there are many reasons to use a high level language in any case (not the least is that you may be able to take advantage of new features in new versions of the processor without having to recode).
> Hey People, this is ludicrous. All these arguments treat assembly > as if it were the ultimate evil. It ain't that bad, folks. Honest.
No, but why give up the advantages of a high level language when you do not have to? Yes there are times when a good assembly programmer can beat a good compiler in terms of speed, and situations where it matters, however it seems that both such situations and good assembly programmers are rare. - William Hughes
On Jul 29, 10:19 am, Randy Yates <ya...@ieee.org> wrote:
> Phil Carmody <thefatphil_demun...@yahoo.co.uk> writes: > > [...] > > But of course that's the programmer taking control. > > To some extent it is, but if you need to "take control," and > you must delve into architecture specifics and write non-portable > C code (at least C code that won't run _fast_ on multiple platforms),
A far cry from non-portable code.
> then assembly provides the ultimate "control."
True. But you have yet to show that it offers more control than a high level language. Yes, an assembler langauge programmer can exploit the fact that he knows that the real and complex arrays are interleaved, but so can the compiler. Yes, changing the data structure (or for that matter the algorithm) may make the processing more efficient, but a C programmer can make the same change for the same reasons, this has to do with machine architecture, not with assembly programming (yes an assembly programmer may know more about the details of the machine architecture, and optimizing performance for a specific machine requires knowing the details of the machine architecture, however, there is no reason that a C programmer cannot know about the machine architecture). What you can do with C and cannot do with assembly is write a limited number of routines, such that for any processor one of the routines will run quickly (and indeed the choice can be make part of the start up).
> > > It appears that that concept offends you when it comes to high level > > languages. > > I wouldn't use the word "offend" - I consider it an abuse of the > high level language.
Why? There is no reason that you should not write a routine tuned to a specific processor in a high level language. Even if the routine will only run at acceptable speed on the one processor (unlikely) there are many reasons to use a high level language in any case (not the least is that you may be able to take advantage of new features in new versions of the processor without having to recode).
> Hey People, this is ludicrous. All these arguments treat assembly > as if it were the ultimate evil. It ain't that bad, folks. Honest.
No, but why give up the advantages of a high level language when you do not have to? Yes there are times when a good assembly programmer can beat a good compiler in terms of speed, and situations where it matters, however it seems that both such situations and good assembly programmers are rare. - William Hughes
William Hughes wrote:


> ... why give up the advantages of a high level language when > you do not have to? Yes there are times when a good assembly > programmer can beat a good compiler in terms of speed, and situations > where it matters, however it seems that both such situations > and good assembly programmers are rare.
I know of no high-level language that gives the programmer access to flag bits like carry and overflow. Are there standard constructs for turning saturating arithmetic on and off? (That's not a rhetorical question. I don't know.) How about enabling and disabling specific interrupts and setting their priorities? Does C know about DMAs? Jerry -- Engineering is the art of making what you want from things you can get. &macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;&macr;
"Randy Yates" <yates@ieee.org> wrote in message 
news:m38x8z2scv.fsf@ieee.org...

> I mean, folks here argue > as if it takes MAN-YEARS to write a single assembly > routine. >
Many years ago, an extensive study involving mammoth software projects in both the commercial and government sectors demonstrated that an average programmer can produce, on average, 10 lines of debugged code per day. The surprising part was that this number held whether the programmer used an assembler or any of the several compiled languages then available! Since one line of assembler (macros aside) generally expands into one machine operation, and one line of compiled code generally expands into several machine operations, one can reasonably conclude that *average* programmers are more productive (they can specify more logical steps) using compiled high-level languages. Ultimately, the debate is still all about developer productivity. It does matter whether a project can't be done because compiler code lacks performance or because correct assembler code can't be produced fast enough by humans. Moore's law will eventually solve the former problem. It will never impact the latter.
On 29 Jul, 20:13, Jerry Avins <j...@ieee.org> wrote:
> William Hughes wrote: > > ... why give up the advantages of a high level language when > > you do not have to? Yes there are times when a good assembly > > programmer can beat a good compiler in terms of speed, and situations > > where it matters, however it seems that both such situations > > and good assembly programmers are rare. > > I know of no high-level language that gives the programmer access to > flag bits like carry and overflow. Are there standard constructs for > turning saturating arithmetic on and off? (That's not a rhetorical > question. I don't know.) How about enabling and disabling specific > interrupts and setting their priorities? Does C know about DMAs?
The answer is probably "no" on all your answers, but that doesn't mean much as such issues are not relevant to most programmers. Those sorts of questions only appear in embedded systems, which means that one either have to code assembly, or add the necessary functionality to the platform-specific C compiler. This thread made me think about run-time overhead in standard C++ compilers. Consider the question of computing Chebyshev polynomials. One formulation of the Chebyshev polynomials T_N(x) and U_N(x) is T_0(x) = 1 U_0(x) = 1 T_N(x) = x*T_N-1(x) - (1-x^2)*U_N-2(x) U_N(x) = x*U_N-1(x) + T_N(x) Given the task of computing, say, T_10(x), one has two options in C and Fortran: 1) Compute all the coefficients in the polynomial and hard-code them in the routine 2) Use a recursive program The former approach is labour-intensive, as the coefficients have to be computed specifically for each degree of the polynomial; the latter induces rune-time overhead due to function calls. With C++, there is a 3rd alternative: Template programming, which communicates the recursive nature of the polynomial to the compiler and leaves the compiler to generate optimized code. This way, the programmer programs efficiently and intuitively (see example below) and gets efficient code at the same time. This idea is tested in the code attached below. It turns out that the template program runs nearly twice as fast as the recursive program. As I said in a different post, I am only starting to learn these things. However, if a C program is slow, it could just as well be due to a inept programmer as to a poor compiler. Rune //// Ought to compile with any C++ compiler #include <iostream.h> #include <time.h> #include <vector> #include <stdlib.h> ////////////////////////////////////////////////////////////////////// // // Template functions template<unsigned long int N> // Forward declaration of double U(const double); // Chebyshev function of 2nd kind template<unsigned long int N> // Chebyshev function of 1st kind double T(const double x) { return x*T<N-1>(x)-(1-x*x)*U<N-2>(x); } template<unsigned long int N> // Chebyshev function of 2nd kind double U(const double x) { return x*U<N-1>(x) + T<N>(x); } template<> // Initial function recurrence double T<0>(const double x) { return 1; } template<> double T<1>(const double x) { return x; } template<> double U<0>(const double x) { return 1; } ////////////////////////////////////////////////////////////////////// // // Standard recursive functions double u(const long unsigned int,const double); // Forward declaration of // Chebyshev function of 2nd kind double t(const long unsigned int N,const double x) { if (N>1) { return x*t(N-1,x) - (1-x*x)*u(N-2,x); } if (N==1) { return x; } return 1; } double u(const long unsigned int N, const double x) { if (N>0) { return x*u(N-1,x) + t(N,x); } return 1; } int main() { const unsigned long int N = 10000000; std::vector<double> x; std::vector<double> y; x.reserve(N); y.reserve(N); long unsigned int n; for (n=0;n<N;++n) { x[n] = (double)rand()/(double)RAND_MAX; } clock_t t1,t2,d1,d2; t1 = clock(); for (n=0;n<N;++n) { y[n] = T<10>(x[n]); // Very intuitive code for // y = T_10(x) } d1 = clock() - t1; t2 = clock(); for (n=0;n<N;++n) { y[n] = t(10,x[n]); } d2 = clock() - t2; std::cout << "Templates : " << d1 << std::endl; std::cout << "Standard : " << d2 << std::endl; return 0; }
On Jul 29, 2:13 pm, Jerry Avins <j...@ieee.org> wrote:
> William Hughes wrote: > > ... why give up the advantages of a high level language when > > you do not have to? Yes there are times when a good assembly > > programmer can beat a good compiler in terms of speed, and situations > > where it matters, however it seems that both such situations > > and good assembly programmers are rare. > > I know of no high-level language that gives the programmer access to > flag bits like carry and overflow. Are there standard constructs for > turning saturating arithmetic on and off? (That's not a rhetorical > question. I don't know.)
I don't think so. However, I think that both saturating and non-saturating arithmetic comply with the C standard so the compiler could certainly do this. Certainly you can have a compiler option like -make_floating_point_fast_even_if_this_will_violate_the_standard
> How about enabling and disabling specific > interrupts and setting their priorities? Does C know about DMAs? >
No. However, C compilers can. The question is not: is the optimal assembler solution at least as good and possibly better that the optimal high level language solution? The answer to this is trivially yes. The question is: is there something that can be done in assembly, that cannot be done, even in theory, in a high level language? - William Hughes
"John E. Hadstate" <jh113355@hotmail.com> writes:

> Many years ago, an extensive study involving mammoth > software projects in both the commercial and government > sectors demonstrated that an average programmer can produce, > on average, 10 lines of debugged code per day. The > surprising part was that this number held whether the > programmer used an assembler or any of the several compiled > languages then available! Since one line of assembler > (macros aside) generally expands into one machine operation, > and one line of compiled code generally expands into several > machine operations, one can reasonably conclude that > *average* programmers are more productive (they can specify > more logical steps) using compiled high-level languages.
Yes, depending on who you believe programmers have a variation in productivity of between 10:1 and 20:1 [1,2]. So a bad C programmer really could be worse than a bad asm programmer. Ciao, Peter K. [1] http://www.joelonsoftware.com/articles/HighNotes.html [2] http://www.codinghorror.com/blog/archives/000072.html -- "And he sees the vision splendid of the sunlit plains extended And at night the wondrous glory of the everlasting stars."
On Jul 29, 9:50 am, Dave Seaman <dsea...@no.such.host> wrote:
> On Sun, 29 Jul 2007 02:51:16 -0000, robert bristow-johnson wrote: > > On Jul 28, 4:50 pm, Jerry Avins <j...@ieee.org> wrote: > >> Until processors routinely execute and n instructions in parallel, all > >> code will be executed sequentially. You might as well write it that way. > > and if instructions have conditionals in them, those would have to be > > executed sequentially, despite the brawn, no? > > Not exactly. Modern processors perform branch prediction and can > conditionally execute instructions in anticipation of a certain branch > being taken. >
lotta pipelining to do that. thanks.
> Oral Arguments in Mumia Abu-Jamal Case heard May 17 > U.S. Court of Appeals, Third Circuit > <http://www.abu-jamal-news.com/>
i'm with you there. similar to Leonard Peltier, although there are detractors of both who say that they're guilty. i don't see how the evidence was sufficient and that they were both prosecuted more because of the victims were law enforcement, not because of a solid case against them. it's pretty clear that neither got a fair and non- politicized trial at the beginning. r b-j
Logan Shaw wrote:
> Jerry Avins wrote: >> Until processors routinely execute and n instructions in parallel, all >> code will be executed sequentially. You might as well write it that way. > > n had been 1 for decades. For most new hardware, it's now 2, and it's > already starting to change to 4. > > - Logan
Modern processor execute lots of instructions in parallel, and out-of-order to minimize stalls. If carefully programmed, you can get sometimes up to 10 microinstruction being executed in parallel. SIMD-capable processors (single instruction, multiple data) such as the G5, P4, Cores, etc, can process up to 16 pieces of data at the same time. I suggest you both go do some reading ;) Best, S.