1

「ハック」タグがまだない理由はわかりませんが(PHPでリストするのは申し訳ありません)、しかし...

ハックのマルチスレッド/非同期機能を使用して、複数のスレッドを使用して配列を歩くことができるかどうか/どのようにできるか疑問に思っています。私はこれを本当に必要としませんが、それは好奇心であり、役に立つかもしれません.

「ハック」の非同期機能のドキュメントを見てきました

http://docs.hhvm.com/manual/en/hack.async.php

そしてちょっと難しい。

これが私が作りたい(または完成させたい)ものの基本的な考え方です:

a) 配列を x セクションに分割し、x "スレッド" で処理するか、b) x スレッドを作成し、それぞれが最新の利用可能な項目を処理します。スレッドがアイテムを処理するとき、親スレッドに新しいアイテムを処理するように要求します。ハックは「スレッド」を行いませんが、同じことを非同期関数で表します

基本的に、最終的な目標は、標準の 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;
}
4

1 に答える 1

3

ハックの非同期関数は、あなたが望むことをするつもりはありません。Hack では、非同期関数はスレッドではありません。これは、一度に複数の計算を行わないように、IO レイテンシとデータ フェッチを隠すためのメカニズムです。(これは、Hack 機能の派生元である C# と同じです。)

非同期関数に関するこのブログ投稿には、適切な説明があります。

数か月前から、Hack には async と呼ばれる機能があり、協調的にマルチタスクを実行するコードを作成できます。これは、複数のコード パスが並行して実行されるという点でスレッド化と似ていますが、特定の瞬間に 1 つのセクションのみを実際に実行することで、マルチスレッド化されたコードに共通するロック競合の問題を回避します。

「それは何の役に立つの?」とあなたがたずねるのが聞こえます。まだ 1 つの CPU にバインドされているため、コードの実行には同じ時間がかかるはずですよね? 技術的にはそのとおりですが、アプリケーションで遅延を引き起こすのはスクリプト コードの実行だけではありません。その最大の原因はおそらく、バックエンド データベースがクエリに応答するのを待つことです。

[...]

[an http] 呼び出しが忙しく応答を待っている間、他のことを実行できない理由はありません。おそらく、さらに要求を発行することさえできます。同じことがデータベース クエリにも当てはまります。ネットワーク クエリと同じくらい時間がかかるか、ネットワークよりも高速なファイル システム アクセスでさえ、数ミリ秒の遅延時間が発生する可能性があり、それらはすべて加算されます。

この点で混乱を招いて申し訳ありません。このように非同期を誤って使用しようとするのはあなただけではありません。現在のドキュメントは、これを説明するのにひどい仕事をしています。ドキュメントの改良を行っています。現在のドラフトの方がいくらかはうまく機能していますが、新しいドキュメントを公開する前に、タスクをファイルして明確にするつもりです。

于 2015-10-04T19:52:24.003 に答える