Overview

pika is a C++ library that builds on the std::execution (P2300) proposal by providing a CPU runtime with user-level threads, as well as integration with CUDA, HIP, and MPI. See Getting started to get started.

Hello, world

Below is a brief overview of what you can do with pika. The majority of the functionality below comes from std::execution. pika adds a high-performance CPU runtime as well as a std::execution scheduler to target the pika runtime. The stdexec repository contains an excellent list of resources for learning more about std::execution itself.

#include <pika/execution.hpp>
#include <pika/init.hpp>
#include <pika/thread.hpp>

#include <fmt/ostream.h>
#include <fmt/printf.h>

#include <iostream>
#include <utility>

int main(int argc, char* argv[])
{
    // Most functionality is found in the pika::execution namespace. If pika is built with stdexec,
    // std::execution will also be found in this namespace.
    namespace ex = pika::execution::experimental;
    // Some additional utilities are in pika::this_thread.
    namespace tt = pika::this_thread::experimental;

    // Start the pika runtime.
    pika::start(argc, argv);

    // Create a std::execution scheduler that runs work on the default pika thread pool.
    ex::thread_pool_scheduler sched{};

    // We can schedule work using sched.
    auto snd1 = ex::transfer_just(sched, 42) | ex::then([](int x) {
        fmt::print(std::cout, "Hello from a pika user-level thread (with id {})!\nx = {}\n",
            pika::this_thread::get_id(), x);
    });

    // The work is started once we call sync_wait.
    tt::sync_wait(std::move(snd1));

    // We can build arbitrary graphs of work using the split and when_all adaptors.
    auto snd2 = ex::just(3.14) | ex::split();
    auto snd3 = ex::transfer(snd2, sched) |
        ex::then([](double pi) { fmt::print(std::cout, "Is this pi: {}?\n", pi); });
    auto snd4 = ex::transfer_when_all(sched, std::move(snd2), ex::just(500.3)) |
        ex::then([](double pi, double r) { return pi * r * r; });
    auto result = tt::sync_wait(ex::when_all(std::move(snd3), std::move(snd4)));
    fmt::print(std::cout, "The result is {}\n", result);

    // Tell the runtime that when there are no more tasks in the queues it is ok to stop.
    pika::finalize();

    // Wait for all work to finish and stop the runtime.
    pika::stop();

    return 0;
}

The example above should output something like:

Hello from a pika user-level thread (with id 0x7fec6000c040)!
x = 42
Is this pi: 3.14?
The result is 785942.2826

Getting help

Please report issues on GitHub. General questions can be asked on GitHub discussions.

Acknowledgements

pika is a fork of HPX focusing on the single-node use case complemented by minimal MPI support.

Name

Pick your favourite meaning from the following: