Skip to content
Snippets Groups Projects
Commit 550cebaa authored by git_unspecified's avatar git_unspecified
Browse files

Provide trivial copy by default

parent f9cd4127
No related branches found
No related tags found
No related merge requests found
#include <argp.h> #include <argp.h>
#include <assert.h>
#include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <iostream>
#include <assert.h>
#include <functional>
#include <string.h> #include <string.h>
#include <math.h>
#include <functional>
#include <iostream>
#include <typeinfo> #include <typeinfo>
#include <vector>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "./pinnedVector/pinnedVector/PinnedVector.h" #include "./pinnedVector/pinnedVector/PinnedVector.h"
#define USE_HPVM #define USE_HPVM
...@@ -28,102 +29,76 @@ ...@@ -28,102 +29,76 @@
using byte = char; using byte = char;
// In a separate file ---------------------- // In a separate file ----------------------
static std::unordered_map<void *, std::pair<const std::type_info *, size_t>> static std::unordered_map<void*, std::pair<const std::type_info*, size_t>>
hpvm_allocation_record; hpvm_allocation_record;
// Lib header provides --------------------- // Lib header provides ---------------------
extern std::unordered_map<void *, std::pair<const std::type_info *, size_t>> extern std::unordered_map<void*, std::pair<const std::type_info*, size_t>>
hpvm_allocation_record; hpvm_allocation_record;
bool is_allocated_memory(void *ptr) { bool is_allocated_memory(void* ptr) {
return hpvm_allocation_record.count(ptr); return hpvm_allocation_record.count(ptr);
} }
size_t allocation_size(void *ptr) { size_t allocation_size(void* ptr) {
if (is_allocated_memory(ptr)) if (is_allocated_memory(ptr)) return hpvm_allocation_record[ptr].second;
return hpvm_allocation_record[ptr].second;
return 0; return 0;
} }
template <class T, class... Args> T *hpvm_new(Args... args) { template <class T, class... Args>
T *obj = new T(args...); T* hpvm_new(Args... args) {
T* obj = new T(args...);
hpvm_allocation_record[obj] = {&typeid(T), sizeof(T)}; hpvm_allocation_record[obj] = {&typeid(T), sizeof(T)};
return obj; return obj;
} }
template <class T, class... Args> void hpvm_delete(T *obj) { template <class T, class... Args>
void hpvm_delete(T* obj) {
hpvm_allocation_record.erase(obj); hpvm_allocation_record.erase(obj);
delete obj; delete obj;
} }
// Hpvm Buf layout: // Hpvm Buf layout:
// [header, pointer_recover_list(size_t[]), obj_buf] // [header, pointer_recover_list(size_t[]), obj_buf]
template <typename T> class HpvmBufHeader { template <typename T>
public: class HpvmBufHeader {
public:
size_t pointer_recover_list_size; size_t pointer_recover_list_size;
size_t obj_size; size_t obj_size;
byte buf[]; byte buf[];
void *get_obj_start() { void* get_obj_start() {
return buf + pointer_recover_list_size * sizeof(size_t); return buf + pointer_recover_list_size * sizeof(size_t);
} }
size_t *get_pointer_list_start() { return (size_t *)buf; } size_t* get_pointer_list_start() { return (size_t*)buf; }
size_t *get_pointer_at(size_t offset) { size_t* get_pointer_at(size_t offset) {
size_t *sub_ptr = (size_t *)((char *)get_obj_start() + offset); size_t* sub_ptr = (size_t*)((char*)get_obj_start() + offset);
return sub_ptr; return sub_ptr;
} }
void to_relative_pointer(void *base) { void to_relative_pointer(void* base) {
for (int i = 0; i < pointer_recover_list_size; i++) { for (int i = 0; i < pointer_recover_list_size; i++) {
size_t pointer_offset = get_pointer_list_start()[i]; size_t pointer_offset = get_pointer_list_start()[i];
size_t *sub_ptr = get_pointer_at(pointer_offset); size_t* sub_ptr = get_pointer_at(pointer_offset);
#ifndef USE_HPVM #ifndef USE_HPVM
std::cout << "To relative: " << (void *)sub_ptr[0]; std::cout << "To relative: " << (void*)sub_ptr[0];
#endif #endif
sub_ptr[0] -= (size_t)base; sub_ptr[0] -= (size_t)base;
#ifndef USE_HPVM #ifndef USE_HPVM
std::cout << " -> " << (void *)sub_ptr[0] << "\n"; std::cout << " -> " << (void*)sub_ptr[0] << "\n";
#endif #endif
} }
} }
void to_absolute_pointer(void *base, bool device = false) { void to_absolute_pointer(void* base, bool device = false) {
// to_relative_pointer((void *)(-(size_t)base)); to_relative_pointer((void*)(-(size_t)base));
if (device) { // FAULT: this will fault
//((char *)(this->get_obj_start()))[0xfffffff] = 1;
}
// assert pointer_recover_list_size > 0
if (pointer_recover_list_size <= 0)
((char *)(this->get_obj_start()))[0xfffffff] = 1;
for (int i = 0; i < pointer_recover_list_size; i++)
if (device) { // FAULT: this will not fault
((char *)(this->get_obj_start()))[0xfffffff] = 1;
}
for (int i = 0; i < pointer_recover_list_size; i++) {
if (device) { // FAULT: this will not fault
((char *)(this->get_obj_start()))[0xfffffff] = 1;
}
size_t pointer_offset = get_pointer_list_start()[i];
size_t *sub_ptr = get_pointer_at(pointer_offset);
#ifndef USE_HPVM
std::cout << "To relative: " << (void *)sub_ptr[0];
#endif
sub_ptr[0] += (size_t)base;
#ifndef USE_HPVM
std::cout << " -> " << (void *)sub_ptr[0] << "\n";
#endif
}
} }
size_t total_size() { size_t total_size() {
return sizeof(*this) + pointer_recover_list_size * sizeof(size_t) + return sizeof(*this) + pointer_recover_list_size * sizeof(size_t) +
obj_size; obj_size;
} }
}; };
template <typename T> class HpvmBuf { template <typename T>
public: class HpvmBuf {
HpvmBufHeader<T> *buf = nullptr; public:
HpvmBufHeader<T>* buf = nullptr;
std::vector<size_t> rel_pointer_list; std::vector<size_t> rel_pointer_list;
PinnedVector<byte> obj_data; PinnedVector<byte> obj_data;
...@@ -132,12 +107,11 @@ public: ...@@ -132,12 +107,11 @@ public:
obj_data.reserve(1); obj_data.reserve(1);
} }
HpvmBufHeader<T> *formulate_device_buffer() { HpvmBufHeader<T>* formulate_device_buffer() {
if (buf) if (buf) free(buf);
free(buf);
size_t buf_size = sizeof(*buf) + rel_pointer_list.size() * sizeof(size_t) + size_t buf_size = sizeof(*buf) + rel_pointer_list.size() * sizeof(size_t) +
obj_data.size(); obj_data.size();
buf = (HpvmBufHeader<T> *)calloc(buf_size, 1); buf = (HpvmBufHeader<T>*)calloc(buf_size, 1);
buf->pointer_recover_list_size = rel_pointer_list.size(); buf->pointer_recover_list_size = rel_pointer_list.size();
buf->obj_size = obj_data.size(); buf->obj_size = obj_data.size();
...@@ -146,36 +120,36 @@ public: ...@@ -146,36 +120,36 @@ public:
buf->pointer_recover_list_size * sizeof(size_t)); buf->pointer_recover_list_size * sizeof(size_t));
memcpy(buf->get_obj_start(), obj_data.data(), buf->obj_size); memcpy(buf->get_obj_start(), obj_data.data(), buf->obj_size);
std::cout << "We will have pointers at offsets: "; std::cout << "We will have pointers at offsets: ";
for (auto i : rel_pointer_list) for (auto i : rel_pointer_list) std::cout << (void*)i << ",";
std::cout << (void *)i << ",";
std::cout << "\n"; std::cout << "\n";
buf->to_relative_pointer(obj_data.data()); buf->to_relative_pointer(obj_data.data());
return buf; return buf;
} }
T *recover_host_accessible_obj() { T* recover_host_accessible_obj() {
buf->to_absolute_pointer(buf->get_obj_start()); buf->to_absolute_pointer(buf->get_obj_start());
return (T *)buf->get_obj_start(); return (T*)buf->get_obj_start();
} }
template <class AllocType = void> AllocType *allocate(size_t size) { template <class AllocType = void>
if (size == 0) AllocType* allocate(size_t size) {
return nullptr; if (size == 0) return nullptr;
size_t old_size = obj_data.size(); size_t old_size = obj_data.size();
obj_data.resize(obj_data.size() + size); obj_data.resize(obj_data.size() + size);
std::cout << "Allocate up to:" << obj_data.size() << " bytes" << std::endl; std::cout << "Allocate up to:" << obj_data.size() << " bytes" << std::endl;
return (AllocType *)(obj_data.data() + old_size); return (AllocType*)(obj_data.data() + old_size);
} }
void register_pointer_in_buf(void *ptr_addr_in_buf) { void register_pointer_in_buf(void* ptr_addr_in_buf) {
rel_pointer_list.push_back((size_t)(ptr_addr_in_buf) - rel_pointer_list.push_back((size_t)(ptr_addr_in_buf) -
(size_t)obj_data.data()); (size_t)obj_data.data());
} }
}; };
// Main user entry to snapshot an object into a buffer // Main user entry to snapshot an object into a buffer
template <class T> HpvmBuf<T> hpvm_snapshot(T *original_obj) { template <class T>
std::cout << "Snapshot: " << (void *)original_obj << std::endl; HpvmBuf<T> hpvm_snapshot(T* original_obj) {
std::cout << "Snapshot: " << (void*)original_obj << std::endl;
HpvmBuf<T> buf; HpvmBuf<T> buf;
hpvm_snapshot_internal(buf, original_obj); hpvm_snapshot_internal(buf, original_obj);
std::cout << "Snapshot Done\n"; std::cout << "Snapshot Done\n";
...@@ -183,23 +157,36 @@ template <class T> HpvmBuf<T> hpvm_snapshot(T *original_obj) { ...@@ -183,23 +157,36 @@ template <class T> HpvmBuf<T> hpvm_snapshot(T *original_obj) {
return buf; return buf;
} }
// Allocated space at end of buffer and do trivial copy
template <class T, class Buf>
T* snapshot_trivial(Buf& buf, T* src) {
auto* dst = buf.template allocate<T>(sizeof(T));
memcpy(dst, src, sizeof(T));
return dst;
}
// User can implement this specialization for deep copy
template <class Buf, class T> template <class Buf, class T>
extern T *hpvm_snapshot_internal(Buf &buf, T *original_obj); extern void hpvm_snapshot_custom(Buf& buf, T* dst_obj,
T* original_obj) {}
// Snapshot function used internally
template <class Buf, class T>
extern T* hpvm_snapshot_internal(Buf& buf, T* original_obj) {
auto* dst = snapshot_trivial(buf, original_obj);
hpvm_snapshot_custom(buf, dst, original_obj);
return dst;
}
// Snapshot an (array of) pointer(s)
template <class T, class Buf> template <class T, class Buf>
void snapshot_pointer(Buf &buf, T *&dst_ptr, T *src_ptr) { void* snapshot_pointer(Buf& buf, T* src_ptr) {
if (is_allocated_memory(src_ptr)) { if (is_allocated_memory(src_ptr)) {
dst_ptr = hpvm_snapshot_internal(buf, src_ptr); auto* dst = hpvm_snapshot_internal(buf, src_ptr);
// TODO: ptr to array larger than 1 elem
buf.register_pointer_in_buf(&dst_ptr); buf.register_pointer_in_buf(&dst_ptr);
} else { return dst;
dst_ptr = nullptr; } else
} return nullptr;
}
template <class T, class Buf> void snapshot_trivial(Buf &buf, T *&dst, T *src) {
dst = buf.template allocate<T>(sizeof(T));
memcpy(dst, src, sizeof(T));
} }
// Library function // Library function
...@@ -208,9 +195,9 @@ template <class T, class Buf> void snapshot_trivial(Buf &buf, T *&dst, T *src) { ...@@ -208,9 +195,9 @@ template <class T, class Buf> void snapshot_trivial(Buf &buf, T *&dst, T *src) {
// User code // User code
// A linked list: // A linked list:
class LNode { class LNode {
public: public:
int val; int val;
LNode *next = nullptr; LNode* next = nullptr;
inline LNode(int v) { val = v; } inline LNode(int v) { val = v; }
void print() { void print() {
std::cout << "[Node " << val << "] -> "; std::cout << "[Node " << val << "] -> ";
...@@ -220,7 +207,7 @@ public: ...@@ -220,7 +207,7 @@ public:
std::cout << "null" std::cout << "null"
<< "\n"; << "\n";
} }
static LNode *create_nodes(std::initializer_list<int> vs) { static LNode* create_nodes(std::initializer_list<int> vs) {
LNode *root = nullptr, *curr = nullptr; LNode *root = nullptr, *curr = nullptr;
for (auto v : vs) { for (auto v : vs) {
if (!root) if (!root)
...@@ -231,44 +218,26 @@ public: ...@@ -231,44 +218,26 @@ public:
return root; return root;
} }
}; };
class X {
public:
int k;
void test(void *addr) {
for (int i = 0; i < k; i++)
// FAULT: this will not fault
((char *)(addr))[0xfffffff] = 1;
}
};
#ifdef USE_HPVM #ifdef USE_HPVM
void stencil(HpvmBufHeader<LNode> *buf_header, size_t header_size) { void stencil(HpvmBufHeader<LNode>* buf_header, size_t header_size) {
void *Section = __hetero_section_begin(); void* Section = __hetero_section_begin();
void *Wrapper = __hetero_task_begin(1, (void *)buf_header, header_size, 1, void* Wrapper = __hetero_task_begin(1, (void*)buf_header, header_size, 1,
(void *)buf_header, header_size); (void*)buf_header, header_size);
__hpvm__hint(hpvm::GPU_TARGET); __hpvm__hint(hpvm::GPU_TARGET);
auto *root = (LNode *)(buf_header->get_obj_start()); auto* root = (LNode*)(buf_header->get_obj_start());
buf_header->to_absolute_pointer(buf_header->get_obj_start(), true); buf_header->to_absolute_pointer(buf_header->get_obj_start(), true);
// X{(int)buf_header->pointer_recover_list_size}.test(buf_header->get_obj_start());
// root->val = (size_t)root->next;
// root->val = buf_header->get_pointer_list_start()[0];
// size_t ptr_ofs1 = buf_header->get_pointer_list_start()[0];
// root->val = buf_header->get_pointer_at(ptr_ofs1)[0];
// (size_t)buf_header->get_obj_start();
// LNode *next = (LNode *)((char *)root + sizeof(LNode));
// next->val = 200;
// root->next->val = 100; root->next->val = 100;
// while (root) { while (root) {
// root->val += 1; root->val += 1;
// root = root->next; // root->val = (size_t)root->next;
// } root = root->next;
}
buf_header->to_relative_pointer(buf_header->get_obj_start()); buf_header->to_relative_pointer(buf_header->get_obj_start());
__hetero_task_end(Wrapper); __hetero_task_end(Wrapper);
...@@ -276,9 +245,8 @@ void stencil(HpvmBufHeader<LNode> *buf_header, size_t header_size) { ...@@ -276,9 +245,8 @@ void stencil(HpvmBufHeader<LNode> *buf_header, size_t header_size) {
} }
#endif #endif
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
LNode* host_obj = LNode::create_nodes({1, 2, 3, 4, 5, 6, 7, 8});
LNode *host_obj = LNode::create_nodes({1, 2, 3, 4, 5, 6, 7, 8});
std::cout << "Before kernel:\n"; std::cout << "Before kernel:\n";
host_obj->print(); host_obj->print();
...@@ -287,17 +255,20 @@ int main(int argc, char *argv[]) { ...@@ -287,17 +255,20 @@ int main(int argc, char *argv[]) {
#ifdef USE_HPVM #ifdef USE_HPVM
std::cout << "Kernel launch!" << std::endl; std::cout << "Kernel launch!" << std::endl;
void *DFG = __hetero_launch((void *)stencil, 1, host_buf.buf, buf_size, 1, void* DFG = __hetero_launch((void*)stencil, 1, host_buf.buf, buf_size, 1,
host_buf.buf, buf_size); host_buf.buf, buf_size);
__hetero_wait(DFG); __hetero_wait(DFG);
#else #else
auto *buf_header = host_buf.buf; auto* buf_header = host_buf.buf;
host_buf.buf->to_absolute_pointer(host_buf.buf->get_obj_start()); host_buf.buf->to_absolute_pointer(buf_header->get_obj_start());
LNode *root = (LNode *)buf_header->get_obj_start(); LNode* root = (LNode*)buf_header->get_obj_start();
size_t ptr_ofs1 = buf_header->get_pointer_list_start()[0]; while (root) {
root->val = buf_header->get_pointer_at(ptr_ofs1)[0]; root->val += 1;
// root->val = (size_t)root->next;
root = root->next;
}
host_buf.buf->to_relative_pointer(host_buf.buf->get_obj_start()); host_buf.buf->to_relative_pointer(host_buf.buf->get_obj_start());
#endif #endif
...@@ -310,14 +281,10 @@ int main(int argc, char *argv[]) { ...@@ -310,14 +281,10 @@ int main(int argc, char *argv[]) {
// User code end--------------------- // User code end---------------------
// HPVM Codegen generates: // HPVM Codegen generates:
template <> template <>
LNode *hpvm_snapshot_internal<HpvmBuf<LNode>, LNode>(HpvmBuf<LNode> &buf, void hpvm_snapshot_custom<HpvmBuf<LNode>, LNode>(HpvmBuf<LNode>& buf,
LNode *original_obj) { LNode* dst_obj,
LNode *new_obj = nullptr; LNode* original_obj) {
// recursive allocation & copies // recursive allocation & copies
snapshot_trivial(buf, new_obj, original_obj); dst_obj->next = snapshot_pointer(buf, original_obj->next);
snapshot_pointer(buf, new_obj->next, original_obj->next);
return new_obj;
} }
// HPVM Codegen end ------------ // HPVM Codegen end ------------
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment