#include #include #include typedef octave_value_list OVL; typedef octave_value OV; // // Statics for timing routines. // static long rt_usec_tu; static long rt_usec_ts; static struct timeval tmstr; // // Fwd. // void rt_usec_init(); volatile double rt_usec(); OVL hmmm1(OVL args); void hmmm2(); void hmmm3(); // // hmmmwrap() // // DLD wrapper for the hmmmN() timing test functions, below. // DEFUN_DLD(hmmmwrap, args, , "Usage: hmmmwrap(length)\n") { OVL retval, tmp; float et; rt_usec_init(); // Click. hmmm3(); // Test function. et = rt_usec(); // Click. fprintf(stderr, "et = %.1f usec\n", et); retval(0) = 0; return retval; } // // hmmm1() // // Read the (1,1) element of argument Matrix. Should not cause copy down // (and doesn't, as long as Matrix a is declared const, as John pointed out.) // OVL hmmm1(OVL args) { OVL retval; double d; retval(0) = -999; const Matrix a = args(0).matrix_value(); d = a(0, 0); // // The following is only to convince compiler not to optimize away // the above assignment d = a(0, 0). // if (args.length() == -1234) // Compiler doesn't know this is impossible fprintf(stderr, "Impossible %f\n", d); return retval; } // // hmmm2() // // Modify the (1,1) element of global "foo", using get/set_global_value(). // Execution time roughly proporational to number of elements of foo, // indicating that copy down occurs. // void hmmm2() { char globname[] = "foo"; if (!is_globally_visible(globname)) { fprintf(stderr, "? is_globally_visible(%s) failed\n", globname); return; } OV val = get_global_value(globname); Matrix a = val.matrix_value(); a(0,0) = -99999; val = a; set_global_value(globname, val); } // // hmmm3() // // Fancier version of hmmm2(), in vain attempt to guess/duplicate how // interpreter can access globals without causing copy down. Same results // as hmmm2(). Numerous variations on this theme attempted (some of them // commented out here) but none seem to do the trick of avoiding copy // down. What's the magic formula? // void hmmm3() { const char globname[] = "foo"; //symbol_record *sr = global_sym_tab->lookup(globname); symbol_record *sr = curr_sym_tab->lookup(globname); if (! sr) { fprintf(stderr, "? xxxx_sym_tabl->lookup(%s) failed\n", globname); return; } //sr->print_info(octave_stdout); //sr->unprotect(); // No help. OV val = sr->def(); Matrix a = val.matrix_value(); a(0,0) = -99999; // Copy down occurs right here... val = a; // ...not here... sr->define(val); // ...and not here. } // ======================================================================= // // Timing routines. // // rt_usec() returns elasped usec since previous call to rt_usec_init(). // void rt_usec_init() { gettimeofday(&tmstr, NULL); rt_usec_tu = tmstr.tv_usec; rt_usec_ts = tmstr.tv_sec; } volatile double rt_usec() { double d; gettimeofday(&tmstr, NULL); d = ((double)tmstr.tv_sec - (double)rt_usec_ts)*1e6 + ((double)tmstr.tv_usec - (double)rt_usec_tu); return d; }