/* 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; i