The RaftLib C++ library, streaming/dataflow concurrency via C++ iostream-like operators

Overview

RaftLib is a C++ Library for enabling stream/data-flow parallel computation. Using simple right shift operators (just like the C++ streams that you would use for string manipulation), you can link parallel compute kernels together. With RaftLib, we do away with explicit use of pthreads, std::thread, OpenMP, or any other parallel "threading" library. These are often mis-used, creating non-deterministic behavior. RaftLib's model allows lock-free FIFO-like access to the communications channels connecting each compute kernel. The full system has many auto-parallelization, optimization, and convenience features that enable relatively simple authoring of performant applications. Feel free to give it a shot, if you have any issues, please create an issue request. Minor issues, the Slack group is the best way to resolve. We take pull requests!! For benchmarking, feel free to send the authors an email. We've started a benchmark collection, however, it's far from complete. We'd love to add your code!!

User Group / Mailing List: slack channel

=============

Build status

CI

Pre-requisites

OS X & Linux

  • Compiler: c++17 capable -> Clang, GNU GCC 5.0+, or Intel icc
  • Latest build runs under Linux with above compilers on both x86 and AArch64, with both pthreads and QThreads.
  • OS X M1 runs, compiles, but has some test case hiccups on templates, but doesn't seem to impact functionality.
  • Note for OS X users without a /user/local, specify an install prefix when using CMake.

Windows

  • Builds and runs under Win10

Install

