Не уверен, почему до сих пор нет тега «взломать» (извините за список в PHP), но …
Мне интересно, возможно ли это / как можно обойти массив, используя несколько потоков, используя многопоточную / асинхронную функцию hack. Мне это действительно не нужно, но это любопытство и может быть полезным.
Я посмотрел документацию по асинхронной функции «Hack»
http://docs.hhvm.com/manual/en/hack.async.php
и это немного сложно.
Вот основная идея того, что я хотел бы сделать (или посмотреть готово):
а) разбить массив на х разделов и обработать его на х «потоки» или б) создать х потоков, и каждый обрабатывает последний доступный элемент, т.е. когда поток обрабатывает элемент, он запрашивает у родительского потока новый для обработки. Hack не делает «потоки», но то же самое представлено функцией asyc
По сути, конечная цель — быстро оптимизировать стандартный блок foreach для работы в нескольких потоках, поэтому требуется минимальное изменение кода, а также узнать, что может сделать хак и как он работает.
В качестве примера я придумал некоторый код, но думаю, что совершенно не понял эту идею.
class ArrayWalkAsync
{
protected $array;
protected $threads = Array();
protected $current_index = 0;
protected $max_index;
protected $threads = 4;
public function array_walk($array)
{
$this->array = $array;
$this->max_index = count($array) - 1;
$result = Array();
for ($i=0;$i<$this->threads;$i++)
{
$this->threads[] = new ArrayWalkThread();
}
$continue = true;
while($continue)
{
$awaitables = Array();
for ($i=0;$i<$this->threads;$i++)
{
$a = $this->proccesNextItem($i);
if ($a)
{
$this->threads[] = $a;
} else {
$continue = false;
}
}
// wait for each
foreach ($awaitables as $awaitable_i)
{
await awaitable_i;
// do something with the result
}
}
}
protected function proccesNextItem($thread_id)
{
if ($this->current_index > $this->max_index)
{
return false;
}
$a = new ArrayWalkItem();
$a->value = $this->array[$this->current_index];
$a->index = $this->current_index;
$this->current_index++;
return $this->threads[$thread_id]->process($a,$this);
}
public function processArrayItem($item)
{
$value = $item->value;
sleep(1);
$item->result = 1;
}
}
class ArrayWalkThread
{
async function process($value,$parent): Awaitable<?ArrayWalkItem>
{
$parent->processArrayItem($a);
}
}
class ArrayWalkItem
{
public $value;
public $result;
}
Асинхронные функции Hack не будут делать то, что вы хотите. В Hack асинхронные функции не являются потоками. Это механизм, позволяющий скрыть задержку ввода-вывода и выборку данных, а не выполнять более одного вычисления одновременно. (Это то же самое, что и в C #, откуда взята функция Hack.)
Этот пост в блоге об асинхронных функциях имеет хорошее объяснение:
В течение нескольких месяцев в Hack была доступна функция async, которая позволяет писать код, который выполняет многозадачность. Это несколько похоже на многопоточность, так как несколько путей кода выполняются параллельно, однако это позволяет избежать проблем конфликта блокировок, общих для многопоточного кода, только фактически выполняя только один раздел в любой данный момент.
«Какая от этого польза?» — слышу я вас. Вы все еще привязаны к одному процессору, поэтому выполнение кода должно занимать столько же времени, верно? Что ж, это технически верно, но выполнение кода скрипта — не единственная причина задержки в вашем приложении. Самая большая часть этого, вероятно, исходит от ожидания баз данных для ответа на запросы.
[…]В то время как [http] вызов занят, сидя на своих руках в ожидании ответа, нет никаких причин, по которым вы не сможете выполнять другие действия, возможно, даже отправлять больше запросов. То же самое относится и к запросам к базе данных, которые могут занимать столько же времени, или даже к доступу к файловой системе, который быстрее, чем к сети, но все же может привести к задержке в несколько миллисекунд, и все они складываются!
Извините за путаницу в этом вопросе — вы не единственный, кто пытается ошибочно использовать асинхронность таким образом. Текущие документы делают ужасный работа по объяснению этого. Мы делаем обновление документации; текущий проект выполняет несколько лучшую работу, но я собираюсь подать задачу, чтобы убедиться, что она кристально чистая, прежде чем мы запустим новые документы.
Других решений пока нет …