PHP - многопоточность функции с pthreads

1

В настоящее время я работаю с pthreads для реализации многопоточности на очень требовательной функции. Пока я получил эту работу:

class Operation extends Thread {
  public function __construct($arg) {
    $this->arg = $arg;
  }  
  public function run() {
    if ($this->arg) {
      $parameters = $this->arg;
      echo my_function($parameters[0],$parameters[1]);
    }
  }
}
$stack = array();
foreach ($work as $operation) { $stack[] = new Operation($operation); };
foreach ($stack as $t) { $t->start(); };

Он выводит результаты напрямую. Я хотел бы, чтобы мои результаты сохранялись один за другим в массиве (в том же порядке было бы неплохо), но, конечно, это не работает:

class Operation extends Thread {
  public function __construct($arg) {
    $this->arg = $arg;
  }  
  public function run() {
    if ($this->arg) {
      $parameters = $this->arg;
      $results[] = my_function($parameters[0],$parameters[1]);
    }
  }
}
$stack = array();
foreach ($work as $operation) { $stack[] = new Operation($operation); };
foreach ($stack as $t) { $t->start(); };
var_dump($results);

Любая помощь будет оценена по достоинству.

Детали:

  • my_function выводит строку UTF-8.
  • 0
    my_function() ли вы показать код my_function() здесь?
  • 0
    Едва. Это огромно, и все переменные на французском языке. Я реорганизовал эту часть кода для удобства читателя. Возможно, у вас есть конкретная идея? Он выводит строку текста UTF-8.
Показать ещё 7 комментариев
Теги:
multithreading
pthreads

2 ответа

2
Лучший ответ

Основная проблема заключается в том, что массивы не являются потокобезопасными, pthreads предоставляет массивные интерфейсы для всех объектов Threaded; Это означает, что вы можете использовать объекты Threaded вместо массивов в многопоточном контексте.

<?php

function demanding(...$params) {
  /* you have parameters here */
  return array(rand(), rand());
}

class Task extends Collectable {
  public function __construct(Threaded $result, $params) {
    $this->result = $result;
    $this->params = $params;
  }

  public function run() {
    $this->result[] = 
      demanding(...$this->params);
  }

  protected $result;
  protected $params;
}

$pool = new Pool(16);

$result = new Threaded();

while (@$i++<16) {
  $pool->submit(
    new Task($result, $argv));
}

$pool->shutdown();

var_dump($result);
?>

Существует не встроенный способ делать многопоточную сортировку, поэтому проще всего сортировать результат, когда потоки закончены.

  • 0
    «Я являюсь автором pthreads для PHP». Ну, я думаю, у меня не было лучшего ответа, большое спасибо за вашу помощь! С этого момента я собираюсь использовать pthreads довольно часто. Будете ли вы предлагать онлайн-ресурсы, которые вы могли бы порекомендовать мне, чтобы научиться использовать их эффективно и элегантно? Я изучил примеры в pthreads Github, вот что помогло мне сделать код выше, но я должен сказать, что это было нелегко!
  • 0
    Это хорошее место для начала gist.github.com/krakjoe/6437782
1

Я уверен, что кто-то может сделать лучше, но он (по-видимому) работает, и это довольно мощный удар. "Ожидание потока" часть очень неэффективна и неэффективна, любая помощь будет оценена!

Прежде всего, проверьте, установлены ли у вас pthreads с помощью phpinfo() или установите https://php.net/manual/en/pthreads.installation.php.

$key = 0;//We initialise the key to sort our results
foreach($iteration as $parameters) {//We make a loop to create the task list 
  $arguments[] = array($key,$parameters,$_POST['stuff'],$another_parameter,...);//We index ALL the parameters our function need for each task ($_POST, $_FILES, $_GET, user defined...) in a nice array
  ++$key;//We increment our key
};

class operation extends Thread {
  public $done = 0;//We initialize the "done" indicator
  public function __construct($arguments) {
    $this->arguments = $arguments;//We put our parameters in a construct
  }
  public function run() {
    if ($this->arguments)
    {
      $parameters = $this->arguments;//We extract the parameters for this worker
      $this->result = array($parameters[0], your_function($parameters[1],$parameters[2],...));//We launch our function and add the key to the result
      $this->done = 1;//This thread is done
    }
  }
}

$stack = array();//Lets initialize our stack
foreach ($arguments as $operation) { $stack[] = new operation($operation); };//We initialize the process
foreach ($stack as $t) { if($t->start()) { $t->join(); }; };//We launch it and wait until all the workers have completed their task

foreach($stack as $strata) {//We get each of the results
  while($strate->done == 0) {sleep(1);};//Inefficient way to wait for the thread to complete, ANY HELP WILL BE APPRECIATED
  $results[] = $strata->result;//Once it done we add it to our results array
};
ksort($results);//We sort our array with our key
foreach($results as $line) { $results_sorted[] = $line[1]; };//We delete the key

Теперь у вас есть $ results_sorted! Наслаждайтесь !

  • 0
    sleep полностью приостановит ядро процессора на 1 секунду. Вы также предполагаете, что ваши темы будут закончены в эту секунду. Вместо ручной блокировки вы можете использовать цикл while, который проверяет, завершены ли потоки, и, если да, присоединяет их. Подход, который мне лично нравится, заключается в использовании цикла обработки событий (libev, libuv) и использовании асинхронного подхода - я уведомляю основной контекст о том, что выполняется конкретный поток, и ожидающий процесс неблокирует, что позволяет использовать ядро ЦП, пока потоки делают их обработку.
  • 0
    Вы правы. Я смотрю в php.net/manual/en/threaded.isteridity.php .
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню