Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re: XS: EXTEND/mPUSHi

by Util (Priest)
on Sep 26, 2011 at 15:46 UTC ( [id://927892]=note: print w/replies, xml ) Need Help??


in reply to XS: EXTEND/mPUSHi

Inline::C uses its own Inline_Stack_(Vars|Reset|Done) macros in place of XS's dSP|EXTEND macros. Inline_Stack_Push is used instead of mPUSHi, although you can still use the mXPUSHi form to simplify. See "#The_Inline_Stack_Macros" in Inline::C.

The Inline docs say that you should be able to use the old macros, but I cannot see how to make that work.

Having made the changes mentioned above, this code now works for me:

#! perl -slw use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => 'rand64fast', CLEAN_AFTER_BUILD => + 0; void rnd( int n ) { // dSP; // static __int64 y = 2463534242; static int y = 2463534242; // My machine is 32-bit. // EXTEND( SP, n ); Inline_Stack_Vars; Inline_Stack_Reset; while( --n ) { y ^= y << 13; y ^= y >> 17; y ^= y << 5; // mPUSHi( (IV)y ); Inline_Stack_Push( sv_2mortal( newSViv(y) ) ); // mXPUSHi(y); // Could have used this instead. Note the added + X } // return; Inline_Stack_Done; } END_C print for rnd( 100 );
Caveat: All my XS knowledge predates Inline::C, so any of the above could be flawed in minor ways.

Replies are listed 'Best First'.
Re^2: XS: EXTEND/mPUSHi
by BrowserUk (Patriarch) on Sep 26, 2011 at 16:30 UTC

    Thanks.

    Yes. I know it can be done using the ludicrously verbose, Camel_Case_And_Underscores inline stack macros. I was trying to understand why I can't use the neater and more concise XS macros from Inline C. I've found I can reduce the requirements to:

    #! perl -slw use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => 'monkeys', CLEAN_AFTER_BUILD => 0; void rnd64( int n ) { Inline_Stack_Vars; static unsigned __int64 y = 88172645463325252i64; EXTEND( SP, n ); while( n-- ) { y ^= y << 13; y ^= y >> 7; y ^= y << 17; mPUSHu( y ); } Inline_Stack_Done; return; }

    But looking at the C produced by the above, it looks like there is a path through the generated wrapper function that avoids both the XSRETURN_EMPTY and the PUTBACK, thus returning whatever has been pushed:

    XS(XS_main_rnd64); /* prototype to pass -Wmissing-prototypes */ XS(XS_main_rnd64) { #ifdef dVAR dVAR; dXSARGS; #else dXSARGS; #endif if (items != 1) croak_xs_usage(cv, "n"); PERL_UNUSED_VAR(ax); /* -Wall */ SP -= items; { int n = (int)SvIV(ST(0)); #line 46 "monkeys.xs" I32* temp; #line 117 "monkeys.c" #line 48 "monkeys.xs" temp = PL_markstack_ptr++; rnd64(n); if (PL_markstack_ptr != temp) { /* truly void, because dXSARGS not invoked */ PL_markstack_ptr = temp; XSRETURN_EMPTY; /* return empty stack */ } /* must have used dXSARGS; list context implied */ return; /* assume stack size is correct */ ### Her +e #line 128 "monkeys.c" PUTBACK; return; } }

    But I'm obviously missing something in the OP code that would cause (or allow) it to follow that path?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I know it can be done using the ludicrously verbose, Camel_Case_And_Underscores inline stack macros

      The camel case can be avoided - use either INLINE_STACK_VARS or inline_stack_vars instead of Inline_Stack_Vars (etc, etc ...).
      But Inline currently offers no alternative to the verbosity or the underscores - which is one of a number of reasons that I, too, often prefer to use the XS equivalents.

      If you ever want to check on what they are, these macros can be found in Inline/C.pm in the "Generate the INLINE.h file" section, or in any Inline-generated Inline.h that you can lay your hands on.

      I think these macros are mostly useful for beginners in that they provide a mantra that gets most jobs done - and despite their verbosity, are easier to remember than the corresponding list of XS symbols. (After a while away from doing any Inline::C or XS stuff, I'm flat out remembering whether I want to start my Inline::C script with "dSP" or "dXSARGS", but I can always remember "Inline_Stack_Vars" :-)

      Cheers,
      Rob

        dXSARGS is the most comprehensive.

        Or you could just look at the error message you get and add the appropriate declaration (spdSP;, axdAX;, markdMARK;, etc).

        Inline/C.pm uses sp = mark;, when it should probably use SP = MARK;, and I'd not even sure if that's officially allowed.

        these macros can be found in Inline/C.pm

        The problem is not in finding their definitions, it is understanding what they do, when they must be used and when not etc.

        Their definitions are all in terms of other (XS) macros, and unwinding those is much harder. And once you have unwound them to the actual code that gets executed, it is generally a horrible mess of nested macro expansions calling a bunch of undocumented apis -- often repetitively -- and manipulating another bunch of undocumented global variables.

        Trying to work out what calls are actually need when, rather than just cargo-culting someone else who cargo-culted someone else who ... is very difficult. Weirdness like the completely unused & redundant PUTBACK; return; sequence generated by the Inline::C wrapper functions just compounds matters.

        I think these macros are mostly useful for beginners in that they provide a mantra that gets most jobs done - and despite their verbosity, are easier to remember than the corresponding list of XS symbols.

        Do you really find verbosity more memorable than conciseness? I don't. I realise that you inherited those definitions, but I think that it is a fallacy to believe they are more memorable than the XS_equivalents.

        With Ike's help above, I've reduced my fast random generator to:

        void rnd64( int n ) { dXSARGS; static unsigned __int64 y = 88172645463325252i64; EXTEND( SP, n ); while( n-- ) { y ^= y << 13; y ^= y >> 7; y ^= y << 17; mPUSHu( y ); } PUTBACK; return; }

        Which appears to work well. It doesn't appear to leak any memory after producing over 12 billion 64-bit rands (in batches of 1 million) in an hour , but that still leaves me with the question of whether I should be resetting the stack to account for the single input parameter, or whether the EXTEND() takes care for that for me?

        And it is this aspect of using Inline::C or XS that leaves me cold. The reason for dipping into the quagmire is to achieve speed unobtainable in Perl, but working out what bits of the templated examples are actually required and when is (it seems) only possible by suck-it-and-see.

        I also wonder if I shouldn't be passing in a reference to the an array and populating it directly, rather than assigning the returned stack to it?

        Equally, rather than creating a whole new bunch of SVs to hold my rands in the target array, couldn't I just modify their IVs in place? Would that be more efficient?


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://927892]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (7)
As of 2024-03-19 10:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found