// $Archive:: $ // $Date: Fri, 16 Jul 2004 20:49:01 -0700 $ // $Revision: 1.3 $ // Description: Domain performance tester // Copyright 2004, Dan Bonachea // Usage: domainperf iters [-s] // -s == silent // to ensure correct operation, compile as: // tcbuild -O --nobcheck --verbose --tc-flags "-Onoinline" domainperf.ti #define assert(x) assert x : "at " + __FILE__+":"+__LINE__+ ": " + #x #define EXPAND(fn) fn(1); fn(2); fn(3); #define EXPAND1(fn,arg1) fn(1,arg1); fn(2,arg1); fn(3,arg1); #define EXPAND2(fn,arg1,arg2) fn(1,arg1,arg2); fn(2,arg1,arg2); fn(3,arg1,arg2); #define EXPAND3(fn,arg1,arg2,arg3) fn(1,arg1,arg2,arg3); fn(2,arg1,arg2,arg3); fn(3,arg1,arg2,arg3); #define EXPAND4(fn,arg1,arg2,arg3,arg4) fn(1,arg1,arg2,arg3,arg4); fn(2,arg1,arg2,arg3,arg4); fn(3,arg1,arg2,arg3,arg4); #ifdef BRUTAL #define INLINE_BODIES inline #else #define INLINE_BODIES #endif public class domainperf { public static boolean silent = false; private static String space = " "; public static String spaces(int num) { if (num <= 0) return ""; int len = space.length(); if (num > len-1) num = len-1; return space.substring(len - num); } public static long iters = 10000; public static long thisiters; public static long scalefactor = 1; public static Timer t = new Timer(); public static double loopoverhead = 0; public static double minsecs = 0.01; public static void report(String desc) { Double.setPrecision(6); String usecs = ""+((t.micros()/thisiters) - loopoverhead); String secs = ""+t.secs(); int fieldw = 9; if (usecs.length() > fieldw) usecs = usecs.substring(0,fieldw); if (secs.length() > fieldw) secs = secs.substring(0,fieldw); if (!silent) System.out.println(desc + ":" + spaces(55-desc.length()) + (t.secs() < minsecs?"?":" ") + usecs + spaces(fieldw-usecs.length()) + " us (" + secs + spaces(fieldw-secs.length()) + " secs" + (thisiters!=iters?",iters="+thisiters+")":")")); } #ifdef COMPLEX_LOOP_ACTION #define LOOPACT(N) \ public static void loopaction##N(int inttemp, boolean booltemp, \ Point pointtemp, RectDomain rtemp, Domain dtemp) {} #else #define LOOPACT(N) \ public static void loopaction##N() {} #endif EXPAND(LOOPACT); #define VARS(prefix) \ prefix int inttemp = 0; \ prefix boolean booltemp = false; \ prefix Point<1> pointtemp1 = [0]; \ prefix Point<2> pointtemp2 = [0,0]; \ prefix Point<3> pointtemp3 = [0,0,0]; \ prefix RectDomain<1> rtemp1 = [pointtemp1:pointtemp1]; \ prefix RectDomain<2> rtemp2 = [pointtemp2:pointtemp2]; \ prefix RectDomain<3> rtemp3 = [pointtemp3:pointtemp3]; \ prefix RectDomain<1> rtempm12 = [pointtemp1:pointtemp1]; \ prefix RectDomain<2> rtempm13 = [pointtemp2:pointtemp2]; \ prefix Domain<1> dtemp1 = [pointtemp1:pointtemp1]; \ prefix Domain<2> dtemp2 = [pointtemp2:pointtemp2]; \ prefix Domain<3> dtemp3 = [pointtemp3:pointtemp3]; \ prefix Point<1> offset1 = [0]; \ prefix Point<2> offset2 = [0,100]; \ prefix Point<3> offset3 = [0,100,10000]; \ prefix Point<1> permute1 = [1]; \ prefix Point<2> permute2 = [2,1]; \ prefix Point<3> permute3 = [2,1,3]; \ prefix RectDomain<1> [1d] ra1temp1; \ prefix RectDomain<2> [1d] ra1temp2; \ prefix RectDomain<3> [1d] ra1temp3; \ prefix Point<1> [1d] pa1temp1; \ prefix Point<2> [1d] pa1temp2; \ prefix Point<3> [1d] pa1temp3; \ EXPAND1(DECLS,prefix); #define DECLARE(prefix,type,N,name,init) prefix type name = init #define OUTPUT(type,N,name) #define DATADECL(prefix,type,N,name,init) \ DECLARE(prefix,type,N,name,init); OUTPUT(type,N,name); // prefix: p = point, s = stride point, r = RectDomain, d = Domain // shape suffix: r = rectangular, q = non-rectangular, u = unit stride, n = non-unit-stride, b = alternate set #define DECLS(N,prefix) \ DATADECL(prefix,Point,N,p##N##a,Point.all(10) + offset##N); \ DATADECL(prefix,Point,N,p##N##b,Point.all(20) + offset##N); \ DATADECL(prefix,Point,N,p##N##c,Point.all(14) + offset##N); \ DATADECL(prefix,Point,N,p##N##d,Point.all(50) + offset##N); \ DATADECL(prefix,Point,N,s##N##1,Point.all(1)); \ DATADECL(prefix,Point,N,s##N##2,Point.all(2)); \ DATADECL(prefix,RectDomain,N,r##N##ru, [p##N##a:p##N##b:s##N##1]); \ DATADECL(prefix,RectDomain,N,r##N##rn, [(2*p##N##a):(2*p##N##b):s##N##2]); \ DATADECL(prefix,RectDomain,N,r##N##rub,[p##N##c:p##N##d:s##N##1]); \ DATADECL(prefix,RectDomain,N,r##N##rnb,[(2*p##N##c):(2*p##N##d):s##N##2]); \ DATADECL(prefix,Domain,N,d##N##ru, r##N##ru); \ DATADECL(prefix,Domain,N,d##N##rn, r##N##rn); \ DATADECL(prefix,Domain,N,d##N##rub,r##N##rub); \ DATADECL(prefix,Domain,N,d##N##rnb,r##N##rnb); \ DATADECL(prefix,Domain,N,d##N##qu, (r##N##ru - r##N##rub)-Point.all(100) + (r##N##ru * r##N##rub)); \ DATADECL(prefix,Domain,N,d##N##qn, (r##N##rn - r##N##rnb)-Point.all(100) + (r##N##rn * r##N##rnb)); \ DATADECL(prefix,Domain,N,d##N##qub, (r##N##rub - r##N##ru)+Point.all(100) + (r##N##ru * r##N##rub)); \ DATADECL(prefix,Domain,N,d##N##qnb, (r##N##rnb - r##N##rn)+Point.all(100) + (r##N##rn * r##N##rnb)); VARS(public static); #define CHECKSIZES(N) \ /* for fairness, maintain the same number of points in the working domains and rectdomains */ \ { int sz1 = r##N##ru.size(); \ int sz2 = r##N##rub.size(); \ \ assert(r##N##ru.size() == sz1); \ assert(r##N##rn.size() == sz1); \ assert(d##N##qu.size() == sz1); \ assert(d##N##qn.size() == sz1); \ assert(d##N##ru.size() == sz1); \ assert(d##N##rn.size() == sz1); \ \ assert(r##N##rub.size() == sz2); \ assert(r##N##rnb.size() == sz2); \ assert(d##N##qub.size() == sz2); \ assert(d##N##qnb.size() == sz2); \ assert(d##N##rub.size() == sz2); \ assert(d##N##rnb.size() == sz2); \ if (!silent) System.out.println(#N+"-d point count:\tsz1="+sz1+"\tsz2="+sz2); \ } #ifdef COMPLEX_LOOP_ACTION #define DO_LOOPACTION(N) loopaction##N(inttemp, booltemp, pointtemp##N, rtemp##N, dtemp##N); #else #define DO_LOOPACTION(N) loopaction##N(); #endif #define TESTLOOP(N, desc, action, iters) do { \ thisiters = iters; \ if (scalefactor > 1) { \ if (thisiters > scalefactor) thisiters /= scalefactor; \ else thisiters = 1; \ } \ for (int j=1; j<20; j++) { \ long limit = thisiters; \ System.gc(); \ t.reset(); \ t.start(); \ for (long i=0; i < limit; i++) { \ action; \ DO_LOOPACTION(N); \ } \ t.stop(); \ if (t.secs() >= minsecs) break; \ else thisiters *= 10; \ } \ report(desc); \ } while (false) #define SCALE(scalefac, actions) do { \ scalefactor *= scalefac; \ actions; \ scalefactor /= scalefac; \ } while (false) public static INLINE_BODIES void pointtests() { //------------------------------------------------------------------------------------ // point tests TESTLOOP(1,"Point<1> create (literal)", pointtemp1 = ([(int)i]), iters); TESTLOOP(2,"Point<2> create (literal)", pointtemp2 = ([(int)i,(int)i]), iters); TESTLOOP(3,"Point<3> create (literal)", pointtemp3 = ([(int)i,(int)i,(int)i]), iters); #define POINTOP(N, result, op) do { \ Point pointtemp; \ TESTLOOP(N,"Point<"+#N+"> "+#op, result (p##N##a op p##N##b), iters); \ pointtemp##N = pointtemp; \ } while (false) EXPAND2(POINTOP, pointtemp =, +); EXPAND2(POINTOP, pointtemp =, -); EXPAND2(POINTOP, pointtemp =, *); EXPAND2(POINTOP, pointtemp =, /); #define POINTOPEQ(N, op) do { \ Point pointtemp; \ TESTLOOP(N,"Point<"+#N+"> "+#op, pointtemp op p##N##a, iters); \ pointtemp##N = pointtemp; \ } while (false) EXPAND1(POINTOPEQ, +=); EXPAND1(POINTOPEQ, -=); EXPAND1(POINTOPEQ, *=); EXPAND1(POINTOPEQ, /=); EXPAND2(POINTOP, booltemp &=, ==); EXPAND2(POINTOP, booltemp &=, !=); EXPAND2(POINTOP, booltemp &=, <); EXPAND2(POINTOP, booltemp &=, <=); #define POINTMETH(N, result, method) do { \ Point pointtemp; \ Point pointpermute = permute##N; \ TESTLOOP(N,"Point<"+#N+"> "+#method, result p##N##a.method, iters); \ pointtemp##N = pointtemp; \ } while (false) EXPAND2(POINTMETH, pointtemp =, all(4)); EXPAND2(POINTMETH, pointtemp =, direction(1,1)); EXPAND2(POINTMETH, pointtemp =, permute(pointpermute)); } public static INLINE_BODIES void createtests() { //------------------------------------------------------------------------------------ // creation test #define RECTDOMAINCREATE(N) do { \ TESTLOOP(N,"unit-stride RectDomain<"+#N+"> create (from Points)", rtemp##N = [p##N##a:p##N##b:s##N##1], iters); \ TESTLOOP(N,"genl-stride RectDomain<"+#N+"> create (from Points)", rtemp##N = [p##N##a:p##N##b:s##N##2], iters); \ TESTLOOP(N,"unit-stride RectDomain<"+#N+"> create (cvt. Domain)", rtemp##N = (RectDomain)d##N##ru, iters); \ TESTLOOP(N,"genl-stride RectDomain<"+#N+"> create (cvt. Domain)", rtemp##N = (RectDomain)d##N##rn, iters); \ } while (false) EXPAND(RECTDOMAINCREATE); #define DOMAINCREATE(N) do { \ TESTLOOP(N,"rect unit-stride Domain<"+#N+"> create (cvt. RectDomain)", dtemp##N = r##N##ru, iters); \ TESTLOOP(N,"rect genl-stride Domain<"+#N+"> create (cvt. RectDomain)", dtemp##N = r##N##rn, iters); \ } while (false) EXPAND(DOMAINCREATE); } public static INLINE_BODIES void queryops1() { //------------------------------------------------------------------------------------ // query operations #define RECTDOMAINQUERYOPS(N, rettarget, method) do { \ Point pointtemp; \ Point pointpermute = permute##N; \ RectDomain rtemp; \ Domain dtemp; \ TESTLOOP(N,"unit-stride RectDomain<"+#N+">."+#method, rettarget r##N##ru.method, iters); \ TESTLOOP(N,"genl-stride RectDomain<"+#N+">."+#method, rettarget r##N##rn.method, iters); \ pointtemp##N = pointtemp; rtemp##N = rtemp; dtemp##N = dtemp; \ } while (false) #define DOMAINQUERYOPS(N, rettarget, method) do { \ Point pointtemp; \ Point pointpermute = permute##N; \ RectDomain rtemp; \ RectDomain [1d] atemp; \ Point [1d] patemp; \ Domain dtemp; \ TESTLOOP(N,"unit-stride rect Domain<"+#N+">."+#method, rettarget d##N##ru.method, iters); \ TESTLOOP(N,"genl-stride rect Domain<"+#N+">."+#method, rettarget d##N##rn.method, iters); \ TESTLOOP(N,"unit-stride non-rect Domain<"+#N+">."+#method, rettarget d##N##qu.method, iters); \ TESTLOOP(N,"genl-stride non-rect Domain<"+#N+">."+#method, rettarget d##N##qn.method, iters); \ pointtemp##N = pointtemp; rtemp##N = rtemp; dtemp##N = dtemp; \ pa1temp##N = patemp; ra1temp##N = atemp; \ } while (false) #define QUERYOPS(N, rettarget, method) do { \ RECTDOMAINQUERYOPS(N, rettarget, method); \ DOMAINQUERYOPS(N, rettarget, method); \ } while (false) EXPAND2(QUERYOPS,inttemp = , size()); EXPAND2(QUERYOPS,booltemp = , isEmpty()); EXPAND2(QUERYOPS,rtemp = , boundingBox()); EXPAND2(QUERYOPS,pointtemp =, min()); EXPAND2(QUERYOPS,pointtemp =, max()); EXPAND2(RECTDOMAINQUERYOPS,booltemp = , isRectangular()); SCALE(10,EXPAND2(DOMAINQUERYOPS,booltemp = , isRectangular())); } public static INLINE_BODIES void queryops2() { SCALE(10,EXPAND2(RECTDOMAINQUERYOPS,rtemp =, permute(pointpermute))); SCALE(100,EXPAND2(DOMAINQUERYOPS,dtemp =, permute(pointpermute))); EXPAND2(RECTDOMAINQUERYOPS,pointtemp =, stride()); EXPAND2(QUERYOPS,booltemp =, contains(pointtemp)); EXPAND2(DOMAINQUERYOPS,atemp =, RectDomainList()); SCALE(100,EXPAND2(DOMAINQUERYOPS,patemp =, PointList())); // untested: // Domain.toDomain(RectDomain atemp[1d]) // Domain.toDomain(Point atemp[1d]) } public static INLINE_BODIES void setops() { //------------------------------------------------------------------------------------ // set operations #define SETOPS(N,prefix,type,rectsuffix,rectdesc) do { \ TESTLOOP(N,"unit-stride "+rectdesc+" "+#type+"<"+#N+"> inter", prefix##temp##N = prefix##N##rectsuffix##u * prefix##N##rectsuffix##ub, iters); \ TESTLOOP(N,"genl-stride "+rectdesc+" "+#type+"<"+#N+"> inter", prefix##temp##N = prefix##N##rectsuffix##n * prefix##N##rectsuffix##nb, iters); \ TESTLOOP(N,"unit-stride "+rectdesc+" "+#type+"<"+#N+"> union", dtemp##N = prefix##N##rectsuffix##u + prefix##N##rectsuffix##ub, iters); \ TESTLOOP(N,"genl-stride "+rectdesc+" "+#type+"<"+#N+"> union", dtemp##N = prefix##N##rectsuffix##n + prefix##N##rectsuffix##nb, iters); \ TESTLOOP(N,"unit-stride "+rectdesc+" "+#type+"<"+#N+"> diff.", dtemp##N = prefix##N##rectsuffix##u - prefix##N##rectsuffix##ub, iters); \ TESTLOOP(N,"genl-stride "+rectdesc+" "+#type+"<"+#N+"> diff.", dtemp##N = prefix##N##rectsuffix##n - prefix##N##rectsuffix##nb, iters); \ } while (false) SCALE(10, EXPAND4(SETOPS,r,RectDomain,r,""); EXPAND4(SETOPS,d,Domain,r,"rect")); SCALE(100,EXPAND4(SETOPS,d,Domain,q,"non-rect")); } public static INLINE_BODIES void manipops() { //------------------------------------------------------------------------------------ // manipulation operations #define MANIP(N, method) do { \ Point stridept = r##N##ru.stride(); \ int stride1 = stridept[1]; \ TESTLOOP(N,"unit-stride RectDomain<"+#N+"> "+#method, rtemp##N = r##N##ru.method, iters); \ stridept = r##N##rn.stride(); \ stride1 = stridept[1]; \ TESTLOOP(N,"genl-stride RectDomain<"+#N+"> "+#method, rtemp##N = r##N##rn.method, iters); \ } while (false) EXPAND1(MANIP, accrete(10,1,stride1)); EXPAND1(MANIP, accrete(1,stridept)); EXPAND1(MANIP, shrink(1,1)); EXPAND1(MANIP, shrink(1)); EXPAND1(MANIP, border(1,1,1)); #define SLICE(N) do { \ TESTLOOP(N,"unit-stride RectDomain<"+#N+"> slice", rtempm1##N = r##N##ru.slice(1), iters); \ TESTLOOP(N,"genl-stride RectDomain<"+#N+"> slice", rtempm1##N = r##N##rn.slice(1), iters); \ } while (false) SLICE(2); SLICE(3); } public static INLINE_BODIES void relops() { //------------------------------------------------------------------------------------ // relational operations #define RELOP(N,prefix,type,rectsuffix,rectdesc, op) do { \ TESTLOOP(N,"unit-stride "+rectdesc+" "+#type+"<"+#N+"> "+#op, booltemp = prefix##N##rectsuffix##u op prefix##N##rectsuffix##ub, iters); \ TESTLOOP(N,"genl-stride "+rectdesc+" "+#type+"<"+#N+"> "+#op, booltemp = prefix##N##rectsuffix##n op prefix##N##rectsuffix##nb, iters); \ } while (false) #define EQUOP(N,prefix,type,rectsuffix,rectdesc,op) do { \ TESTLOOP(N,"unit-stride "+rectdesc+" "+#type+"<"+#N+"> "+#op, booltemp = prefix##N##rectsuffix##u.equals(prefix##N##rectsuffix##ub), iters); \ TESTLOOP(N,"genl-stride "+rectdesc+" "+#type+"<"+#N+"> "+#op, booltemp = prefix##N##rectsuffix##n.equals(prefix##N##rectsuffix##nb), iters); \ } while (false) #define NEQUOP(N,prefix,type,rectsuffix,rectdesc,op) do { \ TESTLOOP(N,"unit-stride "+rectdesc+" "+#type+"<"+#N+"> "+#op, booltemp = !( prefix##N##rectsuffix##u.equals(prefix##N##rectsuffix##ub)), iters); \ TESTLOOP(N,"genl-stride "+rectdesc+" "+#type+"<"+#N+"> "+#op, booltemp = !( prefix##N##rectsuffix##n.equals(prefix##N##rectsuffix##nb)), iters); \ } while (false) #define RELOPS(N,prefix,type,rectsuffix,rectdesc) do { \ EQUOP(N,prefix,type,rectsuffix,rectdesc, .equals); \ NEQUOP(N,prefix,type,rectsuffix,rectdesc, ! .equals); \ RELOP(N,prefix,type,rectsuffix,rectdesc, >); \ RELOP(N,prefix,type,rectsuffix,rectdesc, >=); \ } while (false) EXPAND4(RELOPS,r,RectDomain,r,""); SCALE(10, EXPAND4(RELOPS,d,Domain,r,"rect" )); SCALE(100, EXPAND4(RELOPS,d,Domain,q,"non-rect" )); } public static INLINE_BODIES void arithops() { //------------------------------------------------------------------------------------ // arithmetic operations #define ARITHOPS(N,prefix,type,op) do { \ SCALE(N, \ TESTLOOP(N,"unit-stride "+#type+"<"+#N+"> "+#op+" Point<"+#N+">", prefix##temp##N = prefix##N##ru op s##N##1, iters); \ TESTLOOP(N,"genl-stride "+#type+"<"+#N+"> "+#op+" Point<"+#N+">", prefix##temp##N = prefix##N##rn op s##N##1, iters); \ ); \ } while (false) EXPAND3(ARITHOPS,r,RectDomain,+); EXPAND3(ARITHOPS,d,Domain,+); EXPAND3(ARITHOPS,r,RectDomain,-); EXPAND3(ARITHOPS,d,Domain,-); EXPAND3(ARITHOPS,r,RectDomain,*); EXPAND3(ARITHOPS,d,Domain,*); SCALE(10, EXPAND3(ARITHOPS,r,RectDomain,/); EXPAND3(ARITHOPS,d,Domain,/); ); } public static void main(String[]args) { if (args.length > 0) try { iters = Integer.parseInt(args[0]); } catch (Throwable exn) {} if (args.length > 1) silent = true; if (Ti.thisProc() == 0) { System.out.println("Running " + iters + " iterations of Domain performance test..."); if (!silent) { System.out.println(""); System.out.println("Timer granularity: " + TickCounter.granularity() + " us"); System.out.println("Timer overhead: " + TickCounter.overhead() + " us"); } #undef DECLARE #undef OUTPUT #define DECLARE(prefix,type,N,name,init) #define OUTPUT(type,N,name) if (!silent) System.out.println(#type+"<"+#N+"> "+#name+" = " + name) EXPAND1(DECLS, final); EXPAND(CHECKSIZES); if (!silent) { System.out.println(""); System.out.println("Description Time per iter excluding loop overhead (Total time) "); System.out.println("------------------------------------------------------------------------------------"); } TESTLOOP(1,"loop overhead", inttemp = (int)i, iters); loopoverhead = (t.micros()/thisiters); pointtests(); createtests(); queryops1(); queryops2(); setops(); manipops(); relops(); arithops(); } Ti.barrier(); if (Ti.thisProc() == 0) System.out.println("done."); }}