<?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. <[email protected]> 
     
    Copyright (cc) 2014 - Amilton de Camargo Jr. <[email protected]> 
*/ 
 
// 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>'; 
 
?>
 
 |