diff --git a/src/.clang-format b/src/.clang-format new file mode 100644 index 0000000000000000000000000000000000000000..b1392af5d193ffd26e7d592d6bdf4d1d9ea391d6 --- /dev/null +++ b/src/.clang-format @@ -0,0 +1,226 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: true +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: NextLine +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^<ext/.*\.h>' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: pb + BasedOnStyle: google +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/src/guided_dc.cc b/src/guided_dc.cc index 5d443d5cdb44bed323f40dc17ba37dcb26e928bb..e3d62346685841697840c01e7908cc121dfa2b9f 100644 --- a/src/guided_dc.cc +++ b/src/guided_dc.cc @@ -11,196 +11,34 @@ #include <unordered_map> #include <vector> -#include "./pinnedVector/pinnedVector/PinnedVector.h" #define USE_HPVM #ifdef USE_HPVM #include "heterocc.h" #endif - -// [cpp obj {ptr 1, ptr2}, ptr1{ptr3}.. ] -> Buffer[ cpp obj{ptr->relative -// address}, *ptr1, *ptr2 ] Library: -// memory_map: tracking allocation type/size/meta_info -// Helper functions: do buffer management -// Codegen: -// Enumerate member, call library -// User code: -// Tell library/Codegen we want to serialize object - -using byte = char; - -// In a separate file ---------------------- -static std::unordered_map<void*, std::pair<const std::type_info*, size_t>> - hpvm_allocation_record; - -// Lib header provides --------------------- -extern std::unordered_map<void*, std::pair<const std::type_info*, size_t>> - hpvm_allocation_record; - -bool is_allocated_memory(void* ptr) { - return hpvm_allocation_record.count(ptr); -} -size_t allocation_size(void* ptr) { - if (is_allocated_memory(ptr)) return hpvm_allocation_record[ptr].second; - return 0; -} - -template <class T, class... Args> -T* hpvm_new(Args... args) { - T* obj = new T(args...); - hpvm_allocation_record[obj] = {&typeid(T), sizeof(T)}; - return obj; -} - -template <class T, class... Args> -void hpvm_delete(T* obj) { - hpvm_allocation_record.erase(obj); - delete obj; -} - -// Hpvm Buf layout: -// [header, pointer_recover_list(size_t[]), obj_buf] -template <typename T> -class HpvmBufHeader { - public: - size_t pointer_recover_list_size; - size_t obj_size; - byte buf[]; - - void* get_obj_start() { - return buf + pointer_recover_list_size * sizeof(size_t); - } - size_t* get_pointer_list_start() { return (size_t*)buf; } - size_t* get_pointer_at(size_t offset) { - size_t* sub_ptr = (size_t*)((char*)get_obj_start() + offset); - return sub_ptr; - } - void to_relative_pointer(void* base) { - for (int i = 0; i < pointer_recover_list_size; i++) { - 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 - } - } - void to_absolute_pointer(void* base, bool device = false) { - to_relative_pointer((void*)(-(size_t)base)); - } - size_t total_size() { - return sizeof(*this) + pointer_recover_list_size * sizeof(size_t) + - obj_size; - } -}; -template <typename T> -class HpvmBuf { - public: - HpvmBufHeader<T>* buf = nullptr; - std::vector<size_t> rel_pointer_list; - PinnedVector<byte> obj_data; - - HpvmBuf() { - rel_pointer_list.reserve(1); - obj_data.reserve(1); - } - - HpvmBufHeader<T>* formulate_device_buffer() { - if (buf) free(buf); - size_t buf_size = sizeof(*buf) + rel_pointer_list.size() * sizeof(size_t) + - obj_data.size(); - buf = (HpvmBufHeader<T>*)calloc(buf_size, 1); - buf->pointer_recover_list_size = rel_pointer_list.size(); - buf->obj_size = obj_data.size(); - - std::cout << "Formulating buffer \n"; - memcpy(buf->get_pointer_list_start(), rel_pointer_list.data(), - buf->pointer_recover_list_size * sizeof(size_t)); - memcpy(buf->get_obj_start(), obj_data.data(), buf->obj_size); - std::cout << "We will have pointers at offsets: "; - for (auto i : rel_pointer_list) std::cout << (void*)i << ","; - std::cout << "\n"; - - buf->to_relative_pointer(obj_data.data()); - return buf; - } - T* recover_host_accessible_obj() { - buf->to_absolute_pointer(buf->get_obj_start()); - return (T*)buf->get_obj_start(); - } - - template <class AllocType = void> - AllocType* allocate(size_t size) { - if (size == 0) return nullptr; - size_t old_size = obj_data.size(); - obj_data.resize(obj_data.size() + size); - std::cout << "Allocate up to:" << obj_data.size() << " bytes" << std::endl; - return (AllocType*)(obj_data.data() + old_size); - } - - void register_pointer_in_buf(void* ptr_addr_in_buf) { - rel_pointer_list.push_back((size_t)(ptr_addr_in_buf) - - (size_t)obj_data.data()); - } -}; - -// Main user entry to snapshot an object into a buffer -template <class T> -HpvmBuf<T> hpvm_snapshot(T* original_obj) { - std::cout << "Snapshot: " << (void*)original_obj << std::endl; - HpvmBuf<T> buf; - hpvm_snapshot_internal(buf, original_obj); - std::cout << "Snapshot Done\n"; - buf.formulate_device_buffer(); - 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> -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> -void* snapshot_pointer(Buf& buf, T* src_ptr) { - if (is_allocated_memory(src_ptr)) { - auto* dst = hpvm_snapshot_internal(buf, src_ptr); - buf.register_pointer_in_buf(&dst_ptr); - return dst; - } else - return nullptr; -} - -// Library function -// ends---------------------------------------------------------- +#include "hpvm_dclib.hpp" // User code // A linked list: class LNode { public: int val; + int* other_vals = nullptr; // arbitrary long array + LNode* next = nullptr; - inline LNode(int v) { val = v; } + inline LNode(int v) { + val = v; + other_vals = hpvm_new_arr<int>(5); + for (int i = 0; i < 5; i++) other_vals[i] = i + 1; + } + void delta(int x) { + val += x; + for (int i = 0; i < 5; i++) other_vals[i] += x; + } void print() { - std::cout << "[Node " << val << "] -> "; + std::cout << "[Node " << val << ": "; + for (int i = 0; i < 5; i++) std::cout << other_vals[i] << ","; + std::cout << "] -> "; + if (next) next->print(); else @@ -227,14 +65,12 @@ void stencil(HpvmBufHeader<LNode>* buf_header, size_t header_size) { (void*)buf_header, header_size); __hpvm__hint(hpvm::GPU_TARGET); - 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()); + auto* root = (LNode*)(buf_header->get_obj_start()); root->next->val = 100; - while (root) { - root->val += 1; + root->delta(1); // root->val = (size_t)root->next; root = root->next; } @@ -251,26 +87,28 @@ int main(int argc, char* argv[]) { host_obj->print(); auto host_buf = hpvm_snapshot(host_obj); - size_t buf_size = host_buf.buf->total_size(); #ifdef USE_HPVM std::cout << "Kernel launch!" << std::endl; - void* DFG = __hetero_launch((void*)stencil, 1, host_buf.buf, buf_size, 1, - host_buf.buf, buf_size); + void* DFG = __hetero_launch((void*)stencil, 1, host_buf.buf, + host_buf.buf->total_size(), 1, host_buf.buf, + host_buf.buf->total_size()); __hetero_wait(DFG); #else +/* auto* buf_header = host_buf.buf; - host_buf.buf->to_absolute_pointer(buf_header->get_obj_start()); + buf_header->to_absolute_pointer(buf_header->get_obj_start()); LNode* root = (LNode*)buf_header->get_obj_start(); while (root) { - root->val += 1; + root->delta(1); // root->val = (size_t)root->next; root = root->next; } - host_buf.buf->to_relative_pointer(host_buf.buf->get_obj_start()); + buf_header->to_relative_pointer(buf_header->get_obj_start()); + */ #endif std::cout << "After kernel in buffer:\n"; @@ -279,12 +117,13 @@ int main(int argc, char* argv[]) { return 0; } // User code end--------------------- -// HPVM Codegen generates: +// User / HPVM Codegen provides: template <> void hpvm_snapshot_custom<HpvmBuf<LNode>, LNode>(HpvmBuf<LNode>& buf, LNode* dst_obj, LNode* original_obj) { // recursive allocation & copies - dst_obj->next = snapshot_pointer(buf, original_obj->next); + snapshot_pointer(buf, dst_obj->next, original_obj->next); + snapshot_pointer(buf, dst_obj->other_vals, original_obj->other_vals); } -// HPVM Codegen end ------------ +// User / HPVM Codegen end ------------ diff --git a/src/hpvm_dclib.hpp b/src/hpvm_dclib.hpp new file mode 100644 index 0000000000000000000000000000000000000000..07d4512f4b733688182d6632e735c518dbe08bee --- /dev/null +++ b/src/hpvm_dclib.hpp @@ -0,0 +1,212 @@ +#include <argp.h> +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <functional> +#include <iostream> +#include <typeinfo> +#include <unordered_map> +#include <vector> + +#include "./pinnedVector/pinnedVector/PinnedVector.h" + +// [cpp obj {ptr 1, ptr2}, ptr1{ptr3}.. ] -> Buffer[ cpp obj{ptr->relative +// address}, *ptr1, *ptr2 ] Library: +// memory_map: tracking allocation type/size/meta_info +// Helper functions: do buffer management +// Codegen: +// Enumerate member, call library +// User code: +// Tell library/Codegen we want to serialize object + +using byte = char; + +// In a separate file ---------------------- +static std::unordered_map<void*, std::pair<const std::type_info*, size_t>> + hpvm_allocation_record; + +// Lib header provides --------------------- +extern std::unordered_map<void*, std::pair<const std::type_info*, size_t>> + hpvm_allocation_record; + +bool is_allocated_memory(void* ptr) { + return hpvm_allocation_record.count(ptr); +} +size_t allocation_size(void* ptr) { + if (is_allocated_memory(ptr)) return hpvm_allocation_record[ptr].second; + return 0; +} + +template <class T, class... Args> +T* hpvm_new(Args... args) { + T* obj = new T(args...); + hpvm_allocation_record[obj] = {&typeid(T), sizeof(T)}; + return obj; +} + +template <class T> +T* hpvm_new_arr(size_t num_obj) { + T* obj = new T[num_obj]; + hpvm_allocation_record[obj] = {&typeid(T), num_obj * sizeof(T)}; + return obj; +} + +template <class T, class... Args> +void hpvm_delete(T* obj) { + hpvm_allocation_record.erase(obj); + delete obj; +} +template <class T, class... Args> +void hpvm_delete_arr(T* obj) { + hpvm_allocation_record.erase(obj); + delete[] obj; +} + +// Hpvm Buf layout: +// [header, pointer_recover_list(size_t[]), obj_buf] +template <typename T> +class HpvmBufHeader { + public: + size_t pointer_recover_list_size; + size_t obj_size; + byte buf[]; + + void* get_obj_start() { + return buf + pointer_recover_list_size * sizeof(size_t); + } + size_t* get_pointer_list_start() { return (size_t*)buf; } + size_t* get_pointer_at(size_t offset) { + size_t* sub_ptr = (size_t*)((char*)get_obj_start() + offset); + return sub_ptr; + } + void to_relative_pointer(void* base) { + for (int i = 0; i < pointer_recover_list_size; i++) { + 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 + } + } + void to_absolute_pointer(void* base) { + to_relative_pointer((void*)(-(long long)base)); + } + size_t total_size() { + return sizeof(*this) + pointer_recover_list_size * sizeof(size_t) + + obj_size; + } +}; +template <typename T> +class HpvmBuf { + public: + HpvmBufHeader<T>* buf = nullptr; + std::vector<size_t> rel_pointer_list; + PinnedVector<byte> obj_data; + + HpvmBuf() { + rel_pointer_list.reserve(1); + obj_data.reserve(1); + } + + HpvmBufHeader<T>* formulate_device_buffer() { + if (buf) free(buf); + size_t buf_size = sizeof(*buf) + rel_pointer_list.size() * sizeof(size_t) + + obj_data.size(); + buf = (HpvmBufHeader<T>*)calloc(buf_size, 1); + buf->pointer_recover_list_size = rel_pointer_list.size(); + buf->obj_size = obj_data.size(); + + std::cout << "Formulating buffer \n"; + memcpy(buf->get_pointer_list_start(), rel_pointer_list.data(), + buf->pointer_recover_list_size * sizeof(size_t)); + memcpy(buf->get_obj_start(), obj_data.data(), buf->obj_size); + std::cout << "We will have pointers at offsets: "; + for (auto i : rel_pointer_list) std::cout << (void*)i << ","; + std::cout << "\n"; + + buf->to_relative_pointer(obj_data.data()); + return buf; + } + T* recover_host_accessible_obj() { + buf->to_absolute_pointer(buf->get_obj_start()); + return (T*)buf->get_obj_start(); + } + + template <class AllocType = void> + AllocType* allocate(size_t size) { + if (size == 0) return nullptr; + size_t old_size = obj_data.size(); + obj_data.resize(obj_data.size() + size); + std::cout << "Allocate up to:" << obj_data.size() << " bytes" << std::endl; + return (AllocType*)(obj_data.data() + old_size); + } + + void register_pointer_in_buf(void* ptr_addr_in_buf) { + rel_pointer_list.push_back((size_t)(ptr_addr_in_buf) - + (size_t)obj_data.data()); + } +}; + +// Main user entry to snapshot an object into a buffer +template <class T> +HpvmBuf<T> hpvm_snapshot(T* original_obj) { + std::cout << "Snapshot: " << (void*)original_obj << std::endl; + HpvmBuf<T> buf; + hpvm_snapshot_internal(buf, original_obj); + std::cout << "Snapshot Done\n"; + buf.formulate_device_buffer(); + 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> +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> +void snapshot_pointer(Buf& buf, T*& dst_ptr, T* src_ptr) { + if (int num_allocation = allocation_size(src_ptr) / sizeof(T)) { + std::cout << "Snapshot pointer to buffer of " << num_allocation + << " elems\n"; + // Ensure array allocation is continuous + T* dst = nullptr; + for (int i = 0; i < num_allocation; i++) { + auto* alloc = snapshot_trivial(buf, src_ptr + i); + if (!dst) dst = alloc; + } + + // Only do deep copy after continuous buffer have been allocated + for (int i = 0; i < num_allocation; i++) + hpvm_snapshot_custom(buf, dst + i, src_ptr + i); + + dst_ptr = dst; + buf.register_pointer_in_buf(&dst_ptr); + } else + dst_ptr = nullptr; +} + +// Library function +// ends----------------------------------------------------------