From 74a3778426202b928add7cafd9dccdc941987cdb Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Mon, 5 Jan 2026 20:07:23 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A6=81=E6=AD=A2=20foreach=20=E4=B8=AD?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=85=A8=E5=B1=80=E5=8F=98=E9=87=8F=E7=9A=84?= =?UTF-8?q?=E5=90=8C=E5=90=8D=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/spectralnorm.php | 178 ++++++++++++++++++++++++++++++++++++++ src/Php/Translator.php | 15 +++- src/functions.php | 1 + 3 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 examples/spectralnorm.php diff --git a/examples/spectralnorm.php b/examples/spectralnorm.php new file mode 100644 index 00000000..8d4e982c --- /dev/null +++ b/examples/spectralnorm.php @@ -0,0 +1,178 @@ +> 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); +} diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 9d33c74d..bb2734aa 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -1334,8 +1334,8 @@ class Translator extends \PhpAot\Core\Translator if (!$this->hasVar($name)) { $this->addLocalVar($name, self::TYPE_REF); $this->beforeStmtLines[] = $name . ' = php::newReference();'; - } else if ($funcName) { - $funcArg = Reflection::getFunctionParameter($funcName, 0); + } else if (!$nativeFunction and $funcName) { + $funcArg = Reflection::getFunctionParameter($funcName, $i); // 需要引用类型的参数,使用临时变量作为引用,并替换掉实际的参数 if ($funcArg and $funcArg->isPassedByReference()) { $tmpVar = $this->genTmpVarName(); @@ -1733,6 +1733,11 @@ class Translator extends \PhpAot\Core\Translator } } + private function unescapeVarName(string $name) + { + return str_replace('_php__var__', '', $name); + } + private function parseInterpolatedStringPart(Node $expr): string { return '"' . $this->escapeString($expr->value) . '"'; @@ -1844,6 +1849,9 @@ class Translator extends \PhpAot\Core\Translator $code .= 'for (auto iter = ' . $iteratorVar . '.begin(); iter != ' . $iteratorVar . '.end(); ++iter) {' . PHP_EOL; $this->indentLevel++; if ($node->keyVar) { + if ($this->hasGlobalVar($keyVar)) { + $this->fatalError($node->keyVar, 'Cannot redefine key variable: ' . $this->unescapeVarName($keyVar)); + } $code .= $this->getIndent() . self::TYPE_VAR . ' ' . $keyVar . ' = iter.key();' . PHP_EOL; $this->addLocalVar($keyVar, self::TYPE_VAR); } @@ -1856,6 +1864,9 @@ class Translator extends \PhpAot\Core\Translator $dim = $this->parseIdentifier($node->valueVar->dim); $code .= $this->getIndent() . "$array.offsetSet($dim, iter.value());"; } else { + if ($this->hasGlobalVar($valueVar)) { + $this->fatalError($node->valueVar, 'Cannot redefine value variable: ' . $this->unescapeVarName($valueVar)); + } $code .= $this->getIndent() . self::TYPE_VAR . ' ' . $valueVar . ' = iter.value();' . PHP_EOL; $this->addLocalVar($valueVar, self::TYPE_VAR); } diff --git a/src/functions.php b/src/functions.php index f76a1a4b..e55b2e4e 100644 --- a/src/functions.php +++ b/src/functions.php @@ -43,5 +43,6 @@ function debug() foreach(func_get_args() as $arg) { var_dump($arg); } + debug_print_backtrace(); exit; } \ No newline at end of file