/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.performance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
import com.opengamma.util.test.TestGroup;
/**
* Just a quick thing to test the performance difference between contiguous and scattered memory using DGEMV()
*/
@Test(groups = TestGroup.UNIT_SLOW)
public class BLAS2Test {
boolean _debug = false;
void dgemv(double[][] mat, double[] vect, double[] ans, int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
ans[i] += mat[i][j] * vect[j];
}
}
}
double[] dgemv(double[][] mat, double[] vect, int m, int n) {
double[] ans = new double[m];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
ans[i] += mat[i][j] * vect[j];
}
}
return ans;
}
void setMatrix(double[][] mat, int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
mat[i][j] = i * n + j;
}
}
}
void printMatrix(double[][] mat, int m, int n) {
final Logger log = LoggerFactory.getLogger(SimpleTimerTest.class);
log.info("Printing matrix");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
log.info("matrix[" + i + "][" + j + "]=" + mat[i][j]);
}
}
}
void setVector(double[] vect, int n) {
for (int i = 0; i < n; i++) {
vect[i] = i;
}
}
void printVector(double[] vect, int n) {
final Logger log = LoggerFactory.getLogger(BLAS2Test.class);
log.info("Printing vector");
for (int i = 0; i < n; i++) {
log.info("vector[" + i + "]=" + vect[i]);
}
}
double[] conMatDGEMV(MatrixCreator mat, double[] vect) {
// final Logger log = LoggerFactory.getLogger(BLAS2Test.class);
double[] ans = new double[mat.getheight()];
// int w=mat.getwidth();
for (int i = 0; i < mat.getheight(); i++) {
for (int j = 0; j < mat.getwidth(); j++) {
ans[i] += mat.getval(i, j) * vect[j];
// log.info("accessing"+mat.getval(i, j)+" by "+vect[j]);
}
}
return ans;
}
void conMatSetMatrix(MatrixCreator mat) {
// final Logger log = LoggerFactory.getLogger(MatrixCreator.class);
for (int i = 0; i < mat.getheight(); i++) {
for (int j = 0; j < mat.getwidth(); j++) {
mat.setval(i, j);
// log.info("writing" + (i * mat.getwidth() + j));
}
}
}
@Test
public void test() {
final Logger log = LoggerFactory.getLogger(BLAS2Test.class);
SimpleTimer timer = new SimpleTimer();
int m = 2 << 10;
int n = 3 << 10;
// int m = 2; // rows
// int n = 3; // columns
double[][] mat = new double[m][n];
setMatrix(mat, m, n);
double[] vect = new double[n];
setVector(vect, n);
double[] answer = new double[m];
MatrixCreator contmat = new MatrixCreator(m, n);
conMatSetMatrix(contmat);
int trials = 1000;
/*
* Trials for pass by reference DGEMV
*/
long dttime = 0;
for (int i = 0; i < trials; i++) {
timer.startTimer();
dgemv(mat, vect, answer, m, n);
timer.stopTimer();
dttime += timer.totalTime();
answer[0] += 1;
}
log.info("Total time using direct reference: " + dttime / 1e9 + "s");
/*
* Trials for java return vomit DGEMV
*/
long ttime = 0;
double[] newans;
for (int i = 0; i < trials; i++) {
timer.startTimer();
newans = dgemv(mat, vect, m, n);
timer.stopTimer();
ttime += timer.totalTime();
newans[0] += 1;
}
log.info("Total time using returned vector: " + ttime / 1e9 + "s");
/*
* Trials for contiguous memory access
*/
long cttime = 0;
double[] conmatans;
// conmatans=conMatDGEMV(contmat,vect);
// log.info("Contig answer");
// printVector(conmatans,m);
for (int i = 0; i < trials; i++) {
timer.startTimer();
conmatans = conMatDGEMV(contmat, vect);
timer.stopTimer();
cttime += timer.totalTime();
conmatans[m - 1] += 1;
}
log.info("Total time using contiguous mem: " + cttime / 1e9 + "s");
log.info("Scalings [contiguous/java]: " + ((double) cttime / ttime));
log.info("Scalings [contiguous/direct]: " + ((double) cttime / dttime));
log.info("Scalings [direct/java]: " + ((double) dttime / ttime));
}
}