Repositories (GitHub)
parallel_f

parallel_f

GitHub Resitory (opens in a new tab)

parallel_f (tasks, queues, lists in parallel threads)

Dieses Projekt beabsichtigt Flexibilität, Leistung und Benutzerfreundlichkeit in der Gebiet des Aufgaben-Parallelismus. Stell dir vor, du kennst jede Aufgaben Abhängigkeiten, parallel_f wird alle Aufgaben entsprechend ausführen. Dies wird mit der task_list Klasse erfolgen. Sie können auch die task_queue Klasse verwenden und die Abhängigkeiten selbst verwalten, wo Aufgaben-Warteschlangen parallel mit ihren Aufgaben in Sequenz ausgeführt werden.

Threads, die die Aufgaben ausführen, werden von der OS-Überhead befreit, indem die virtuellen Threads (vthreads) anstelle der Erstellung eines Threads pro Aufgabe verwendet werden. Die vthread-Manager erstellen einen virtuellen Thread pro geplanten (scheduled) vthread, der von einem Hardware-Thread pro CPU ausgeführt wird.

Dies ist ein "Hallo Welt" Beispiel mit einer Aufgabe in einer Liste:

int main()
{
    auto task = parallel_f::make_task([]()
    {
        std::cout << "Hello World" << std::endl;
    });

    parallel_f::task_list tl;

    tl.append(task);
    tl.finish();

    parallel_f::stats::instance::get().show_stats();
}

Der Haupt-Thread erzeugt eine Aufgabe über make_task, fügt sie der Liste hinzu und ruft finish auf, um sie zu planen und aufzurufen. Danach wartet der Haupt-Thread darauf, dass die Aufgabe abgeschlossen ist.

Schauen wir uns ein komplexeres Beispiel mit Abhängigkeiten an:

int main()
{
    auto func = [](auto a)
    {
        parallel_f::logInfo("Function %s...\n", a.c_str());

        std::this_thread::sleep_for(std::chrono::milliseconds(100));

        parallel_f::logInfo("Function %s done.\n", a.c_str());
    };


    std::vector<std::shared_ptr<parallel_f::task_base>> tasks;

    for (int i=0; i<17; i++)
        tasks.push_back(parallel_f::make_task(func, std::string("running task") + std::to_string(i)));


    parallel_f::task_list tl;

    auto a1_id = tl.append(tasks[0]);
    auto a2_id = tl.append(tasks[1]);
    auto a3_id = tl.append(tasks[2]);
    auto a4_id = tl.append(tasks[3]);
    auto a5_id = tl.append(tasks[4], a1_id, a2_id);
    auto a6_id = tl.append(tasks[5], a2_id, a3_id);
    auto a7_id = tl.append(tasks[6], a3_id, a4_id);
    auto a8_id = tl.append(tasks[7], a5_id);
    auto a9_id = tl.append(tasks[8], a6_id);
    auto a10_id = tl.append(tasks[9], a7_id);
    auto a11_id = tl.append(tasks[10], a8_id, a9_id, a10_id);
    auto a12_id = tl.append(tasks[11], a8_id, a9_id, a10_id);
    auto a13_id = tl.append(tasks[12], a8_id, a9_id, a10_id);
    auto a14_id = tl.append(tasks[13], a8_id, a9_id, a10_id);
    auto a15_id = tl.append(tasks[14], a8_id);
    auto a16_id = tl.append(tasks[15], a9_id);
    auto a17_id = tl.append(tasks[16], a10_id);

    tl.finish();


    parallel_f::stats::instance::get().show_stats();
}

Die Ausgabe sieht so aus:

(*) [07:55:26.430] ( 4140) Function running task0...
(*) [07:55:26.432] ( 5140) Function running task1...
(*) [07:55:26.432] ( 5312) Function running task3...
(*) [07:55:26.432] (11412) Function running task2...
(*) [07:55:26.538] (11412) Function running task2 done.
(*) [07:55:26.538] ( 5312) Function running task3 done.
(*) [07:55:26.538] ( 5140) Function running task1 done.
(*) [07:55:26.538] ( 5312) Function running task6...
(*) [07:55:26.538] ( 3256) Function running task5...
(*) [07:55:26.538] ( 4140) Function running task0 done.
(*) [07:55:26.539] (11412) Function running task4...
(*) [07:55:26.650] (11412) Function running task4 done.
(*) [07:55:26.650] ( 3256) Function running task5 done.
(*) [07:55:26.650] ( 4140) Function running task8...
(*) [07:55:26.650] (11412) Function running task7...
(*) [07:55:26.650] ( 5312) Function running task6 done.
(*) [07:55:26.651] ( 3256) Function running task9...
(*) [07:55:26.762] (11412) Function running task7 done.
(*) [07:55:26.762] ( 3256) Function running task9 done.
(*) [07:55:26.762] ( 5312) Function running task14...
(*) [07:55:26.762] ( 5140) Function running task16...
(*) [07:55:26.762] ( 4140) Function running task8 done.
(*) [07:55:26.762] (11412) Function running task10...
(*) [07:55:26.762] ( 3256) Function running task11...
(*) [07:55:26.762] ( 4140) Function running task12...
(*) [07:55:26.871] ( 4140) Function running task12 done.
(*) [07:55:26.871] ( 3256) Function running task11 done.
(*) [07:55:26.871] (11412) Function running task10 done.
(*) [07:55:26.871] ( 3256) Function running task13...
(*) [07:55:26.871] ( 5140) Function running task16 done.
(*) [07:55:26.871] ( 5312) Function running task14 done.
(*) [07:55:26.871] (11412) Function running task15...
(*) [07:55:26.991] (11412) Function running task15 done.
(*) [07:55:26.991] ( 3256) Function running task13 done.
Load '0': 0.588 (3 vthreads)
Load '1': 0.386 (2 vthreads)
Load '2': 0.998 (5 vthreads)
Load '3': 0.587 (3 vthreads)
Load '4': 0.809 (4 vthreads)
Load all: 3.368 (17 vthreads), total busy 330.526% (0.570 seconds)