/* Modified 6/27/00 by Keith Seymour -- seymour@cs.utk.edu -Increased problem size to 500x500 -Fixed matgen() random number generation. -Updated event handling to 1.1 model. -Modified deprecated method calls. -Cleaned up code. -Added PII/PIII/Win2000 options Modified 3/3/97 by David M. Doolin (dmd) doolin@cs.utk.edu Fixed error in matgen() method. Added some comments. Modified 2/17/97 by Paul McMahan mcmahan@cs.utk.edu and Shilpa Singhal singhal@cs.utk.edu Added support for new cgi-script which handles submissions Modified 1/22/97 by Paul McMahan mcmahan@cs.utk.edu Added more Mac processor options to form. Optimized by Jonathan Hardwick (jch@cs.cmu.edu), 3/28/96 Compare to Linkpack.java. Optimizations performed: - added "final" modifier to performance-critical methods. - changed lines of the form "a[i] = a[i] + x" to "a[i] += x". - minimized array references using common subexpression elimination. - eliminated unused variables. - undid an unrolled loop. - added temporary 1D arrays to hold frequently-used columns of 2D arrays. - wrote my own abs() method See http://www.cs.cmu.edu/~jch/java/linpack.html for more details. Ported to Java by Reed Wade (wade@cs.utk.edu) 2/96 built using JDK 1.0 on solaris using "javac -O Linpack.java" Translated to C by Bonnie Toy 5/88 (modified on 2/25/94 to fix a problem with daxpy for unequal increments or equal increments not equal to 1. Jack Dongarra) */ import java.applet.Applet; import java.awt.event.*; import java.awt.*; import java.net.*; import java.io.*; import java.util.*; public class Linpack extends Applet implements ActionListener { String applet_version = "LinpackJavaV2.1"; /* problem size = psize x psize */ static final int psize = 500; Button doit_b; String doit_b_string = "Press To Run Benchmark (may take a few moments)"; StatsGraph graph_c; Label mesg_l; Label os_l, cpu_l; Choice os_m, cpu_m; Label comments_l; TextField comments_e; Label name_l; TextField name_e; Label email_l; TextField email_e; Button submit_b; double mflops_result = 0.0; double residn_result = 0.0; double time_result = 0.0; double eps_result = 0.0; double total = 0.0; public void init () { setLayout(new BorderLayout()); Panel c1 = new Panel(); c1.setLayout(new BorderLayout()); doit_b = new Button(doit_b_string); doit_b.addActionListener(this); c1.add("North", doit_b); doit_b.setForeground(Color.blue); graph_c = new StatsGraph(); c1.add("Center", graph_c); graph_c.setSize(getSize().width, getSize().height); add("Center", c1); Panel c2 = new Panel(); c2.setLayout(new GridLayout(6,1)); /** mesg_l = new Label("If you would like to submit this timing fill in the boxes and hit Submit", Label.CENTER); **/ mesg_l = new Label("The submission of timings has been disabled", Label.CENTER); c2.add(mesg_l); /** Disabled 02/24/2009 submissions were being spammed Panel c2_2 = new Panel(); os_l = new Label(" Operating System:"); c2_2.add(os_l); os_m = new Choice(); c2_2.add(os_m); os_m.addItem("Other"); os_m.addItem("Digital Unix (OSF)"); os_m.addItem("FreeBSD"); os_m.addItem("IRIX"); os_m.addItem("SunOS 4x"); os_m.addItem("Solaris 2x"); os_m.addItem("Linux"); os_m.addItem("Windows95/98"); os_m.addItem("WindowsNT"); os_m.addItem("Windows2000"); os_m.addItem("Mac OS"); cpu_l = new Label(" CPU:"); c2_2.add(cpu_l); cpu_m = new Choice(); c2_2.add(cpu_m); cpu_m.addItem("Other"); cpu_m.addItem("Alpha"); cpu_m.addItem("Intel 386"); cpu_m.addItem("Intel 486"); cpu_m.addItem("Intel Pentium"); cpu_m.addItem("Intel P6"); cpu_m.addItem("Intel PII"); cpu_m.addItem("Intel PIII"); cpu_m.addItem("Mac"); cpu_m.addItem("MIPS"); cpu_m.addItem("Motorola 68K"); cpu_m.addItem("PowerPC 601"); cpu_m.addItem("PowerPC 603e"); cpu_m.addItem("PowerPC 604"); cpu_m.addItem("PowerPC 604e"); cpu_m.addItem("Sparc1"); cpu_m.addItem("Sparc2"); cpu_m.addItem("SparcIPX"); cpu_m.addItem("Sparc5"); cpu_m.addItem("Sparc10"); cpu_m.addItem("Sparc20"); cpu_m.addItem("UltraSparc"); c2.add(c2_2); Panel c2_3 = new Panel(); comments_l = new Label("Details:"); c2_3.add(comments_l); comments_e = new TextField(40); c2_3.add(comments_e); c2.add(c2_3); Panel c2_4 = new Panel(); name_l = new Label("Your Name:"); c2_4.add(name_l); name_e = new TextField(35); c2_4.add(name_e); c2.add(c2_4); Panel c2_5 = new Panel(); email_l = new Label("Email (required for submissions):"); c2_5.add(email_l); email_e = new TextField(25); c2_5.add(email_e); c2.add(c2_5); submit_b = new Button("Submit This Run"); submit_b.addActionListener(this); submit_b.setEnabled(false); c2.add(submit_b); */ add("South", c2); graph_c.load_graph(); } final double abs (double d) { return (d >= 0) ? d : -d; } double second_orig = -1; double second() { if (second_orig==-1) { second_orig = System.currentTimeMillis(); } return (System.currentTimeMillis() - second_orig)/1000; } public void run_benchmark (int n, int ldaa) { int lda = ldaa+1; double a[][] = new double[ldaa][lda]; double b[] = new double[ldaa]; double x[] = new double[ldaa]; double cray,ops,norma,normx; double resid,time; double kf; int i,ntimes,info,kflops; int ipvt[] = new int[ldaa]; cray = .056; ops = (2.0e0*(n*n*n))/3.0 + 2.0*(n*n); /* Norm a == max element. */ norma = matgen(a,lda,n,b); time = second(); /* Factor a. */ info = dgefa(a,lda,n,ipvt); /* Solve ax=b. */ dgesl(a,lda,n,ipvt,b,0); total = second() - time; for (i = 0; i < n; i++) { x[i] = b[i]; } norma = matgen(a,lda,n,b); for (i = 0; i < n; i++) { b[i] = -b[i]; } dmxpy(n,b,n,lda,x,a); resid = 0.0; normx = 0.0; for (i = 0; i < n; i++) { resid = (resid > abs(b[i])) ? resid : abs(b[i]); normx = (normx > abs(x[i])) ? normx : abs(x[i]); } eps_result = epslon((double)1.0); residn_result = resid/( n*norma*normx*eps_result ); residn_result += 0.005; // for rounding residn_result = (int)(residn_result*100); residn_result /= 100; time_result = total; time_result += 0.005; // for rounding time_result = (int)(time_result*100); time_result /= 100; mflops_result = ops/(1.0e6*total); mflops_result += 0.0005; // for rounding mflops_result = (int)(mflops_result*1000); mflops_result /= 1000; } final double matgen (double a[][], int lda, int n, double b[]) { Random gen; double norma; int init, i, j; init = 1325; norma = 0.0; gen = new Random(); gen.setSeed(init); /* Next two for() statements switched. Solver wants * matrix in column order. --dmd 3/3/97 */ for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { a[j][i] = gen.nextDouble() - .5; norma = (a[j][i] > norma) ? a[j][i] : norma; } } for (i = 0; i < n; i++) { b[i] = 0.0; } for (j = 0; j < n; j++) { for (i = 0; i < n; i++) { b[i] += a[j][i]; } } return norma; } /* dgefa factors a double precision matrix by gaussian elimination. dgefa is usually called by dgeco, but it can be called directly with a saving in time if rcond is not needed. (time for dgeco) = (1 + 9/n)*(time for dgefa) . on entry a double precision[n][lda] the matrix to be factored. lda integer the leading dimension of the array a . n integer the order of the matrix a . on return a an upper triangular matrix and the multipliers which were used to obtain it. the factorization can be written a = l*u where l is a product of permutation and unit lower triangular matrices and u is upper triangular. ipvt integer[n] an integer vector of pivot indices. info integer = 0 normal value. = k if u[k][k] .eq. 0.0 . this is not an error condition for this subroutine, but it does indicate that dgesl or dgedi will divide by zero if called. use rcond in dgeco for a reliable indication of singularity. linpack. this version dated 08/14/78. cleve moler, university of new mexico, argonne national lab. functions blas daxpy,dscal,idamax */ final int dgefa( double a[][], int lda, int n, int ipvt[]) { double[] col_k, col_j; double t; int j,k,kp1,l,nm1; int info; // gaussian elimination with partial pivoting info = 0; nm1 = n - 1; if (nm1 >= 0) { for (k = 0; k < nm1; k++) { col_k = a[k]; kp1 = k + 1; // find l = pivot index l = idamax(n-k,col_k,k,1) + k; ipvt[k] = l; // zero pivot implies this column already triangularized if (col_k[l] != 0) { // interchange if necessary if (l != k) { t = col_k[l]; col_k[l] = col_k[k]; col_k[k] = t; } // compute multipliers t = -1.0/col_k[k]; dscal(n-(kp1),t,col_k,kp1,1); // row elimination with column indexing for (j = kp1; j < n; j++) { col_j = a[j]; t = col_j[l]; if (l != k) { col_j[l] = col_j[k]; col_j[k] = t; } daxpy(n-(kp1),t,col_k,kp1,1, col_j,kp1,1); } } else { info = k; } } } ipvt[n-1] = n-1; if (a[(n-1)][(n-1)] == 0) info = n-1; return info; } /** * dgesl solves the double precision system * a * x = b or trans(a) * x = b * using the factors computed by dgeco or dgefa. * * on entry * * a double precision[n][lda] * the output from dgeco or dgefa. * * lda integer * the leading dimension of the array a . * * n integer * the order of the matrix a . * * ipvt integer[n] * the pivot vector from dgeco or dgefa. * * b double precision[n] * the right hand side vector. * * job integer * = 0 to solve a*x = b , * = nonzero to solve trans(a)*x = b where * trans(a) is the transpose. * * on return * * b the solution vector x . * * error condition * * a division by zero will occur if the input factor contains a * zero on the diagonal. technically this indicates singularity * but it is often caused by improper arguments or improper * setting of lda . it will not occur if the subroutines are * called correctly and if dgeco has set rcond .gt. 0.0 * or dgefa has set info .eq. 0 . * * to compute inverse(a) * c where c is a matrix * with p columns * dgeco(a,lda,n,ipvt,rcond,z) * if (!rcond is too small){ * for (j=0,j= 1) { for (k = 0; k < nm1; k++) { l = ipvt[k]; t = b[l]; if (l != k){ b[l] = b[k]; b[k] = t; } kp1 = k + 1; daxpy(n-(kp1),t,a[k],kp1,1,b,kp1,1); } } // now solve u*x = y for (kb = 0; kb < n; kb++) { k = n - (kb + 1); b[k] /= a[k][k]; t = -b[k]; daxpy(k,t,a[k],0,1,b,0,1); } } else { // job = nonzero, solve trans(a) * x = b. first solve trans(u)*y = b for (k = 0; k < n; k++) { t = ddot(k,a[k],0,1,b,0,1); b[k] = (b[k] - t)/a[k][k]; } // now solve trans(l)*x = y if (nm1 >= 1) { //for (kb = 1; kb < nm1; kb++) { for (kb = 0; kb < nm1; kb++) { k = n - (kb+1); kp1 = k + 1; b[k] += ddot(n-(kp1),a[k],kp1,1,b,kp1,1); l = ipvt[k]; if (l != k) { t = b[l]; b[l] = b[k]; b[k] = t; } } } } } /** * constant times a vector plus a vector. * jack dongarra, linpack, 3/11/78. **/ final void daxpy( int n, double da, double dx[], int dx_off, int incx, double dy[], int dy_off, int incy) { int i,ix,iy; if ((n > 0) && (da != 0)) { if (incx != 1 || incy != 1) { // code for unequal increments or equal increments not equal to 1 ix = 0; iy = 0; if (incx < 0) ix = (-n+1)*incx; if (incy < 0) iy = (-n+1)*incy; for (i = 0;i < n; i++) { dy[iy +dy_off] += da*dx[ix +dx_off]; ix += incx; iy += incy; } return; } else { // code for both increments equal to 1 for (i=0; i < n; i++) dy[i +dy_off] += da*dx[i +dx_off]; } } } /** * forms the dot product of two vectors. * jack dongarra, linpack, 3/11/78. **/ final double ddot( int n, double dx[], int dx_off, int incx, double dy[], int dy_off, int incy) { double dtemp; int i,ix,iy; dtemp = 0; if (n > 0) { if (incx != 1 || incy != 1) { // code for unequal increments or equal increments not equal to 1 ix = 0; iy = 0; if (incx < 0) ix = (-n+1)*incx; if (incy < 0) iy = (-n+1)*incy; for (i = 0;i < n; i++) { dtemp += dx[ix +dx_off]*dy[iy +dy_off]; ix += incx; iy += incy; } } else { // code for both increments equal to 1 for (i=0;i < n; i++) dtemp += dx[i +dx_off]*dy[i +dy_off]; } } return(dtemp); } /** * scales a vector by a constant. * jack dongarra, linpack, 3/11/78. **/ final void dscal( int n, double da, double dx[], int dx_off, int incx) { int i,nincx; if (n > 0) { if (incx != 1) { // code for increment not equal to 1 nincx = n*incx; for (i = 0; i < nincx; i += incx) dx[i +dx_off] *= da; } else { // code for increment equal to 1 for (i = 0; i < n; i++) dx[i +dx_off] *= da; } } } /** * finds the index of element having max. absolute value. * jack dongarra, linpack, 3/11/78. **/ final int idamax( int n, double dx[], int dx_off, int incx) { double dmax, dtemp; int i, ix, itemp=0; if (n < 1) { itemp = -1; } else if (n ==1) { itemp = 0; } else if (incx != 1) { // code for increment not equal to 1 dmax = (dx[dx_off] < 0.0) ? -dx[dx_off]: dx[dx_off]; ix = 1 + incx; for (i = 0; i < n; i++) { dtemp = (dx[ix + dx_off] < 0.0) ? -dx[ix + dx_off]: dx[ix + dx_off]; if (dtemp > dmax) { itemp = i; dmax = dtemp; } ix += incx; } } else { // code for increment equal to 1 itemp = 0; dmax = (dx[dx_off] < 0.0)? -dx[dx_off] : dx[dx_off]; for (i = 0; i < n; i++) { dtemp = (dx[i + dx_off] < 0.0) ? -dx[i+dx_off]: dx[i+dx_off]; if (dtemp > dmax) { itemp = i; dmax = dtemp; } } } return (itemp); } /** * estimate unit roundoff in quantities of size x. * * this program should function properly on all systems * satisfying the following two assumptions, * 1. the base used in representing dfloating point * numbers is not a power of three. * 2. the quantity a in statement 10 is represented to * the accuracy used in dfloating point variables * that are stored in memory. * the statement number 10 and the go to 10 are intended to * force optimizing compilers to generate code satisfying * assumption 2. * under these assumptions, it should be true that, * a is not exactly equal to four-thirds, * b has a zero for its last bit or digit, * c is not exactly equal to one, * eps measures the separation of 1.0 from * the next larger dfloating point number. * the developers of eispack would appreciate being informed * about any systems where these assumptions do not hold. * * ***************************************************************** * this routine is one of the auxiliary routines used by eispack iii * to avoid machine dependencies. * ***************************************************************** * * this version dated 4/6/83. **/ final double epslon (double x) { double a,b,c,eps; a = 4.0e0/3.0e0; eps = 0; while (eps == 0) { b = a - 1.0; c = b + b + b; eps = abs(c-1.0); } return(eps*abs(x)); } /** * purpose: * multiply matrix m times vector x and add the result to vector y. * * parameters: * * n1 integer, number of elements in vector y, and number of rows in * matrix m * * y double [n1], vector of length n1 to which is added * the product m*x * * n2 integer, number of elements in vector x, and number of columns * in matrix m * * ldm integer, leading dimension of array m * * x double [n2], vector of length n2 * * m double [ldm][n2], matrix of n1 rows and n2 columns **/ final void dmxpy ( int n1, double y[], int n2, int ldm, double x[], double m[][]) { int j,i; // cleanup odd vector for (j = 0; j < n2; j++) { for (i = 0; i < n1; i++) { y[i] += x[j]*m[j][i]; } } } public void actionPerformed(ActionEvent evt) { Object source = evt.getSource(); if (source==doit_b) { doit_b.setLabel("...running benchmark (" + psize +"x"+psize +")"); run_benchmark(psize,psize*2); doit_b.setLabel(doit_b_string); /** Disabled 02/24/2009 to stop spammers submit_b.setEnabled(true); **/ graph_c.setCurrentRun(mflops_result, residn_result, time_result, eps_result); graph_c.repaint(); } else if (source==submit_b) { try { String OS = os_m.getSelectedItem(); String CPU = cpu_m.getSelectedItem(); if(OS.equals("Other")) OS = ""; if (CPU.equals("Other")) CPU = ""; String months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; Calendar c = Calendar.getInstance(); String DATE = c.get(Calendar.DAY_OF_MONTH) +" "+ months[c.get(Calendar.MONTH)] +" "+ c.get(Calendar.YEAR); String s = ("http://www.netlib.org/cgi-bin/linpackjava/linpackjava.pl?" // String s = ("http://netlib3.cs.utk.edu/cgi-bin/linpackjava/linpackjava.pl?" + "email=" + URLEncoder.encode(email_e.getText()) + "&mflops=" + mflops_result + "&time=" + time_result + "&cpu=" + URLEncoder.encode(cpu_m.getSelectedItem()) + "&os=" + URLEncoder.encode(os_m.getSelectedItem()) + "&comments=" + URLEncoder.encode(comments_e.getText()) + "&name=" + URLEncoder.encode(name_e.getText()) + "&currtime=" + System.currentTimeMillis() + "&residn=" + residn_result + "&epsilon=" + eps_result + "&version=" + applet_version ); URL url = new URL(s); getAppletContext().showDocument(url); } catch (Exception e) { mesg_l.setText("!!submission failed for some reason"); } } else { System.out.println("Unknown source."); } } } class StatsGraph extends Canvas { double max_mflops = 0.0; Vector data_list = new Vector(10); boolean couldnt_load = false; double mflops_result = 0.0; double residn_result = 0.0; double time_result = 0.0; double eps_result = 0.0; String dataURL = "http://www.netlib.org/benchmark/linpackjava/linpackData"; // String dataURL = "http://netlib3.cs.utk.edu/benchmark/linpackjava/linpackData"; void load_graph() { /* open the linpackData file */ InputStream is; try { is = new URL(dataURL).openStream(); } catch (Exception e) { couldnt_load = true; System.out.println(e.getMessage()); return; } StreamTokenizer st = new StreamTokenizer(new InputStreamReader(is)); /* allow various commenting methods */ st.commentChar('#'); st.slashStarComments(true); st.slashSlashComments(true); st.quoteChar('"'); st.parseNumbers(); // TT_NUMBER , nval try { while (st.TT_EOF != st.nextToken()) { double mflops = 0.0; String label = ""; String info = ""; int itemtype = 0; DataItem item; // first item label while ('"'!=st.ttype && st.TT_EOF != st.nextToken()) /*spin*/; if ('"'==st.ttype) label = st.sval; // second item itemtype while (st.TT_NUMBER!=st.ttype && st.TT_EOF != st.nextToken()) /*spin*/; if (st.TT_NUMBER==st.ttype) itemtype = (int)st.nval; // third item info while ('"'!=st.ttype && st.TT_EOF != st.nextToken()) /*spin*/; if ('"'==st.ttype) info = st.sval; // second fourth mflops while (st.TT_NUMBER!=st.ttype && st.TT_EOF != st.nextToken()) /*spin*/; if (st.TT_NUMBER==st.ttype) { mflops = st.nval; if (mflops > max_mflops) max_mflops = mflops; item = new DataItem(mflops, itemtype, info, label); data_list.addElement(item); } } } catch (Exception e) { couldnt_load = true; return; } try { is.close(); } catch (Exception e) { couldnt_load = true; return; } } public void paint(Graphics g) { Font font = g.getFont(); // save the default font Font minifont = new Font(font.getName(), font.getStyle(), 8); // smaller int pad=20; if (mflops_result > max_mflops) max_mflops = mflops_result; // clear background g.setColor(getBackground()); g.fillRect(1, 1, getSize().width - 2, getSize().height - 2); g.setColor(getForeground()); if (couldnt_load) { g.drawString("Error: couldn't load Linpack data file", 10,50); return; } DataItem item; int i; // pad is size of border around bars area, same on all 3 sides // 0 element is not displayed, it is the scale (max value) int x, y2; int w,h; // width and height excluding pad w = getSize().width - pad*2; h = getSize().height- pad*2; for (i=1; i100) { g.setColor(Color.yellow); g.drawString("Warning: there appears to be a problem with", 30, 30); g.drawString("the floating point arithmetic on this machine!!", 30, 50); } } } void drawStringRising(Graphics g, int rise, String s, int x, int y) { // for each char : draw, rise char chars[] = s.toCharArray(); String _s; FontMetrics fm = g.getFontMetrics(); int l=s.length(); for (int i=0; i