Make a build directory (for the instructions below, we'll write [build]). If you want to build the OpenCV example, then you'll need to add to your cmake invocation:

-DBUILD_WOPENCV=true 

To use the QThreads User space HPC threading library you will need to use the version with the RaftLib org and follow the RaftLib specific readme. This QThreads version has patches for hwloc2.x applied and fixes for test cases. To compile RaftLib with QThreads linked, add the following (assumes the QThreads library is in your path):

-DUSEQTHREAD=1

Building the examples, benchmarks and tests can be disabled using:

-DBUILD_EXAMPLES=false
-DBUILD_BENCHMARKS=false
-DBUILD_TESTS=false

To build:

mkdir [build]
cd [build]
cmake ..
make && make test
sudo make install

NOTE: The default prefix in the makefile is:

PREFIX ?= /usr/local

Using

  • When building applications with RaftLib, on Linux it is best to use the pkg-config file, as an example, using the poc.cpp example,
g++ `pkg-config --cflags raftlib` poc.cpp -o poc `pkg-config --libs raftlib`

Feel free to substitute your favorite build tool. I use Ninja and make depending on which machine I'm on. To change out, use cmake to generate the appropriate build files with the -Gxxx flag.

Citation

If you use this framework for something that gets published, please cite it as:

@article{blc16,
  author = {Beard, Jonathan C and Li, Peng and Chamberlain, Roger D},
  title = {RaftLib: A C++ Template Library for High Performance Stream Parallel Processing},
  year = {2016},
  doi = {http://dx.doi.org/10.1177/1094342016672542},
  eprint = {http://hpc.sagepub.com/content/early/2016/10/18/1094342016672542.full.pdf+html},
  journal = {International Journal of High Performance Computing Applications}
}

Other Info Sources

Comments
  • make link syntax less clunky, more c++ like

    make link syntax less clunky, more c++ like

    Issue

    I've had several requests to make the syntax for linking compute kernels less clunky and more C++ like. That means keeping the map::link syntax but also supporting something with a bit more polish.

    Potential Solution

    int
    main( int argc, char **argv )
    {  
       //generic random kernel instantiations
       kernel f;
       kernel g;
       //explicit declaration of map for example, potentially keep hidden one for compatibility
       map m;
       //in order version
       m >> f >> "a"_o >> "b"_i >> g;
       //out order version
       m >> f >> "a"_o >> raft::ooo >> "b"_i >> g;
       m.exe();
       return( EXIT_SUCCESS );
    }
    
    opened by jonathan-beard 28
  • Compiling RaftLib for Windows

    Compiling RaftLib for Windows

    Currently RaftLib is using the Makefile system, which works well for Linux and OS X. However, I also need to have RaftLib available in Windows, and available for Visual Studio projects.

    At the moment, how can I compile RaftLib in such a way that it can be readily used by Visual-Studio-based projects? If I compile using cygwin Makefile system, then can the library still be usable by Visual Studio?

    In the long run, would it be a good idea to migrate RaftLib to Cmake, so that it can automatically generate build scripts for any systems?

    enhancement 
    opened by kcleung 18
  • Affinitylib

    Affinitylib

    @f-tischler , Can you double check to make sure I'm not stomping on any of the updates you planned? @mr-j0nes, wouldn't mind an extra set of eyes just in case....

    Primary changes for this pull request are:

    • move core affinity code out to separate module
    • move demangle code to separate module
    • update cmake files to support namespace injection
    • bugfix in mapbase.hpp which could leave uninitialized portinfo objects
    • move "portNotFound" code from header and place in cpp file so that demangle gets into an object vs. being re-included in every header/raft file (would be a pain with the namespace injection later on)
    • Fix pkg-config install mechanism to make building raftlib apps far easier
    • update versions of shm, affinity, demangle libs (to also include shm bug fix)
    opened by jonathan-beard 11
  • Question: are std::string ports supported?

    Question: are std::string ports supported?

    I've been playing around with raftlib, but I've hit a brick wall when trying to output strings: Here is my test kernel:

    class Sum : public raft::kernel
    {
    public:
        Sum()
            : raft::kernel()
        {
            // Define ports
            input.addPort<T>("input_a", "input_b");
            output.addPort<std::string>("sum");
        }
    
        raft::kstatus run() override
        {
            T a, b;
            input["input_a"].pop(a);
            input["input_b"].pop(b);
    
            auto c(output["sum"].template allocate_s<std::string>());
            std::stringstream ss;
            ss << a << " + " << b << " = " << (a + b) << " [" << GetCurrentThreadId() << "]\n";
            *c = ss.str();
    
            return raft::proceed;
        }
    };
    

    This crashes inside map::exe() after completing the kernels and deallocating memory. I've tried allocate and send and that doesn't run at all.

    So my question is: Are std::string typed ports supported or am I doing something stupid?

    opened by Cthutu 10
  • Need to support non-POD pointers such as smart pointers

    Need to support non-POD pointers such as smart pointers

    RaftLib is an actor-oriented framework for stream processing, and one of the most important applications are video stream processing, which uses data structures such as cv::Mat from OpenCV or similar data structures, that use non-POD pointers such as smart pointers within the structure.

    However, as illustrated in Issue #4, currently non-POD pointers are not supported and the presence of such in objects in queues will cause segfault.

    This makes raftlib unusable in any substantial applications that involves complex data structures, and is a shopstopper for RaftLib. Therefore we need to add support of non-POD pointers to RaftLib as top priority

    enhancement 
    opened by kcleung 10
  • Compiling on Windows

    Compiling on Windows

    Just started trying to compile Master on Windows using CMake. Is Boost a requirement? It's not listed, but I am getting errors finding demangle.hpp as well as affinity.hpp (not sure if that's from boost or not...)

    I should mention I tried compiling from v2020.07.01 tag as well with the same result.

    Any help?

    opened by Meneleus 9
  • One input split in several outputs

    One input split in several outputs

    Hey Jonathan, hope you're doing well..

    Say we have A >> B >> C A sends one message to B. B then splits this message into several hundreds of other messages that needs to send to C.

    The problem I face is the following:

    If I return raft::proceed after B sends a message to C, then the framework does not start B again (because B already consumed the input message from A)

    If B sends all messages to C in a loop without returning raft::proceed it might happen that the queue gets saturated with so many messages.

    So what is the best way to proceed in this scenario ?

    Thanks in advance..

    opened by mr-j0nes 6
  • How to

    How to "ZeroCopy" from source to destination ?

    Hi there,

    Great job with the lib. Let's say I have A >> B >> C. Is it possible to allocate data on A and just release it on C ? I don't seem to understand how to do it ..

    Thanks.. PS: in a different post I provided a "poc.cpp" where I show (more or less) what I want to do ..

    question 
    opened by mr-j0nes 6
  • about running the examples

    about running the examples

    hi, I clone all the project from the github and compile the project, but I still can't make the examples, I want to know if the examples don't match the api now?

    opened by dengbo 6
  • File not found error for

    File not found error for "hh.hpp" during raftlib compilation using pkgconfig

    Describe the bug

    Raftlib code compilation gives "file does not exist error" for "raftinc/hh.hpp." On inspection, the file is included in defs.hpp but doesn't exist anywhere in the source code. Not sure if its renamed or removed completely

    Steps To Reproduce

    • run any example (the sum example in the getting started section of raftlib), and it doesn't compile using pkg-config by throwing the error

    Expected behavior

    Raftlib example code to compile

    bug 
    opened by ameyand98 5
  • finished back-porting parser-improvement changes, need to check win64…

    finished back-porting parser-improvement changes, need to check win64…

    In progress, will set to draft momentarily.

    In this pull request

    • changes for the fifo, ringbuffers, blocked structures
    • aim is to make all structures with the ringbuffer compatible once again with shared memory so we can go back to multiprocess in addition to multi-thread.
    • changes should also make it amenable to make the fifo itself a module, and therefore be able to insert whatever FIFOs we want to (e.g. #zeromq, https://github.com/zeromq/libzmq) and boostfifo, even MPI with wrappers.

    @f-tischler, could you look over chances with an eye towards win, I'm gonna double check momentarily to make doubly sure I didn't miss any Win specific guards that were supposed to be in place.

    opened by jonathan-beard 5
  • File reader with repetitions; Correct cmake configuration with QThread library local install; Simplify add_port recursion helper and use unordered_set for kernelkeeper

    File reader with repetitions; Correct cmake configuration with QThread library local install; Simplify add_port recursion helper and use unordered_set for kernelkeeper

    • [x] ## Description
    1. In order to adjust benchmark working size without bringing huge files, we let filereader kernel optionally take an argument, repetitions, which is the number of times a file is read repeatedly to feed the dataflow graph with arbitrary data to process.
    2. The QThread include path was added with leading -I and the compiling options generated by cmake would be collapsed (missing space between two -I) making include directories invalid.

    Type of change

    • [x] Bug fix (non-breaking change which fixes an issue)
    • [x] New feature (non-breaking change which adds functionality)
    • [x] This change requires a documentation update

    How Has This Been Tested?

    Changes are individually tested with the word search example.

    • [ ] Runs locally on Windows
    • [x] Runs locally on Linux
    • [ ] Runs locally on OS X

    Details

    QThread library is compiled and installed at /bambo/qthread_install.

    RaftLib build is configured with the cmake command:

    $ QTHREAD_PATH=/bambo/qthread_install/ cmake -DCMAKE_INSTALL_PREFIX=/bambo/raft_install ..
    

    Then make install.

    To compile the search example:

    $ export PKG_CONFIG_PATH=/mnt/ampere3/bambo/bmkvl/raft_install/pkgconfig/:$PKG_CONFIG_PATH
    $ g++ -o search -DQTHREAD_FOUND $(pkg-config --cflags raftlib) ../examples/cppalgo/search/bmh.cpp $(pkg-config --libs raftlib)
    

    To run the search example:

    $ ./search ../examples/cppalgo/search/alice.txt
    # or with 2 repetitions
    $ ./search ../examples/cppalgo/search/alice.txt 2
    

    Checklist:

    • [ ] My code follows the style guidelines of this project
    • [x] I have performed a self-review of my own code
    • [ ] I have commented my code, particularly in hard-to-understand areas
    • [ ] I have made corresponding changes to the documentation
    • [x] My changes generate no new warnings
    • [x] I have added tests that prove my fix is effective or that my feature works
    • [x] New and existing unit tests pass locally with my changes
    • [x] Any dependent changes have been merged and published in downstream modules
    • [x] I have checked my code and corrected any misspellings
    opened by BamboWu 0
  • Leading _kset_ to _kset_ join operator fails to parse in DSL

    Leading _kset_ to _kset_ join operator fails to parse in DSL

    Describe the bug

    The following line of code:

     m += ( raft::kset( g0, g1, g2 ) >> raft::kset( a, b, c ) ) >= ( j >> print );
    

    should parse according to the grammar, indeed there is a test case in the dev branch to ensure that this is the case. Syntax, however, fails to parse in the master branch.

    To fix, pull test cases to master branch, and debug from there.

    Steps To Reproduce

    Run test case ksetContContJoin.cpp

    Expected behavior

    • M producers in first kset should be joined to M consumers in second kset
    opened by jonathan-beard 1
  • Map having no data source (a kernel has input only) could trigger segfault when execution starts.

    Map having no data source (a kernel has input only) could trigger segfault when execution starts.

    Bug Description

    If we build a map with no data source, meaning every kernel in the map has an input port, then a segmentation fault would be triggered upon execution.

    Example To Reproduce the Bug

    #include <iostream>
    #include <raft>
    
    class MasterKernel : public raft::kernel {
    
    private:
        int dim;
        long chunk_size;
        bool waiting = false;
        uint8_t task_id;
    
    public:
        MasterKernel(int _dim, long _chunk_size) :
            raft::kernel(), dim(_dim), chunk_size(_chunk_size) {
            std::cout << "master constructor\n";
            // Create ports
            input.addPort<uint8_t>("input");
            output.addPort<uint8_t>("output");
            task_id = 0;
        }
    
        virtual raft::kstatus run() {
            size_t numRead = 0;
    
            //std::cout << "Master waiting=" << waiting << std::endl;
            //if (waiting) {
            //    input["input"].recycle();
            //    waiting = false;
            //    if (2 == task_id) {
            //        return raft::stop;
            //    }
            //}
    
            // Get the number of points to operate on
            std::cout << "Master reads " << numRead << std::endl;
    
            // Push our output data
            output["output"].push<uint8_t>(task_id++);
            waiting = true;
            std::cout << "Master pushed\n";
    
            return raft::proceed;
        }
    };
    
    
    class LocalSearchKernel : public raft::kernel {
        int id;
    
    public:
        LocalSearchKernel(int _id) : raft::kernel(), id(_id) {
            std::cout << "search constructor\n";
            // Create ports
            input.addPort<uint8_t>("input");
            output.addPort<uint8_t>("output");
        }
        virtual raft::kstatus run() {
            uint8_t &taskid( input["input"].peek<uint8_t>() );
            std::cout << __func__ << "(pop taskid=" << taskid << ")\n";
            output["output"].push<uint8_t>(taskid);
            input["input"].recycle();
    
            return raft::proceed;
        }
    };
    
    int main() {
      MasterKernel master(1, 10);
      LocalSearchKernel search(2);
    
      raft::map m;
    
      m += master >> search;
      m += search >> master;
    
      std::cout << "Executing map\n";
        // Execute the map
      m.exe< partition_dummy, pool_schedule, stdalloc, no_parallel >();
    
    }
    
    opened by BamboWu 1
  • Download all submodules with code zip download

    Download all submodules with code zip download

    Is your feature request related to a problem? Please describe. Feature request related to closed issue #138, all submodules are not auto-downloaded when using the zip download. When compiling, no .git file is present and an ambiguous error message results.

    Describe the solution you'd like Either download the code within the cmake or some server side script that would enable github to package the correct files for download.

    Describe alternatives you've considered

    1. add a hook in the cmake helper that does the git submodule initialization to check for a .git file first and if none exists then use the cmake download functionality to pull it down.
    2. we could simply add a warning in the cmake script to download the appropriate files.

    Additional context None

    opened by jonathan-beard 0
  • Can't get stream operators to work

    Can't get stream operators to work

    I'm working on Windows and for some reason I can't get stream operators to work. I have created a series of nodes (in my case I need them to be pointers. I tested this first by modifying one of the examples and that worked fine. However, in my code base I get an error. I'm porting a data flow application to use raftlib, converting connections to mappings. Here is my code:

    for (Argument* out : function->inputs()) {
      for (Port* dest : out->connections()) {
        Statement* destStatement = dest->owner();
          raft_statement* destNode = statementMap[destStatement]; // raft_statement is a kernel
          m += (*inputNode)[out->name()] >> (*destNode)[dest->name()]; // inputNode is a kernel
        }
      }
    }
    

    The error I get is:

    error C2678: binary '>>': no operator found which takes a left-hand operand of type 'raft::kernel' (or there is no acceptable conversion)
    while trying to match the argument list '(raft::kernel, raft::kernel)'
    

    Any ideas what I can be doing wrong?

    opened by Meneleus 6
Releases(v2020.07.01)
The C++ Standard Library for Parallelism and Concurrency

Documentation: latest, development (master) HPX HPX is a C++ Standard Library for Concurrency and Parallelism. It implements all of the corresponding

The STE||AR Group 2.1k Jan 3, 2023
A header-only C++ library for task concurrency

transwarp Doxygen documentation transwarp is a header-only C++ library for task concurrency. It allows you to easily create a graph of tasks where eve

Christian Blume 592 Dec 19, 2022
HPX is a C++ Standard Library for Concurrency and Parallelism

HPX is a C++ Standard Library for Concurrency and Parallelism. It implements all of the corresponding facilities as defined by the C++ Standard. Additionally, in HPX we implement functionalities proposed as part of the ongoing C++ standardization process. We also extend the C++ Standard APIs to the distributed case.

The STE||AR Group 2.1k Dec 30, 2022
Yet Another Concurrency Library

YACLib YACLib (Yet Another Concurrency Library) is a C++ library for concurrent tasks execution. Documentation Install guide About dependencies Target

null 193 Dec 28, 2022
Async++ concurrency framework for C++11

Async++ Async++ is a lightweight concurrency framework for C++11. The concept was inspired by the Microsoft PPL library and the N3428 C++ standard pro

Amanieu d'Antras 1.1k Dec 30, 2022
Concurrency Kit 2.1k Jan 4, 2023
The libdispatch Project, (a.k.a. Grand Central Dispatch), for concurrency on multicore hardware

Grand Central Dispatch Grand Central Dispatch (GCD or libdispatch) provides comprehensive support for concurrent code execution on multicore hardware.

Apple 2.3k Jan 3, 2023
Go-style concurrency in C

LIBMILL Libmill is a library that introduces Go-style concurrency to C. Documentation For the documentation check the project website: http://libmill.

Martin Sustrik 2.6k Dec 31, 2022
Modern concurrency for C++. Tasks, executors, timers and C++20 coroutines to rule them all

concurrencpp, the C++ concurrency library concurrencpp is a tasking library for C++ allowing developers to write highly concurrent applications easily

David Haim 1.2k Jan 3, 2023
Complementary Concurrency Programs for course "Linux Kernel Internals"

Complementary Programs for course "Linux Kernel Internals" Project Listing tpool: A lightweight thread pool. tinync: A tiny nc implementation using co

null 237 Dec 20, 2022
Task System presented in "Better Code: Concurrency - Sean Parent"

task_system task_system provides a task scheduler for modern C++. The scheduler manages an array of concurrent queues A task, when scheduled, is enque

Pranav 31 Dec 7, 2022
Laughably simple Actor concurrency framework for C++20

Light Actor Framework Concurrency is a breeze. Also a nightmare, if you ever used synchronization techniques. Mostly a nightmare, though. This tiny li

Josip Palavra 93 Dec 27, 2022
Deadlockempire.github.io - The Deadlock Empire: Slay dragons, learn concurrency!

The Deadlock Empire A game that teaches locking and concurrency. It runs on https://deadlockempire.github.io. Contributing We gladly welcome all contr

null 810 Dec 23, 2022
Libgo - Go-style concurrency in C++11

libgo libgo -- a coroutine library and a parallel Programming Library Libgo is a stackful coroutine library for collaborative scheduling written in C+

null 2.8k Dec 26, 2022
Coroutine - C++11 single .h asymmetric coroutine implementation via ucontext / fiber

C++11 single .h asymmetric coroutine implementation API in namespace coroutine: routine_t create(std::function<void()> f); void destroy(routine_t id);

null 390 Dec 20, 2022
This is a study on how to do create a queue via IPC (inter-process communication)

IPC queue This is a study on how to do create a queue via IPC (inter-process communication). Please take a look at the examples of producer and consum

Tarcísio Zotelli Ferraz 1 Nov 28, 2022
A easy to use multithreading thread pool library for C. It is a handy stream like job scheduler with an automatic garbage collector. This is a multithreaded job scheduler for non I/O bound computation.

A easy to use multithreading thread pool library for C. It is a handy stream-like job scheduler with an automatic garbage collector for non I/O bound computation.

Hyoung Min Suh 12 Jun 4, 2022
Small library helping you with basic stuff like getting metrics out of your code, thread naming, etc.

CommonPP commonpp is a multi purpose library easing very few operations like: Getting metrics out of your program (counter, gauge, statistical descrip

Thomas Sanchez 28 Oct 31, 2022
stdgpu: Efficient STL-like Data Structures on the GPU

stdgpu: Efficient STL-like Data Structures on the GPU Features | Examples | Documentation | Building | Integration | Contributing | License | Contact

Patrick Stotko 777 Jan 8, 2023