I was doing this program to multiply arrays, I saw that it correctly calculates the result, but there is no performance gain by putting more threads, often even worsening performance despite being running on a quad-core smartphone. I would like to know if I am doing something very wrong (I do not know much about parallelism) or this problem is not worth paralleling.
The program was based on this question: link
Thank you.
public class MainActivity extends Activity {
private int SIZE;
private static final int THRESHOLD = 64;
private int MAX_THREADS;
private double valor;
private ExecutorService executor = null;
private TextView textTamanhoMatrizes;
private TextView multiplicacaoConcluida;
private TextView textQuantidadeThreads;
private TextView textValorElementos;
private EditText valorElementos;
private EditText tamanhoMatrizes;
private EditText quantidadeThreads;
private TextView textTempoExecucao;
private TextView tempoExecucao;
private Button buttonMultiplicarMatrizes;
double matrizA[][] ;
double matrizB[][];
double matrizResultante[][];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textTamanhoMatrizes = (TextView) findViewById(R.id.textTamanhoMatrizes);
textQuantidadeThreads = (TextView) findViewById(R.id.textQuantidadeThreads);
tamanhoMatrizes = (EditText) findViewById(R.id.tamanhoMatrizes);
textValorElementos = (TextView)findViewById(R.id.textValorElementos);
quantidadeThreads = (EditText) findViewById(R.id.quantidadeThreads);
valorElementos = (EditText) findViewById(R.id.valorElementos);
textTempoExecucao = (TextView) findViewById(R.id.textTempoExecucao);
tempoExecucao = (TextView) findViewById(R.id.tempoExecucao);
buttonMultiplicarMatrizes = (Button) findViewById(R.id.buttonMultiplicarMatrizes);
multiplicacaoConcluida = (TextView) findViewById(R.id.multiplicacaoConcluida);
multiplicacaoConcluida.setVisibility(View.INVISIBLE);
textTempoExecucao.setVisibility(View.INVISIBLE);
tempoExecucao.setVisibility(View.INVISIBLE);
buttonMultiplicarMatrizes.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SIZE = Integer.valueOf(tamanhoMatrizes.getText().toString());
MAX_THREADS = Integer.valueOf(quantidadeThreads.getText().toString());
valor = Double.valueOf(valorElementos.getText().toString());
matrizA = new double[SIZE][SIZE];
matrizB = new double[SIZE][SIZE];
matrizResultante = new double[SIZE][SIZE];
init(matrizA, matrizB, SIZE, valor);
executor = Executors.newFixedThreadPool(SIZE);
Long tempoInicial =0L;
Long tempoFinal=0L;
MatrixMultiplyTask mainTask = new MatrixMultiplyTask(matrizA, 0, 0, matrizB, 0, 0, matrizResultante, 0, 0, SIZE);
tempoInicial = android.os.SystemClock.uptimeMillis();
Future future = executor.submit(mainTask);
try {
future.get();
tempoFinal = android.os.SystemClock.uptimeMillis();
multiplicacaoConcluida.setVisibility(View.VISIBLE);
textTempoExecucao.setVisibility(View.VISIBLE);
tempoExecucao.setText((tempoFinal-tempoInicial)+" ms");
tempoExecucao.setVisibility(View.VISIBLE);
Toast.makeText(getBaseContext(), "Início : "+tempoInicial+" Fim: "+tempoFinal+" Total: "+(tempoFinal-tempoInicial)+ "ms", Toast.LENGTH_LONG).show();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
if (matrizA == null || matrizB == null) {
Toast.makeText(getBaseContext(), "Erro ao gerar matriz A ou matriz B", Toast.LENGTH_SHORT).show();
return;
}
}
});
}
static void init(double[][] matrizA2, double[][] matrizB2, int n, double valor) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
matrizA2[i][j] = valor;
matrizB2[i][j] = valor;
}
}
}
public class Seq implements Runnable {
private final MatrixMultiplyTask a;
private final MatrixMultiplyTask b;
public Seq(MatrixMultiplyTask a, MatrixMultiplyTask b) {
this.a = a;
this.b = b;
}
public void run() {
a.run();
b.run();
}
}
private class MatrixMultiplyTask implements Runnable {
private final double[][] A; // Matrix A
private final int aRow; // first row of current quadrant of A
private final int aCol; // first column of current quadrant of A
private final double[][] B; // Similarly for B
private final int bRow;
private final int bCol;
private final double[][] C; // Similarly for result matrix C
private final int cRow;
private final int cCol;
private final int size;
public MatrixMultiplyTask(double[][] A, int aRow, int aCol, double[][] B,
int bRow, int bCol, double[][] C, int cRow, int cCol, int size) {
this.A = A;
this.aRow = aRow;
this.aCol = aCol;
this.B = B;
this.bRow = bRow;
this.bCol = bCol;
this.C = C;
this.cRow = cRow;
this.cCol = cCol;
this.size = size;
}
public void run() {
//System.out.println("Thread: " + Thread.currentThread().getName());
if (size <= THRESHOLD) {
multiplyStride2();
} else {
int h = size / 2;
Seq seq1 = new Seq(new MatrixMultiplyTask(A,
aRow, aCol, // A11
B, bRow, bCol, // B11
C, cRow, cCol, // C11
h),
new MatrixMultiplyTask(A, aRow, aCol + h, // A12
B, bRow + h, bCol, // B21
C, cRow, cCol, // C11
h));
Seq seq2 = new Seq(new MatrixMultiplyTask(A,
aRow, aCol, // A11
B, bRow, bCol + h, // B12
C, cRow, cCol + h, // C12
h),
new MatrixMultiplyTask(A, aRow, aCol + h, // A12
B, bRow + h, bCol + h, // B22
C, cRow, cCol + h, // C12
h));
Seq seq3 = new Seq(new MatrixMultiplyTask(A, aRow
+ h, aCol, // A21
B, bRow, bCol, // B11
C, cRow + h, cCol, // C21
h),
new MatrixMultiplyTask(A, aRow + h, aCol + h, // A22
B, bRow + h, bCol, // B21
C, cRow + h, cCol, // C21
h));
Seq seq4 = new Seq(new MatrixMultiplyTask(A, aRow
+ h, aCol, // A21
B, bRow, bCol + h, // B12
C, cRow + h, cCol + h, // C22
h),
new MatrixMultiplyTask(A, aRow + h, aCol + h, // A22
B, bRow + h, bCol + h, // B22
C, cRow + h, cCol + h, // C22
h));
final FutureTask s1Task = new FutureTask(seq2, null);
final FutureTask s2Task = new FutureTask(seq3, null);
final FutureTask s3Task = new FutureTask(seq4, null);
executor.execute(s1Task);
executor.execute(s2Task);
executor.execute(s3Task);
seq1.run();
s1Task.run();
s2Task.run();
s3Task.run();
try {
s1Task.get();
s2Task.get();
s3Task.get();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
executor.shutdownNow();
}
}
}
public void multiplyStride2() {
for (int j = 0; j < size; j += 2) {
for (int i = 0; i < size; i += 2) {
double[] a0 = A[aRow + i];
double[] a1 = A[aRow + i + 1];
float s00 = 0.0F;
float s01 = 0.0F;
float s10 = 0.0F;
float s11 = 0.0F;
for (int k = 0; k < size; k += 2) {
double[] b0 = B[bRow + k];
s00 += a0[aCol + k] * b0[bCol + j];
s10 += a1[aCol + k] * b0[bCol + j];
s01 += a0[aCol + k] * b0[bCol + j + 1];
s11 += a1[aCol + k] * b0[bCol + j + 1];
double[] b1 = B[bRow + k + 1];
s00 += a0[aCol + k + 1] * b1[bCol + j];
s10 += a1[aCol + k + 1] * b1[bCol + j];
s01 += a0[aCol + k + 1] * b1[bCol + j + 1];
s11 += a1[aCol + k + 1] * b1[bCol + j + 1];
}
C[cRow + i][cCol + j] += s00;
C[cRow + i][cCol + j + 1] += s01;
C[cRow + i + 1][cCol + j] += s10;
C[cRow + i + 1][cCol + j + 1] += s11;
}
}
}
}
}