package fr.lip6.kernel;
import java.util.ArrayList;
import java.util.Arrays;
import fr.lip6.type.TrainingSample;
/**
* Simple multithreaded implementation over a given Kernel. The multithreading comes only when
* computing the Gram matrix.
* Number of Threads is function of available processors.
* @author dpicard
*
* @param
*/
public class ThreadedKernel extends Kernel {
/**
*
*/
private static final long serialVersionUID = -2193768216118832033L;
protected Kernel k;
private double[][] matrix;
/**
* MultiThread the given kernel
* @param kernel
*/
public ThreadedKernel(Kernel kernel)
{
this.k = kernel;
}
@Override
public double valueOf(T t1, T t2) {
return k.valueOf(t1, t2);
}
@Override
public double valueOf(T t1) {
return k.valueOf(t1);
}
/* (non-Javadoc)
* @see fr.lip6.kernel.Kernel#getKernelMatrix(java.util.ArrayList)
*/
@Override
public double[][] getKernelMatrix(ArrayList> e) {
matrix = new double[e.size()][e.size()];
int nbc = ((int)Math.sqrt(2*Runtime.getRuntime().availableProcessors()))+1;
// int nbc = 1;
int icrem = e.size()/nbc ;
System.err.println("("+this.toString()+") Launching "+(nbc*nbc)+" block");
ArrayList threads = new ArrayList();
for(int i = 0 ; i < e.size() ; i+=icrem)
for(int j = 0 ; j < e.size() ; j+=icrem)
{
MatrixThread t = new MatrixThread(matrix, e, i, i+icrem, j, j+icrem);
threads.add(t);
t.start();
}
boolean cont = true;
while(cont)
{
cont = false;
for(MatrixThread t : threads)
if(!t.hasFinished() && t.isAlive())
cont = true;
Thread.yield();
}
System.err.println("("+this.toString()+") done.");
// for(int i = 0 ; i < e.size(); i++)
// if(matrix[i][i] == 0)
// {
// System.out.println(toString()+" error calcul matrix : i="+i+" m="+matrix[i][i]);
// System.out.println("kernel:");
// for(double[] d: matrix)
// {
// System.out.println(Arrays.toString(d));
// }
// System.out.println(toString()+" error calcul matrix : i="+i+" m="+matrix[i][i]);
// System.exit(0);
// }
return matrix;
}
private class MatrixThread extends Thread
{
double[][] m;
ArrayList> e;
int mini, maxi, minj, maxj;
boolean finished = false;
/**
* @param m
* @param e
* @param mini
* @param maxi
* @param minj
* @param maxj
*/
public MatrixThread(double[][] m, ArrayList> e, int mini, int maxi,
int minj, int maxj) {
this.m = m;
this.e = e;
this.mini = mini;
this.maxi = Math.min(maxi, e.size());
this.minj = minj;
this.maxj = Math.min(maxj, e.size());
}
public void run() {
finished = false;
for (int i = mini; i < maxi; i++) {
for (int j = minj; j < maxj; j++) {
T t1 = e.get(i).sample;
T t2 = e.get(j).sample;
double v = valueOf(t1, t2);
if(!Double.isNaN(v))
{
m[i][j] = valueOf(t1, t2);
}
else
{
System.out.println("NAN : v="+v);
System.out.println("t1="+Arrays.toString((double[])t1));
System.out.println("t1="+Arrays.toString((double[])t2));
System.exit(0);
}
}
}
finished = true;
}
public boolean hasFinished()
{
return finished;
}
}
}