parent
bf09f600ba
commit
74a3778426
3 changed files with 192 additions and 2 deletions
@ -0,0 +1,178 @@ |
||||
<?php |
||||
|
||||
/* |
||||
The Computer Language Benchmarks Game |
||||
https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ |
||||
|
||||
contributed by Nikita Popov |
||||
*/ |
||||
|
||||
|
||||
function A($i, $j) |
||||
{ |
||||
return 1.0 / (((($i + $j) * ($i + $j + 1)) >> 1) + $i + 1); |
||||
} |
||||
|
||||
function Av($n, $v, $start, $end) |
||||
{ |
||||
global $_tpl; |
||||
$Av = $_tpl; |
||||
for ($i = $start; $i < $end; ++$i) { |
||||
$sum = 0.0; |
||||
foreach ($v as $j => $v_j) { |
||||
$sum += A($i, $j) * $v_j; |
||||
} |
||||
$Av[$i] = $sum; |
||||
} |
||||
return $Av; |
||||
} |
||||
|
||||
function Atv($n, $v, $start, $end) |
||||
{ |
||||
global $_tpl; |
||||
$Atv = $_tpl; |
||||
for ($i = $start; $i < $end; ++$i) { |
||||
$sum = 0.0; |
||||
foreach ($v as $j => $v_j) { |
||||
$sum += A($j, $i) * $v_j; |
||||
} |
||||
$Atv[$i] = $sum; |
||||
} |
||||
return $Atv; |
||||
} |
||||
|
||||
function AtAv($n, $v, $start, $end, $sync) |
||||
{ |
||||
|
||||
$tmp = Av($n, $v, $start, $end); |
||||
if ($sync) $tmp = sync($tmp); |
||||
|
||||
$tmp = Atv($n, $tmp, $start, $end); |
||||
if ($sync) $tmp = sync($tmp); |
||||
|
||||
return $tmp; |
||||
} |
||||
|
||||
function sync($tmp) |
||||
{ |
||||
global $parent, $chunk_data_size, $total_data_size, $pipe, $pipes; |
||||
|
||||
if (!$parent) { |
||||
$data = call_user_func_array('pack', array_merge(['d*'], $tmp)); |
||||
safe_write($pipe, $data); |
||||
return array_values(unpack('d*', safe_read($pipe, $total_data_size))); |
||||
} else { |
||||
$tmps = array(); |
||||
foreach ($pipes as $_pipe) { |
||||
$tmps[] = unpack('d*', safe_read($_pipe, $chunk_data_size)); |
||||
} |
||||
$tmps[] = $tmp; |
||||
$tmp = call_user_func_array('array_merge', $tmps); |
||||
|
||||
$data = call_user_func_array('pack', array_merge(['d*'], $tmp)); |
||||
foreach ($pipes as $_pipe) { |
||||
safe_write($_pipe, $data); |
||||
} |
||||
return $tmp; |
||||
} |
||||
} |
||||
|
||||
function safe_write($fd, $data) |
||||
{ |
||||
$len = strlen($data); |
||||
do { |
||||
$w = fwrite($fd, $data); |
||||
$len -= $w; |
||||
} while ($len && ($data = substr($data, $w)) !== FALSE); |
||||
} |
||||
|
||||
function safe_read($fd, $len) |
||||
{ |
||||
$data = ''; |
||||
while ($len > 0) { |
||||
$d = fread($fd, $len); |
||||
$len -= strlen($d); |
||||
$data .= $d; |
||||
} |
||||
return $data; |
||||
} |
||||
|
||||
function pipe() |
||||
{ |
||||
return stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, 0); |
||||
} |
||||
|
||||
function main() |
||||
{ |
||||
$begin = microtime(TRUE); |
||||
global $argc, $argv, $parent, $chunk_data_size, $total_data_size, $pipe, $pipes, $_tpl; |
||||
$n = $argc > 2 ? $argv[2] : 1; |
||||
|
||||
$procs = 1; |
||||
if (file_exists('/proc/cpuinfo')) { |
||||
$procs = preg_match_all('/^processor\s/m', file_get_contents('/proc/cpuinfo'), $discard); |
||||
} |
||||
|
||||
if ($n < $procs) { |
||||
$procs = 1; |
||||
} |
||||
|
||||
$chunk_size = (int)($n / $procs); |
||||
$double_size = strlen(pack('d', 0.0)); |
||||
$chunk_data_size = $double_size * $chunk_size; |
||||
$total_data_size = $double_size * $n; |
||||
|
||||
$pipes = array(); |
||||
$parent = FALSE; |
||||
for ($i = 0; $i < $procs; ++$i) { |
||||
$range_begin = $i * $chunk_size; |
||||
if ($i < ($procs - 1)) { |
||||
$pipe = pipe(); |
||||
if (!$pipe) { |
||||
die('could not create pipe'); |
||||
} |
||||
$pipes[] = $pipe[0]; |
||||
$pipe = $pipe[1]; |
||||
$range_end = $range_begin + $chunk_size; |
||||
$pid = pcntl_fork(); |
||||
if ($pid === -1) { |
||||
die('could not fork'); |
||||
} else if ($pid) { |
||||
continue; |
||||
} |
||||
break; |
||||
} else { |
||||
$range_end = $n; |
||||
$parent = TRUE; |
||||
} |
||||
} |
||||
|
||||
$u = array_fill(0, $n, 1.0); |
||||
$_tpl = array_fill($range_begin, $range_end - $range_begin, 0.0); |
||||
$sync = $procs > 0; |
||||
|
||||
for ($i = 0; $i < 10; $i++) { |
||||
$v = AtAv($n, $u, $range_begin, $range_end, $sync); |
||||
$u = AtAv($n, $v, $range_begin, $range_end, $sync); |
||||
} |
||||
|
||||
if (!$parent) { |
||||
exit(0); |
||||
} |
||||
|
||||
$childs = $procs - 1; |
||||
while ($childs--) { |
||||
pcntl_wait($s); |
||||
} |
||||
|
||||
$vBv = 0.0; |
||||
$vv = 0.0; |
||||
$i = 0; |
||||
foreach ($v as $val) { |
||||
$vBv += $u[$i] * $val; |
||||
$vv += $val * $val; |
||||
++$i; |
||||
} |
||||
printf("%0.9f\n", sqrt($vBv / $vv)); |
||||
printf("Time: %.9f\n", microtime(TRUE) - $begin); |
||||
} |
||||
Loading…
Reference in new issue