Skip to content
Snippets Groups Projects

hpvm-deepcopy

A deepcopy utility allowing automatic snapshot of arbitrary C/C++ objects into a continuous member buffer, with optional custom behavior override.

This utilize contains a compiler frontend and a runtime library, and must be used in combination.

Usage

While designed in the intention to collaborate with HPVM, this utility have no inherent dependency on the HPVM project, and can be used on its own to enable other usages like sending arbitrary objects over pipes or network.

Various examples of different complexity using this deepcopy utility with HPVM can be found in src/tests. A few quirks, like turning off run-time exception handling, is required by HPVM, and user should refer to the HPVM documentation for more details.

During Program Development

Using Deepcopy

  1. Include src/hpvm_dclib.hpp, in front of any other includes. This is important.

    #include "hpvm_dclib.hpp"
    // Make sure dclib is at front of everything
  2. For an arbitrary cpp object, one can snapshot it into a contiguous buffer automatically using hpvm_do_snapshot(T*):

    MatrixXd mat1(2, 5);
    auto m1b = hpvm_do_snapshot(&mat1); // Perform snapshot
  3. The snapshotted object can be freely moved around, serialize, and deserialize, be referring to:

    m1b.buf // Buffer start pointer
    m1b.buf->total_size() // Buffer size
  4. Wrap any usage of the object between unwind and rewind code (usually on GPU kernel if using HPVM OCL backend):

    auto& mat1d = *use_on_device<MatrixXd>(m1b.buf);
    
    mat1d(0, 1) = 999;  // Or use the object however needed
    
    done_use_on_device(m1b.buf);

During Compilation

  1. Run out frontend after the preprocessor to obtain the correctly transformed source file.

    {HPVM_PATH}/build/bin/clang++ -O1 {other_compiler_flags} {source_file_name}.cc -E -o {source_file_name}.deepcopy.cc
    {HPVM_PATH}/build/bin/hetero-dc {source_file_name}.deepcopy.cc -- {libclang_flags}
    # Continue using {source_file_name}.deepcopy.cc just like {source_file_name}.cc

    where {libclang_flags} could be anything you pass into the clang-frontend, e,g -std=c++23.

  2. (This is no longer needed if using the most recent release of HPVM. The run-time module have been bundled together with the hpvm-rt library)Build and link run-time library with the program.

    {HPVM_PATH}/build/bin/clang++ -fPIC -c src/hpvm_dclib.cpp -o hpvm_dclib.o
    # Then link hpvm_dclib.o with the rest of your project
  3. And deepcopy should now work as expected. build.sh provides and example to build a few testcases together with HPVM.

Supporting Deepcopy

  1. Any memory allocation intended to be used by objects potentially copied must be allocated and de-allocated using dclib functions:

    void* hpvm_malloc(size_t sz) 
    void hpvm_free(void* ptr)
    T* hpvm_new(Args... args)
    T* hpvm_new_arr(size_t num_obj)
    void hpvm_delete(T* obj)
    void hpvm_delete_arr(T* obj)

    And any library need to be patched replacing allocation calls to be used with deepcopy. Memory segments not allocated using our allocator will be ignored.

    • To handle std:: container, we provide a memory allocator, without type restrictions on what they holds (and they can be recursive):
    DeepCopyAlloc<T>>;
    // e.g
    std::vector<int, DeepCopyAlloc<int>> my_deepcopyable_int_vector;
    • We also provide a patched version of Eigen, in src/eigen.
  2. If the user wish to override the deepcopy behavior of a certain type, e.g., only selectively copying certain fields, the user should specialize the following templated function:

    template <class T>
    extern typename std::enable_if<has_custom_behavior<T>::value>::type
    hpvm_snapshot_custom(HpvmBuf& buf, T* dst_obj, T* original_obj);

    for the chosen type T.

Known Limitations

  1. Virtual functions on object only works if the address space does not change.
  2. Pointers pointing to the middle of a buffer will not be fixed after copying.

Internals

A more in-depth description of how the low level bit works can be found here.

image