<?php
/*
File: matrix.php
Description: Matrix multiplication example using CThreads library.
Usage: Call from the browser this file.
URL Parameters:
threads - (int) number of threads (2 default)
size - (int) size of the matrix (size x size) (4 default)
print - (int) 1 to print out, 0 to not
Author: Amilton de Camargo Jr. <amilton@dicasemgeral.com>
Copyright (cc) 2014 - Amilton de Camargo Jr. <amilton@dicasemgeral.com>
*/
// Include CThreads library
require_once('CThreads.php');
///////// FUNCTIONS //////////
// Function that generates a matrix
// Arguments:
// (int) $size - Size of the matrix (size x size)
// (int) $rand_from - First number range
// (int) $rand_to - Last number range
// Return:
// (array) $matrix - Generated matrix
function GenerateMatrix($size=0, $rand_from=1, $rand_to=2)
{
// If it got an invalid size
if ( $size < 2 )
return array();
$matrix = array();
// Generate the matrix
for ( $i=0; $i<$size; $i++ )
for ( $j=0; $j<$size; $j++ )
$matrix[$i][$j] = ($rand_from == $rand_to) ? $rand_from : mt_rand($rand_from, $rand_to);
return $matrix;
}
// Function that prints a matrix
// Arguments:
// (array) $matrix - Matrix to be printed
// (int) $size - Matrix size
// Return:
// (void)
function PrintMatrix($matrix=array(), $size=0)
{
// If invalid arguments
if ( !is_array($matrix) || $size < 0 )
return;
// Print the matrix
for ( $i=0; $i<$size; $i++ )
{
for ( $j=0; $j<$size; $j++ )
echo $matrix[$i][$j] . ' ';
echo '<br>';
}
}
// Function to calculate a piece of a matrix
// Arguments:
// (array/int/float/String) $args - Arguments for the function
// Return:
// (array) $ret - Array with startpoint, endpoint, and result matrix
function Multiply($args)
{
// If not a valid argument
if ( !is_array($args) )
return;
// Get the arguments
$t_number = $args['t_number']; // Thread ID
$size = $args['size']; // Matrix size
$threads = $args['threads']; // Number of threads
$first = $args['first']; // First matrix
$second = $args['second']; // Second matrix
$result = array(); // Result matrix (local)
if ( $threads > 1 )
{
// Calculate the thread's boundaries
$rows = (int) ($size / $threads);
$start = (int) ($rows * $t_number);
$end = (int) ($start + $rows);
$dif = (int) ($size - ( $threads * $rows ));
// If it is the first thread and the matrix size is odd
if ( $t_number == 0 && $size % 2 != 0 && $dif > 0 )
$end += $dif;
}
else
{
$start = 0;
$end = $size;
}
// Perform the calculation
for ( $i=$start; $i<$end; $i++ )
for( $j=0; $j<$size; $j++ )
for( $k=0; $k<$size; $k++ )
$result[$i][$j] += $first[$i][$k] * $second[$k][$j]; // Save the result to the resultant matrix
// Return the values
$ret = array();
$ret['start'] = $start;
$ret['end'] = $end;
$ret['result'] = $result;
return $ret;
}
// Get the result form all calculations and make the final matrix
// Arguments:
// (array) $results - Results from threads
// (int) $threads - Number of threads
// (int) $size - Matrix size
// Return:
// (array) $result - Result matrix from multiplication
function FinalResult($results=array(), $threads=0, $size=0)
{
$result = array();
for ( $t=0; $t<$threads; $t++ )
{
$start = $results[$t]['start'];
$end = $results[$t]['end'];
$res = $results[$t]['result'];
for ( $i=$start; $i<$end; $i++ )
for ( $j=0; $j<$size; $j++ )
$result[$i][$j] = $res[$i][$j];
}
return $result;
}
//////////// MAIN PROGRAM /////////////
$threads = (isset($_GET['threads'])) ? (int) $_GET['threads'] : 2; // Number of threads
$m_size = (isset($_GET['size'])) ? (int) $_GET['size'] : 4; // Matrix size
$matrix1 = GenerateMatrix($m_size); // First matrix
$matrix2 = GenerateMatrix($m_size); // Second matrix
$result = array(); // Result of the multiplication
$thread_handle = new CThreads(); // Thread handles object
$printOut = (isset($_GET['print'])) ? (int) $_GET['print'] : true; // Boolean variable whether to print or not
// Print tha matrices
if ( $printOut )
{
echo '<b>Matrix Multiplication</b><br><br>';
echo '<table><tr><td>';
echo 'Matrix 1:<br><br>';
PrintMatrix($matrix1, $m_size);
echo '</td><td width="50"> </td><td>';
echo 'Matrix 2:<br><br>';
PrintMatrix($matrix2, $m_size);
echo '</td></tr></table>';
}
echo "<br>> Using {$threads} thread(s) to calculate...<br>";
// Beginning timestamp
$parallel_start_time = microtime(true);
if ( $threads == 1 )
{
// Set the arguments
$args = array(); // Initialize the variable
$args['t_number'] = 0; // Thread ID
$args['size'] = $m_size; // Matrix size
$args['threads'] = 1; // Number of threads
$args['first'] = $matrix1; // First matrix
$args['second'] = $matrix2; // Second matrix
// Perform the calculation and get the result
$threads_results[0] = Multiply($args);
}
else
{
// Create the threads
for ( $i=0; $i<$threads; $i++ )
{
// Set the arguments
$args = array(); // Initialize the variable
$args['t_number'] = $i; // Thread ID
$args['size'] = $m_size; // Matrix size
$args['threads'] = $threads; // Number of threads
$args['first'] = $matrix1; // First matrix
$args['second'] = $matrix2; // Second matrix
// Create the thread and set the function to call and its arguments
$thread_handle->AddThread('Multiply', $args, true);
}
// Run all threads
$thread_handle->Run();
// Get the result from all threads
$threads_results = $thread_handle->GetResults();
}
// End timestamp
$parallel_end_time = microtime(true);
// Get the final result
$result = FinalResult($threads_results, $threads, $m_size);
// Print out the result
if ( $printOut )
{
echo '<br>Result:<br><br>';
PrintMatrix($result, $m_size);
}
echo '<br>Parallel part done in '.round($parallel_end_time-$parallel_start_time, 3).' seconds<br>';
?>
|