├── communication.cpp ├── options.txt ├── agent.cu ├── agent_struct.cpp ├── result_info.h ├── result_info.cpp ├── kernel.h ├── soa ├── kernel_soa.h ├── agent.h ├── agent.cpp ├── agent_functor.cuh ├── algae.h ├── ackermann.h ├── communication.h ├── fibonacci.h ├── agent_functor.h └── kernel_soa.cu ├── config_manager.h ├── config_manager.cpp ├── README ├── agent_struct.h ├── interaction_step.vcxproj.filters ├── parse_net.h ├── input.txt ├── algae.h ├── fibonacci.h ├── cantor_dust.h ├── ackermann.h ├── parse_net.cpp ├── agent.cuh ├── interaction_step.vcxproj ├── communication.h ├── main.cpp └── kernel.cu /communication.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /options.txt: -------------------------------------------------------------------------------- 1 | verbose 0 2 | print_final 1 3 | pause 1 4 | ruleset 2 5 | file_output 1 6 | soa 0 7 | eval_all 1 8 | pause_between_inputs 0 -------------------------------------------------------------------------------- /agent.cu: -------------------------------------------------------------------------------- 1 | //agent.cpp 2 | 3 | //#include 4 | //#include 5 | 6 | //#include 7 | //#include 8 | //#include 9 | //#include 10 | 11 | //#include "agent.cuh" 12 | -------------------------------------------------------------------------------- /agent_struct.cpp: -------------------------------------------------------------------------------- 1 | #include "agent_struct.h" 2 | 3 | 4 | // print an agent 5 | __host__ 6 | std::ostream& operator<< (std::ostream& os, const ingpu::Agent& a) { 7 | os << std::setiosflags(std::ios::left); 8 | if (a.name >= 'a' && a.name <= 'z') { 9 | os << std::setw(2) << a.id; 10 | } 11 | else { 12 | os << std::setw(2) << a.name; 13 | } 14 | os << std::resetiosflags(std::ios::left); 15 | 16 | return os; 17 | } -------------------------------------------------------------------------------- /result_info.h: -------------------------------------------------------------------------------- 1 | //info class about a result of an interaction 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | class result_info { 8 | public: 9 | result_info(); 10 | result_info(const int result, 11 | const int num_loops, 12 | const int total_interactions, 13 | const float com_time=0, 14 | const float int_time=0); 15 | 16 | //members 17 | int result; 18 | int num_loops; 19 | int total_interactions; 20 | float com_time; 21 | float int_time; 22 | std::vector loops_per_step; 23 | 24 | 25 | }; -------------------------------------------------------------------------------- /result_info.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "result_info.h" 3 | 4 | 5 | result_info::result_info() 6 | { 7 | result=0; 8 | num_loops=1; 9 | total_interactions=0; 10 | loops_per_step = std::vector(0); 11 | } 12 | 13 | result_info::result_info(const int result, const int num_loops, const int total_interactions, 14 | const float com_time, 15 | const float int_time) 16 | { 17 | this->result = result; 18 | this->num_loops = num_loops; 19 | this->total_interactions = total_interactions; 20 | this->com_time = com_time; 21 | this->int_time = int_time; 22 | loops_per_step = std::vector(0); 23 | } -------------------------------------------------------------------------------- /kernel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "agent_struct.h" 5 | #include "result_info.h" 6 | 7 | result_info test_interaction_step(const int ruleset, thrust::host_vector& in_lhs_host, thrust::host_vector& in_rhs_host, const bool verbose, const bool print_final_result=true, 8 | const bool pause=false); 9 | 10 | result_info partition_interaction_step(const int ruleset, thrust::host_vector& in_lhs_host, thrust::host_vector& in_rhs_host, const bool verbose, const bool print_final_result=true, 11 | const bool pause=false); -------------------------------------------------------------------------------- /soa/kernel_soa.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | //#include "agent.h" 5 | #include "../result_info.h" 6 | 7 | 8 | using namespace thrust; 9 | 10 | namespace soa { 11 | 12 | result_info interaction_loop( 13 | const int ruleset, 14 | host_vector& host_lhs_ids, 15 | host_vector& host_lhs_names, 16 | host_vector& host_lhs_arities, 17 | host_vector& host_lhs_p1s, 18 | host_vector& host_lhs_p2s, 19 | host_vector& host_lhs_p3s, 20 | host_vector& host_lhs_p4s, 21 | host_vector& host_rhs_ids, 22 | host_vector& host_rhs_names, 23 | host_vector& host_rhs_arities, 24 | host_vector& host_rhs_p1s, 25 | host_vector& host_rhs_p2s, 26 | host_vector& host_rhs_p3s, 27 | host_vector& host_rhs_p4s, 28 | const bool verbose, const bool print_final, const bool pause); 29 | 30 | } -------------------------------------------------------------------------------- /soa/agent.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace thrust; 9 | 10 | namespace soa { 11 | enum AGENT_TUPLE{ID, NAME, ARITY, P1, P2, P3, P4}; 12 | enum EQUATION_TUPLE{LHS, RHS}; 13 | // agent typedefs 14 | // TODO make name_type a string later on 15 | typedef char name_type; 16 | typedef int id_type; 17 | typedef int arity_type; 18 | typedef int port_type; 19 | // an agent is basically a thrust tuple 20 | typedef tuple agent; 21 | typedef tuple equation; 22 | 23 | } 24 | 25 | // print an agent 26 | __host__ 27 | std::ostream& operator<< (std::ostream& os, const soa::agent& a); 28 | 29 | __host__ 30 | std::ostream& operator<< (std::ostream& os, const soa::equation& a); 31 | 32 | void print_equation(const soa::agent& lhs, const soa::agent& rhs); -------------------------------------------------------------------------------- /config_manager.h: -------------------------------------------------------------------------------- 1 | // class config manager 2 | // singleton 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | typedef std::map config_map; 9 | 10 | class config_manager 11 | { 12 | public: 13 | //get the instance 14 | static config_manager* inst(); 15 | 16 | static void load(const std::string& filepath) {inst()->load_config(filepath); } 17 | static float get(const std::string& key) { return inst()->value(key); } 18 | static int get_int(const std::string& key) { return static_cast(inst()->value(key)); } 19 | static bool get_bool(const std::string& key) { if (inst()->value(key) == 0) return false; else return true; } 20 | 21 | void load_config(const std::string& filepath); 22 | const config_map config() const {return config_;} 23 | const float value(const std::string& key); 24 | 25 | private: 26 | config_manager() {} 27 | virtual ~config_manager() {} 28 | 29 | 30 | config_map config_; 31 | 32 | }; -------------------------------------------------------------------------------- /config_manager.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "config_manager.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | config_manager* config_manager::inst() 11 | { 12 | static config_manager the_instance; 13 | return &the_instance; 14 | } 15 | 16 | void config_manager::load_config(const std::string& filepath) 17 | { 18 | std::ifstream fp_in; 19 | fp_in.open(filepath, std::ios::in); 20 | if (!fp_in.is_open()) { 21 | std::cout << "error opening file " << filepath << std::endl; 22 | return; 23 | } 24 | 25 | string key; 26 | float value; 27 | 28 | while (getline(fp_in, key, ' ')) 29 | { 30 | fp_in >> value; 31 | config_[key] = value; 32 | 33 | getline(fp_in, key); 34 | } 35 | std::cout << "done loading config\n" << endl; 36 | } 37 | 38 | const float config_manager::value(const std::string& key) 39 | { 40 | config_map::iterator it; 41 | it = config_.find(key); 42 | if (it != config_.end()) { 43 | return it->second; 44 | } 45 | 46 | return -1; 47 | } -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------ 2 | ingpu - an experimental GPU-based interaction nets evaluator 3 | ------------------------------------------------------------ 4 | author: Eugen Jiresch 5 | for any comments, suggestions, feedback, please send an email to: jiresch (at) logic . at 6 | 7 | 8 | Requirements: 9 | ------------- 10 | CUDA 4.0 or later 11 | Boost 1.47 or later 12 | ingpu uses some C++ 0x features 13 | 14 | Build: 15 | ------ 16 | Project files for Visual Studio 2010 are provided. 17 | 18 | Usage: 19 | ------ 20 | Currently, rulesets are coded as C++ CUDA kernels. To add your own, implement a header file similar to ackermann.h or fibonacci.h . 21 | sample kernels provided: 22 | ackermann.h 23 | fibonacci.h 24 | algae.h (basic L-System) 25 | cantor_dust.h (Cantor dust fractal set) 26 | 27 | Running ingpu will evaluate the input nets in input.txt. 28 | The following options are available in options.txt: 29 | verbose: print debug information during reduction 30 | print_final: print the final set of rules 31 | pause: if verbose is enabled, pause after each interaction/communication loop 32 | ruleset: 1 = ackermann, 2 = L-System, 3 = fibonacci. to add your own ruleset, modify kernel.cu at line 796. 33 | file_output: output some statistics/profiling to out.csv 34 | soa: use "structure of arrays" input data instead of "array of structures" (default). work in progress, may crash for some rules/inputs 35 | eval_all: evaluate all (uncommented) inputs in input.txt. If set to 0, only the first input is evaluated. 36 | pause_between_inputs: pause after evaluating each input net. 37 | 38 | 39 | Current known issues: 40 | --------------- 41 | - sometimes crashes for large inputs 42 | - soa mode is broken for ackermann 43 | - VS2010 Debug mode is broken on some machines -------------------------------------------------------------------------------- /soa/agent.cpp: -------------------------------------------------------------------------------- 1 | // soa agent tuple 2 | 3 | #include "agent.h" 4 | #include 5 | #include 6 | 7 | using namespace soa; 8 | 9 | // return a dummy tuple 10 | 11 | 12 | // print an agent 13 | __host__ 14 | std::ostream& operator<< (std::ostream& os, const soa::agent& a) { 15 | os << std::setiosflags(std::ios::left); 16 | name_type name = thrust::get(a); 17 | if (name >= 'a' && name <= 'z') { 18 | os << std::setw(2) << thrust::get(a); 19 | } 20 | else { 21 | os << std::setw(2) << name; 22 | } 23 | os << std::resetiosflags(std::ios::left); 24 | 25 | return os; 26 | } 27 | 28 | // print an agent 29 | __host__ 30 | std::ostream& operator<< (std::ostream& os, const soa::equation& a) { 31 | os << std::setiosflags(std::ios::left) 32 | << get<0>(a) 33 | << "=" 34 | << get<1>(a); 35 | os << std::resetiosflags(std::ios::left); 36 | 37 | return os; 38 | } 39 | 40 | void print_equation(const soa::agent& lhs, const soa::agent& rhs) 41 | { 42 | std::string left_args, right_args; 43 | if (thrust::get(lhs) == 0) { 44 | left_args = ""; 45 | } 46 | else { 47 | 48 | std::stringstream out; 49 | out << "(" << get(lhs); 50 | if (thrust::get(lhs) > 1) { 51 | out << ", " << get(lhs); 52 | } 53 | if (thrust::get(lhs) > 2) { 54 | out << ", " << get(lhs); 55 | } 56 | if (thrust::get(lhs) > 3) { 57 | out << ", " << get(lhs); 58 | } 59 | out << ")"; 60 | 61 | left_args = out.str(); 62 | } 63 | 64 | if (thrust::get(rhs) == 0) { 65 | right_args = " "; 66 | } 67 | else { 68 | std::stringstream out; 69 | out << "(" << get(rhs); 70 | if (thrust::get(rhs) > 1) { 71 | out << ", " << get(rhs); 72 | } 73 | if (thrust::get(rhs) > 2) { 74 | out << ", " << get(rhs); 75 | } 76 | if (thrust::get(rhs) > 3) { 77 | out << ", " << get(rhs); 78 | } 79 | out << ")"; 80 | right_args = out.str(); 81 | } 82 | std::cout << lhs 83 | << left_args 84 | << " = " 85 | << rhs 86 | << right_args 87 | << std::setw(10) << " (" 88 | << thrust::get(lhs) << ", " << get(rhs) << ") \n"; 89 | 90 | } 91 | -------------------------------------------------------------------------------- /agent_struct.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define MAX_PORTS 4 7 | 8 | namespace ingpu { 9 | 10 | enum EQUATION_TUPLE{LHS, RHS}; 11 | 12 | // Agents/Variables 13 | struct Agent 14 | { 15 | int id; // unique id of the agent 16 | char name; // name of the agent - determines agent (upper case) or variable (lower case) 17 | int arity; // maximum arity = 4 18 | int ports[4]; // contains ids of connected agents 19 | 20 | //dummy constructor 21 | __host__ __device__ 22 | Agent() : id(0), name('Z'), arity(0) { 23 | for (int i=0; iid = a.id; 92 | this->name = a.name; 93 | this->arity = a.arity; 94 | for (int i=0; i < a.arity; ++i) { 95 | this->ports[i] = a.ports[i]; 96 | } 97 | return *this; 98 | } 99 | }; 100 | 101 | } 102 | 103 | // print an agent 104 | __host__ 105 | std::ostream& operator<< (std::ostream& os, const ingpu::Agent& a); 106 | -------------------------------------------------------------------------------- /interaction_step.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | soa 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | soa 26 | 27 | 28 | soa 29 | 30 | 31 | soa 32 | 33 | 34 | soa 35 | 36 | 37 | soa 38 | 39 | 40 | 41 | 42 | soa 43 | 44 | 45 | 46 | 47 | 48 | 49 | Resources 50 | 51 | 52 | Resources 53 | 54 | 55 | soa 56 | 57 | 58 | 59 | 60 | 61 | 62 | soa 63 | 64 | 65 | 66 | 67 | {575db932-3ad3-4912-9bef-bfba0c3d078e} 68 | 69 | 70 | {1c64136a-5ca1-402d-9add-df1fecfe4bdd} 71 | 72 | 73 | -------------------------------------------------------------------------------- /parse_net.h: -------------------------------------------------------------------------------- 1 | // parsing agent structs from input or a file 2 | // largely based on boost::spirit's "parsing into a struct tutorial" 3 | // http://www.boost.org/doc/libs/1_47_0/libs/spirit/doc/html/spirit/qi/tutorials/employee___parsing_into_structs.html 4 | 5 | #ifndef PARSENET_H_ 6 | #define PARSENET_H_ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "agent_struct.h" 19 | #include "soa/agent.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | using namespace std::tr1; 27 | using namespace std; 28 | using namespace ingpu; 29 | 30 | 31 | namespace parse_net { 32 | 33 | //namespace shortcuts 34 | namespace qi = boost::spirit::qi; 35 | namespace ascii = boost::spirit::ascii; 36 | 37 | //change this to char in the future 38 | typedef std::string agent_symbol; 39 | typedef std::string variable_symbol; 40 | 41 | //raw agent struct 42 | //reads symbols, but doesnt have correct agent ids yet 43 | struct raw_agent{ 44 | agent_symbol symbol; 45 | std::vector ports; 46 | 47 | 48 | std::string to_string(); 49 | }; 50 | } 51 | 52 | // We need to tell fusion about our raw_agent struct 53 | // to make it a first-class fusion citizen. This has to 54 | // be in global scope. 55 | BOOST_FUSION_ADAPT_STRUCT( 56 | parse_net::raw_agent, 57 | (parse_net::agent_symbol, symbol) 58 | (std::vector, ports) 59 | ) 60 | 61 | namespace parse_net { 62 | // ---------------- 63 | // raw agent parser 64 | // ---------------- 65 | // TODO: parsing A() (parentheses with no ports) will yield an error! 66 | struct raw_agent_parser : qi::grammar 67 | { 68 | raw_agent_parser() : raw_agent_parser::base_type(start) 69 | { 70 | using ascii::alpha; 71 | using ascii::alnum; 72 | 73 | start %= 74 | +(alnum) 75 | >> -( 76 | '(' 77 | >> (+(alnum) % ',') 78 | >> ')' 79 | ) 80 | ; 81 | 82 | } 83 | 84 | qi::rule start; 85 | }; 86 | 87 | bool parse_single(const std::string& filepath, std::vector& raws); 88 | bool parse_all(const std::string& filepath, vector>& raws_vector); 89 | 90 | void build_agents(const std::vector& raws, std::vector& agents); 91 | // soa version 92 | void build_agents(const std::vector& raws, 93 | std::vector& ids, 94 | std::vector& names, 95 | std::vector& arities, 96 | std::vector& p1s, 97 | std::vector& p2s, 98 | std::vector& p3s, 99 | std::vector& p4s); 100 | } 101 | #endif -------------------------------------------------------------------------------- /soa/agent_functor.cuh: -------------------------------------------------------------------------------- 1 | /* 2 | agent.h 3 | an agent struct and some functions 4 | */ 5 | 6 | //#pragma once 7 | #ifndef AGENT_H_ 8 | #define AGENT_H_ 9 | 10 | //#include 11 | #include 12 | #include 13 | #include 14 | #include "agent.h" 15 | #include 16 | 17 | using namespace soa; 18 | 19 | namespace soa { 20 | 21 | // our input for IN evaluation 22 | typedef thrust::tuple input_tuple; 23 | typedef thrust::unary_function int_functor; 24 | 25 | // iterator types 26 | typedef thrust::device_vector::iterator agent_iter; 27 | typedef thrust::tuple agent_iter_tuple; 28 | typedef thrust::zip_iterator equation_iter; 29 | 30 | struct has_name : public thrust::unary_function 31 | { 32 | char name; 33 | 34 | __host__ __device__ 35 | has_name(const char c) : name(c) {} 36 | 37 | __host__ __device__ 38 | bool operator()(const agent& agent) { 39 | return name == get(agent); 40 | } 41 | }; 42 | 43 | // greater comparison function 44 | // oriented communication equations are smaller than everything 45 | // else, compare lexicographically 46 | struct comm_equation_greater : public thrust::binary_function 47 | { 48 | 49 | __host__ __device__ 50 | bool operator()(const equation& first, const equation& second) 51 | { 52 | //Agent lhs_first = get(first); 53 | //Agent rhs_first = get(first); 54 | // 55 | //Agent lhs_second = get(second); 56 | //Agent rhs_second = get(second); 57 | 58 | // if both LHSes are variables, compare the RHSes 59 | // agents (upper case) precede variables (lower case) 60 | if ( is_variable(get(first) ) && is_variable(get(second)) ) { 61 | return (get(get(first)) < get(get(second)) ); 62 | } 63 | 64 | //default: compare lhs names lexicographically 65 | return ( get(get(first)) > get(get(second))); 66 | } 67 | }; 68 | 69 | 70 | // checks equations for top-level variables 71 | // returns 1 if lhs is a variable 72 | // 2 if rhs is 73 | // 3 for both 74 | // 0 else 75 | __host__ __device__ 76 | int top_level_variables(const equation& e) 77 | { 78 | int result = 0; 79 | if (is_variable(get(e))) 80 | result++; 81 | if (is_variable(get(e))) 82 | result += 2; 83 | 84 | return result; 85 | } 86 | 87 | // checks for tlv, boolean version 88 | __host__ __device__ 89 | bool has_toplevel_variable(const equation& e) 90 | { 91 | if (is_variable(get(e))) 92 | return true; 93 | else 94 | return is_variable(get(e)); 95 | } 96 | 97 | //orient equations t=x -> x=t 98 | struct orient_functor 99 | { 100 | template 101 | __host__ __device__ 102 | void operator()(Equ eq) 103 | { 104 | if (!is_variable(get(eq)) && is_variable(get(eq))) 105 | { 106 | thrust::swap(get(eq), get(eq)); 107 | } 108 | } 109 | }; 110 | 111 | //orient equations t=x -> x=t 112 | struct orient_functor_transform : public thrust::unary_function 113 | { 114 | __host__ __device__ 115 | equation operator()(const equation eq) 116 | { 117 | equation result(eq); 118 | if (!is_variable(get(eq)) && is_variable(get(eq))) 119 | { 120 | thrust::swap(get(result), get(result)); 121 | } 122 | 123 | return result; 124 | } 125 | }; 126 | 127 | 128 | __host__ 129 | void print_equations(const thrust::host_vector& lhses, const thrust::host_vector& rhses) 130 | { 131 | for( unsigned int i = 0; i < lhses.size(); i++) { 132 | print_equation(lhses[i], rhses[i]); 133 | } 134 | std::cout << std::endl; 135 | } 136 | 137 | void print_equations(const thrust::host_vector equations) 138 | { 139 | for( unsigned int i = 0; i < equations.size(); i++) { 140 | print_equation(get(equations[i]), get(equations[i])); 141 | } 142 | std::cout << std::endl; 143 | } 144 | 145 | } 146 | 147 | 148 | #endif -------------------------------------------------------------------------------- /input.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | // -------------- 4 | // ackermann 5 | // -------------- 6 | 7 | 8 | //D(a,b) = S(x) 9 | 10 | // ack(1,2) 11 | //A(r,x)=S(a), x=S(y), y=S(z), z=O, a=O 12 | 13 | // ack(3,8) 14 | //A(r,x)=S(a), x=S(y), y=S(z), z=S(u), u=S(v), v=S(w), w=S(t), t=S(q), q=S(s), s=O, a=S(b), b=S(c), c=O 15 | 16 | // ack(3,7) 17 | //A(r,x)=S(a), x=S(y), y=S(z), z=S(u), u=S(v), v=S(w), w=S(t), t=S(q), q=O, a=S(b), b=S(c), c=O 18 | 19 | // ack(3,6) 20 | //A(r,x)=S(a), x=S(y), y=S(z), z=S(u), u=S(v), v=S(w), w=S(t), t=O, a=S(b), b=S(c), c=O 21 | 22 | // ack(3,5) 23 | //A(r,x)=S(a), x=S(y), y=S(z), z=S(u), u=S(v), v=S(w), w=O, a=S(b), b=S(c), c=O 24 | 25 | // ack(3,4) 26 | //A(r,x)=S(a), x=S(y), y=S(z), z=S(u), u=S(v), v=O, a=S(b), b=S(c), c=O 27 | 28 | // ack(3,3) 29 | //A(r,x)=S(a), x=S(y), y=S(z), z=S(u), u=O, a=S(b), b=S(c), c=O 30 | 31 | // ack(3,2) 32 | //A(r,x)=S(a), x=S(y), y=S(z), z=O, a=S(b), b=S(c), c=O 33 | 34 | // ack(3,1) 35 | //A(r,x)=S(a), x=S(y), y=O, a=S(b), b=S(c), c=O 36 | 37 | // ack(2,2) 38 | //A(r,x)=S(a), x=S(y), y=S(z), z=O, a=S(b), b=O 39 | 40 | 41 | // ack(1,1) 42 | //A(r,x)=S(a),x=S(y),y=O,a=O 43 | 44 | //ack(0,0) 45 | 46 | 47 | // -------------- 48 | // fibonacci 49 | // -------------- 50 | 51 | //fib(1) 52 | //F(r)=S(a),a=O 53 | 54 | //fib(6) 55 | //F(r)=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=O 56 | 57 | //fib(10) 58 | //F(r)=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(i),i=S(j),j=O 59 | 60 | //fib(11) 61 | //F(r)=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(i),i=S(j),j=S(k),k=O 62 | 63 | //fib(12) 64 | //F(r)=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(i),i=S(j),j=S(k),k=S(l),l=O 65 | 66 | //fib(15) 67 | //F(r)=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(i),i=S(j),j=S(k),k=S(l),l=S(m),m=S(n),n=S(p),p=O 68 | 69 | //fib(20) 70 | //F(r)=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(i),i=S(j),j=S(k),k=S(l),l=S(m),m=S(n),n=S(p),p=S(q), q=S(s), s=S(t), t=S(u), u=S(v),v=O 71 | 72 | //fib(3) 73 | //F(r)=S(a),a=S(b),b=S(c),c=O 74 | 75 | 76 | 77 | 78 | // ----------------- 79 | // algae L-system 80 | // A -> AB, B -> A 81 | // ----------------- 82 | 83 | // 1 84 | 85 | //A(s) = L(r,i), i=S(a), a=O 86 | //2 87 | A(s) = L(r,i9001), i9001=S(i9002), i9002=S(ib), ib=O 88 | //3 89 | //A(s) = L(r,i), i=S(a), a=S(b), b=S(c), c=O 90 | 91 | 92 | // 5 93 | //A(s) = L(r,i), i=S(a), a=S(b), b=S(c), c=S(d), d=S(e), e=O 94 | 95 | // 7 96 | //A(s) = L(r,i), i=S(a), a=S(b), b=S(c), c=S(d), d=S(e), e=S(f), f=S(g), g=O 97 | 98 | // 8 99 | //A(s) = L(r,i), i=S(a), a=S(b), b=S(c), c=S(d), d=S(e), e=S(f), f=S(g), g=S(h), h=O 100 | 101 | // 9 102 | //A(s) = L(r,i), i=S(a), a=S(b), b=S(c), c=S(d), d=S(e), e=S(f), f=S(g), g=S(h), h=S(j), j=O 103 | 104 | // 10 105 | //A(s) = L(r,i), i=S(a), a=S(b), b=S(c), c=S(d), d=S(e), e=S(f), f=S(g), g=S(h), h=S(j), j=S(k), k=O 106 | 107 | // 11 108 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k), k=S(l), l=O 109 | 110 | // 12 111 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=O 112 | 113 | // 15 114 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=O 115 | 116 | // 18 117 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=S(q), q=S(t), t=S(u), u=O 118 | 119 | // 20 120 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=S(q), q=S(t), t=S(u), u=S(v), v=S(w), w=O 121 | 122 | // 21 123 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=S(q), q=S(t), t=S(u), u=S(v), v=S(w), w=S(x), x=O 124 | 125 | // 22 126 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=S(q), q=S(t), t=S(u), u=S(v), v=S(w), w=S(x), x=S(y), y=O 127 | 128 | // 23 129 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=S(q), q=S(t), t=S(u), u=S(v), v=S(w), w=S(x), x=S(y), y=S(z), z=O 130 | 131 | // 24 132 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=S(q), q=S(t), t=S(u), u=S(v), v=S(w), w=S(x), x=S(y), y=S(z), z=S(z1), z1=O 133 | 134 | // 25 135 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=S(q), q=S(t), t=S(u), u=S(v), v=S(w), w=S(x), x=S(y), y=S(z), z=S(z1), z1=S(z2), z2=O 136 | 137 | // 26 138 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=S(q), q=S(t), t=S(u), u=S(v), v=S(w), w=S(x), x=S(y), y=S(z), z=S(z1), z1=S(z2), z2=S(z3), z3=O 139 | 140 | // 27 141 | //A(s) = L(r,i),i=S(a),a=S(b),b=S(c),c=S(d),d=S(e),e=S(f),f=S(g),g=S(h),h=S(j),j=S(k),k=S(l), l=S(m), m=S(n), n=S(o), o=S(p), p=S(q), q=S(t), t=S(u), u=S(v), v=S(w), w=S(x), x=S(y), y=S(z), z=S(z1), z1=S(z2), z2=S(z3), z3=S(z4), z4=O 142 | 143 | 144 | // ----------------- 145 | // symbolic addition 146 | // ----------------- 147 | 148 | //1 + 1 149 | //A(r,y) = S(x), y=S(z), z=O, x=O 150 | 151 | // test 152 | //a=B,x=A,a=C,x=i,i=A,E=E 153 | //b=V,A=B, x=z,z=a,a=b,E=E,x=r 154 | -------------------------------------------------------------------------------- /algae.h: -------------------------------------------------------------------------------- 1 | // algae functor 2 | // computes nth iteration of original L-system to model algae groth 3 | // en.wikipedia.org/wiki/L-system 4 | 5 | //IMPORTANT 6 | // RHS equations must be oriented 7 | 8 | //#pragma once 9 | #ifndef ALGAE_H_ 10 | #define ALGAE_H_ 11 | 12 | #include "cuda_runtime.h" 13 | #include "device_launch_parameters.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | //#include "device_functions.h" 21 | 22 | #include "agent.cuh" 23 | 24 | using namespace ingpu; 25 | using namespace thrust; 26 | 27 | //max new indices per interaction 28 | const int algae_max_idx = 9; 29 | 30 | struct algae_functor : public int_functor { 31 | 32 | int * index_ptr; 33 | __host__ __device__ 34 | algae_functor(int * ptr) : index_ptr(ptr) {} 35 | 36 | 37 | template 38 | __device__ 39 | void operator()(Tuple equations) 40 | { 41 | 42 | //get lhs and rhs of the equations 43 | Agent lhs = thrust::get<0>(equations); 44 | Agent rhs = thrust::get<1>(equations); 45 | 46 | // default: no interaction was performed 47 | thrust::get<8>(equations) = false; 48 | 49 | 50 | // if both sides are agents 51 | // rewrite the equations 52 | //TODO replace is_upper by direct char comparison 53 | if (is_upper(lhs.name) && is_upper(rhs.name)) { 54 | 55 | //sort pair lexicographically (active pairs are symmetric) 56 | if (rhs.name < lhs.name ) { 57 | lhs = rhs; 58 | rhs = thrust::get<0>(equations); 59 | } 60 | 61 | // A(s) >< L(r,i) => M(r,s)~i; 62 | if (lhs.name == 'A' && rhs.name == 'L') { 63 | // wires 64 | const int s = lhs.ports[0]; 65 | const int r = rhs.ports[0]; 66 | const int i = rhs.ports[1]; 67 | // M(r,s)~i 68 | get<0>(equations) = Agent(i, 'i', 0); 69 | get<1>(equations) = Agent(rhs.id, 'M', 2, r, s); 70 | 71 | get<8>(equations) = true; // we performed an interaction 72 | } 73 | // B(s) >< L(r,i) => N(r,s)~i; 74 | else if (lhs.name == 'B' && rhs.name == 'L') { 75 | // wires 76 | const int s = lhs.ports[0]; 77 | const int r = rhs.ports[0]; 78 | const int i = rhs.ports[1]; 79 | // M(r,s)~i 80 | get<0>(equations) = Agent(i, 'i', 0); 81 | get<1>(equations) = Agent(lhs.id, 'N', 2, r, s); 82 | 83 | get<8>(equations) = true; // we performed an interaction 84 | } 85 | // M(r,s) >< O => r~A(s) 86 | else if (lhs.name == 'M' && rhs.name == 'O') { 87 | // wires 88 | const int r = lhs.ports[0]; 89 | const int s = lhs.ports[1]; 90 | // r~A(s) 91 | get<0>(equations) = Agent(r); 92 | get<1>(equations) = Agent(lhs.id, 'A', 1, s); 93 | 94 | get<8>(equations) = true; // we performed an interaction 95 | } 96 | // N(r,s) >< O => r~B(s) 97 | else if (lhs.name == 'N' && rhs.name == 'O') { 98 | // wires 99 | const int r = lhs.ports[0]; 100 | const int s = lhs.ports[1]; 101 | // r~A(s) 102 | get<0>(equations) = Agent(r); 103 | get<1>(equations) = Agent(lhs.id, 'B', 1, s); 104 | 105 | get<8>(equations) = true; // we performed an interaction 106 | } 107 | // M(r,s) >< S(i) => L(r,d)~A(y), L(y,e)~B(s), D(d,e)~i 108 | else if (lhs.name == 'M' && rhs.name == 'S') { 109 | int new_index = atomicAdd(&index_ptr[0], algae_max_idx); 110 | // wires 111 | const int r = lhs.ports[0]; 112 | const int s = lhs.ports[1]; 113 | const int i = rhs.ports[0]; 114 | const int d = new_index++; 115 | const int y = new_index++; 116 | const int e = new_index++; 117 | // L(r,d)~A(y) 118 | get<0>(equations) = Agent(new_index++, 'L', 2, r, d); 119 | get<1>(equations) = Agent(new_index++, 'A', 1, y); 120 | // L(y,e)~B(s) 121 | get<2>(equations) = Agent(new_index++, 'L', 2, y, e); 122 | get<3>(equations) = Agent(new_index++, 'B', 1, s); 123 | // D(d,e)~i 124 | get<4>(equations) = Agent(i); 125 | get<5>(equations) = Agent(new_index++, 'D', 2, d, e); 126 | 127 | get<8>(equations) = true; // we performed an interaction 128 | } 129 | // N(r,s) >< S(i) => L(r,x)~A(s) 130 | else if (lhs.name == 'N' && rhs.name == 'S') { 131 | // wires 132 | const int r = lhs.ports[0]; 133 | const int s = lhs.ports[1]; 134 | const int i = rhs.ports[0]; 135 | // L(r,x)~A(s) 136 | get<0>(equations) = Agent(lhs.id, 'L', 2, r, i); 137 | get<1>(equations) = Agent(rhs.id, 'A', 1, s); 138 | 139 | get<8>(equations) = true; // we performed an interaction 140 | } 141 | // O >< d(x,y) => O~x, O~y; 142 | else if (lhs.name == 'D' && rhs.name == 'O' ) { 143 | int new_index = atomicAdd(&index_ptr[0], 1); 144 | // eps~x 145 | thrust::get<1>(equations) = rhs; 146 | thrust::get<0>(equations) = Agent(lhs.ports[0], 'v', 0);//*(rhs.ports[0].get()); 147 | // eps~y goes to equations array A 148 | thrust::get<2>(equations) = Agent(lhs.ports[1], 'v', 0);//*(rhs.ports[1].get()); 149 | thrust::get<3>(equations) = Agent(new_index, 'O', 0); 150 | 151 | thrust::get<8>(equations) = true; // we performed an interaction 152 | } 153 | // S(z) >< d(x,y) => S(a)~x, S(b)~y, d(a,b)~z; 154 | else if (lhs.name == 'D' && rhs.name == 'S' ) { 155 | int new_index = atomicAdd(&index_ptr[0], 4); 156 | //wires 157 | const int x = lhs.ports[0]; 158 | const int y = lhs.ports[1]; 159 | const int z = rhs.ports[0]; 160 | const int a = new_index++; 161 | const int b = new_index++; 162 | rhs.ports[0] = a; 163 | Agent s(new_index++, 'S', 1); 164 | s.ports[0] = b; 165 | lhs.ports[0] = a; 166 | lhs.ports[1] = b; 167 | // S(a)~x 168 | thrust::get<1>(equations) = rhs; 169 | thrust::get<0>(equations) = Agent(x, 'x', 0);//*(rhs.ports[0].get()); 170 | // S(b)~y 171 | thrust::get<3>(equations) = s; 172 | thrust::get<2>(equations) = Agent(y, 'y', 0);//*(rhs.ports[1].get()); 173 | // d(a,b)~ z 174 | get<4>(equations) = Agent(z, 'v', 0); 175 | get<5>(equations) = lhs; 176 | 177 | thrust::get<8>(equations) = true; // we performed an interaction 178 | } 179 | } 180 | } 181 | }; 182 | 183 | #endif -------------------------------------------------------------------------------- /soa/algae.h: -------------------------------------------------------------------------------- 1 | // algae functor 2 | // computes nth iteration of original L-system to model algae groth 3 | // en.wikipedia.org/wiki/L-system 4 | 5 | //IMPORTANT 6 | // RHS equations must be oriented 7 | 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "agent_functor.h" 17 | 18 | using namespace soa; 19 | using namespace thrust; 20 | 21 | namespace soa { 22 | 23 | //max new indices per interaction 24 | const int algae_max_idx = 9; 25 | 26 | struct algae_functor : public int_functor { 27 | 28 | int * index_ptr; 29 | __host__ __device__ 30 | algae_functor(int * ptr) : index_ptr(ptr) {} 31 | 32 | 33 | template 34 | __device__ 35 | void operator()(Tuple equations) 36 | { 37 | 38 | //get lhs and rhs of the equations 39 | agent lhs = thrust::get<0>(equations); 40 | agent rhs = thrust::get<1>(equations); 41 | 42 | // default: no interaction was performed 43 | thrust::get<8>(equations) = false; 44 | 45 | 46 | // if both sides are agents 47 | // rewrite the equations 48 | if (is_upper( get(lhs) ) && is_upper( get(lhs) )) { 49 | 50 | //sort pair lexicographically (active pairs are symmetric) 51 | if (get(rhs) < get(lhs) ) { 52 | lhs = rhs; 53 | rhs = thrust::get<0>(equations); 54 | } 55 | 56 | name_type lhs_name = get(lhs); 57 | name_type rhs_name = get(rhs); 58 | 59 | // A(s) >< L(r,i) => M(r,s)~i; 60 | if (lhs_name == 'A' && rhs_name == 'L') { 61 | int new_index = atomicAdd(&index_ptr[0], 1); 62 | // wires 63 | const int s = get(lhs); 64 | const int r = get(rhs); 65 | const int i = get(rhs); 66 | // M(r,s)~i 67 | get<0>(equations) = make_agent(i, 'i', 0); 68 | get<1>(equations) = make_agent(new_index, 'M', 2, r, s); 69 | 70 | get<8>(equations) = true; // we performed an interaction 71 | } 72 | // B(s) >< L(r,i) => N(r,s)~i; 73 | else if (lhs_name == 'B' && rhs_name == 'L') { 74 | int new_index = atomicAdd(&index_ptr[0], 1); 75 | // wires 76 | const int s = get(lhs); 77 | const int r = get(rhs); 78 | const int i = get(rhs); 79 | // M(r,s)~i 80 | get<0>(equations) = make_agent(i, 'i', 0); 81 | get<1>(equations) = make_agent(new_index, 'N', 2, r, s); 82 | 83 | get<8>(equations) = true; // we performed an interaction 84 | } 85 | // M(r,s) >< O => r~A(s) 86 | else if (lhs_name == 'M' && rhs_name == 'O') { 87 | int new_index = atomicAdd(&index_ptr[0], 1); 88 | // wires 89 | const int r = get(lhs); 90 | const int s = get(lhs); 91 | // r~A(s) 92 | get<0>(equations) = make_agent(r); 93 | get<1>(equations) = make_agent(new_index, 'A', 1, s); 94 | 95 | get<8>(equations) = true; // we performed an interaction 96 | } 97 | // N(r,s) >< O => r~B(s) 98 | else if (lhs_name == 'N' && rhs_name == 'O') { 99 | int new_index = atomicAdd(&index_ptr[0], 1); 100 | // wires 101 | const int r = get(lhs); 102 | const int s = get(lhs); 103 | // r~A(s) 104 | get<0>(equations) = make_agent(r); 105 | get<1>(equations) = make_agent(new_index, 'B', 1, s); 106 | 107 | get<8>(equations) = true; // we performed an interaction 108 | } 109 | // M(r,s) >< S(i) => L(r,d)~A(y), L(y,e)~B(s), D(d,e)~i 110 | else if (lhs_name == 'M' && rhs_name == 'S') { 111 | int new_index = atomicAdd(&index_ptr[0], algae_max_idx); 112 | // wires 113 | const int r = get(lhs); 114 | const int s = get(lhs); 115 | const int i = get(rhs); 116 | const int d = new_index++; 117 | const int y = new_index++; 118 | const int e = new_index++; 119 | // L(r,d)~A(y) 120 | get<0>(equations) = make_agent(new_index++, 'L', 2, r, d); 121 | get<1>(equations) = make_agent(new_index++, 'A', 1, y); 122 | // L(y,e)~B(s) 123 | get<2>(equations) = make_agent(new_index++, 'L', 2, y, e); 124 | get<3>(equations) = make_agent(new_index++, 'B', 1, s); 125 | // D(d,e)~i 126 | get<4>(equations) = make_agent(i); 127 | get<5>(equations) = make_agent(new_index++, 'D', 2, d, e); 128 | 129 | get<8>(equations) = true; // we performed an interaction 130 | } 131 | // N(r,s) >< S(i) => L(r,x)~A(s) 132 | else if (lhs_name == 'N' && rhs_name == 'S') { 133 | int new_index = atomicAdd(&index_ptr[0], 2); 134 | // wires 135 | const int r = get(lhs); 136 | const int s = get(lhs); 137 | const int i = get(rhs); 138 | // L(r,x)~A(s) 139 | get<0>(equations) = make_agent(new_index++, 'L', 2, r, i); 140 | get<1>(equations) = make_agent(new_index++, 'A', 1, s); 141 | 142 | get<8>(equations) = true; // we performed an interaction 143 | } 144 | // O >< d(x,y) => O~x, O~y; 145 | else if (lhs_name == 'D' && rhs_name == 'O' ) { 146 | int new_index = atomicAdd(&index_ptr[0], algae_max_idx); 147 | // eps~x 148 | thrust::get<1>(equations) = rhs; 149 | thrust::get<0>(equations) = make_agent(get(lhs), 'z', 0);//*(get(rhs).get()); 150 | // eps~y goes to equations array A 151 | thrust::get<3>(equations) = make_agent(new_index, 'O', 0); 152 | thrust::get<2>(equations) = make_agent(get(lhs), 'z', 0);//*(get(rhs).get()); 153 | 154 | thrust::get<8>(equations) = true; // we performed an interaction 155 | } 156 | // S(z) >< d(x,y) => S(a)~x, S(b)~y, d(a,b)~z; 157 | else if (lhs_name == 'D' && rhs_name == 'S' ) { 158 | int new_index = atomicAdd(&index_ptr[0], algae_max_idx); 159 | //wires 160 | const int x = get(lhs); 161 | const int y = get(lhs); 162 | const int z = get(rhs); 163 | const int a = new_index++; 164 | const int b = new_index++; 165 | //get(rhs) = a; 166 | //agent s = ; 167 | //get(s) = b; 168 | //get(lhs) = a; 169 | //get(lhs) = b; 170 | // S(a)~x 171 | thrust::get<1>(equations) = make_agent(new_index++, 'S', 1, a); 172 | thrust::get<0>(equations) = make_agent(x, 'x', 0);//*(get(rhs).get()); 173 | // S(b)~y 174 | thrust::get<3>(equations) = make_agent(new_index++, 'S', 1, b); 175 | thrust::get<2>(equations) = make_agent(y, 'y', 0);//*(get(rhs).get()); 176 | // d(a,b)~ z 177 | get<4>(equations) = make_agent(z, 'z', 0); 178 | get<5>(equations) = make_agent(new_index++, 'D', 2, a, b); 179 | 180 | thrust::get<8>(equations) = true; // we performed an interaction 181 | } 182 | } 183 | } 184 | }; 185 | 186 | } -------------------------------------------------------------------------------- /fibonacci.h: -------------------------------------------------------------------------------- 1 | // fibonacci functor 2 | 3 | 4 | //#pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "agent.cuh" 12 | 13 | using namespace ingpu; 14 | using namespace thrust; 15 | 16 | //max new indices per interaction 17 | const int max_idx = 7; 18 | 19 | struct fibonacci_functor : public int_functor { 20 | 21 | int * index_ptr; 22 | __host__ __device__ 23 | fibonacci_functor(int * ptr) : index_ptr(ptr) {} 24 | 25 | template 26 | __device__ 27 | void operator()(Tuple equations) 28 | { 29 | 30 | //get lhs and rhs of the equations 31 | Agent lhs = get<0>(equations); 32 | Agent rhs = get<1>(equations); 33 | 34 | // default: no interaction was performed 35 | get<8>(equations) = false; 36 | 37 | 38 | // if both sides are agents 39 | // rewrite the equations 40 | if (is_upper(lhs.name) && is_upper(rhs.name)) { 41 | 42 | //sort pair lexicographically (active pairs are symmetric) 43 | if (rhs.name < lhs.name ) { 44 | lhs = rhs; 45 | rhs = thrust::get<0>(equations); 46 | } 47 | 48 | // A(r, y) >< 0 => r~y 49 | if (lhs.name == 'A' && rhs.name == 'O') { 50 | 51 | //r~y 52 | thrust::get<0>(equations) = Agent(lhs.ports[0], 'r', 0); 53 | thrust::get<1>(equations) = Agent(lhs.ports[1], 'y', 0); 54 | 55 | thrust::get<8>(equations) = true; // we performed an interaction 56 | } 57 | // A(r, y) >< S(x) => r~S(w), A(w, y)~x 58 | else if (lhs.name == 'A' && rhs.name == 'S') { 59 | int new_index = atomicAdd(&index_ptr[0], max_idx); 60 | //wires 61 | int x = rhs.ports[0]; 62 | int r = lhs.ports[0]; 63 | int w = new_index; // new variable w 64 | 65 | // r~S(w) 66 | rhs.ports[0] = w; 67 | thrust::get<0>(equations) = Agent(r, 'r', 0); 68 | thrust::get<1>(equations) = rhs; 69 | // A(w, y)~x 70 | lhs.ports[0] = w; 71 | thrust::get<2>(equations) = Agent(x, 'x', 0); 72 | thrust::get<3>(equations) = lhs; 73 | 74 | thrust::get<8>(equations) = true; // we performed an interaction 75 | } 76 | // fib(r) >< O => r~O; 77 | else if (lhs.name == 'F' && rhs.name == 'O') { 78 | // wires 79 | const int r = lhs.ports[0]; 80 | //r~O 81 | get<0>(equations) = Agent(r, 'r', 0); 82 | get<1>(equations) = rhs; 83 | 84 | thrust::get<8>(equations) = true; // we performed an interaction 85 | } 86 | // fib(r) >< S(x) => fib2(r)~x; 87 | else if (lhs.name == 'F' && rhs.name == 'S') { 88 | // wires 89 | const int r = lhs.ports[0]; 90 | const int x = rhs.ports[0]; 91 | Agent g(lhs.id, 'G', 1); 92 | g.ports[0] = r; 93 | // G(r)~x 94 | get<0>(equations) = Agent(x, 'x', 0); 95 | get<1>(equations) = g; 96 | 97 | thrust::get<8>(equations) = true; // we performed an interaction 98 | } 99 | // fib2(r) >< O => r~S(a), a~O; 100 | else if (lhs.name == 'G' && rhs.name == 'O') { 101 | int new_index = atomicAdd(&index_ptr[0], max_idx); 102 | // wires 103 | const int r = lhs.ports[0]; 104 | const int a = new_index; 105 | Agent s(lhs.id, 'S', 1); 106 | s.ports[0] = a; 107 | //r~S(a) 108 | get<0>(equations) = Agent(r, 'r',0); 109 | get<1>(equations) = s; 110 | //a~O 111 | get<2>(equations) = Agent(a, 'a',0); 112 | get<3>(equations) = rhs; 113 | 114 | 115 | thrust::get<8>(equations) = true; // we performed an interaction 116 | } 117 | // fib-(r) >< O => r~O; 118 | else if (lhs.name == 'H' && rhs.name == 'O') { 119 | // wires 120 | const int r = lhs.ports[0]; 121 | //r~O 122 | get<0>(equations) = Agent(r, 'r', 0); 123 | get<1>(equations) = rhs; 124 | 125 | thrust::get<8>(equations) = true; // we performed an interaction 126 | } 127 | // fib-(r) >< S(x) => fib(r)~x; 128 | else if (lhs.name == 'H' && rhs.name == 'S') { 129 | // wires 130 | const int r = lhs.ports[0]; 131 | const int x = rhs.ports[0]; 132 | Agent g(lhs.id, 'F', 1); 133 | g.ports[0] = r; 134 | // G(r)~x 135 | get<0>(equations) = Agent(x, 'x', 0); 136 | get<1>(equations) = g; 137 | 138 | thrust::get<8>(equations) = true; // we performed an interaction 139 | } 140 | // fib2(r) >< S(x) => add(r,a)~b, fib-(a)~d, fib(b)~e, D(d,e)~x 141 | else if (lhs.name == 'G' && rhs.name == 'S') { 142 | int new_index = atomicAdd(&index_ptr[0], max_idx); 143 | // wires 144 | const int r = lhs.ports[0]; 145 | const int x = rhs.ports[0]; 146 | const int a = new_index; 147 | const int b = new_index + 1; 148 | const int d = new_index + 2; 149 | const int e = new_index + 3; 150 | Agent add(lhs.id, 'A', 2); 151 | add.ports[0] = r; 152 | add.ports[1] = a; 153 | Agent fibmin(rhs.id, 'G', 1); 154 | fibmin.ports[0] = a; 155 | Agent fib(new_index + 4, 'F', 1); 156 | fib.ports[0] = b; 157 | Agent delta(new_index + 5, 'D', 2); 158 | delta.ports[0] = d; 159 | delta.ports[1] = e; 160 | 161 | // add(r,a)~b 162 | get<0>(equations) = Agent(b); 163 | get<1>(equations) = add; 164 | //fib-(a)~d 165 | get<2>(equations) = Agent(d); 166 | get<3>(equations) = fibmin; 167 | // fib(b), e 168 | get<4>(equations) = Agent(e); 169 | get<5>(equations) = fib; 170 | // D(d,e)~x 171 | get<6>(equations) = Agent(x); 172 | get<7>(equations) = delta; 173 | 174 | thrust::get<8>(equations) = true; // we performed an interaction 175 | } 176 | // O >< d(x,y) => O~x, O~y; 177 | else if (lhs.name == 'D' && rhs.name == 'O' ) { 178 | int new_index = atomicAdd(&index_ptr[0], max_idx); 179 | // eps~x 180 | thrust::get<1>(equations) = rhs; 181 | thrust::get<0>(equations) = Agent(lhs.ports[0], 'z', 0);//*(rhs.ports[0].get()); 182 | // eps~y goes to equations array A 183 | thrust::get<3>(equations) = Agent(new_index, 'O', 0); 184 | thrust::get<2>(equations) = Agent(lhs.ports[1], 'z', 0);//*(rhs.ports[1].get()); 185 | thrust::get<8>(equations) = true; // we performed an interaction 186 | } 187 | // S(z) >< d(x,y) => S(a)~x, S(b)~y, d(a,b)~z; 188 | else if (lhs.name == 'D' && rhs.name == 'S' ) { 189 | int new_index = atomicAdd(&index_ptr[0], max_idx); 190 | //wires 191 | const int x = lhs.ports[0]; 192 | const int y = lhs.ports[1]; 193 | const int z = rhs.ports[0]; 194 | const int a = new_index + 1; 195 | const int b = new_index + 2; 196 | rhs.ports[0] = a; 197 | Agent s(new_index, 'S', 1); 198 | s.ports[0] = b; 199 | lhs.ports[0] = a; 200 | lhs.ports[1] = b; 201 | // S(a)~x 202 | thrust::get<1>(equations) = rhs; 203 | thrust::get<0>(equations) = Agent(x, 'x', 0);//*(rhs.ports[0].get()); 204 | // S(b)~y 205 | thrust::get<3>(equations) = s; 206 | thrust::get<2>(equations) = Agent(y, 'y', 0);//*(rhs.ports[1].get()); 207 | // d(a,b)~ z 208 | get<4>(equations) = Agent(z, 'z', 0); 209 | get<5>(equations) = lhs; 210 | 211 | thrust::get<8>(equations) = true; // we performed an interaction 212 | } 213 | } 214 | } 215 | }; -------------------------------------------------------------------------------- /soa/ackermann.h: -------------------------------------------------------------------------------- 1 | // ackermann functor soa version 2 | 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "agent_functor.h" 12 | 13 | using namespace soa; 14 | using namespace thrust; 15 | 16 | namespace soa { 17 | //max new indices per interaction 18 | const int ackermann_max_idx = 6; 19 | 20 | struct ackermann_functor : public int_functor { 21 | 22 | int * index_ptr; 23 | __host__ __device__ 24 | ackermann_functor(int * ptr) : index_ptr(ptr) {} 25 | 26 | template 27 | __device__ 28 | void operator()(Tuple equations) 29 | { 30 | 31 | //get lhs and rhs of the equations 32 | agent lhs = thrust::get<0>(equations); 33 | agent rhs = thrust::get<1>(equations); 34 | 35 | // default: no interaction was performed 36 | thrust::get<8>(equations) = false; 37 | 38 | 39 | // if both sides are agents 40 | // rewrite the equations 41 | if (is_upper( get(lhs) ) && is_upper( get(lhs) )) { 42 | 43 | //sort pair lexicographically (active pairs are symmetric) 44 | if (get(rhs) < get(lhs) ) { 45 | lhs = rhs; 46 | rhs = thrust::get<0>(equations); 47 | } 48 | 49 | name_type lhs_name = get(lhs); 50 | name_type rhs_name = get(rhs); 51 | 52 | // P(r) = S(x) => r~x; 53 | if (lhs_name == 'P' && rhs_name == 'S') { 54 | // wires 55 | const int r = get(lhs); 56 | const int x = get(rhs); 57 | // r~x 58 | get<0>(equations) = make_agent(r, 'r', 0); 59 | get<1>(equations) = make_agent(x, 'x', 0); 60 | 61 | thrust::get<8>(equations) = true; // we performed an interaction 62 | } 63 | // A(r,n) >< O => r~S(n); 64 | else if (lhs_name == 'A' && rhs_name == 'O') { 65 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 66 | agent s = make_agent(new_index, 'S', 1); 67 | //wires 68 | const int r = get(lhs); 69 | const int n = get(lhs); 70 | get(s) = n; 71 | // r~S(n) 72 | get<0>(equations) = make_agent(r, 'r', 0); 73 | get<1>(equations) = s; 74 | 75 | get<8>(equations) = true; // we performed an interaction 76 | } 77 | // A(r,n) >< S(m) => B(r,x) = n, x = S(m) 78 | else if (lhs_name == 'A' && rhs_name == 'S') { 79 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 80 | agent b(get(lhs), 'B', 2); 81 | agent x = make_agent(new_index, 'x', 0); 82 | //wires 83 | const int r = get(lhs); 84 | const int n = get(lhs); 85 | //b.ports[0] = r; 86 | //b.ports[1] = x); 87 | 88 | // B(r,x) = n 89 | get<1>(equations) = make_agent(get(lhs), 'B', 2, r, get(x), 0 , 0); 90 | get<0>(equations) = agent(n, 'n', 0); 91 | // x = s(m) 92 | get<2>(equations) = x; 93 | get<3>(equations) = rhs; 94 | 95 | thrust::get<8>(equations) = true; // we performed an interaction 96 | } 97 | // B(r,m) >< O => A(r, x) = y, P(y) = m, x = S(z), z = O 98 | else if (lhs_name == 'B' && rhs_name == 'O') { 99 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 100 | agent x = make_agent(new_index, 'x', 0); 101 | agent y = make_agent(new_index + 1, 'y', 0); 102 | agent z = make_agent(new_index + 2, 'z', 0); 103 | agent p = make_agent(new_index + 3, 'P', 1); 104 | agent s = make_agent(new_index + 4, 'S', 1); 105 | agent a = make_agent(get(lhs), 'A', 2); 106 | //wires 107 | const int r = get(lhs); 108 | const int m = get(lhs); 109 | get(a) = r; 110 | get(a) = get(x); 111 | get(p) = get(y); 112 | get(s) = get(z); 113 | 114 | // y = A(r,x); 115 | get<0>(equations) = y; 116 | get<1>(equations) = a; 117 | // m = P(y) 118 | get<2>(equations) = make_agent(m, 'm', 0); 119 | get<3>(equations) = p; 120 | // x = S(z) 121 | get<4>(equations) = x; 122 | get<5>(equations) = s; 123 | // z = 0 124 | get<6>(equations) = z; 125 | get<7>(equations) = rhs; 126 | 127 | thrust::get<8>(equations) = true; // we performed an interaction 128 | } 129 | // B(r,m) >< S(n) => A(r,s)~x, P(x)~d, A(s,n)~e, D(d,e)~m; 130 | else if (lhs_name == 'B' && rhs_name == 'S') { 131 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 132 | agent p = make_agent(get(rhs), 'P', 1); 133 | agent a1 = make_agent(get(lhs), 'A', 2); 134 | agent x = make_agent(new_index, 'x', 0); 135 | agent s = make_agent(new_index + 1, 's', 0); 136 | agent d = make_agent(new_index + 2, 'd', 0); 137 | agent e = make_agent(new_index + 3, 'e', 0); 138 | agent a2 = make_agent(new_index + 4, 'A', 2); 139 | agent delta = make_agent(new_index + 5, 'D', 2); 140 | //wires 141 | const int r = get(lhs); 142 | const int m = get(lhs); 143 | const int n = get(rhs); 144 | get(a1) = r; 145 | get(a1) = get(s); 146 | get(p) = get(x); 147 | get(a2) = get(s); 148 | get(a2) = n; 149 | get(delta) = get(d); 150 | get(delta) = get(e); 151 | // A(r,s) ~ x 152 | get<1>(equations) = a1; 153 | get<0>(equations) = x; 154 | // P(x) ~ d 155 | get<3>(equations) = p; 156 | get<2>(equations) = d; 157 | // A(s,n) ~ e 158 | get<5>(equations) = a2; 159 | get<4>(equations) = e; 160 | // D(d,e) ~ m 161 | get<6>(equations) = make_agent(m, 'm', 0); 162 | get<7>(equations) = delta; 163 | 164 | thrust::get<8>(equations) = true; // we performed an interaction 165 | } 166 | // O >< d(x,y) => O~x, O~y; 167 | else if (lhs_name == 'D' && rhs_name == 'O' ) { 168 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 169 | // eps~x 170 | thrust::get<1>(equations) = rhs; 171 | thrust::get<0>(equations) = make_agent(get(lhs), 'z', 0);//*(get(rhs).get()); 172 | // eps~y goes to equations array A 173 | thrust::get<3>(equations) = make_agent(new_index, 'O', 0); 174 | thrust::get<2>(equations) = make_agent(get(lhs), 'z', 0);//*(get(rhs).get()); 175 | 176 | thrust::get<8>(equations) = true; // we performed an interaction 177 | } 178 | // S(z) >< d(x,y) => S(a)~x, S(b)~y, d(a,b)~z; 179 | else if (lhs_name == 'D' && rhs_name == 'S' ) { 180 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 181 | //wires 182 | const int x = get(lhs); 183 | const int y = get(lhs); 184 | const int z = get(rhs); 185 | const int a = new_index + 1; 186 | const int b = new_index + 2; 187 | get(rhs) = a; 188 | agent s = make_agent(new_index, 'S', 1); 189 | get(s) = b; 190 | get(lhs) = a; 191 | get(lhs) = b; 192 | // S(a)~x 193 | thrust::get<1>(equations) = rhs; 194 | thrust::get<0>(equations) = make_agent(x, 'x', 0);//*(get(rhs).get()); 195 | // S(b)~y 196 | thrust::get<3>(equations) = s; 197 | thrust::get<2>(equations) = make_agent(y, 'y', 0);//*(get(rhs).get()); 198 | // d(a,b)~ z 199 | get<4>(equations) = make_agent(z, 'z', 0); 200 | get<5>(equations) = lhs; 201 | 202 | thrust::get<8>(equations) = true; // we performed an interaction 203 | } 204 | } 205 | } 206 | }; 207 | 208 | } 209 | -------------------------------------------------------------------------------- /soa/communication.h: -------------------------------------------------------------------------------- 1 | /* 2 | communication.h 3 | does a communication step 4 | SOA version 5 | */ 6 | 7 | #pragma once 8 | 9 | //#pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "agent_functor.h" 22 | 23 | using namespace soa; 24 | 25 | namespace soa { 26 | 27 | // do two agents have the same top level variable (TLV) 28 | struct has_tlv_functor : public thrust::unary_function 29 | { 30 | int tlv_id; 31 | 32 | __host__ __device__ 33 | has_tlv_functor(const int _tlv_id) : tlv_id(_tlv_id) {} 34 | 35 | __host__ __device__ 36 | bool operator()(const equation& eq) const 37 | { 38 | //check if the lhs is a variable 39 | if ( is_variable( get(eq) ) ) { 40 | 41 | if (get(get(eq)) == tlv_id) { 42 | return true; 43 | } 44 | else { 45 | //check if the rhs is a variable 46 | //agent r = get(t); 47 | if (is_variable(get(eq))) { 48 | 49 | return (get(get(eq)) == tlv_id); //neither agent is a variable 50 | } 51 | } 52 | } 53 | return false; 54 | } 55 | }; 56 | 57 | // do two agents have the same top level variable (TLV) 58 | struct find_tlv_functor : public thrust::unary_function 59 | { 60 | int tlv_id; 61 | 62 | __host__ __device__ 63 | find_tlv_functor(const int _tlv_id) : tlv_id(tlv_id) {} 64 | 65 | __host__ __device__ 66 | bool operator()(const equation& eq) const 67 | { 68 | //check if the lhs is a variable 69 | if (!is_agent(get(eq))) { 70 | 71 | if (get( get(eq) ) == tlv_id) { 72 | return true; 73 | } 74 | else { 75 | //check if the rhs is a variable 76 | //agent r = get(t); 77 | if (!is_agent(get(eq))) { 78 | 79 | return (get( get(eq) ) == tlv_id); //neither agent is a variable 80 | } 81 | } 82 | } 83 | return false; 84 | } 85 | }; 86 | 87 | 88 | 89 | 90 | // does an equation have a TLV 91 | struct is_tlv_equation_functor 92 | { 93 | __host__ __device__ 94 | bool operator()(equation t) 95 | { 96 | //check if the lhs is a variable 97 | if (!is_agent(get(t))) { 98 | return true; 99 | } 100 | else { 101 | //check if the rhs is a variable 102 | return (!is_agent(get(t))); 103 | } 104 | } 105 | }; 106 | 107 | // does an equation have a TLV as its lhs? 108 | struct is_oriented_tlv_equation_functor 109 | { 110 | __host__ __device__ 111 | bool operator()(equation t) 112 | { 113 | //check if the lhs is a variable 114 | return is_variable(get(t)) && is_agent(get(t)); 115 | } 116 | }; 117 | 118 | // TODO dont check name, check ID ( == -1) 119 | // dummy equation test functor 120 | struct dummy_test_functor 121 | { 122 | __host__ __device__ 123 | bool operator()(const agent t) 124 | { 125 | return (get(t) == 'Z'); 126 | } 127 | }; 128 | 129 | struct dummy_test_functor_tuple 130 | { 131 | __host__ __device__ 132 | bool operator()(const thrust::tuple t) 133 | { 134 | agent l = thrust::get<0>(t); 135 | return (get(l) == 'Z'); 136 | } 137 | }; 138 | 139 | // do two equations have a common tlv? 140 | // assumes equations are oriented 141 | struct common_tlv_functor : public thrust::binary_function 142 | { 143 | __host__ __device__ 144 | bool operator()(const equation& t, const equation& s) 145 | { 146 | //TODO: we assume that no two non-variable agents have distinct ids 147 | // this may cause bugs when ids are assigned to non-variable agents more than once 148 | // (which should not happen) 149 | agent t_lhs = get(t); 150 | agent s_lhs = get(s); 151 | if (get(t_lhs) == get(s_lhs) ) 152 | return true; 153 | 154 | agent s_rhs = get(s); 155 | if (get(t_lhs) == get(s_rhs)) 156 | return true; 157 | 158 | agent t_rhs = get(t); 159 | if (get(t_rhs) == get(s_lhs)) 160 | return true; 161 | 162 | if (get(t_rhs) == get(s_rhs) ) 163 | return true; 164 | 165 | return false; 166 | } 167 | }; 168 | 169 | // performs a single communication 170 | // by resolving a common tlv 171 | struct comm_reduce_functor : public thrust::binary_function 172 | { 173 | __host__ __device__ 174 | equation operator()(const equation& t, const equation& s) 175 | { 176 | 177 | agent t_lhs = get(t); 178 | agent t_rhs = get(t); 179 | agent s_lhs = get(s); 180 | agent s_rhs = get(s); 181 | 182 | if (get(t_lhs) == get(s_lhs) ) { 183 | //orient if necessary 184 | if (!is_variable(t_rhs) && is_variable(s_rhs)) 185 | { 186 | thrust::swap(t_rhs, s_rhs); 187 | } 188 | return thrust::make_tuple(t_rhs, s_rhs); 189 | } 190 | 191 | if (get(t_lhs) == get(s_rhs)) { 192 | //orient if necessary 193 | if (!is_variable(t_rhs) && is_variable(s_lhs)) 194 | { 195 | thrust::swap(t_rhs, s_lhs); 196 | } 197 | return thrust::make_tuple(t_rhs, s_lhs); 198 | } 199 | 200 | if (get(t_rhs) == get(s_lhs)) { 201 | //orient if necessary 202 | if (!is_variable(t_lhs) && is_variable(s_rhs)) 203 | { 204 | thrust::swap(t_lhs, s_rhs); 205 | } 206 | return thrust::make_tuple(t_lhs, s_rhs); 207 | } 208 | 209 | if (get(t_rhs) == get(s_rhs)) { 210 | //orient if necessary 211 | if (!is_variable(t_lhs) && is_variable(s_lhs)) 212 | { 213 | thrust::swap(t_lhs, s_lhs); 214 | } 215 | return thrust::make_tuple(t_lhs, s_lhs); 216 | } 217 | 218 | // at this point, something has gone wrong 219 | // (no common tlv) 220 | // return an equation of dummy agents 221 | return thrust::make_tuple(agent(), agent()); 222 | } 223 | }; 224 | 225 | // parallel communication step using reduce_by_key 226 | int comm_step_parallel(equation_iter& start, equation_iter& end, 227 | equation_iter& result_start, equation_iter& result_end, 228 | device_vector::iterator& keys_start, device_vector::iterator& keys_end, 229 | const int input_size, const unsigned int communication_watch = 0) 230 | { 231 | int comm_counter = 1; 232 | 233 | //StopWatch::get(communication_watch).start(); 234 | 235 | thrust::device_vector keys_out(input_size); 236 | 237 | //TODO improve comm_reduce functor 238 | auto new_end = thrust::reduce_by_key(keys_start, keys_end, start, 239 | keys_out.begin(), result_start, thrust::equal_to(), comm_reduce_functor() 240 | ); 241 | 242 | //StopWatch::get(communication_watch).stop(); 243 | 244 | int diff = new_end.first - keys_out.begin(); 245 | diff = input_size - diff; 246 | //std::cout << diff << std::endl; 247 | if (diff == 0) { 248 | return 0; 249 | } 250 | result_end = new_end.second; 251 | //end = end - diff; 252 | 253 | return diff; 254 | } 255 | 256 | 257 | } -------------------------------------------------------------------------------- /soa/fibonacci.h: -------------------------------------------------------------------------------- 1 | // fibonacci functor 2 | 3 | 4 | //#pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "agent_functor.h" 12 | 13 | using namespace soa; 14 | using namespace thrust; 15 | 16 | //max new indices per interaction 17 | const int max_idx = 7; 18 | 19 | namespace soa { 20 | 21 | struct fibonacci_functor : public int_functor { 22 | 23 | int * index_ptr; 24 | __host__ __device__ 25 | fibonacci_functor(int * ptr) : index_ptr(ptr) {} 26 | 27 | template 28 | __device__ 29 | void operator()(Tuple equations) 30 | { 31 | 32 | //get lhs and rhs of the equations 33 | agent lhs = get<0>(equations); 34 | agent rhs = get<1>(equations); 35 | 36 | // default: no interaction was performed 37 | get<8>(equations) = false; 38 | 39 | 40 | // if both sides are agents 41 | // rewrite the equations 42 | if (is_upper( get(lhs) ) && is_upper( get(lhs) )) { 43 | 44 | //sort pair lexicographically (active pairs are symmetric) 45 | if (get(rhs) < get(lhs) ) { 46 | lhs = rhs; 47 | rhs = thrust::get<0>(equations); 48 | } 49 | 50 | name_type lhs_name = get(lhs); 51 | name_type rhs_name = get(rhs); 52 | 53 | // A(r, y) >< 0 => r~y 54 | if (lhs_name == 'A' && rhs_name == 'O') { 55 | 56 | //r~y 57 | thrust::get<0>(equations) = make_agent(get(lhs), 'r', 0); 58 | thrust::get<1>(equations) = make_agent(get(lhs), 'y', 0); 59 | 60 | thrust::get<8>(equations) = true; // we performed an interaction 61 | } 62 | // A(r, y) >< S(x) => r~S(w), A(w, y)~x 63 | else if (lhs_name == 'A' && rhs_name == 'S') { 64 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 65 | //wires 66 | int x = get(rhs); 67 | int r = get(lhs); 68 | int w = new_index; // new variable w 69 | 70 | // r~S(w) 71 | get(rhs) = w; 72 | thrust::get<0>(equations) = make_agent(r, 'r', 0); 73 | thrust::get<1>(equations) = rhs; 74 | // A(w, y)~x 75 | get(lhs) = w; 76 | thrust::get<2>(equations) = make_agent(x, 'x', 0); 77 | thrust::get<3>(equations) = lhs; 78 | 79 | thrust::get<8>(equations) = true; // we performed an interaction 80 | } 81 | // fib(r) >< O => r~O; 82 | else if (lhs_name == 'F' && rhs_name == 'O') { 83 | // wires 84 | const int r = get(lhs); 85 | //r~O 86 | get<0>(equations) = make_agent(r, 'r', 0); 87 | get<1>(equations) = rhs; 88 | 89 | thrust::get<8>(equations) = true; // we performed an interaction 90 | } 91 | // fib(r) >< S(x) => fib2(r)~x; 92 | else if (lhs_name == 'F' && rhs_name == 'S') { 93 | // wires 94 | const int r = get(lhs); 95 | const int x = get(rhs); 96 | agent g = make_agent(get(lhs), 'G', 1); 97 | get(g) = r; 98 | // G(r)~x 99 | get<0>(equations) = make_agent(x, 'x', 0); 100 | get<1>(equations) = g; 101 | 102 | thrust::get<8>(equations) = true; // we performed an interaction 103 | } 104 | // fib2(r) >< O => r~S(a), a~O; 105 | else if (lhs_name == 'G' && rhs_name == 'O') { 106 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 107 | // wires 108 | const int r = get(lhs); 109 | const int a = new_index; 110 | agent s(get(lhs), 'S', 1); 111 | get(s) = a; 112 | //r~S(a) 113 | get<0>(equations) = make_agent(r, 'r',0); 114 | get<1>(equations) = s; 115 | //a~O 116 | get<2>(equations) = make_agent(a, 'a',0); 117 | get<3>(equations) = rhs; 118 | 119 | 120 | thrust::get<8>(equations) = true; // we performed an interaction 121 | } 122 | // fib-(r) >< O => r~O; 123 | else if (lhs_name == 'H' && rhs_name == 'O') { 124 | // wires 125 | const int r = get(lhs); 126 | //r~O 127 | get<0>(equations) = make_agent(r, 'r', 0); 128 | get<1>(equations) = rhs; 129 | 130 | thrust::get<8>(equations) = true; // we performed an interaction 131 | } 132 | // fib-(r) >< S(x) => fib(r)~x; 133 | else if (lhs_name == 'H' && rhs_name == 'S') { 134 | // wires 135 | const int r = get(lhs); 136 | const int x = get(rhs); 137 | agent g(get(lhs), 'F', 1); 138 | get(g) = r; 139 | // G(r)~x 140 | get<0>(equations) = make_agent(x, 'x', 0); 141 | get<1>(equations) = g; 142 | 143 | thrust::get<8>(equations) = true; // we performed an interaction 144 | } 145 | // fib2(r) >< S(x) => add(r,a)~b, fib-(a)~d, fib(b)~e, D(d,e)~x 146 | else if (lhs_name == 'G' && rhs_name == 'S') { 147 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 148 | // wires 149 | const int r = get(lhs); 150 | const int x = get(rhs); 151 | const int a = new_index; 152 | const int b = new_index + 1; 153 | const int d = new_index + 2; 154 | const int e = new_index + 3; 155 | agent add(get(lhs), 'A', 2); 156 | get(add) = r; 157 | get(add) = a; 158 | agent fibmin = make_agent(get(rhs), 'G', 1); 159 | get(fibmin) = a; 160 | agent fib = make_agent(new_index + 4, 'F', 1); 161 | get(fib) = b; 162 | agent delta(new_index + 5, 'D', 2); 163 | get(delta) = d; 164 | get(delta) = e; 165 | 166 | // add(r,a)~b 167 | get<0>(equations) = make_agent(b); 168 | get<1>(equations) = add; 169 | //fib-(a)~d 170 | get<2>(equations) = make_agent(d); 171 | get<3>(equations) = fibmin; 172 | // fib(b), e 173 | get<4>(equations) = make_agent(e); 174 | get<5>(equations) = fib; 175 | // D(d,e)~x 176 | get<6>(equations) = make_agent(x); 177 | get<7>(equations) = delta; 178 | 179 | thrust::get<8>(equations) = true; // we performed an interaction 180 | } 181 | // O >< d(x,y) => O~x, O~y; 182 | else if (lhs_name == 'D' && rhs_name == 'O' ) { 183 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 184 | // eps~x 185 | thrust::get<1>(equations) = rhs; 186 | thrust::get<0>(equations) = make_agent(get(lhs), 'z', 0);//*(get(rhs).get()); 187 | // eps~y goes to equations array A 188 | thrust::get<3>(equations) = make_agent(new_index, 'O', 0); 189 | thrust::get<2>(equations) = make_agent(get(lhs), 'z', 0);//*(get(rhs).get()); 190 | thrust::get<8>(equations) = true; // we performed an interaction 191 | } 192 | // S(z) >< d(x,y) => S(a)~x, S(b)~y, d(a,b)~z; 193 | else if (lhs_name == 'D' && rhs_name == 'S' ) { 194 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 195 | //wires 196 | const int x = get(lhs); 197 | const int y = get(lhs); 198 | const int z = get(rhs); 199 | const int a = new_index + 1; 200 | const int b = new_index + 2; 201 | get(rhs) = a; 202 | agent s(new_index, 'S', 1); 203 | get(s) = b; 204 | get(lhs) = a; 205 | get(lhs) = b; 206 | // S(a)~x 207 | thrust::get<1>(equations) = rhs; 208 | thrust::get<0>(equations) = make_agent(x, 'x', 0);//*(get(rhs).get()); 209 | // S(b)~y 210 | thrust::get<3>(equations) = s; 211 | thrust::get<2>(equations) = make_agent(y, 'y', 0);//*(get(rhs).get()); 212 | // d(a,b)~ z 213 | get<4>(equations) = make_agent(z, 'z', 0); 214 | get<5>(equations) = lhs; 215 | 216 | thrust::get<8>(equations) = true; // we performed an interaction 217 | } 218 | } 219 | } 220 | }; 221 | 222 | } -------------------------------------------------------------------------------- /cantor_dust.h: -------------------------------------------------------------------------------- 1 | // cantor_dust functor 2 | // computes cantor fractal set on a real line 3 | // en.wikipedia.org/wiki/L-system 4 | // A -> ABA 5 | // B -> BBB 6 | 7 | //IMPORTANT 8 | // RHS equations must be oriented 9 | 10 | //#pragma once 11 | #ifndef CANTOR_DUST_H_ 12 | #define CANTOR_DUST_H_ 13 | 14 | #include "cuda_runtime.h" 15 | #include "device_launch_parameters.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | //#include "device_functions.h" 23 | 24 | #include "agent.cuh" 25 | 26 | using namespace ingpu; 27 | using namespace thrust; 28 | 29 | //max new indices per interaction 30 | const int cantor_dust_max_idx = 9; 31 | 32 | struct cantor_dust_functor : public int_functor { 33 | 34 | int * index_ptr; 35 | __host__ __device__ 36 | cantor_dust_functor(int * ptr) : index_ptr(ptr) {} 37 | 38 | 39 | template 40 | __device__ 41 | void operator()(Tuple equations) 42 | { 43 | 44 | //get lhs and rhs of the equations 45 | Agent lhs = thrust::get<0>(equations); 46 | Agent rhs = thrust::get<1>(equations); 47 | 48 | // default: no interaction was performed 49 | thrust::get<8>(equations) = false; 50 | 51 | 52 | // if both sides are agents 53 | // rewrite the equations 54 | //TODO replace is_upper by direct char comparison 55 | if (is_upper(lhs.name) && is_upper(rhs.name)) { 56 | 57 | //sort pair lexicographically (active pairs are symmetric) 58 | if (rhs.name < lhs.name ) { 59 | lhs = rhs; 60 | rhs = thrust::get<0>(equations); 61 | } 62 | 63 | // A(s) >< L(r,i) => M(r,s)~i; 64 | if (lhs.name == 'A' && rhs.name == 'L') { 65 | // wires 66 | const int s = lhs.ports[0]; 67 | const int r = rhs.ports[0]; 68 | const int i = rhs.ports[1]; 69 | // M(r,s)~i 70 | get<0>(equations) = Agent(i, 'i', 0); 71 | get<1>(equations) = Agent(rhs.id, 'M', 2, r, s); 72 | 73 | get<8>(equations) = true; // we performed an interaction 74 | } 75 | // B(s) >< L(r,i) => N(r,s)~i; 76 | else if (lhs.name == 'B' && rhs.name == 'L') { 77 | // wires 78 | const int s = lhs.ports[0]; 79 | const int r = rhs.ports[0]; 80 | const int i = rhs.ports[1]; 81 | // M(r,s)~i 82 | get<0>(equations) = Agent(i, 'i', 0); 83 | get<1>(equations) = Agent(lhs.id, 'N', 2, r, s); 84 | 85 | get<8>(equations) = true; // we performed an interaction 86 | } 87 | // M(r,s) >< O => r~A(s) 88 | else if (lhs.name == 'M' && rhs.name == 'O') { 89 | // wires 90 | const int r = lhs.ports[0]; 91 | const int s = lhs.ports[1]; 92 | // r~A(s) 93 | get<0>(equations) = Agent(r); 94 | get<1>(equations) = Agent(lhs.id, 'A', 1, s); 95 | 96 | get<8>(equations) = true; // we performed an interaction 97 | } 98 | // N(r,s) >< O => r~B(s) 99 | else if (lhs.name == 'N' && rhs.name == 'O') { 100 | // wires 101 | const int r = lhs.ports[0]; 102 | const int s = lhs.ports[1]; 103 | // r~A(s) 104 | get<0>(equations) = Agent(r); 105 | get<1>(equations) = Agent(lhs.id, 'B', 1, s); 106 | 107 | get<8>(equations) = true; // we performed an interaction 108 | } 109 | // M(r,s) >< S(i) => L(r,d)~A(y), L(y,e)~B(z), L(z,f)~A(s), D(d,e,f)~i 110 | else if (lhs.name == 'M' && rhs.name == 'S') { 111 | int new_index = atomicAdd(&index_ptr[0], 11); 112 | // wires 113 | const int r = lhs.ports[0]; 114 | const int s = lhs.ports[1]; 115 | const int i = rhs.ports[0]; 116 | const int d = new_index++; 117 | const int e = new_index++; 118 | const int f = new_index++; 119 | const int y = new_index++; 120 | const int z = new_index++; 121 | // L(r,d)~A(y) 122 | get<0>(equations) = Agent(new_index++, 'L', 2, r, d); 123 | get<1>(equations) = Agent(new_index++, 'A', 1, y); 124 | // L(y,e)~B(z) 125 | get<2>(equations) = Agent(new_index++, 'L', 2, y, e); 126 | get<3>(equations) = Agent(new_index++, 'B', 1, z); 127 | // L(z,f)~A(s) 128 | get<4>(equations) = Agent(new_index++, 'L', 2, z, f); 129 | get<5>(equations) = Agent(new_index++, 'A', 1, s); 130 | // D(d,e)~i 131 | get<6>(equations) = Agent(i); 132 | get<7>(equations) = Agent(new_index++, 'D', 3, d, e, f); 133 | 134 | get<8>(equations) = true; // we performed an interaction 135 | } 136 | // N(r,s) >< S(i) => L(r,d)~B(y), L(y,e)~B(z), L(z,f)~B(s), D(d,e,f)~i 137 | else if (lhs.name == 'N' && rhs.name == 'S') { 138 | int new_index = atomicAdd(&index_ptr[0], 11); 139 | // wires 140 | const int r = lhs.ports[0]; 141 | const int s = lhs.ports[1]; 142 | const int i = rhs.ports[0]; 143 | const int d = new_index++; 144 | const int e = new_index++; 145 | const int f = new_index++; 146 | const int y = new_index++; 147 | const int z = new_index++; 148 | // L(r,d)~A(y) 149 | get<0>(equations) = Agent(new_index++, 'L', 2, r, d); 150 | get<1>(equations) = Agent(new_index++, 'B', 1, y); 151 | // L(y,e)~B(z) 152 | get<2>(equations) = Agent(new_index++, 'L', 2, y, e); 153 | get<3>(equations) = Agent(new_index++, 'B', 1, z); 154 | // L(z,f)~A(s) 155 | get<4>(equations) = Agent(new_index++, 'L', 2, z, f); 156 | get<5>(equations) = Agent(new_index++, 'B', 1, s); 157 | // D(d,e)~i 158 | get<6>(equations) = Agent(i); 159 | get<7>(equations) = Agent(new_index++, 'D', 3, d, e, f); 160 | 161 | get<8>(equations) = true; // we performed an interaction 162 | } 163 | // O >< D(x,y,z) => O~x, O~y, O~z; 164 | else if (lhs.name == 'D' && rhs.name == 'O' ) { 165 | int new_index = atomicAdd(&index_ptr[0], 2); 166 | // O~x 167 | thrust::get<1>(equations) = rhs; 168 | thrust::get<0>(equations) = Agent(lhs.ports[0], 'v', 0);//*(rhs.ports[0].get()); 169 | // O~y 170 | thrust::get<3>(equations) = Agent(new_index++, 'O', 0); 171 | thrust::get<2>(equations) = Agent(lhs.ports[1], 'v', 0);//*(rhs.ports[1].get()); 172 | // O~z 173 | thrust::get<5>(equations) = Agent(new_index, 'O', 0); 174 | thrust::get<4>(equations) = Agent(lhs.ports[2], 'v', 0);//*(rhs.ports[0].get()); 175 | 176 | thrust::get<8>(equations) = true; // we performed an interaction 177 | } 178 | // S(n) >< D(x,y,z) => S(a)~x, S(b)~y, S(c), D(a,b,c)~n; 179 | else if (lhs.name == 'D' && rhs.name == 'S' ) { 180 | int new_index = atomicAdd(&index_ptr[0], 5); 181 | //wires 182 | const int x = lhs.ports[0]; 183 | const int y = lhs.ports[1]; 184 | const int z = lhs.ports[2]; 185 | const int n = rhs.ports[0]; 186 | const int a = new_index++; 187 | const int b = new_index++; 188 | const int c = new_index++; 189 | rhs.ports[0] = a; 190 | Agent s(new_index++, 'S', 1); 191 | s.ports[0] = b; 192 | lhs.ports[0] = a; 193 | lhs.ports[1] = b; 194 | lhs.ports[2] = c; 195 | // S(a)~x 196 | thrust::get<1>(equations) = rhs; 197 | thrust::get<0>(equations) = Agent(x, 'x', 0);//*(rhs.ports[0].get()); 198 | // S(b)~y 199 | thrust::get<3>(equations) = s; 200 | thrust::get<2>(equations) = Agent(y, 'y', 0);//*(rhs.ports[1].get()); 201 | // S(c)~z 202 | thrust::get<5>(equations) = Agent(new_index++, 'S', 1, c); 203 | thrust::get<4>(equations) = Agent(z, 'z', 0);//*(rhs.ports[1].get()); 204 | // D(a,b,c)~ n 205 | get<6>(equations) = Agent(n, 'v', 0); 206 | get<7>(equations) = lhs; 207 | 208 | thrust::get<8>(equations) = true; // we performed an interaction 209 | } 210 | } 211 | } 212 | }; 213 | 214 | #endif -------------------------------------------------------------------------------- /ackermann.h: -------------------------------------------------------------------------------- 1 | // ackermann functor 2 | 3 | 4 | //#pragma once 5 | #ifndef ACKERMANN_H_ 6 | #define ACKERMANN_H_ 7 | 8 | #include "cuda_runtime.h" 9 | #include "device_launch_parameters.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | //#include "device_functions.h" 17 | 18 | #include "agent.cuh" 19 | 20 | using namespace ingpu; 21 | using namespace thrust; 22 | 23 | //max new indices per interaction 24 | const int ackermann_max_idx = 6; 25 | 26 | struct ackermann_functor : public int_functor { 27 | 28 | int * index_ptr; 29 | __host__ __device__ 30 | ackermann_functor(int * ptr) : index_ptr(ptr) {} 31 | 32 | 33 | template 34 | __device__ 35 | void operator()(Tuple equations) 36 | { 37 | 38 | //get lhs and rhs of the equations 39 | Agent lhs = thrust::get<0>(equations); 40 | Agent rhs = thrust::get<1>(equations); 41 | 42 | // default: no interaction was performed 43 | thrust::get<8>(equations) = false; 44 | 45 | 46 | // if both sides are agents 47 | // rewrite the equations 48 | if (is_upper(lhs.name) && is_upper(rhs.name)) { 49 | 50 | //sort pair lexicographically (active pairs are symmetric) 51 | if (rhs.name < lhs.name ) { 52 | lhs = rhs; 53 | rhs = thrust::get<0>(equations); 54 | } 55 | 56 | // P(r) = S(x) => r~x; 57 | if (lhs.name == 'P' && rhs.name == 'S') { 58 | // wires 59 | const int r = lhs.ports[0]; 60 | const int x = rhs.ports[0]; 61 | // r~x 62 | thrust::get<0>(equations) = Agent(r, 'r', 0); 63 | thrust::get<1>(equations) = Agent(x, 'x', 0); 64 | 65 | thrust::get<8>(equations) = true; // we performed an interaction 66 | } 67 | // A(r,n) >< O => r~S(n); 68 | else if (lhs.name == 'A' && rhs.name == 'O') { 69 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 70 | Agent s(new_index, 'S', 1); 71 | //wires 72 | const int r = lhs.ports[0]; 73 | const int n = lhs.ports[1]; 74 | s.ports[0] = n; 75 | // r~S(n) 76 | thrust::get<0>(equations) = Agent(r, 'r', 0); 77 | thrust::get<1>(equations) = s; 78 | 79 | thrust::get<8>(equations) = true; // we performed an interaction 80 | } 81 | // A(r,n) >< S(m) => B(r,x) = n, x = S(m) 82 | else if (lhs.name == 'A' && rhs.name == 'S') { 83 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 84 | Agent b(lhs.id, 'B', 2); 85 | Agent x(new_index, 'x', 0); 86 | //wires 87 | const int r = lhs.ports[0]; 88 | const int n = lhs.ports[1]; 89 | b.ports[0] = r; 90 | b.ports[1] = x.id; 91 | 92 | // B(r,x) = n 93 | get<1>(equations) = b; 94 | get<0>(equations) = Agent(n, 'n', 0); 95 | // x = s(m) 96 | get<2>(equations) = x; 97 | get<3>(equations) = rhs; 98 | 99 | thrust::get<8>(equations) = true; // we performed an interaction 100 | } 101 | // B(r,m) >< O => A(r, x) = y, P(y) = m, x = S(z), z = O 102 | else if (lhs.name == 'B' && rhs.name == 'O') { 103 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 104 | Agent x(new_index, 'x', 0); 105 | Agent y(new_index + 1, 'y', 0); 106 | Agent z(new_index + 2, 'z', 0); 107 | Agent p(new_index + 3, 'P', 1); 108 | Agent s(new_index + 4, 'S', 1); 109 | Agent a(lhs.id, 'A', 2); 110 | //wires 111 | const int r = lhs.ports[0]; 112 | const int m = lhs.ports[1]; 113 | a.ports[0] = r; 114 | a.ports[1] = x.id; 115 | p.ports[0] = y.id; 116 | s.ports[0] = z.id; 117 | 118 | // y = A(r,x); 119 | get<0>(equations) = y; 120 | get<1>(equations) = a; 121 | // m = P(y) 122 | get<2>(equations) = Agent(m, 'm', 0); 123 | get<3>(equations) = p; 124 | // x = S(z) 125 | get<4>(equations) = x; 126 | get<5>(equations) = s; 127 | // z = 0 128 | get<6>(equations) = z; 129 | get<7>(equations) = rhs; 130 | 131 | thrust::get<8>(equations) = true; // we performed an interaction 132 | } 133 | // B(r,m) >< S(n) => A(r,s)~x, P(x)~d, A(s,n)~e, D(d,e)~m; 134 | else if (lhs.name == 'B' && rhs.name == 'S') { 135 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 136 | Agent p(rhs.id, 'P', 1); 137 | Agent a1(lhs.id, 'A', 2); 138 | Agent x(new_index, 'x', 0); 139 | Agent s(new_index + 1, 's', 0); 140 | Agent d(new_index + 2, 'd', 0); 141 | Agent e(new_index + 3, 'e', 0); 142 | Agent a2(new_index + 4, 'A', 2); 143 | Agent delta(new_index + 5, 'D', 2); 144 | //wires 145 | const int r = lhs.ports[0]; 146 | const int m = lhs.ports[1]; 147 | const int n = rhs.ports[0]; 148 | a1.ports[0] = r; 149 | a1.ports[1] = s.id; 150 | p.ports[0] = x.id; 151 | a2.ports[0] = s.id; 152 | a2.ports[1] = n; 153 | delta.ports[0] = d.id; 154 | delta.ports[1] = e.id; 155 | // A(r,s) ~ x 156 | get<1>(equations) = a1; 157 | get<0>(equations) = x; 158 | // P(x) ~ d 159 | get<3>(equations) = p; 160 | get<2>(equations) = d; 161 | // A(s,n) ~ e 162 | get<5>(equations) = a2; 163 | get<4>(equations) = e; 164 | // D(d,e) ~ m 165 | get<6>(equations) = Agent(m, 'm', 0); 166 | get<7>(equations) = delta; 167 | 168 | 169 | thrust::get<8>(equations) = true; // we performed an interaction 170 | } 171 | // O >< d(x,y) => O~x, O~y; 172 | else if (lhs.name == 'D' && rhs.name == 'O' ) { 173 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 174 | // eps~x 175 | thrust::get<1>(equations) = rhs; 176 | thrust::get<0>(equations) = Agent(lhs.ports[0], 'z', 0);//*(rhs.ports[0].get()); 177 | // eps~y goes to equations array A 178 | thrust::get<3>(equations) = Agent(new_index, 'O', 0); 179 | thrust::get<2>(equations) = Agent(lhs.ports[1], 'z', 0);//*(rhs.ports[1].get()); 180 | 181 | thrust::get<8>(equations) = true; // we performed an interaction 182 | } 183 | // S(z) >< d(x,y) => S(a)~x, S(b)~y, d(a,b)~z; 184 | else if (lhs.name == 'D' && rhs.name == 'S' ) { 185 | int new_index = atomicAdd(&index_ptr[0], ackermann_max_idx); 186 | //wires 187 | const int x = lhs.ports[0]; 188 | const int y = lhs.ports[1]; 189 | const int z = rhs.ports[0]; 190 | const int a = new_index + 1; 191 | const int b = new_index + 2; 192 | rhs.ports[0] = a; 193 | Agent s(new_index, 'S', 1); 194 | s.ports[0] = b; 195 | lhs.ports[0] = a; 196 | lhs.ports[1] = b; 197 | // S(a)~x 198 | thrust::get<1>(equations) = rhs; 199 | thrust::get<0>(equations) = Agent(x, 'x', 0);//*(rhs.ports[0].get()); 200 | // S(b)~y 201 | thrust::get<3>(equations) = s; 202 | thrust::get<2>(equations) = Agent(y, 'y', 0);//*(rhs.ports[1].get()); 203 | // d(a,b)~ z 204 | get<4>(equations) = Agent(z, 'z', 0); 205 | get<5>(equations) = lhs; 206 | 207 | thrust::get<8>(equations) = true; // we performed an interaction 208 | } 209 | } 210 | } 211 | }; 212 | 213 | void build_ack_input(thrust::host_vector& in_lhs, thrust::host_vector& in_rhs) 214 | { 215 | in_lhs[0] = Agent(1, 'S', 1); 216 | in_rhs[0] = Agent(2, 'x', 0); 217 | 218 | in_lhs[1] = Agent(3, 'A', 2); 219 | in_lhs[1].ports[0] = 0; 220 | in_rhs[1] = Agent(4, 'S', 1); 221 | in_lhs[1].ports[1] = in_rhs[0].id; 222 | 223 | in_lhs[2] = Agent(5, 'O', 0); 224 | in_rhs[2] = Agent(6, 'y', 0); 225 | in_rhs[1].ports[0] = in_rhs[2].id; 226 | 227 | in_lhs[3] = Agent(7, 'O', 0); 228 | in_rhs[3] = Agent(8, 'y', 0); 229 | in_lhs[0].ports[0] = in_rhs[3].id; 230 | } 231 | 232 | #endif -------------------------------------------------------------------------------- /soa/agent_functor.h: -------------------------------------------------------------------------------- 1 | /* 2 | agent.h 3 | an agent struct and some functions 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "agent.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace soa; 16 | using namespace thrust; 17 | 18 | namespace soa { 19 | 20 | // our input for IN evaluation 21 | typedef thrust::tuple input_tuple; 22 | typedef thrust::unary_function int_functor; 23 | 24 | //typedefs for soa input 25 | typedef device_vector::iterator id_iter; 26 | typedef device_vector::iterator name_iter; 27 | typedef device_vector::iterator arity_iter; 28 | typedef device_vector::iterator port_iter; 29 | //tuple of these iterators 30 | typedef tuple agent_iter_tuple; 31 | typedef zip_iterator agent_iter; 32 | typedef zip_iterator< tuple > equation_iter; 33 | 34 | 35 | __host__ __device__ 36 | agent dummy() 37 | { 38 | return thrust::make_tuple(0, 'Z', 0, 0, 0, 0, 0); 39 | } 40 | 41 | 42 | __host__ __device__ 43 | agent make_agent(const id_type id, const name_type name, const arity_type arity) 44 | { 45 | return thrust::make_tuple(id, name, arity, 0, 0, 0, 0); 46 | } 47 | 48 | __host__ __device__ 49 | agent make_agent( const name_type name) 50 | { 51 | return thrust::make_tuple(0, name, 0, 0, 0, 0, 0); 52 | } 53 | 54 | __host__ __device__ 55 | agent make_agent( const id_type id) 56 | { 57 | return thrust::make_tuple(id, 'v', 0, 0, 0, 0, 0); 58 | } 59 | 60 | __host__ __device__ 61 | agent make_agent(const id_type id, const name_type name, const arity_type arity, const port_type p1, const port_type p2 = 0, const port_type p3 = 0, const port_type p4 = 0) 62 | { 63 | return thrust::make_tuple(id, name, arity, p1, p2, p3, p4); 64 | } 65 | 66 | __host__ __device__ 67 | bool is_upper(const name_type c) 68 | { 69 | return (c >= 'A' && c <= 'Z'); 70 | } 71 | 72 | __host__ __device__ 73 | bool is_lower(const name_type c) 74 | { 75 | return (c >= 'a' && c <= 'z'); 76 | } 77 | 78 | __host__ __device__ 79 | bool is_variable( const agent a) 80 | { 81 | return is_lower(get(a)); 82 | } 83 | 84 | __host__ __device__ 85 | bool is_agent( const agent a) 86 | { 87 | return is_upper(get(a)); 88 | } 89 | 90 | __host__ __device__ 91 | bool is_dummy( const agent a) 92 | { 93 | return (get(a) == -1); 94 | } 95 | 96 | struct is_dummy_functor 97 | { 98 | __host__ __device__ 99 | bool operator() (const agent a) 100 | { 101 | return (get(a) == -1); 102 | } 103 | }; 104 | 105 | struct is_dummy_equation_functor 106 | { 107 | __host__ __device__ 108 | bool operator() (const equation& e) 109 | { 110 | return (get(get<1>(e)) < 1) || (get(get<0>(e)) < 1); 111 | } 112 | }; 113 | 114 | struct is_proper_equation_functor 115 | { 116 | __host__ __device__ 117 | bool operator() (const equation& e) 118 | { 119 | return (get(get<1>(e)) > 0) && (get(get<0>(e)) > 0) ; 120 | } 121 | }; 122 | 123 | struct has_name : public thrust::unary_function 124 | { 125 | char name; 126 | 127 | __host__ __device__ 128 | has_name(const char c) : name(c) {} 129 | 130 | __host__ __device__ 131 | bool operator()(const agent& agent) { 132 | return name == get(agent); 133 | } 134 | }; 135 | 136 | struct has_name_tuple : public thrust::unary_function 137 | { 138 | char name; 139 | 140 | __host__ __device__ 141 | has_name_tuple(const char c) : name(c) {} 142 | 143 | __host__ __device__ 144 | bool operator()(const equation& e) { 145 | return name == get(get<1>(e)); 146 | } 147 | }; 148 | 149 | struct is_invalid_tuple : public thrust::unary_function 150 | { 151 | __host__ __device__ 152 | bool operator()(const equation& e) { 153 | return (0 == get(get<1>(e))) || (0 == get(get<0>(e))); 154 | } 155 | //__host__ __device__ 156 | //bool operator()(const equation& e) { 157 | // return ((-1) > get(get<1>(e))) || ((-1) > get(get<0>(e))); 158 | //} 159 | }; 160 | 161 | // greater comparison function 162 | // oriented communication equations are smaller than everything 163 | // else, compare lexicographically 164 | struct comm_equation_greater : public thrust::binary_function 165 | { 166 | 167 | __host__ __device__ 168 | bool operator()(const equation& first, const equation& second) 169 | { 170 | //Agent lhs_first = get(first); 171 | //Agent rhs_first = get(first); 172 | // 173 | //Agent lhs_second = get(second); 174 | //Agent rhs_second = get(second); 175 | 176 | // if both LHSes are variables, compare the RHSes 177 | // agents (upper case) precede variables (lower case) 178 | if ( is_variable(get(first) ) && is_variable(get(second)) ) { 179 | return (get(get(first)) < get(get(second)) ); 180 | } 181 | 182 | //default: compare lhs names lexicographically 183 | return ( get(get(first)) > get(get(second))); 184 | } 185 | }; 186 | 187 | 188 | //checks equations for top-level variables 189 | //returns 1 if lhs is a variable 190 | // 2 if rhs is 191 | // 3 for both 192 | // 0 else 193 | __host__ __device__ 194 | int top_level_variables(const equation& e) 195 | { 196 | int result = 0; 197 | if (is_variable(get(e))) 198 | result++; 199 | if (is_variable(get(e))) 200 | result += 2; 201 | 202 | return result; 203 | } 204 | 205 | // checks for tlv, boolean version 206 | __host__ __device__ 207 | bool has_toplevel_variable(const equation& e) 208 | { 209 | if (is_variable(get(e))) 210 | return true; 211 | else 212 | return is_variable(get(e)); 213 | } 214 | 215 | //orient equations t=x -> x=t 216 | struct orient_functor 217 | { 218 | template 219 | __host__ __device__ 220 | void operator()(Equ eq) 221 | { 222 | if (!is_variable(get(eq)) && is_variable(get(eq))) 223 | { 224 | thrust::swap(get(eq), get(eq)); 225 | } 226 | } 227 | }; 228 | 229 | //orient equations t=x -> x=t 230 | struct orient_functor_transform : public thrust::unary_function 231 | { 232 | __host__ __device__ 233 | equation operator()(const equation eq) 234 | { 235 | equation result(eq); 236 | if (!is_variable(get(eq)) && is_variable(get(eq))) 237 | { 238 | thrust::swap(get(result), get(result)); 239 | } 240 | 241 | return result; 242 | } 243 | }; 244 | 245 | 246 | void print_equations(const thrust::host_vector equations) 247 | { 248 | for( unsigned int i = 0; i < equations.size(); i++) { 249 | print_equation(get(equations[i]), get(equations[i])); 250 | } 251 | std::cout << std::endl; 252 | } 253 | 254 | void print_equations(const thrust::host_vector& lhses, const thrust::host_vector& rhses) 255 | { 256 | for( unsigned int i = 0; i < lhses.size(); i++) { 257 | print_equation(lhses[i], rhses[i]); 258 | } 259 | std::cout << std::endl; 260 | } 261 | 262 | 263 | } 264 | -------------------------------------------------------------------------------- /parse_net.cpp: -------------------------------------------------------------------------------- 1 | #include "parse_net.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace qi = boost::spirit::qi; 14 | namespace ascii = boost::spirit::ascii; 15 | 16 | 17 | using namespace ingpu; 18 | 19 | bool parse_net::parse_single(const std::string& filepath, std::vector& raws) 20 | { 21 | using qi::phrase_parse; 22 | using qi::_1; 23 | using ascii::space; 24 | using ascii::alpha; 25 | using ascii::alnum; 26 | 27 | std::ifstream fp_in; 28 | fp_in.open(filepath, std::ios::in); 29 | if (!fp_in.is_open()) { 30 | std::cout << "error opening file " << filepath << std::endl; 31 | return false; 32 | } 33 | 34 | std::string str; 35 | bool result = false; 36 | while ( getline(fp_in, str) ) 37 | { 38 | if (str.empty()) 39 | continue; 40 | // ignore commented line 41 | if (str[0] == '/' || str[1] == '/') 42 | continue; 43 | 44 | //raw_agent parsing 45 | // ---------------- 46 | //std::vector ra; 47 | parse_net::raw_agent_parser p; 48 | result = phrase_parse(str.begin(), str.end(), 49 | ( 50 | (p >> '=' >> p) % ',' 51 | ) 52 | , space, raws); 53 | if (result) { 54 | std::cout << "----------------------------\nparsed string: " << str << std::endl; 55 | break; 56 | } 57 | } 58 | 59 | return result; 60 | } 61 | 62 | 63 | bool parse_net::parse_all(const std::string& filepath, vector>& raws_vector) 64 | { 65 | using qi::phrase_parse; 66 | using qi::_1; 67 | using ascii::space; 68 | using ascii::alpha; 69 | using ascii::alnum; 70 | 71 | std::ifstream fp_in; 72 | fp_in.open(filepath, std::ios::in); 73 | if (!fp_in.is_open()) { 74 | std::cout << "error opening file " << filepath << std::endl; 75 | return false; 76 | } 77 | 78 | std::string str; 79 | bool result = false; 80 | while ( getline(fp_in, str) ) 81 | { 82 | if (str.empty()) 83 | continue; 84 | // ignore commented line 85 | if (str[0] == '/' || str[1] == '/') 86 | continue; 87 | 88 | //raw_agent parsing 89 | // ---------------- 90 | std::vector raws; 91 | parse_net::raw_agent_parser p; 92 | result = phrase_parse(str.begin(), str.end(), 93 | ( 94 | (p >> '=' >> p) % ',' 95 | ) 96 | , space, raws); 97 | if (result) { 98 | raws_vector.push_back(raws); 99 | std::cout << "----------------------------\nparsed string: " << str << std::endl; 100 | } 101 | } 102 | 103 | return result; 104 | } 105 | 106 | std::string parse_net::raw_agent::to_string() 107 | { 108 | std::string result = ""; 109 | result += this->symbol; 110 | if (this->ports.size() > 0) 111 | { 112 | result += '('; 113 | BOOST_FOREACH(variable_symbol port, this->ports) 114 | { 115 | result += port; 116 | result += " "; 117 | } 118 | result += ')'; 119 | } 120 | 121 | return result; 122 | } 123 | 124 | void parse_net::build_agents(const std::vector& raws, std::vector& agents) 125 | { 126 | typedef parse_net::raw_agent raw; 127 | typedef std::unordered_map id_map; 128 | id_map map; 129 | 130 | int id_counter=1; 131 | BOOST_FOREACH(raw ragent, raws) 132 | { 133 | int raw_port_size = ragent.ports.size(); 134 | if (raw_port_size > MAX_PORTS) { 135 | std::cerr << "error: agent " << ragent.symbol << "has too many ports, using only the first " << MAX_PORTS << " ports\n"; 136 | } 137 | Agent a(0, ragent.symbol.at(0), std::min(raw_port_size, MAX_PORTS)); 138 | id_map::iterator it = map.find(ragent.symbol); 139 | // if symbol has not occured before or is upper case 140 | if ( ( it == map.end() ) || (a.name >= 'A' && a.name <= 'Z') ) 141 | { 142 | //assign a new id and add it to the map 143 | a.id = id_counter; 144 | if ( it == map.end() ) { 145 | // only new variables get added to the map 146 | map[ragent.symbol] = id_counter; 147 | } 148 | id_counter++; 149 | } 150 | else { 151 | a.id = it->second; 152 | } 153 | // assing ids to the ports the same way 154 | for (int i=0; i < a.arity; ++i) { 155 | std::string current_symbol = ragent.ports[i]; 156 | id_map::iterator it = map.find( current_symbol ); 157 | // if symbol has not occured before or is upper case 158 | if ( ( it == map.end() ) || ( current_symbol.at(0) >= 'A' && current_symbol.at(0) <= 'Z') ) 159 | { 160 | //assign a new id and add it to the map 161 | a.ports[i] = id_counter; 162 | if ( it == map.end() ) { 163 | // only new variables get added to the map 164 | map[ current_symbol ] = id_counter; 165 | } 166 | id_counter++; 167 | } 168 | else { 169 | a.ports[i] = it->second; 170 | } 171 | } 172 | 173 | //we are done building, add the agent to the output vector 174 | agents.push_back(a); 175 | } 176 | 177 | 178 | } 179 | 180 | //build a set of soa agents from parsed raw agents 181 | void parse_net::build_agents(const std::vector& raws, 182 | std::vector& ids, 183 | std::vector& names, 184 | std::vector& arities, 185 | std::vector& p1s, 186 | std::vector& p2s, 187 | std::vector& p3s, 188 | std::vector& p4s) 189 | { 190 | 191 | typedef parse_net::raw_agent raw; 192 | typedef std::unordered_map id_map; 193 | id_map map; 194 | 195 | int id_counter=1; 196 | BOOST_FOREACH(raw ragent, raws) 197 | { 198 | int raw_port_size = ragent.ports.size(); 199 | if (raw_port_size > MAX_PORTS) { 200 | std::cerr << "error: agent " << ragent.symbol << "has too many ports, using only the first " << MAX_PORTS << " ports\n"; 201 | } 202 | //soa::agent a = soa::make_agent(0, ragent.symbol, std::min(raw_port_size, MAX_PORTS)); 203 | soa::id_type id = 0; 204 | soa::name_type name = ragent.symbol.at(0); 205 | soa::arity_type arity = std::min(raw_port_size, MAX_PORTS); 206 | id_map::iterator it = map.find(ragent.symbol); 207 | // if symbol has not occured before or is upper case 208 | if ( ( it == map.end() ) || (name >= 'A' && name <= 'Z') ) 209 | { 210 | //assign a new id and add it to the map 211 | id = id_counter; 212 | if ( it == map.end() ) { 213 | // only new variables get added to the map 214 | map[ragent.symbol] = id_counter; 215 | } 216 | id_counter++; 217 | } 218 | else { 219 | id = it->second; 220 | } 221 | // assing ids to the ports the same way 222 | int final_ports[MAX_PORTS]; 223 | for (int i=0; i < arity; ++i) { 224 | std::string current_symbol = ragent.ports[i]; 225 | id_map::iterator it = map.find( current_symbol ); 226 | // if symbol has not occured before or is upper case 227 | if ( ( it == map.end() ) || ( current_symbol.at(0) >= 'A' && current_symbol.at(0) <= 'Z') ) 228 | { 229 | //assign a new id and add it to the map 230 | final_ports[i] = id_counter; 231 | if ( it == map.end() ) { 232 | // only new variables get added to the map 233 | map[ current_symbol ] = id_counter; 234 | } 235 | id_counter++; 236 | } 237 | else { 238 | final_ports[i] = it->second; 239 | } 240 | } 241 | 242 | //we are done building, add the agent to the output vector 243 | ids.push_back(id); 244 | names.push_back(name); 245 | arities.push_back(arity); 246 | p1s.push_back(final_ports[0]); 247 | p2s.push_back(final_ports[1]); 248 | p3s.push_back(final_ports[2]); 249 | p4s.push_back(final_ports[3]); 250 | } 251 | } -------------------------------------------------------------------------------- /agent.cuh: -------------------------------------------------------------------------------- 1 | /* 2 | agent.h 3 | an agent struct and some functions 4 | */ 5 | 6 | //#pragma once 7 | #ifndef AGENT_H_ 8 | #define AGENT_H_ 9 | 10 | //#include 11 | #include 12 | #include 13 | #include 14 | #include "agent_struct.h" 15 | 16 | using namespace thrust; 17 | 18 | namespace ingpu { 19 | 20 | // equation is a tuple of 2 agents 21 | typedef thrust::tuple equation; 22 | // our input for IN evaluation 23 | typedef thrust::tuple input_tuple; 24 | typedef thrust::unary_function int_functor; 25 | 26 | // iterator types 27 | typedef thrust::device_vector::iterator agent_iter; 28 | typedef thrust::tuple agent_iter_tuple; 29 | typedef thrust::zip_iterator equation_iter; 30 | 31 | 32 | __host__ __device__ 33 | Agent get_lhs(equation eq) 34 | { 35 | return thrust::get<0>(eq); 36 | } 37 | 38 | __host__ __device__ 39 | Agent get_rhs(equation eq) 40 | { 41 | return thrust::get<1>(eq); 42 | } 43 | 44 | 45 | // device version of isupper(char) 46 | __host__ __device__ 47 | bool is_upper(const char c) 48 | { 49 | return (c >= 'A' && c <= 'Z'); 50 | } 51 | 52 | __host__ __device__ 53 | bool is_lower(const char c) 54 | { 55 | return (c >= 'a' && c <= 'z'); 56 | } 57 | 58 | //agent is not a variable 59 | __host__ __device__ 60 | bool is_agent(const Agent a) 61 | { 62 | return is_upper(a.name); 63 | } 64 | 65 | //agent is a variable 66 | __host__ __device__ 67 | bool is_variable(const Agent a) 68 | { 69 | return is_lower(a.name); 70 | } 71 | 72 | struct has_name : public thrust::unary_function 73 | { 74 | char name; 75 | 76 | __host__ __device__ 77 | has_name(const char c) : name(c) {} 78 | 79 | __host__ __device__ 80 | bool operator()(const Agent& agent) { 81 | return name == agent.name; 82 | } 83 | }; 84 | 85 | //debug - look for specific symbols 86 | struct has_name_special : public thrust::unary_function 87 | { 88 | 89 | __host__ __device__ 90 | bool operator()(const Agent& agent) { 91 | //return 'S' == agent.name || 'N' == agent.name || 'M' == agent.name; 92 | return 'A' != agent.name && 'B' != agent.name; 93 | } 94 | }; 95 | 96 | // greater comparison function 97 | // oriented communication equations are smaller than everything 98 | // else, compare lexicographically 99 | struct comm_equation_greater : public thrust::binary_function 100 | { 101 | 102 | __host__ __device__ 103 | bool operator()(const equation& first, const equation& second) 104 | { 105 | // if both LHSes are variables, compare the RHSes 106 | // agents (upper case) precede variables (lower case) 107 | char c = get<0>(first).name; 108 | char d = get<0>(second).name; 109 | if ( (c >= 'a' && c <= 'z') && (d >= 'a' && d <= 'z') ) { 110 | return (get<0>(first).id < get<0>(second).id); 111 | } 112 | 113 | //default: compare lhs names lexicographically 114 | return (get<0>(first).name > get<0>(second).name); 115 | } 116 | }; 117 | 118 | 119 | // checks equations for top-level variables 120 | // returns 1 if lhs is a variable 121 | // 2 if rhs is 122 | // 3 for both 123 | // 0 else 124 | __host__ __device__ 125 | int top_level_variables(const equation& e) 126 | { 127 | int result = 0; 128 | if (is_variable(get_lhs(e))) 129 | result++; 130 | if (is_variable(get_rhs(e))) 131 | result += 2; 132 | 133 | return result; 134 | } 135 | 136 | // checks for tlv, boolean version 137 | __host__ __device__ 138 | bool has_toplevel_variable(const equation& e) 139 | { 140 | if (is_variable(get_lhs(e))) 141 | return true; 142 | else 143 | return is_variable(get_rhs(e)); 144 | } 145 | 146 | //orient equations t=x -> x=t 147 | struct orient_functor 148 | { 149 | template 150 | __host__ __device__ 151 | void operator()(Equ eq) 152 | { 153 | if (!is_variable(get_lhs(eq)) && is_variable(get_rhs(eq))) 154 | { 155 | thrust::swap(thrust::get<0>(eq), thrust::get<1>(eq)); 156 | } 157 | } 158 | }; 159 | 160 | 161 | //is an equation active 162 | struct is_active_functor 163 | { 164 | template 165 | __host__ __device__ 166 | bool operator()(Equ eq) 167 | { 168 | const char c = thrust::get<0>(eq).name; 169 | return (c >= 'A' && c <= 'Z'); 170 | } 171 | }; 172 | 173 | //is an equation active 174 | struct is_not_active_functor 175 | { 176 | template 177 | __host__ __device__ 178 | bool operator()(Equ eq) 179 | { 180 | const char c = thrust::get<0>(eq).name; 181 | return !(c >= 'A' && c <= 'Z'); 182 | } 183 | }; 184 | 185 | 186 | //is an equation active 187 | struct is_active_agent 188 | { 189 | __host__ __device__ 190 | bool operator()(const Agent& a) 191 | { 192 | const char c = a.name; 193 | return (c >= 'A' && c <= 'Z'); 194 | } 195 | }; 196 | 197 | //orient equations t=x -> x=t 198 | struct orient_functor_transform : public thrust::unary_function 199 | { 200 | __host__ __device__ 201 | equation operator()(const equation eq) 202 | { 203 | equation result(eq); 204 | if (!is_variable(get_lhs(eq)) && is_variable(get_rhs(eq))) 205 | { 206 | thrust::swap(thrust::get<0>(result), thrust::get<1>(result)); 207 | } 208 | 209 | return result; 210 | } 211 | }; 212 | 213 | void print_equations(const thrust::host_vector& lhses, const thrust::host_vector& rhses) 214 | { 215 | for(unsigned int i = 0; i < lhses.size(); i++) { 216 | std::string left_args, right_args; 217 | if (lhses[i].arity == 0) { 218 | left_args = ""; 219 | } 220 | else { 221 | 222 | std::stringstream out; 223 | out << "(" << lhses[i].ports[0]; 224 | for (unsigned int ar = 1; ar < lhses[i].arity; ar++) { 225 | out << ", "; 226 | out << lhses[i].ports[ar]; 227 | } 228 | out << ")"; 229 | 230 | left_args = out.str(); 231 | } 232 | 233 | if (rhses[i].arity == 0) { 234 | right_args = " "; 235 | } 236 | else { 237 | std::stringstream out; 238 | out << "(" << rhses[i].ports[0]; 239 | for (int ar = 1; ar < rhses[i].arity; ar++) { 240 | out << ", "; 241 | out << rhses[i].ports[ar]; 242 | } 243 | out << ")"; 244 | 245 | right_args = out.str(); 246 | } 247 | std::cout << lhses[i] 248 | << left_args 249 | << " = " 250 | << rhses[i] 251 | << right_args 252 | << std::setw(10) << " (" 253 | << lhses[i].id << ", " << rhses[i].id << ") \n"; 254 | } 255 | std::cout << std::endl; 256 | } 257 | 258 | void print_equations(const thrust::host_vector equations) 259 | { 260 | for(unsigned int i = 0; i < equations.size(); i++) { 261 | std::string left_args, right_args; 262 | if (get_lhs(equations[i]).arity == 0) { 263 | left_args = ""; 264 | } 265 | else { 266 | 267 | std::stringstream out; 268 | out << "(" << get_lhs(equations[i]).ports[0]; 269 | for (unsigned int ar = 1; ar < get_lhs(equations[i]).arity; ar++) { 270 | out << ", "; 271 | out << get_lhs(equations[i]).ports[ar]; 272 | } 273 | out << ")"; 274 | 275 | left_args = out.str(); 276 | } 277 | 278 | if (get_rhs(equations[i]).arity == 0) { 279 | right_args = " "; 280 | } 281 | else { 282 | std::stringstream out; 283 | out << "(" << get_rhs(equations[i]).ports[0]; 284 | for (int ar = 1; ar < get_rhs(equations[i]).arity; ar++) { 285 | out << ", "; 286 | out << get_rhs(equations[i]).ports[ar]; 287 | } 288 | out << ")"; 289 | 290 | right_args = out.str(); 291 | } 292 | std::cout << get_lhs(equations[i]) 293 | << left_args 294 | << " = " 295 | << get_rhs(equations[i]) 296 | << right_args 297 | << std::setw(10) << " (" 298 | << get_lhs(equations[i]).id << ", " << get_rhs(equations[i]).id << ") \n"; 299 | } 300 | std::cout << std::endl; 301 | } 302 | 303 | 304 | 305 | void print_equations(const equation_iter begin, const equation_iter end) 306 | { 307 | thrust::host_vector equations(begin, end); 308 | print_equations(equations); 309 | } 310 | 311 | 312 | } 313 | 314 | 315 | #endif -------------------------------------------------------------------------------- /interaction_step.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {EFC96B86-827A-4068-AE84-3D38EDCE1DC5} 15 | interaction_step 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | true 42 | $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.0\CUDALibraries\common\inc; 43 | $(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib;C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.0\C\common\lib\win32 44 | 45 | 46 | true 47 | $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.0\C\common\inc 48 | $(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameC:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.0\C\common\lib\win32 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | D:\Program Files (x86)\boost\boost_1_47;%(AdditionalIncludeDirectories);$(CudaToolkitIncludeDir) 55 | ProgramDatabase 56 | 57 | 58 | true 59 | Console 60 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);freeglut.lib;glew32.lib;cutil32D.lib;cutil32.lib 61 | D:\Program Files (x86)\boost\boost_1_47\lib;%(AdditionalLibraryDirectories);C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.0\C\common\lib\Win32 62 | true 63 | 64 | 65 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 66 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 67 | 68 | 69 | C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.0\CUDALibraries\common\inc 70 | compute_11,sm_20 71 | --opencc-options -OPT:Olimit=99999 %(AdditionalOptions) 72 | 73 | 74 | 75 | 76 | Level3 77 | MaxSpeed 78 | true 79 | true 80 | ..\Program Files (x86)\boost\boost_1_47;%(AdditionalIncludeDirectories);$(CudaToolkitIncludeDir) 81 | 82 | 83 | true 84 | true 85 | true 86 | Console 87 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);freeglut.lib;glew32.lib;cutil32.lib 88 | ..\Program Files (x86)\boost\boost_1_47\lib;%(AdditionalLibraryDirectories);$(CudaToolkitLibDir);C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.0\C\common\lib\win32 89 | 90 | 91 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 92 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 93 | 94 | 95 | C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 4.0\C\common\inc 96 | compute_11,sm_13 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /communication.h: -------------------------------------------------------------------------------- 1 | /* 2 | communication.h 3 | does a communication step 4 | */ 5 | 6 | #ifndef COMMUNICATION_H_ 7 | #define COMMUNICATION_H_ 8 | 9 | //#pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "agent.cuh" 19 | #include 20 | #include 21 | 22 | using namespace ingpu; 23 | 24 | namespace ingpu { 25 | 26 | // do two agents have the same top level variable (TLV) 27 | struct has_tlv_functor : public thrust::unary_function 28 | { 29 | int tlv_id; 30 | 31 | __host__ __device__ 32 | has_tlv_functor(const int _tlv_id) : tlv_id(_tlv_id) {} 33 | 34 | __host__ __device__ 35 | bool operator()(const equation& eq) const 36 | { 37 | //check if the lhs is a variable 38 | if ( is_variable( get(eq) ) ) { 39 | 40 | if (get(eq).id == tlv_id) { 41 | return true; 42 | } 43 | else { 44 | //check if the rhs is a variable 45 | //Agent r = get_rhs(t); 46 | if (is_variable(get_rhs(eq))) { 47 | 48 | return (get_rhs(eq).id == tlv_id); //neither agent is a variable 49 | } 50 | } 51 | } 52 | return false; 53 | } 54 | }; 55 | 56 | // do two agents have the same top level variable (TLV) 57 | struct find_tlv_functor : public thrust::unary_function 58 | { 59 | int tlv_id; 60 | 61 | __host__ __device__ 62 | find_tlv_functor(const int _tlv_id) : tlv_id(tlv_id) {} 63 | 64 | __host__ __device__ 65 | bool operator()(const equation& eq) const 66 | { 67 | //check if the lhs is a variable 68 | if (!is_agent(get(eq))) { 69 | 70 | if (get(eq).id == tlv_id) { 71 | return true; 72 | } 73 | else { 74 | //check if the rhs is a variable 75 | //Agent r = get_rhs(t); 76 | if (!is_agent(get_rhs(eq))) { 77 | 78 | return (get_rhs(eq).id == tlv_id); //neither agent is a variable 79 | } 80 | } 81 | } 82 | return false; 83 | } 84 | }; 85 | 86 | 87 | 88 | 89 | // does an equation have a TLV 90 | struct is_tlv_equation_functor 91 | { 92 | __host__ __device__ 93 | bool operator()(equation t) 94 | { 95 | //check if the lhs is a variable 96 | if (!is_agent(get(t))) { 97 | return true; 98 | } 99 | else { 100 | //check if the rhs is a variable 101 | return (!is_agent(get_rhs(t))); 102 | } 103 | } 104 | }; 105 | 106 | // does an equation have a TLV as its lhs? 107 | struct is_oriented_tlv_equation_functor 108 | { 109 | __host__ __device__ 110 | bool operator()(equation t) 111 | { 112 | //check if the lhs is a variable 113 | return is_variable(get(t)) && is_agent(get_rhs(t)); 114 | } 115 | }; 116 | 117 | // dummy equation test functor 118 | struct dummy_test_functor 119 | { 120 | __host__ __device__ 121 | bool operator()(const Agent t) 122 | { 123 | return (t.name == 'Z'); 124 | } 125 | }; 126 | 127 | struct dummy_test_functor_tuple 128 | { 129 | __host__ __device__ 130 | bool operator()(const thrust::tuple& t) 131 | { 132 | return (thrust::get<0>(t).name == 'Z'); 133 | } 134 | }; 135 | 136 | struct valid_tuple_functor 137 | { 138 | __host__ __device__ 139 | bool operator()(const thrust::tuple& t) 140 | { 141 | return (thrust::get<0>(t).name != 'Z'); 142 | } 143 | }; 144 | 145 | // do two equations have a common tlv? 146 | // assumes equations are oriented 147 | struct common_tlv_functor : public thrust::binary_function 148 | { 149 | __host__ __device__ 150 | bool operator()(equation t, equation s) 151 | { 152 | //TODO: we assume that no two non-variable agents have distinct ids 153 | // this may cause bugs when ids are assigned to non-variable agents more than once 154 | // (which should not happen) 155 | 156 | if (get(t).id == get(s).id) 157 | return true; 158 | 159 | else if (get(t).id == get(s).id) 160 | return true; 161 | 162 | else if (get(t).id == get(s).id) 163 | return true; 164 | 165 | else if (get(t).id == get(s).id) 166 | return true; 167 | 168 | return false; 169 | } 170 | }; 171 | 172 | struct smaller_tlv_functor : public thrust::binary_function 173 | { 174 | __host__ __device__ 175 | bool operator()(const equation& t, const equation& s) 176 | { 177 | //TODO: consider LHS tlvs only 178 | 179 | return get<0>(t).id < get<0>(s).id; 180 | } 181 | }; 182 | 183 | 184 | struct greater_tlv_functor : public thrust::binary_function 185 | { 186 | __host__ __device__ 187 | bool operator()(equation t, equation s) 188 | { 189 | //TODO: consider LHS tlvs only 190 | 191 | return get(t).id > get(s).id; 192 | } 193 | }; 194 | 195 | struct equal_tlv_functor : public thrust::binary_function 196 | { 197 | __host__ __device__ 198 | bool operator()(equation t, equation s) 199 | { 200 | //TODO: consider LHS tlvs only 201 | 202 | return get(t).id == get(s).id; 203 | } 204 | }; 205 | 206 | // retuns the tlv id of the LHS 207 | struct get_tlv_functor : public thrust::unary_function 208 | { 209 | __host__ __device__ 210 | int operator()(const equation& t) 211 | { 212 | //TODO: consider LHS tlvs only 213 | return get<0>(t).id; 214 | } 215 | }; 216 | 217 | // retuns the tlv id of the LHS 218 | struct get_tlv_single_functor : public thrust::unary_function 219 | { 220 | __host__ __device__ 221 | int operator()(const Agent& t) 222 | { 223 | //TODO: consider LHS tlvs only 224 | return t.id; 225 | } 226 | }; 227 | 228 | struct different_tlv_functor : public thrust::binary_function 229 | { 230 | __host__ __device__ 231 | bool operator()(equation t, equation s) 232 | { 233 | //TODO: consider LHS tlvs only 234 | 235 | return !(get(t).id == get(s).id); 236 | } 237 | }; 238 | 239 | struct comm_functor : public thrust::binary_function 240 | { 241 | __host__ __device__ 242 | equation operator()(equation t, equation s) 243 | { 244 | //TODO: consider LHS tlvs only 245 | 246 | const char c = get(s).id; 247 | // swap lhs/rhs if rhs is a tlv 248 | if (c >= 'A' && c <= 'Z') { 249 | return thrust::make_tuple(get(s), get(t)); 250 | } 251 | //TODO: more efficient to add 'else' here? 252 | return thrust::make_tuple(get(t), get(s)); 253 | } 254 | }; 255 | 256 | // performs a single communication 257 | // by resolving a common tlv 258 | struct comm_reduce_functor : public thrust::binary_function 259 | { 260 | __host__ __device__ 261 | equation operator()(const equation& t, const equation& s) 262 | { 263 | if (get(t).id == get(s).id) { 264 | //orient if necessary 265 | //make the agent with the smaller name the LHS 266 | //this means that if one of them is a tlv and the other an agent, 267 | //the tlv will be on the lhs 268 | if (get(t).name < get(s).name) 269 | { 270 | return thrust::make_tuple(get(s), get(t));//thrust::swap(get(t), get(s)); 271 | } 272 | return thrust::make_tuple(get(t), get(s)); 273 | } 274 | 275 | else if (get(t).id == get(s).id) { 276 | //orient if necessary 277 | if (get(t).name < get(s).name) 278 | { 279 | return thrust::make_tuple( get(s), get(t));//thrust::swap(get(t), get(s)); 280 | } 281 | return thrust::make_tuple(get(t), get(s)); 282 | } 283 | 284 | else if (get(t).id == get(s).id) { 285 | //orient if necessary 286 | if (get(t).name < get(s).name) 287 | { 288 | return thrust::make_tuple(get(s), get(t));//thrust::swap(get(t), get(s)); 289 | } 290 | return thrust::make_tuple(get(t), get(s)); 291 | } 292 | 293 | else if (get(t).id == get(s).id) { 294 | //orient if necessary 295 | if (get(t).name < get(s).name) 296 | { 297 | return thrust::make_tuple(get(s), get(t));//thrust::swap(get(t), get(s)); 298 | } 299 | return thrust::make_tuple(get(t), get(s)); 300 | } 301 | 302 | // at this point, something has gone wrong 303 | // (no common tlv) 304 | // return an equation of dummy agents 305 | return thrust::make_tuple(Agent(), Agent()); 306 | } 307 | }; 308 | 309 | 310 | //clear the additional result arrays 311 | struct clear_functor { 312 | 313 | template 314 | __host__ __device__ 315 | void operator()(Tuple& equations) 316 | { 317 | thrust::get<0>(equations).name = 'Z'; 318 | thrust::get<1>(equations).name = 'Z'; 319 | thrust::get<2>(equations).name = 'Z'; 320 | thrust::get<3>(equations).name = 'Z'; 321 | thrust::get<4>(equations).name = 'Z'; 322 | thrust::get<5>(equations).name = 'Z'; 323 | thrust::get<6>(equations) = false; 324 | } 325 | 326 | }; 327 | 328 | // parallel communication step using reduce_by_key 329 | int comm_step_parallel(equation_iter& start, equation_iter& end, equation_iter& result_start, equation_iter& result_end, const int input_size, const int loop, const unsigned int communication_watch = 0) 330 | { 331 | int comm_counter = 1; 332 | //equation_iter new_end; 333 | 334 | //StopWatch::get(communication_watch).start(); 335 | 336 | thrust::device_vector keys(input_size); 337 | thrust::device_vector keys_out(input_size); 338 | thrust::transform(start, end, keys.begin(), get_tlv_functor()); 339 | 340 | //thrust::adjacent_difference(ids_begin, ids_end, diffs.begin()); 341 | 342 | //new_end = thrust::reduce_by_key(start, end, start, 343 | // thrust::make_discard_iterator(), result_start, common_tlv_functor(), comm_reduce_functor() 344 | // ).second; 345 | 346 | auto new_end = thrust::reduce_by_key(keys.begin(), keys.end(), start, 347 | keys_out.begin(), result_start, thrust::equal_to(), comm_reduce_functor() 348 | ); 349 | 350 | //StopWatch::get(communication_watch).stop(); 351 | 352 | int diff = new_end.first - keys_out.begin(); 353 | diff = input_size - diff; 354 | //std::cout << diff << std::endl; 355 | if (diff == 0) { 356 | return 0; 357 | } 358 | result_end = new_end.second; 359 | //end = end - diff; 360 | 361 | return diff; 362 | } 363 | 364 | 365 | } 366 | 367 | #endif -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "parse_net.h" 3 | #include "kernel.h" 4 | #include "config_manager.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "soa/kernel_soa.h" 10 | #include 11 | 12 | using namespace ingpu; 13 | using namespace std; 14 | using namespace thrust; 15 | 16 | void eval_single(thrust::host_vector& in_lhs_host, thrust::host_vector& in_rhs_host) 17 | { 18 | //------- 19 | //options 20 | bool print_final_net = config_manager::get_bool("print_final"); 21 | bool verbose = config_manager::get_bool("verbose"); 22 | bool pause = config_manager::get_bool("pause"); 23 | const int ruleset = config_manager::get_int("ruleset"); 24 | //partition or regular 25 | bool partition = config_manager::get_bool("partition"); 26 | 27 | //timer 28 | const unsigned int mywatch = StopWatch::create(); 29 | StopWatch::get(mywatch).start(); 30 | 31 | /* ---------------- 32 | // interaction loop 33 | ---------------- */ 34 | //arbitrary_transformation_example(); 35 | result_info rinfo; 36 | //if (partition) { 37 | // rinfo = 38 | // partition_interaction_step(ruleset, in_lhs_host, in_rhs_host, verbose, print_final_net, pause); 39 | //} 40 | //else { 41 | rinfo = 42 | test_interaction_step(ruleset, in_lhs_host, in_rhs_host, verbose, print_final_net, pause); 43 | //} 44 | //test_interaction_step(in_lhs_host, in_rhs_host, verbose, ins_type, print_final_net, pause); 45 | // soa::interaction_loop( l_ids, l_names, l_arities, l_p1s, l_p2s, l_p3s, l_p4s,r_ids, r_names, r_arities, r_p1s, r_p2s, r_p3s, r_p4s, verbose, print_final_net); 46 | 47 | StopWatch::get(mywatch).stop(); 48 | 49 | // stop and destroy timer 50 | float time_elapsed = StopWatch::get(mywatch).getTime() / 1000.0; 51 | printf ("elapsed time %.5f seconds.\n------------------\n", time_elapsed); 52 | StopWatch::destroy(mywatch); 53 | 54 | std::cout << "total loops: " << rinfo.num_loops << std::endl; 55 | std::cout << "total interactions: " << rinfo.total_interactions << " ( " << ( static_cast(rinfo.total_interactions / time_elapsed)) << " / sec )" << std::endl; 56 | const float avg_interactions = static_cast(rinfo.total_interactions) / static_cast(rinfo.num_loops); 57 | std::cout << "average interactions per loop: " << avg_interactions << std::endl; 58 | 59 | std::cout << "result (number of S symbols): " << rinfo.result << std::endl; 60 | std::cout << "\n----------------------------\n"; 61 | 62 | //write stuff to file: 63 | if (config_manager::get_bool("file_output")) { 64 | std::ofstream outfile; 65 | outfile.open("out.csv", ios::app); 66 | outfile 67 | << time_elapsed << ";" 68 | << rinfo.num_loops << ";" 69 | << rinfo.total_interactions << ";" 70 | << avg_interactions << ";" 71 | << (rinfo.total_interactions / time_elapsed) << ";" 72 | << rinfo.com_time << ";" 73 | << (rinfo.com_time / time_elapsed) << ";" 74 | << rinfo.result 75 | << "\n"; 76 | outfile.close(); 77 | } 78 | } 79 | 80 | void eval_all(vector < thrust::host_vector >& in_lhs_vector, vector< thrust::host_vector >& in_rhs_vector) 81 | { 82 | size_t num_inputs = in_lhs_vector.size(); 83 | std::cout << "evaluating " << num_inputs << " inputs\n"; 84 | // file i/o 85 | if (config_manager::get_bool("file_output")) { 86 | std::ofstream outfile; 87 | outfile.open("out.csv"); 88 | outfile << "elapsed time;loops;interactions; avg interactions/loop; interactions/sec; com time; com time %;result \n"; 89 | outfile.close(); 90 | } 91 | const bool pause_between_inputs = config_manager::get_bool("pause_between_inputs"); 92 | for (unsigned int i=0; i< num_inputs; ++i) { 93 | eval_single(in_lhs_vector[i], in_rhs_vector[i]); 94 | if (pause_between_inputs) { 95 | std::cout << "press any key to continue\n"; 96 | getch(); 97 | } 98 | } 99 | } 100 | 101 | void eval_single_soa(host_vector& l_ids, host_vector& l_names, 102 | host_vector& l_arities, 103 | host_vector& l_p1s, 104 | host_vector& l_p2s, 105 | host_vector& l_p3s, 106 | host_vector& l_p4s, 107 | host_vector& r_ids, host_vector& r_names, 108 | host_vector& r_arities, 109 | host_vector& r_p1s, 110 | host_vector& r_p2s, 111 | host_vector& r_p3s, 112 | host_vector& r_p4s) 113 | { 114 | //------- 115 | //options 116 | bool print_final_net = config_manager::get_bool("print_final"); 117 | bool verbose = config_manager::get_bool("verbose"); 118 | bool pause = config_manager::get_bool("pause"); 119 | const int ruleset = config_manager::get_int("ruleset"); 120 | 121 | //timer 122 | const unsigned int mywatch = StopWatch::create(); 123 | StopWatch::get(mywatch).start(); 124 | 125 | /* ---------------- 126 | // interaction loop 127 | ---------------- */ 128 | //arbitrary_transformation_example(); 129 | result_info rinfo = 130 | // test_interaction_step(in_lhs_host, in_rhs_host, verbose, ins_type, print_final_net); 131 | soa::interaction_loop(ruleset, l_ids, l_names, l_arities, l_p1s, l_p2s, l_p3s, l_p4s,r_ids, r_names, r_arities, r_p1s, r_p2s, r_p3s, r_p4s, verbose, print_final_net, pause); 132 | 133 | StopWatch::get(mywatch).stop(); 134 | 135 | // stop and destroy timer 136 | float time_elapsed = StopWatch::get(mywatch).getTime() / 1000.0; 137 | printf ("elapsed time %.5f seconds.\n------------------\n", time_elapsed); 138 | StopWatch::destroy(mywatch); 139 | 140 | std::cout << "total loops: " << rinfo.num_loops << std::endl; 141 | std::cout << "total interactions: " << rinfo.total_interactions << " ( " << ( static_cast(rinfo.total_interactions / time_elapsed)) << " / sec )" << std::endl; 142 | const float avg_interactions = static_cast(rinfo.total_interactions) / static_cast(rinfo.num_loops); 143 | std::cout << "average interactions per loop: " << avg_interactions << std::endl; 144 | 145 | std::cout << "result (number of S symbols): " << rinfo.result << std::endl; 146 | std::cout << "\n----------------------------\n"; 147 | 148 | //write stuff to file: 149 | if (config_manager::get_bool("file_output")) { 150 | std::ofstream outfile; 151 | outfile.open("out.csv", ios::app); 152 | outfile 153 | << time_elapsed << ";" 154 | << rinfo.num_loops << ";" 155 | << rinfo.total_interactions << ";" 156 | << avg_interactions << ";" 157 | << (rinfo.total_interactions / time_elapsed) << ";" 158 | << rinfo.com_time << ";" 159 | << (rinfo.com_time / time_elapsed) << ";" 160 | << rinfo.result 161 | << "\n"; 162 | outfile.close(); 163 | } 164 | } 165 | 166 | 167 | void eval_all_soa(vector< host_vector >& l_ids, vector< host_vector >& l_names, 168 | vector< host_vector >& l_arities, 169 | vector< host_vector >& l_p1s, 170 | vector< host_vector >& l_p2s, 171 | vector< host_vector >& l_p3s, 172 | vector< host_vector >& l_p4s, 173 | vector< host_vector >& r_ids, vector< host_vector >& r_names, 174 | vector< host_vector >& r_arities, 175 | vector< host_vector >& r_p1s, 176 | vector< host_vector >& r_p2s, 177 | vector< host_vector >& r_p3s, 178 | vector< host_vector >& r_p4s) 179 | { 180 | size_t num_inputs = l_ids.size(); 181 | std::cout << "evaluating " << num_inputs << " inputs\n"; 182 | // file i/o 183 | if (config_manager::get_bool("file_output")) { 184 | std::ofstream outfile; 185 | outfile.open("out.csv"); 186 | outfile << "elapsed time;loops;interactions; avg interactions/loop; interactions/sec; com time; com time %;result \n"; 187 | outfile.close(); 188 | } 189 | for (unsigned int i=0; i< num_inputs; ++i) { 190 | eval_single_soa(l_ids[i], l_names[i], l_arities[i], l_p1s[i], l_p2s[i], l_p3s[i], l_p4s[i], 191 | r_ids[i], r_names[i], r_arities[i], r_p1s[i], r_p2s[i], r_p3s[i], r_p4s[i]); 192 | } 193 | } 194 | 195 | int main() 196 | { 197 | //load options 198 | config_manager::inst()->load_config("options.txt"); 199 | 200 | //raw_agent parsing 201 | // ---------------- 202 | std::string str = "input.txt"; 203 | std::vector ra; 204 | std::vector< vector > ra_vector; 205 | std::vector agents; 206 | std::vector< vector > agents_vector; 207 | // ------------------------- 208 | //test building of soa agents 209 | // -------------------------- 210 | vector< vector > ids; 211 | vector< vector > names; 212 | vector< vector > arities; 213 | vector< vector > p1s; 214 | vector< vector > p2s; 215 | vector< vector > p3s; 216 | vector< vector > p4s; 217 | 218 | parse_net::raw_agent_parser p; 219 | // multi parse of all inputs 220 | if (parse_net::parse_all(str, ra_vector)) 221 | { 222 | std::cout << "-------------------------\n"; 223 | std::cout << "Parsing succeeded\n"; 224 | std::cout << str << " Parses OK: " << std::endl; 225 | int vector_size = ra_vector.size(); 226 | //resize soa_vectors 227 | ids.resize(vector_size); names.resize(vector_size); arities.resize(vector_size); 228 | p1s.resize(vector_size); p2s.resize(vector_size); p3s.resize(vector_size); p4s.resize(vector_size); 229 | //convert to proper agents now 230 | agents_vector.resize(vector_size); 231 | for (unsigned int i=0; i< ra_vector.size(); ++i) { 232 | agents_vector[i] = vector(); 233 | build_agents(ra_vector[i], agents_vector[i]); 234 | //soa version 235 | if (config_manager::get_bool("soa") ) { 236 | //init soa arrays for the current input 237 | ids[i] = vector(); names[i] = vector(); arities[i] = vector(); 238 | p1s[i] = vector(); p2s[i] = vector(); p3s[i] = vector(); p4s[i] = vector(); 239 | //build soa arrays for the current input 240 | build_agents(ra_vector[i], ids[i], names[i], arities[i], p1s[i], p2s[i], p3s[i], p4s[i]); 241 | } 242 | } 243 | } 244 | else 245 | { 246 | std::cout << "-------------------------\n"; 247 | std::cout << "Parsing failed\n"; 248 | std::cout << "-------------------------\n"; 249 | } 250 | 251 | 252 | 253 | //splitting agents into lhs and rhs 254 | thrust::host_vector lhs; 255 | thrust::host_vector rhs; 256 | vector< thrust::host_vector > lhs_vector; 257 | vector< thrust::host_vector > rhs_vector; 258 | 259 | //all inputs split 260 | for (unsigned int input=0; input < agents_vector.size(); ++input) { 261 | thrust::host_vector lhs_temp; 262 | thrust::host_vector rhs_temp; 263 | //fill the temporary vectors 264 | for (unsigned int i = 0; i < agents_vector[input].size(); ++i) { 265 | if ((i % 2) == 0) 266 | lhs_temp.push_back(agents_vector[input][i]); 267 | else 268 | rhs_temp.push_back(agents_vector[input][i]); 269 | } 270 | //append temporary vectors 271 | lhs_vector.push_back(lhs_temp); 272 | rhs_vector.push_back(rhs_temp); 273 | } 274 | 275 | //-------------- 276 | // soa splitting 277 | //-------------- 278 | 279 | vector< host_vector > l_ids_vector, r_ids_vector; 280 | vector< host_vector > l_names_vector, r_names_vector; 281 | vector< host_vector > l_arities_vector, r_arities_vector; 282 | vector< host_vector > l_p1s_vector, r_p1s_vector; 283 | vector< host_vector > l_p2s_vector, r_p2s_vector; 284 | vector< host_vector > l_p3s_vector, r_p3s_vector; 285 | vector< host_vector > l_p4s_vector, r_p4s_vector; 286 | 287 | if (config_manager::get_bool("soa") ) 288 | { 289 | //outer loop 290 | for (unsigned int input = 0; input < ids.size(); ++input) { 291 | // temporary arrays 292 | host_vector l_ids, r_ids; 293 | host_vector l_names, r_names; 294 | host_vector l_arities, r_arities; 295 | host_vector l_p1s, r_p1s; 296 | host_vector l_p2s, r_p2s; 297 | host_vector l_p3s, r_p3s; 298 | host_vector l_p4s, r_p4s; 299 | 300 | //split arrays for the current input 301 | for (unsigned int i = 0; i < ids[input].size(); ++i) { 302 | if ((i % 2) == 0) { 303 | l_ids.push_back(ids[input][i]); 304 | l_names.push_back(names[input][i]); 305 | l_arities.push_back(arities[input][i]); 306 | l_p1s.push_back(p1s[input][i]); 307 | l_p2s.push_back(p2s[input][i]); 308 | l_p3s.push_back(p3s[input][i]); 309 | l_p4s.push_back(p4s[input][i]); 310 | } 311 | else { 312 | r_ids.push_back(ids[input][i]); 313 | r_names.push_back(names[input][i]); 314 | r_arities.push_back(arities[input][i]); 315 | r_p1s.push_back(p1s[input][i]); 316 | r_p2s.push_back(p2s[input][i]); 317 | r_p3s.push_back(p3s[input][i]); 318 | r_p4s.push_back(p4s[input][i]); 319 | } 320 | } 321 | 322 | // add the arrays to the input vector 323 | // lhs 324 | l_ids_vector.push_back(l_ids); 325 | l_names_vector.push_back(l_names); 326 | l_arities_vector.push_back(l_arities); 327 | l_p1s_vector.push_back(l_p1s); 328 | l_p2s_vector.push_back(l_p2s); 329 | l_p3s_vector.push_back(l_p3s); 330 | l_p4s_vector.push_back(l_p4s); 331 | // rhs 332 | r_ids_vector.push_back(r_ids); 333 | r_names_vector.push_back(r_names); 334 | r_arities_vector.push_back(r_arities); 335 | r_p1s_vector.push_back(r_p1s); 336 | r_p2s_vector.push_back(r_p2s); 337 | r_p3s_vector.push_back(r_p3s); 338 | r_p4s_vector.push_back(r_p4s); 339 | } 340 | } 341 | 342 | //evaluation 343 | //---------- 344 | //soa 345 | if ( config_manager::get_bool("soa")) { 346 | 347 | std::cout << "data mode: soa\n"; 348 | if (config_manager::get_bool("eval_all") ) { 349 | eval_all_soa(l_ids_vector, l_names_vector, l_arities_vector, l_p1s_vector, l_p2s_vector, l_p3s_vector, l_p4s_vector, 350 | r_ids_vector, r_names_vector, r_arities_vector, r_p1s_vector, r_p2s_vector, r_p3s_vector, r_p4s_vector); 351 | } 352 | else { 353 | eval_single_soa(l_ids_vector[0], l_names_vector[0], l_arities_vector[0], l_p1s_vector[0], l_p2s_vector[0], l_p3s_vector[0], l_p4s_vector[0], 354 | r_ids_vector[0], r_names_vector[0], r_arities_vector[0], r_p1s_vector[0], r_p2s_vector[0], r_p3s_vector[0], r_p4s_vector[0]); 355 | } 356 | } 357 | //regular evaluation 358 | else { 359 | if (config_manager::get_bool("partition")) { 360 | //std::cout << "data mode: partition\n"; 361 | } 362 | else { 363 | std::cout << "data mode: regular\n"; 364 | } 365 | if (config_manager::get_bool("eval_all") ) { 366 | eval_all(lhs_vector, rhs_vector); 367 | } 368 | else { 369 | eval_single(lhs_vector[0], rhs_vector[0]); 370 | } 371 | } 372 | //// ------ 373 | ////options 374 | //bool print_final_net = config_manager::get_bool("print_final"); 375 | //bool verbose = config_manager::get_bool("verbose"); 376 | //int ins_type = config_manager::get_int("ins"); 377 | 378 | ////timer 379 | //const unsigned int mywatch = StopWatch::create(); 380 | //StopWatch::get(mywatch).start(); 381 | 382 | ///* ---------------- 383 | //// interaction loop 384 | // ---------------- */ 385 | ////arbitrary_transformation_example(); 386 | //result_info rinfo = 387 | // test_interaction_step(lhs, rhs, verbose, ins_type, print_final_net); 388 | //// soa::interaction_loop( l_ids, l_names, l_arities, l_p1s, l_p2s, l_p3s, l_p4s,r_ids, r_names, r_arities, r_p1s, r_p2s, r_p3s, r_p4s, verbose, print_final_net); 389 | 390 | /* ---------------- 391 | // interaction loop 392 | ---------------- */ 393 | //arbitrary_transformation_example(); 394 | //test_interaction_step(lhs, rhs, verbose, ins_type, print_final_net); 395 | //soa::interaction_loop( l_ids, l_names, l_arities, l_p1s, l_p2s, l_p3s, l_p4s,r_ids, r_names, r_arities, r_p1s, r_p2s, r_p3s, r_p4s, verbose, print_final_net, pause); 396 | //StopWatch::get(mywatch).stop(); 397 | 398 | //// stop and destroy timer 399 | //printf ("elapsed time %.5f seconds.\n------------------\n", StopWatch::get(mywatch).getTime() / 1000.0 ); 400 | //StopWatch::destroy(mywatch); 401 | 402 | //std::cout << "total loops: " << rinfo.num_loops << std::endl; 403 | //std::cout << "total interactions: " << rinfo.total_interactions << std::endl; 404 | //const float avg_interactions = static_cast(rinfo.total_interactions) / static_cast(rinfo.num_loops); 405 | //std::cout << "average interactions per loop: " << avg_interactions << std::endl; 406 | 407 | //std::cout << "result (number of S symbols): " << rinfo.result << std::endl; 408 | 409 | std::cout << "press any key to continue...\n"; 410 | getch(); 411 | 412 | return 0; 413 | } -------------------------------------------------------------------------------- /soa/kernel_soa.cu: -------------------------------------------------------------------------------- 1 | #include "kernel_soa.h" 2 | #include "cuda_runtime.h" 3 | #include "device_launch_parameters.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | //#include "agent.h" 38 | #include "ackermann.h" 39 | #include "fibonacci.h" 40 | #include "algae.h" 41 | #include "agent_functor.h" 42 | #include "communication.h" 43 | 44 | 45 | using namespace thrust; 46 | using namespace soa; 47 | 48 | namespace soa { 49 | //print a vector 50 | template 51 | void print_range(const std::string& name, Iterator first, Iterator last) 52 | { 53 | typedef typename std::iterator_traits::value_type T; 54 | 55 | std::cout << name << ": "; 56 | thrust::copy(first, last, std::ostream_iterator(std::cout, " ")); 57 | std::cout << std::endl; 58 | } 59 | } 60 | 61 | //void resize_input(const int size) 62 | //{ 63 | // lhs_ids.resize(size); lhs_arities.resize(size); lhs_names.resize(size); 64 | // lhs_p1s.resize(size); lhs_p2s.resize(size); lhs_p3s.resize(size); lhs_p4s.resize(size); 65 | // rhs_ids.resize(size); rhs_arities.resize(size); rhs_names.resize(size); 66 | // rhs_p1s.resize(size); rhs_p2s.resize(size); rhs_p3s.resize(size); rhs_p4s.resize(size); 67 | //} 68 | 69 | //clear the additional result arrays 70 | //TODO only clear indices to speedup 71 | struct clear_functor { 72 | 73 | template 74 | __host__ __device__ 75 | void operator()(Tuple& equations) 76 | { 77 | thrust::get<0>(equations) = thrust::make_tuple(0, 'Z', 0, 0, 0, 0, 0); 78 | thrust::get<1>(equations) = thrust::make_tuple(0, 'Z', 0, 0, 0, 0, 0); 79 | } 80 | 81 | }; 82 | 83 | 84 | /*------------------------- 85 | Interaction Nets Evaluation 86 | -------------------------*/ 87 | result_info soa::interaction_loop( 88 | const int ruleset, 89 | host_vector& host_lhs_ids, 90 | host_vector& host_lhs_names, 91 | host_vector& host_lhs_arities, 92 | host_vector& host_lhs_p1s, 93 | host_vector& host_lhs_p2s, 94 | host_vector& host_lhs_p3s, 95 | host_vector& host_lhs_p4s, 96 | host_vector& host_rhs_ids, 97 | host_vector& host_rhs_names, 98 | host_vector& host_rhs_arities, 99 | host_vector& host_rhs_p1s, 100 | host_vector& host_rhs_p2s, 101 | host_vector& host_rhs_p3s, 102 | host_vector& host_rhs_p4s, 103 | const bool verbose, const bool print_final, const bool pause) 104 | { 105 | // -------------- 106 | // initialization 107 | // -------------- 108 | //input size 109 | int input_size = host_lhs_ids.size(); 110 | //the full size of the vector, including virtual auxiliary vectors 111 | int vector_size = input_size * 4; 112 | //auxiliary vector size 113 | int aux_input_size = input_size; 114 | 115 | //make a device pointer for tracking agent indices 116 | //------------------------------------------ 117 | const size_t ptr_size = 2; 118 | //create a dev ptr 119 | thrust::device_ptr dev_ptr = thrust::device_malloc(ptr_size); 120 | //TODO: ugly hardcoded intial index again! 121 | dev_ptr[0] = 100; 122 | 123 | std::cout << "done allocating\n"; 124 | //extract the raw pointer 125 | int * index_ptr = thrust::raw_pointer_cast(dev_ptr); 126 | 127 | //stopwatches 128 | const unsigned int interaction_watch = StopWatch::create(); 129 | const unsigned int communication_watch = StopWatch::create(); 130 | 131 | //track whether an interaction step was made 132 | thrust::device_vector normal(vector_size); 133 | 134 | // transfer the input to the device 135 | //--------------------------------- 136 | thrust::device_vector lhs_ids(host_lhs_ids), lhs_arities(host_lhs_arities), lhs_p1s(host_lhs_p1s), lhs_p2s(host_lhs_p2s), lhs_p3s(host_lhs_p3s), lhs_p4s(host_lhs_p4s); 137 | device_vector lhs_names(host_lhs_names); 138 | thrust::device_vector rhs_ids(host_rhs_ids), rhs_arities(host_rhs_arities), rhs_p1s(host_rhs_p1s), rhs_p2s(host_rhs_p2s), rhs_p3s(host_rhs_p3s), rhs_p4s(host_rhs_p4s); 139 | device_vector rhs_names(host_rhs_names); 140 | 141 | 142 | // --------------- 143 | // input iterators 144 | //---------------- 145 | //resize to full vector size 146 | lhs_ids.resize(vector_size); lhs_arities.resize(vector_size); lhs_names.resize(vector_size); 147 | lhs_p1s.resize(vector_size); lhs_p2s.resize(vector_size); lhs_p3s.resize(vector_size); lhs_p4s.resize(vector_size); 148 | rhs_ids.resize(vector_size); rhs_arities.resize(vector_size); rhs_names.resize(vector_size); 149 | rhs_p1s.resize(vector_size); rhs_p2s.resize(vector_size); rhs_p3s.resize(vector_size); rhs_p4s.resize(vector_size); 150 | 151 | //input 152 | agent_iter lhs_iter_begin = thrust::make_zip_iterator( 153 | thrust::make_tuple( lhs_ids.begin(),lhs_names.begin(),lhs_arities.begin(), 154 | lhs_p1s.begin(),lhs_p2s.begin(),lhs_p3s.begin(), lhs_p4s.begin()) ); 155 | auto rhs_iter_begin = thrust::make_zip_iterator( 156 | thrust::make_tuple( rhs_ids.begin(), rhs_names.begin(), rhs_arities.begin(), 157 | rhs_p1s.begin(), rhs_p2s.begin(), rhs_p3s.begin(), rhs_p4s.begin() ) ); 158 | 159 | auto lhs_iter_end = thrust::make_zip_iterator( 160 | thrust::make_tuple( lhs_ids.end(),lhs_names.end(),lhs_arities.end(), 161 | lhs_p1s.end(),lhs_p2s.end(),lhs_p3s.end(),lhs_p4s.end()) ); 162 | auto rhs_iter_end = thrust::make_zip_iterator( 163 | thrust::make_tuple( rhs_ids.end(), rhs_names.end(), rhs_arities.end(), 164 | rhs_p1s.end(), rhs_p2s.end(), rhs_p3s.end(), rhs_p4s.end() ) ); 165 | 166 | equation_iter in_iter_begin = make_zip_iterator(make_tuple(lhs_iter_begin, rhs_iter_begin)); 167 | auto in_iter_end = make_zip_iterator(make_tuple(lhs_iter_end, rhs_iter_end)); 168 | //end of the actual input 169 | equation_iter input_end = in_iter_begin + input_size; 170 | 171 | //print_range("ids", lhs_names.begin(), lhs_names.end()); 172 | //print_range("ids", rhs_names.begin(), rhs_names.end()); 173 | 174 | // additional result vectors 175 | // TODO implement those 176 | 177 | //functor creation 178 | soa::ackermann_functor ack_functor(index_ptr); 179 | fibonacci_functor fib_functor(index_ptr); 180 | soa::algae_functor alg_functor(index_ptr); 181 | //add_functor functor; 182 | 183 | //loop variables 184 | int num_interactions = 0; 185 | int num_communications = 0; 186 | int num_loops = 0; 187 | int total_interactions = 0; 188 | 189 | if (verbose) { 190 | std::cout << "input:\n---------------\n"; 191 | print_equations( host_vector(in_iter_begin, in_iter_end) ); 192 | } 193 | 194 | //auxiliary iterators for comm step 195 | //auxiliary vector tuple to avoid in-place reduce 196 | //lhs 197 | thrust::device_vector aux_lhs_ids(aux_input_size), 198 | aux_lhs_arities(aux_input_size), 199 | aux_lhs_p1s(aux_input_size), 200 | aux_lhs_p2s(aux_input_size), 201 | aux_lhs_p3s(aux_input_size), 202 | aux_lhs_p4s(aux_input_size); 203 | device_vector aux_lhs_names(aux_input_size); 204 | //rhs 205 | thrust::device_vector aux_rhs_ids(aux_input_size), 206 | aux_rhs_arities(aux_input_size), 207 | aux_rhs_p1s(aux_input_size), 208 | aux_rhs_p2s(aux_input_size), 209 | aux_rhs_p3s(aux_input_size), 210 | aux_rhs_p4s(aux_input_size); 211 | device_vector aux_rhs_names(aux_input_size); 212 | // auxiliary iterators 213 | // aux iter lhs 214 | agent_iter aux_lhs_iter_begin = thrust::make_zip_iterator( 215 | thrust::make_tuple( aux_lhs_ids.begin(),aux_lhs_names.begin(),aux_lhs_arities.begin(), 216 | aux_lhs_p1s.begin(),aux_lhs_p2s.begin(),aux_lhs_p3s.begin(), aux_lhs_p4s.begin()) ); 217 | auto aux_rhs_iter_begin = thrust::make_zip_iterator( 218 | thrust::make_tuple( aux_rhs_ids.begin(), aux_rhs_names.begin(), aux_rhs_arities.begin(), 219 | aux_rhs_p1s.begin(), aux_rhs_p2s.begin(), aux_rhs_p3s.begin(), aux_rhs_p4s.begin() ) ); 220 | // aux iter rhs 221 | auto aux_lhs_iter_end = thrust::make_zip_iterator( 222 | thrust::make_tuple( aux_lhs_ids.end(),aux_lhs_names.end(),aux_lhs_arities.end(), 223 | aux_lhs_p1s.end(),aux_lhs_p2s.end(),aux_lhs_p3s.end(),aux_lhs_p4s.end()) ); 224 | auto aux_rhs_iter_end = thrust::make_zip_iterator( 225 | thrust::make_tuple( aux_rhs_ids.end(), aux_rhs_names.end(), aux_rhs_arities.end(), 226 | aux_rhs_p1s.end(), aux_rhs_p2s.end(), aux_rhs_p3s.end(), aux_rhs_p4s.end() ) ); 227 | equation_iter aux_iter_begin = make_zip_iterator(make_tuple(aux_lhs_iter_begin, aux_rhs_iter_begin)); 228 | equation_iter aux_iter_end = make_zip_iterator(make_tuple(aux_lhs_iter_end, aux_rhs_iter_end)); 229 | 230 | 231 | //additional result arrays 232 | // ----------------------- 233 | //// A 234 | //thrust::device_vector a_lhs_ids(input_size, -1), a_lhs_arities(input_size), a_lhs_p1s(input_size), a_lhs_p2s(input_size), a_lhs_p3s(input_size), a_lhs_p4s(input_size); 235 | //device_vector a_lhs_names(input_size, 'Z'); 236 | //thrust::device_vector a_rhs_ids(input_size, -1), a_rhs_arities(input_size), a_rhs_p1s(input_size), a_rhs_p2s(input_size), a_rhs_p3s(input_size), a_rhs_p4s(input_size); 237 | //device_vector a_rhs_names(input_size, 'Z'); 238 | //// B 239 | //thrust::device_vector b_rhs_ids(input_size, -1), b_rhs_arities(input_size), b_rhs_p1s(input_size), b_rhs_p2s(input_size), b_rhs_p3s(input_size), b_rhs_p4s(input_size); 240 | //device_vector b_rhs_names(input_size, 'Z'); 241 | //thrust::device_vector b_lhs_ids(input_size, -1), b_lhs_arities(input_size), b_lhs_p1s(input_size), b_lhs_p2s(input_size), b_lhs_p3s(input_size), b_lhs_p4s(input_size); 242 | //device_vector b_lhs_names(input_size, 'Z'); 243 | //// C 244 | //thrust::device_vector c_lhs_ids(input_size, -1), c_lhs_arities(input_size), c_lhs_p1s(input_size), c_lhs_p2s(input_size), c_lhs_p3s(input_size), c_lhs_p4s(input_size); 245 | //device_vector c_lhs_names(input_size, 'Z'); 246 | //thrust::device_vector c_rhs_ids(input_size, -1), c_rhs_arities(input_size), c_rhs_p1s(input_size), c_rhs_p2s(input_size), c_rhs_p3s(input_size), c_rhs_p4s(input_size); 247 | //device_vector c_rhs_names(input_size, 'Z'); 248 | 249 | //equation_iter c_iter_begin = input_end + input_size * 2; 250 | //auto c_iter_end = input_end + input_size * 3; 251 | 252 | 253 | /*-------------------------- 254 | // START OF INTERACTION LOOP 255 | ----------------------------*/ 256 | do { 257 | 258 | //virtual result array A 259 | agent_iter a_lhs_iter_begin = lhs_iter_begin + input_size; 260 | agent_iter a_rhs_iter_begin = rhs_iter_begin + input_size; 261 | agent_iter a_lhs_iter_end = lhs_iter_begin + input_size * 2; 262 | agent_iter a_rhs_iter_end = rhs_iter_begin + input_size * 2; 263 | equation_iter a_iter_begin = make_zip_iterator(make_tuple(a_lhs_iter_begin, a_rhs_iter_begin)); 264 | auto a_iter_end = make_zip_iterator(make_tuple(a_lhs_iter_end, a_rhs_iter_end)); 265 | 266 | //virtual result array B 267 | agent_iter b_lhs_iter_begin = lhs_iter_begin + input_size * 2; 268 | agent_iter b_rhs_iter_begin = rhs_iter_begin + input_size * 2; 269 | agent_iter b_lhs_iter_end = lhs_iter_begin + input_size * 3; 270 | agent_iter b_rhs_iter_end = rhs_iter_begin + input_size * 3; 271 | equation_iter b_iter_begin = make_zip_iterator(make_tuple(b_lhs_iter_begin, b_rhs_iter_begin)); 272 | auto b_iter_end = make_zip_iterator(make_tuple(b_lhs_iter_end, b_rhs_iter_end)); 273 | 274 | //virtual result array C 275 | agent_iter c_lhs_iter_begin = lhs_iter_begin + input_size * 3; 276 | agent_iter c_rhs_iter_begin = rhs_iter_begin + input_size * 3; 277 | agent_iter c_lhs_iter_end = lhs_iter_begin + input_size * 4; 278 | agent_iter c_rhs_iter_end = rhs_iter_begin + input_size * 4; 279 | equation_iter c_iter_begin = make_zip_iterator(make_tuple(c_lhs_iter_begin, c_rhs_iter_begin)); 280 | auto c_iter_end = make_zip_iterator(make_tuple(c_lhs_iter_end, c_rhs_iter_end)); 281 | 282 | //// invalid test 283 | //if (thrust::any_of(in_iter_begin, in_iter_end, is_invalid_tuple() ) ) { 284 | // std::cout << "invalid tuple before int step detected!\n"; 285 | // break; 286 | //} 287 | 288 | 289 | if (verbose) { 290 | std::cout << "input:\n---------------\n"; 291 | print_equations( host_vector(in_iter_begin, input_end) ); 292 | } 293 | 294 | //----------------- 295 | // interaction step 296 | // ---------------- 297 | //virtual result vectors are at input_size * {1,2,3} 298 | switch( ruleset ) { 299 | case 1: 300 | thrust::for_each( 301 | make_zip_iterator(make_tuple(lhs_iter_begin, rhs_iter_begin, a_lhs_iter_begin, a_rhs_iter_begin, 302 | b_lhs_iter_begin, b_rhs_iter_begin, c_lhs_iter_begin, c_rhs_iter_begin, normal.begin())), 303 | make_zip_iterator(make_tuple(lhs_iter_begin + input_size, rhs_iter_begin + input_size, a_lhs_iter_end, a_rhs_iter_end, 304 | b_lhs_iter_end, b_rhs_iter_end, c_lhs_iter_end, c_rhs_iter_end, normal.end())), 305 | ack_functor 306 | ); 307 | break; 308 | case 2: 309 | thrust::for_each( 310 | make_zip_iterator(make_tuple(lhs_iter_begin, rhs_iter_begin, 311 | lhs_iter_begin + input_size, rhs_iter_begin + input_size, 312 | lhs_iter_begin + input_size * 2, rhs_iter_begin + input_size * 2, 313 | lhs_iter_begin + input_size * 3, rhs_iter_begin + input_size * 3, 314 | normal.begin())), 315 | make_zip_iterator(make_tuple(lhs_iter_begin + input_size, rhs_iter_begin + input_size, 316 | lhs_iter_begin + input_size * 2, rhs_iter_begin + input_size * 2, 317 | lhs_iter_begin + input_size * 3, rhs_iter_begin + input_size * 3, 318 | lhs_iter_begin + input_size * 4, rhs_iter_begin + input_size * 4, 319 | normal.end())), 320 | alg_functor 321 | ); 322 | break; 323 | case 3: 324 | thrust::for_each( 325 | make_zip_iterator(make_tuple(lhs_iter_begin, rhs_iter_begin, 326 | lhs_iter_begin + input_size, rhs_iter_begin + input_size, 327 | lhs_iter_begin + input_size * 2, rhs_iter_begin + input_size * 2, 328 | lhs_iter_begin + input_size * 3, rhs_iter_begin + input_size * 3, 329 | normal.begin())), 330 | make_zip_iterator(make_tuple(lhs_iter_begin + input_size, rhs_iter_begin + input_size, 331 | lhs_iter_begin + input_size * 2, rhs_iter_begin + input_size * 2, 332 | lhs_iter_begin + input_size * 3, rhs_iter_begin + input_size * 3, 333 | lhs_iter_begin + input_size * 4, rhs_iter_begin + input_size * 4, 334 | normal.end())), 335 | fib_functor 336 | ); 337 | break; 338 | } 339 | // interaction step done 340 | // --------------------- 341 | 342 | //raw interaction kernel measure time 343 | //StopWatch::get(interaction_watch).stop(); 344 | 345 | //StopWatch::get(interaction_watch).start(); 346 | //check if we performed one or more interactions 347 | num_interactions = thrust::count(normal.begin(), normal.end(), true); 348 | if (num_interactions > 0) { 349 | num_loops++; 350 | if (verbose) 351 | std::cout << "interactions: " << num_interactions << "\n"; 352 | } 353 | else { 354 | if (verbose) { 355 | std::cout << "equations are in int normal form\n\n"; 356 | } 357 | break; 358 | } 359 | 360 | //print_range("ids", lhs_names.begin(), lhs_names.end()); 361 | if (verbose) { 362 | std::cout << "result of int step:\n----------------\n"; 363 | print_equations( host_vector(in_iter_begin, input_end) ); 364 | print_equations( host_vector(a_iter_begin, a_iter_end) ); 365 | print_equations( host_vector(b_iter_begin, b_iter_end) ); 366 | print_equations( host_vector(c_iter_begin, c_iter_end) ); 367 | } 368 | 369 | //dummy removal 370 | //TODO use reduce by key for speedup 371 | //input end is set to the end of the non-dummies 372 | //in_iter_end remains at the actual end of the vectors 373 | input_end = thrust::remove_if(in_iter_begin, in_iter_end, is_dummy_equation_functor()); 374 | input_size = input_end - in_iter_begin; 375 | //cleanup functor 376 | //thrust::fill(lhs_ids.begin() + input_size, lhs_ids.end(), 0); 377 | //// invalid test 378 | //if (thrust::any_of(in_iter_begin, in_iter_end, is_invalid_tuple() ) ) { 379 | // std::cout << "invalid tuple after merge detected!\n"; 380 | // break; 381 | //} 382 | 383 | if (verbose) { 384 | std::cout << "post merge:\n--------------\n"; 385 | print_equations( host_vector(in_iter_begin, input_end) ); 386 | print_equations( host_vector(input_end, in_iter_end) ); 387 | } 388 | 389 | 390 | //StopWatch::get(communication_watch).start(); 391 | 392 | StopWatch::get(interaction_watch).start(); 393 | // sorting and aux vector handling 394 | // ------------------------------- 395 | //resize aux vectors if necessary 396 | if (input_size > aux_input_size) { 397 | aux_input_size = input_size; 398 | //resize and set iterators 399 | aux_lhs_ids.resize(aux_input_size); aux_lhs_arities.resize(aux_input_size); aux_lhs_names.resize(aux_input_size); 400 | aux_lhs_p1s.resize(aux_input_size); aux_lhs_p2s.resize(aux_input_size); aux_lhs_p3s.resize(aux_input_size); aux_lhs_p4s.resize(aux_input_size); 401 | aux_rhs_ids.resize(aux_input_size); aux_rhs_arities.resize(aux_input_size); aux_rhs_names.resize(aux_input_size); 402 | aux_rhs_p1s.resize(aux_input_size); aux_rhs_p2s.resize(aux_input_size); aux_rhs_p3s.resize(aux_input_size); aux_rhs_p4s.resize(aux_input_size); 403 | 404 | } 405 | //set iterators 406 | // aux iter lhs 407 | aux_rhs_iter_begin = thrust::make_zip_iterator( 408 | thrust::make_tuple( aux_rhs_ids.begin(), aux_rhs_names.begin(), aux_rhs_arities.begin(), 409 | aux_rhs_p1s.begin(), aux_rhs_p2s.begin(), aux_rhs_p3s.begin(), aux_rhs_p4s.begin() ) ); 410 | aux_lhs_iter_begin = thrust::make_zip_iterator( 411 | thrust::make_tuple( aux_lhs_ids.begin(),aux_lhs_names.begin(),aux_lhs_arities.begin(), 412 | aux_lhs_p1s.begin(),aux_lhs_p2s.begin(),aux_lhs_p3s.begin(), aux_lhs_p4s.begin()) ); 413 | 414 | equation_iter aux_iter_begin = make_zip_iterator(make_tuple(aux_lhs_iter_begin, aux_rhs_iter_begin)); 415 | 416 | //get get a vector for the permutations 417 | //thrust::device_vector permutation(input_size); 418 | //thrust::sequence(permutation.begin(), permutation.end()); 419 | 420 | //sort by id of the lhs 421 | //thrust::sort_by_key(lhs_ids.begin(), lhs_ids.begin() + input_size, permutation.begin()); 422 | 423 | //orient sorting 424 | //thrust::sort(in_iter_begin, input_end, soa::comm_equation_greater()); 425 | 426 | //if (verbose) { 427 | // print_range("permutation", permutation.begin(), permutation.end()); 428 | //} 429 | //if (verbose) { 430 | // std::cout << "empty aux vector (size = " << aux_input_size <<" ):\n--------------\n"; 431 | // print_equations( host_vector(aux_iter_begin, aux_iter_begin + aux_input_size) ); 432 | //} 433 | ////gather the sorted elements into the aux vector 434 | //thrust::gather(permutation.begin(), permutation.end(), in_iter_begin, aux_iter_begin); 435 | 436 | //crappy sort 437 | // TODO copying isnt really slow 438 | thrust::copy(in_iter_begin, input_end, aux_iter_begin); 439 | thrust::sort_by_key(lhs_ids.begin(), lhs_ids.begin() + input_size, aux_iter_begin); 440 | 441 | if (verbose) { 442 | std::cout << "sorted aux vector (size = " << aux_input_size <<" ):\n--------------\n"; 443 | print_equations( host_vector(aux_iter_begin, aux_iter_begin + aux_input_size) ); 444 | } 445 | StopWatch::get(interaction_watch).stop(); 446 | 447 | /*------------------------ 448 | / Communication step 449 | --------------------------*/ 450 | StopWatch::get(communication_watch).start(); 451 | // parallel communication 452 | num_communications = comm_step_parallel( 453 | aux_iter_begin, aux_iter_begin + input_size, 454 | in_iter_begin, input_end, 455 | aux_lhs_ids.begin(), aux_lhs_ids.begin() + input_size, 456 | input_size, 457 | communication_watch); 458 | input_size = input_end - in_iter_begin; 459 | 460 | if (verbose) { 461 | std::cout << "post communicate (input_size = " << input_size <<" ):\n--------------\n"; 462 | print_equations( host_vector(in_iter_begin, input_end) ); 463 | print_equations( host_vector(input_end, in_iter_end) ); 464 | } 465 | 466 | //// invalid test 467 | //if (thrust::any_of(in_iter_begin, in_iter_end, is_invalid_tuple() ) ) { 468 | // std::cout << "invalid tuple after communicate detected!\n"; 469 | // break; 470 | //} 471 | /*------------------------------ 472 | / communication end 473 | -------------------------------*/ 474 | StopWatch::get(communication_watch).stop(); 475 | 476 | 477 | /*------------------------------ 478 | / cleanup 479 | -------------------------------*/ 480 | //interaction statisitics 481 | total_interactions += num_interactions; 482 | 483 | // exit condition 484 | // no interactions and no communications in the previous loop 485 | if (num_interactions < 1 && num_communications < 1) { 486 | break; 487 | } 488 | 489 | //resize if necessary 490 | if (vector_size < (input_size * 4) ) { 491 | //resize 492 | vector_size = input_size * 4; 493 | //resize to full vector size 494 | lhs_ids.resize(vector_size); lhs_arities.resize(vector_size); lhs_names.resize(vector_size); 495 | lhs_p1s.resize(vector_size); lhs_p2s.resize(vector_size); lhs_p3s.resize(vector_size); lhs_p4s.resize(vector_size); 496 | rhs_ids.resize(vector_size); rhs_arities.resize(vector_size); rhs_names.resize(vector_size); 497 | rhs_p1s.resize(vector_size); rhs_p2s.resize(vector_size); rhs_p3s.resize(vector_size); rhs_p4s.resize(vector_size); 498 | //resize normal vector 499 | normal.resize(vector_size); 500 | thrust::fill(normal.begin(), normal.end(), false); 501 | //redo iterators 502 | //input 503 | lhs_iter_begin = thrust::make_zip_iterator( 504 | thrust::make_tuple( lhs_ids.begin(),lhs_names.begin(),lhs_arities.begin(), 505 | lhs_p1s.begin(),lhs_p2s.begin(),lhs_p3s.begin(), lhs_p4s.begin()) ); 506 | rhs_iter_begin = thrust::make_zip_iterator( 507 | thrust::make_tuple( rhs_ids.begin(), rhs_names.begin(), rhs_arities.begin(), 508 | rhs_p1s.begin(), rhs_p2s.begin(), rhs_p3s.begin(), rhs_p4s.begin() ) ); 509 | 510 | lhs_iter_end = thrust::make_zip_iterator( 511 | thrust::make_tuple( lhs_ids.end(),lhs_names.end(),lhs_arities.end(), 512 | lhs_p1s.end(),lhs_p2s.end(),lhs_p3s.end(),lhs_p4s.end()) ); 513 | rhs_iter_end = thrust::make_zip_iterator( 514 | thrust::make_tuple( rhs_ids.end(), rhs_names.end(), rhs_arities.end(), 515 | rhs_p1s.end(), rhs_p2s.end(), rhs_p3s.end(), rhs_p4s.end() ) ); 516 | 517 | in_iter_begin = make_zip_iterator(make_tuple(lhs_iter_begin, rhs_iter_begin)); 518 | in_iter_end = make_zip_iterator(make_tuple(lhs_iter_end, rhs_iter_end)); 519 | //end of the actual input 520 | input_end = in_iter_begin + input_size; 521 | 522 | if (verbose) { 523 | std::cout << "post resize (input_size = " << input_size <<" )::\n--------------\n"; 524 | print_equations( host_vector(in_iter_begin, input_end) ); 525 | print_equations( host_vector(input_end, in_iter_end) ); 526 | } 527 | } 528 | 529 | //cleanup functor 530 | thrust::fill(lhs_ids.begin() + input_size, lhs_ids.end(), 0); 531 | thrust::fill(rhs_ids.begin() + input_size, rhs_ids.end(), 0); 532 | 533 | //if (verbose) { 534 | //std::cout << "post cleanup:\n--------------\n"; 535 | // print_equations( host_vector(in_iter_begin, input_end) ); 536 | // print_equations( host_vector(input_end, in_iter_end) ); 537 | //} 538 | 539 | 540 | normal.resize(input_size, false); 541 | 542 | if (verbose) { 543 | std::cout << "\n-------------------------------------\n"; 544 | std::cout << "end of interaction loop\n"; 545 | std::cout << "-------------------------------------\n"; 546 | if (pause) { 547 | std::cout << "press a key to continue\n"; 548 | getch(); 549 | } 550 | } 551 | } while (true); 552 | /*--------------------- 553 | / END OF LOOP 554 | -----------------------*/ 555 | 556 | if (print_final) { 557 | std::cout << "\n result\n-----------\n"; 558 | print_equations( host_vector(in_iter_begin, input_end) ); 559 | } 560 | 561 | //compute result for addition tests 562 | int s = thrust::count_if(in_iter_begin, input_end, has_name_tuple('S')); 563 | //std::cout << "S symbols: " << s << std::endl; 564 | 565 | //highest index: 566 | std::cout << "maximum index used: " << dev_ptr[0] << std::endl; 567 | // stop and destroy timer 568 | float int_time = StopWatch::get(interaction_watch).getTime() / 1000.0; 569 | float com_time = StopWatch::get(communication_watch).getTime() / 1000.0; 570 | printf ("total interaction time %.5f seconds.\n", int_time ); 571 | printf ("total communication time %.5f seconds.\n", com_time ); 572 | StopWatch::destroy(communication_watch); 573 | StopWatch::destroy(interaction_watch); 574 | 575 | return result_info(s, num_loops, total_interactions, com_time, int_time); 576 | 577 | } 578 | 579 | 580 | // 581 | //// interaction combinators 582 | //struct add_functor 583 | //{ 584 | //template 585 | //__host__ __device__ 586 | //void operator()(Tuple equations) 587 | //{ 588 | // //get lhs and rhs of the equations 589 | // agent lhs = thrust::get<0>(equations); 590 | // agent rhs = thrust::get<1>(equations); 591 | // 592 | // // default: no interaction was performed 593 | // thrust::get<8>(equations) = false; 594 | // 595 | // 596 | // // if both sides are agents 597 | // // rewrite the equations 598 | // 599 | // if (is_upper( get(lhs) ) && is_upper( get(lhs) )) { 600 | // 601 | // //sort pair lexicographically (active pairs are symmetric) 602 | // if (get(rhs) < get(lhs) ) { 603 | // lhs = rhs; 604 | // rhs = thrust::get<0>(equations); 605 | // } 606 | // 607 | // name_type lhs_name = get(lhs); 608 | // name_type rhs_name = get(rhs); 609 | // 610 | // // A(r, y) >< 0 => r~y 611 | // if (lhs_name == 'A' && rhs_name == 'O') { 612 | // 613 | // //r~y 614 | // thrust::get<0>(equations) = make_agent(get(lhs), 'r', 0); 615 | // thrust::get<1>(equations) = make_agent(get(lhs), 'y', 0); 616 | // 617 | // thrust::get<8>(equations) = true; // we performed an interaction 618 | // } 619 | // // A(r, y) >< S(x) => r~S(w), A(w, y)~x 620 | // else if (lhs_name == 'A' && rhs_name == 'S') { 621 | // int new_index = thrust::get<9>(equations); 622 | // thrust::get<9>(equations) = -1; //remove used index 623 | // //wires 624 | // int x = get(rhs); 625 | // int r = get(lhs); 626 | // int w = new_index; // new variable w 627 | // 628 | // // r~S(w) 629 | // get(rhs) = w; 630 | // thrust::get<0>(equations) = make_agent(r, 'r', 0); 631 | // thrust::get<1>(equations) = rhs; 632 | // // A(w, y)~x 633 | // get(lhs) = w; 634 | // thrust::get<2>(equations) = make_agent(x, 'x', 0); 635 | // thrust::get<3>(equations) = lhs; 636 | // 637 | // thrust::get<8>(equations) = true; // we performed an interaction 638 | // } 639 | // } 640 | // } 641 | //}; 642 | -------------------------------------------------------------------------------- /kernel.cu: -------------------------------------------------------------------------------- 1 | 2 | #include "cuda.h" 3 | #include "kernel.h" 4 | #include "cuda_runtime.h" 5 | #include "device_launch_parameters.h" 6 | #include "device_functions.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include "agent.cuh" 46 | #include "ackermann.h" 47 | #include "communication.h" 48 | #include "fibonacci.h" 49 | #include "algae.h" 50 | #include "config_manager.h" 51 | 52 | #include 53 | #include 54 | //#include "parse_net.h" 55 | 56 | //print a vector 57 | //template 58 | //void print_range(const std::string& name, Iterator first, Iterator last) 59 | //{ 60 | // typedef typename std::iterator_traits::value_type T; 61 | // 62 | // std::cout << name << ": "; 63 | // thrust::copy(first, last, std::ostream_iterator(std::cout, " ")); 64 | // std::cout << std::endl; 65 | //} 66 | 67 | /*------------------------- 68 | Interaction Nets Evaluation 69 | -------------------------*/ 70 | 71 | result_info partition_interaction_step(const int ruleset, 72 | thrust::host_vector& in_lhs_host, thrust::host_vector& in_rhs_host, const bool verbose, const bool print_final_result, const bool pause) 73 | { 74 | // --------- 75 | // constants 76 | // --------- 77 | //input size 78 | int input_size = in_lhs_host.size(); 79 | 80 | //make a device pointer for tracking agent indices 81 | //------------------------------------------ 82 | const size_t ptr_size = 1; 83 | //create a dev ptr 84 | thrust::device_ptr dev_ptr = thrust::device_malloc(ptr_size); 85 | //TODO: ugly hardcoded intial index again! 86 | dev_ptr[0] = 100; 87 | int maximum_index = 100; //track max index, to check for int overflow 88 | 89 | std::cout << "done allocating\n"; 90 | //extract the raw pointer 91 | int * index_ptr = thrust::raw_pointer_cast(dev_ptr); 92 | 93 | 94 | // transfer the input to the device 95 | //--------------------------------- 96 | thrust::device_vector in_lhs(in_lhs_host); 97 | thrust::device_vector in_rhs(in_rhs_host); 98 | 99 | // paritioning 100 | //------------ 101 | 102 | //zip lhs and rhs together 103 | equation_iter in_begin = thrust::make_zip_iterator( thrust::make_tuple(in_lhs.begin(), in_rhs.begin() ) ); 104 | equation_iter in_end = thrust::make_zip_iterator( thrust::make_tuple(in_lhs.end(), in_rhs.end() ) ); 105 | 106 | //get the partition between aps and tlvs 107 | is_active_functor active_functor; 108 | equation_iter in_partition = thrust::partition(in_begin, in_end, active_functor); 109 | 110 | int ap_size = in_partition - in_begin; 111 | //create two vector pairs: active pairs (aps) and top-level variable equations (tlvs) 112 | thrust::device_vector aps_L(in_lhs.begin(), in_lhs.begin() + ap_size); 113 | thrust::device_vector aps_R(in_rhs.begin(), in_rhs.begin() + ap_size); 114 | thrust::device_vector tlvs_L(in_lhs.begin() + ap_size, in_lhs.end()); 115 | thrust::device_vector tlvs_R(in_rhs.begin() + ap_size, in_rhs.end()); 116 | 117 | equation_iter aps_begin = thrust::make_zip_iterator( thrust::make_tuple(aps_L.begin(), aps_R.begin() ) ); 118 | equation_iter aps_end = thrust::make_zip_iterator( thrust::make_tuple(aps_L.end(), aps_R.end() ) ); 119 | equation_iter tlvs_begin = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.begin(), tlvs_R.begin() ) ); 120 | equation_iter tlvs_end = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.end(), tlvs_R.end() ) ); 121 | 122 | std::cout << "aps:\n"; 123 | //TODO sorting aps is perhaps unneccessary 124 | thrust::sort(aps_begin, aps_end, smaller_tlv_functor()); 125 | print_equations(aps_L, aps_R); 126 | thrust::sort(tlvs_begin, tlvs_end, smaller_tlv_functor()); 127 | std::cout << "tlvs:\n"; 128 | print_equations(tlvs_L, tlvs_R); 129 | 130 | //new result arrays 131 | thrust::device_vector a_L(ap_size); 132 | thrust::device_vector a_R(ap_size); 133 | thrust::device_vector b_L(ap_size); 134 | thrust::device_vector b_R(ap_size); 135 | thrust::device_vector c_L(ap_size); 136 | thrust::device_vector c_R(ap_size); 137 | 138 | //result vectors 139 | thrust::host_vector result_lhs(in_lhs.size()); 140 | thrust::host_vector result_rhs(in_rhs.size()); 141 | 142 | if (verbose) { 143 | print_equations(in_lhs, in_rhs); 144 | } 145 | 146 | //loop variable 147 | //int num_interactions = 0; 148 | int num_loops = 0; 149 | //int total_interactions = 0; 150 | int total_interactions_partition = 0; 151 | 152 | //functor selection 153 | //----------------- 154 | ackermann_functor ack_functor(index_ptr); 155 | //add_functor functor; 156 | //ic_functor functor2; 157 | //fibonacci_functor functor(index_ptr); 158 | algae_functor alg_functor(index_ptr); 159 | 160 | //stopwatches 161 | const unsigned int interaction_watch = StopWatch::create(); 162 | const unsigned int communication_watch = StopWatch::create(); 163 | 164 | // --------------- 165 | // start of loop 166 | // --------------- 167 | do { 168 | 169 | if (verbose) { 170 | std::cout << "aps:\n"; 171 | print_equations(aps_begin, aps_end); 172 | } 173 | 174 | //original int start position 175 | StopWatch::get(interaction_watch).start(); 176 | // ------------------------------------------- 177 | // apply interaction step to list of equations 178 | // ------------------------------------------- 179 | switch (ruleset) { 180 | case 1: 181 | //ap only version 182 | thrust::for_each( 183 | thrust::make_zip_iterator(thrust::make_tuple( 184 | aps_L.begin(), 185 | aps_R.begin(), 186 | a_L.begin(), a_R.begin(), b_L.begin(), b_R.begin(), c_L.begin(), c_R.begin(), thrust::make_discard_iterator() ) ), 187 | thrust::make_zip_iterator(thrust::make_tuple( 188 | aps_L.end(), 189 | aps_R.end(), 190 | a_L.end(), a_R.end(), b_L.end(), b_R.end(), c_L.end(), c_R.end(), thrust::make_discard_iterator() ) ), 191 | ack_functor 192 | ); 193 | break; 194 | case 2: 195 | //ap only version 196 | thrust::for_each( 197 | thrust::make_zip_iterator(thrust::make_tuple( 198 | aps_L.begin(), 199 | aps_R.begin(), 200 | a_L.begin(), a_R.begin(), b_L.begin(), b_R.begin(), c_L.begin(), c_R.begin(), thrust::make_discard_iterator() ) ), 201 | thrust::make_zip_iterator(thrust::make_tuple( 202 | aps_L.end(), 203 | aps_R.end(), 204 | a_L.end(), a_R.end(), b_L.end(), b_R.end(), c_L.end(), c_R.end(), thrust::make_discard_iterator() ) ), 205 | alg_functor 206 | ); 207 | break; 208 | 209 | } 210 | 211 | //------------------------------------------------ 212 | // end of interaction step 213 | //------------------------------------------------ 214 | 215 | //StopWatch::get(interaction_watch).stop(); 216 | 217 | if (verbose) { 218 | std::cout << "partition interactions: " << ap_size << "\n"; 219 | } 220 | 221 | // partition interaction count 222 | total_interactions_partition += ap_size; 223 | 224 | //StopWatch::get(interaction_watch).stop(); 225 | // merge equation arrays 226 | // TODO less copy operations 227 | // AP only copying 228 | // ---------------- 229 | 230 | aps_L.resize(ap_size * 4); 231 | aps_R.resize(ap_size * 4); 232 | 233 | // append A to aps 234 | thrust::copy(a_L.begin(), a_L.end(), aps_L.begin() + ap_size); 235 | thrust::copy(a_R.begin(), a_R.end(), aps_R.begin() + ap_size); 236 | 237 | // append B to aps 238 | thrust::copy(b_L.begin(), b_L.end(), aps_L.begin() + ap_size*2); 239 | thrust::copy(b_R.begin(), b_R.end(), aps_R.begin() + ap_size*2); 240 | 241 | // append C to aps 242 | thrust::copy(c_L.begin(), c_L.end(), aps_L.begin() + ap_size*3); 243 | thrust::copy(c_R.begin(), c_R.end(), aps_R.begin() + ap_size*3); 244 | 245 | if (verbose) { 246 | std::cout << "aps after result merge:\n---------------\n"; 247 | print_equations(aps_L, aps_R); 248 | } 249 | 250 | //remove dummy equations for aps 251 | // TODO do I need to reset aps_begin aswell? 252 | aps_begin = thrust::make_zip_iterator( thrust::make_tuple(aps_L.begin(), aps_R.begin() ) ); 253 | aps_end = thrust::make_zip_iterator( thrust::make_tuple(aps_L.end(), aps_R.end() ) ); 254 | // note: remove_if is stable 255 | equation_iter aps_new_end = thrust::remove_if( 256 | aps_begin, 257 | aps_end, 258 | dummy_test_functor_tuple() 259 | ); 260 | 261 | //TODO make this conditional if no dummies have been removed 262 | ap_size = aps_new_end - aps_begin; 263 | aps_L.resize(ap_size); 264 | aps_R.resize(ap_size); 265 | //update iterators 266 | aps_begin = thrust::make_zip_iterator( thrust::make_tuple(aps_L.begin(), aps_R.begin() ) ); 267 | aps_end = thrust::make_zip_iterator( thrust::make_tuple(aps_L.end(), aps_R.end() ) ); 268 | 269 | //if (verbose) { 270 | // std::cout << "aps after dummy removal:\n---------------\n"; 271 | // print_equations(aps_L, aps_R); 272 | //} 273 | 274 | //aps 275 | //partition result again by aps and tlvs 276 | //TODO is it faster just to sort? 277 | equation_iter aps_partition = thrust::partition(aps_begin, aps_end, active_functor); 278 | if (verbose) { 279 | std::cout << "new tlvs: " << (aps_end - aps_partition) << std::endl; 280 | } 281 | 282 | //we only care about sortedness of tlvs 283 | thrust::sort(aps_partition, aps_end, smaller_tlv_functor()); 284 | 285 | if (verbose) { 286 | std::cout << "aps after dummy removal and sort:\n---------------\n"; 287 | print_equations(aps_L, aps_R); 288 | } 289 | 290 | //original int watch position 291 | StopWatch::get(interaction_watch).stop(); 292 | 293 | // -------------------------------------------------------------------- 294 | // communication part: find eligible tlv pairs and reduce them to an AP 295 | // -------------------------------------------------------------------- 296 | /*StopWatch::get(communication_watch).start();*/ 297 | 298 | // the result may contain communication-eligible pairs of TLVs 299 | // sort out duplicate tlvs with unique 300 | // ------------------------------------ 301 | //non-uniques vector 302 | thrust::device_vector uniques(aps_L.size()); 303 | //number of APs after interaction 304 | int num_post_int_aps = aps_partition - aps_begin; 305 | //number of TLVS after interaction 306 | int num_post_int_tlvs = aps_end - aps_partition; 307 | //get unique TLV equations 308 | auto uniques_end = thrust::unique_copy(aps_partition, aps_end, uniques.begin(), equal_tlv_functor()); 309 | int num_uniques = uniques_end - uniques.begin(); 310 | if (num_uniques < num_post_int_tlvs) { 311 | // there are non_unique tlvs, we need to move them from the aps vector to the tlvs vector 312 | uniques.resize(num_uniques); 313 | if (verbose) { 314 | std::cout << "we have uniques:" << num_uniques << " (of " << num_post_int_tlvs << " tlvs), loop "<< num_loops <<" \n---------------------\n"; 315 | print_equations(uniques); 316 | } 317 | //get the non_uniques 318 | //TODO maximum size for non-unique tlvs: num_post_int_tlvs - num_uniques? 319 | thrust::device_vector non_uniques(num_post_int_tlvs - num_uniques); 320 | //get the non_uniques via set_difference 321 | //unique_copy is not stable, so sort it again 322 | thrust::sort(uniques.begin(), uniques.end(), smaller_tlv_functor()); 323 | thrust::sort(aps_partition, aps_end, smaller_tlv_functor()); 324 | 325 | if (verbose) { 326 | std::cout << "aps, tlv partition, loop " << num_loops << ": \n"; 327 | print_equations(aps_partition, aps_end); 328 | } 329 | assert( ((aps_end - aps_partition) - num_uniques) == num_post_int_tlvs - uniques.size()); 330 | //random weirdness testing 331 | //if (num_loops == 16) { 332 | // thrust::device_vector bla(aps_partition + config_manager::get_int("set_diff_test_start"), aps_partition + config_manager::get_int("set_diff_test_length")); 333 | // std::cout << "auxiliary aps testing " << num_loops << ": \n"; 334 | // print_equations(bla); 335 | // auto non_uniques_end = thrust::set_difference(bla.begin(), bla.end(), uniques.begin(), uniques.end(), non_uniques.begin(), smaller_tlv_functor()); 336 | // std::cout << "set_diff with aps empty:\n"; 337 | // int size = non_uniques_end - non_uniques.begin(); 338 | // print_equations(non_uniques); 339 | //} 340 | // set_difference is fine, no in-place update 341 | auto non_uniques_end = thrust::set_difference(aps_partition, aps_end, uniques.begin(), uniques.end(), non_uniques.begin(), smaller_tlv_functor()); 342 | if (verbose) { 343 | std::cout << "got past set difference\n"; 344 | } 345 | //if (verbose) { 346 | // std::cout << "non_uniques pre _resize: \n---------------------\n"; 347 | // print_equations(non_uniques); 348 | //} 349 | int num_non_uniques = non_uniques_end - non_uniques.begin(); 350 | if (verbose) { 351 | std::cout << "num_non_uniques: " << num_non_uniques << std::endl; 352 | } 353 | non_uniques.resize(num_non_uniques); 354 | if (verbose) { 355 | std::cout << "non_uniques:" << num_non_uniques << " \n---------------------\n"; 356 | print_equations(non_uniques); 357 | } 358 | // the non_uniques vector should be completely filled, assert that 359 | //std::cout << (non_uniques_end - non_uniques.begin()) << " vs " << (non_uniques.end() - non_uniques.begin()) << std::endl; 360 | //assert( (non_uniques_end - non_uniques.begin()) == non_uniques.size() ); 361 | //remove non_uniques from aps vector 362 | //TODO safe to assign aps_end right away? 363 | aps_end = thrust::unique(aps_partition, aps_end, equal_tlv_functor()); 364 | //resize and update iterators 365 | aps_L.resize(aps_end - aps_begin); 366 | aps_R.resize(aps_end - aps_begin); 367 | aps_begin = thrust::make_zip_iterator( thrust::make_tuple(aps_L.begin(), aps_R.begin() ) ); 368 | aps_end = thrust::make_zip_iterator( thrust::make_tuple(aps_L.end(), aps_R.end() ) ); 369 | aps_partition = aps_begin + num_post_int_aps; 370 | if (verbose) { 371 | std::cout << "aps after unique removal:" << num_non_uniques << " \n---------------------\n"; 372 | print_equations(aps_L, aps_R); 373 | } 374 | if (verbose) { 375 | std::cout << "previous tlvs: \n---------------------\n"; 376 | print_equations(tlvs_L, tlvs_R); 377 | } 378 | //merge non_uniques into tlvs vector 379 | int old_tlv_size = tlvs_L.size(); 380 | tlvs_L.resize(tlvs_L.size() + non_uniques.size()); 381 | tlvs_R.resize(tlvs_R.size() + non_uniques.size()); 382 | //tlv iterator update 383 | tlvs_begin = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.begin(), tlvs_R.begin() ) ); 384 | tlvs_end = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.end(), tlvs_R.end() ) ); 385 | // TODO remove in-place update 386 | //tlvs_end = thrust::merge(non_uniques.begin(), non_uniques.end(), tlvs_begin, tlvs_begin + old_tlv_size, tlvs_begin, smaller_tlv_functor()); 387 | //instead of merge, copy and then sort 388 | //TODO triangle swap with extra vector and merge could be faster 389 | tlvs_end = thrust::copy(non_uniques.begin(), non_uniques.end(), tlvs_begin + old_tlv_size); 390 | thrust::sort( tlvs_begin, tlvs_end, smaller_tlv_functor() ); 391 | if (verbose) { 392 | std::cout << "unique merged tlvs: \n---------------------\n"; 393 | print_equations(tlvs_L, tlvs_R); 394 | } 395 | 396 | } 397 | 398 | //determine the maximum number of communications 399 | int max_communications = aps_end - aps_partition; 400 | int num_non_intersecting_tlvs = max_communications; 401 | 402 | thrust::device_vector tlv_intersection_1(0); 403 | // intersection 1: find the PREVIOUS tlvs that appear in the result 404 | // ---------------------------------------------------------------- 405 | if ( tlvs_begin != tlvs_end && (max_communications > 0) ) { 406 | tlv_intersection_1.resize( (tlvs_end - tlvs_begin) + (aps_end - aps_partition) ); 407 | thrust::sort(aps_partition, aps_end, smaller_tlv_functor()); 408 | thrust::sort(tlvs_begin, tlvs_end, smaller_tlv_functor()); 409 | if (verbose) { 410 | //std::cout << "tlvs:\n---------------\n"; 411 | std::cout << "max communications: " << max_communications << std::endl; 412 | //std::cout << "got till 1nd intersection computation (sorted stuff before)\n"; 413 | } 414 | //set-intersection is fine here, no in-place update 415 | auto intersection_end = thrust::set_intersection(tlvs_begin, tlvs_end, aps_partition, aps_end, tlv_intersection_1.begin(), smaller_tlv_functor()); 416 | tlv_intersection_1.resize( intersection_end - tlv_intersection_1.begin() ); 417 | } 418 | 419 | if (verbose) { 420 | //std::cout << "got till 2nd intersection computation\n"; 421 | } 422 | 423 | // intersection 2: find the RESULT tlvs that appear in intersection 1 424 | // ------------------------------------------------------------------ 425 | thrust::device_vector tlv_intersection_2(tlv_intersection_1.size()); 426 | if (tlv_intersection_1.size() > 0 ) { 427 | //intersection is fine, no in-place update 428 | auto intersection_end2 = thrust::set_intersection(aps_partition, aps_end, tlv_intersection_1.begin(), tlv_intersection_1.end(), tlv_intersection_2.begin(), smaller_tlv_functor()); 429 | tlv_intersection_2.resize( intersection_end2 - tlv_intersection_2.begin() ); 430 | num_non_intersecting_tlvs -= tlv_intersection_2.size(); 431 | 432 | } 433 | 434 | if (verbose) { 435 | std::cout << "tlvs:\n---------------\n"; 436 | print_equations(tlvs_L, tlvs_R); 437 | } 438 | 439 | 440 | // ----------------------------------------------- 441 | // partitioned communication step of intersections 442 | // communicate the items of intersections 1 and 2 pairwise 443 | // ----------------------------------------------- 444 | if (tlv_intersection_1.size() > 0) { 445 | if (verbose) { 446 | std::cout << "tlv intersections (1): \n---------------------\n"; 447 | print_equations(tlv_intersection_1); 448 | std::cout << " + (2) \n"; 449 | print_equations(tlv_intersection_2); 450 | } 451 | 452 | // communication happens here! 453 | comm_functor cf; 454 | // transform allows in-place update 455 | thrust::transform(tlv_intersection_1.begin(), tlv_intersection_1.end(), tlv_intersection_2.begin(), tlv_intersection_1.begin(), cf); 456 | 457 | if (verbose) { 458 | std::cout << "partition communication result (intersection 1): \n---------------------\n"; 459 | print_equations(tlv_intersection_1); 460 | } 461 | } 462 | 463 | 464 | 465 | 466 | // ---------------- 467 | // partition update 468 | // ---------------- 469 | 470 | //move non-intersecting tlvs to tlvs vector 471 | // ---------------------------------------- 472 | //make a new vector for the non-intersecting tlvs 473 | //TODO this will break if non-intersecting tlvs contains two communication-eligible tlvs! 474 | if (num_non_intersecting_tlvs > 0) { 475 | thrust::device_vector non_intersecting_tlvs((aps_end - aps_partition) + tlv_intersection_2.size()); 476 | //only do set difference if there are intersects 477 | if (tlv_intersection_2.size() > 0) { 478 | //TODO stuff crashes here 479 | // maybe size isnt right? 480 | thrust::sort(aps_partition, aps_end, smaller_tlv_functor()); 481 | thrust::sort(tlv_intersection_2.begin(), tlv_intersection_2.end(), smaller_tlv_functor()); 482 | if (verbose) { 483 | std::cout << "compute non-intersecting tlvs, loop "<< num_loops <<"\n"; 484 | std::cout << "current aps: \n---------------------\n"; 485 | print_equations(aps_L, aps_R); 486 | std::cout << " (intersection 2) \n---------------------\n"; 487 | print_equations(tlv_intersection_2); 488 | } 489 | // set operation is fine, no in-place-update 490 | auto non_intersect_end = thrust::set_difference(aps_partition, aps_end, tlv_intersection_2.begin(), tlv_intersection_2.end(), non_intersecting_tlvs.begin(), smaller_tlv_functor()); 491 | non_intersecting_tlvs.resize(non_intersect_end - non_intersecting_tlvs.begin()); 492 | if (verbose) { 493 | std::cout << "non-intersecting tlvs: \n---------------------\n"; 494 | print_equations(non_intersecting_tlvs); 495 | } 496 | } 497 | //if there are no intersections, then it means that all tlvs from aps vector should go to tlvs vector straight 498 | else { 499 | if (verbose) { 500 | std::cout << "intersections empty, copying tlvs from aps straight\n"; 501 | } 502 | thrust::copy(aps_partition, aps_end, non_intersecting_tlvs.begin()); 503 | } 504 | //if (verbose) 505 | //{ 506 | //std::cout << "non-intersecting tlvs: \n---------------------\n"; 507 | //print_equations(non_intersecting_tlvs); 508 | //std::cout << "tlvs before merge: \n---------------------\n"; 509 | //print_equations(tlvs_L, tlvs_R); 510 | //} 511 | 512 | //merge into tlvs vector 513 | // TODO will copy keep tlv order? (assumption: only tlvs with new ids will be copied) 514 | int old_tlv_size = tlvs_L.size(); 515 | tlvs_L.resize(old_tlv_size + non_intersecting_tlvs.size()); 516 | tlvs_R.resize(old_tlv_size + non_intersecting_tlvs.size()); 517 | tlvs_begin = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.begin(), tlvs_R.begin() ) ); 518 | // replace merge by copy/sort 519 | // TODO triangle swap + merge might be faster 520 | tlvs_end = thrust::copy(non_intersecting_tlvs.begin(), non_intersecting_tlvs.end(), tlvs_begin + old_tlv_size); 521 | thrust::sort(tlvs_begin, tlvs_end, smaller_tlv_functor() ); 522 | 523 | tlvs_end = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.end(), tlvs_R.end() ) ); 524 | //if (verbose) { 525 | //std::cout << "merged tlvs: \n---------------------\n"; 526 | //print_equations(tlvs_L, tlvs_R); 527 | //} 528 | 529 | } 530 | 531 | // move new APs to aps vector 532 | //partition comm result into aps and tlvs 533 | int num_new_actives = 0; 534 | if (tlv_intersection_1.size() > 0) { 535 | // copy is not stable, but APs dont need to be sorted 536 | thrust::copy(tlv_intersection_1.begin(), tlv_intersection_1.end(), aps_partition); 537 | num_new_actives = tlv_intersection_1.size(); 538 | if (verbose) { 539 | std::cout << "partition: number of new aps:" << num_new_actives << "\n"; 540 | } 541 | } 542 | int num_non_aps = aps_end - aps_partition; 543 | aps_L.resize(aps_L.size() - (num_non_aps - num_new_actives)); 544 | aps_R.resize(aps_R.size() - (num_non_aps - num_new_actives)); 545 | ap_size = aps_L.size(); 546 | 547 | if (verbose) { 548 | std::cout << "new ap partition: \n---------------------\n"; 549 | print_equations(aps_L, aps_R); 550 | } 551 | 552 | if (verbose) { 553 | std::cout << "old tlv partition: \n---------------------\n"; 554 | print_equations(tlvs_L, tlvs_R); 555 | //std::cout << "second tlv intersection: \n---------------------\n"; 556 | //print_equations(tlv_intersection_2); 557 | } 558 | 559 | // move new TLVs to tlvs vector 560 | // only if there are intersections 561 | if (tlv_intersection_2.size() > 0) { 562 | //resize tlvs to maximum possible difference 563 | int tlvs_old_size = tlvs_L.size(); 564 | tlvs_L.resize( tlvs_old_size + tlv_intersection_2.size() ); 565 | tlvs_R.resize( tlvs_R.size() + tlv_intersection_2.size() ); 566 | //update iterators 567 | tlvs_begin = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.begin(), tlvs_R.begin() ) ); 568 | tlvs_end = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.end(), tlvs_R.end() ) ); 569 | if (verbose) { 570 | std::cout << " (intersection 2), loop "<< num_loops <<" \n---------------------\n"; 571 | print_equations(tlv_intersection_2); 572 | } 573 | //assert( thrust::is_sorted(tlvs_begin, tlvs_end, smaller_tlv_functor() ) ); 574 | //assert(thrust::is_sorted(tlv_intersection_2.begin(), tlv_intersection_2.end(), smaller_tlv_functor() ) ); 575 | //if (verbose) { 576 | // thrust::device_vector test(tlvs_R.size()); 577 | // std::cout << "doing the test\n"; 578 | // thrust::copy(tlvs_begin, tlvs_begin + tlvs_old_size, test.begin()); 579 | // std::cout << "copied tlvs\n"; 580 | // thrust::copy(tlv_intersection_2.begin(), tlv_intersection_2.end(), test.begin()); 581 | // std::cout << "copied intersections\n"; 582 | // std::cout << "sorted stuff\n"; 583 | // auto test_end = thrust::set_union(tlvs_begin, tlvs_begin + tlvs_old_size, tlv_intersection_2.begin(), tlv_intersection_2.end(), test.begin(), smaller_tlv_functor()); 584 | // std::cout << " (symmetric difference test 2) \n---------------------\n"; 585 | // print_equations(test); 586 | //} 587 | thrust::sort(tlvs_begin, tlvs_begin + tlvs_old_size, smaller_tlv_functor()); 588 | //TODO why is intersection_2 not sorted here? 589 | thrust::sort(tlv_intersection_2.begin(), tlv_intersection_2.end(), smaller_tlv_functor()); 590 | //TODO remove in-place update 591 | //auto tlvs_new_end = thrust::set_symmetric_difference(tlvs_begin, tlvs_begin + tlvs_old_size, tlv_intersection_2.begin(), tlv_intersection_2.end(), tlvs_begin, smaller_tlv_functor()); 592 | // get an auxiliary vector as large as tlvs and intersection 2 together 593 | thrust::device_vector tlvs_symmetric_diff(tlvs_L.size()); 594 | auto tlvs_new_end = thrust::set_difference(tlvs_begin, tlvs_begin + tlvs_old_size, tlv_intersection_2.begin(), tlv_intersection_2.end(), tlvs_symmetric_diff.begin(), smaller_tlv_functor()); 595 | int tlvs_new_size = tlvs_new_end - tlvs_symmetric_diff.begin(); 596 | //swap tlvs vector and auxiliary vector 597 | //TODO could also use intersection 1 here to save memory? 598 | StopWatch::get(communication_watch).start(); 599 | thrust::swap_ranges(tlvs_symmetric_diff.begin(), tlvs_new_end, tlvs_begin); 600 | StopWatch::get(communication_watch).stop(); 601 | // the symmetric difference should now be in tlvs_L/tlvs_R 602 | 603 | //resize tlvs 604 | tlvs_L.resize(tlvs_new_size); 605 | tlvs_R.resize(tlvs_new_size); 606 | if (verbose) { 607 | std::cout << "new tlv partition: \n---------------------\n"; 608 | print_equations(tlvs_L, tlvs_R); 609 | } 610 | } 611 | 612 | // iterator update 613 | aps_begin = thrust::make_zip_iterator( thrust::make_tuple(aps_L.begin(), aps_R.begin() ) ); 614 | aps_end = thrust::make_zip_iterator( thrust::make_tuple(aps_L.end(), aps_R.end() ) ); 615 | tlvs_begin = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.begin(), tlvs_R.begin() ) ); 616 | tlvs_end = thrust::make_zip_iterator( thrust::make_tuple(tlvs_L.end(), tlvs_R.end() ) ); 617 | 618 | //StopWatch::get(interaction_watch).stop(); 619 | 620 | //update number of loops 621 | num_loops++; 622 | 623 | //maximum index update 624 | int new_maximum_index = dev_ptr[0]; 625 | if (new_maximum_index < maximum_index) { 626 | std::cout << "error: index overflow: " << new_maximum_index << " " << maximum_index << std::endl; 627 | break; 628 | } 629 | maximum_index = new_maximum_index; 630 | 631 | //StopWatch::get(communication_watch).stop(); 632 | //partition termination condition 633 | if (ap_size < 1) { 634 | if (verbose) { 635 | 636 | std::cout << "------------------------\nap partition empty ("<< ap_size <<") , were done!\n------------------------\n"; 637 | } 638 | break; 639 | } 640 | else { 641 | //resize additional result vectors 642 | a_L.clear(); a_R.clear(); 643 | a_L.resize(ap_size); a_R.resize(ap_size); 644 | b_L.clear(); b_R.clear(); 645 | b_L.resize(ap_size); b_R.resize(ap_size); 646 | c_L.clear(); c_R.clear(); 647 | c_L.resize(ap_size); c_R.resize(ap_size); 648 | } 649 | 650 | if (verbose) { 651 | std::cout << "\n-------------------------------------\n"; 652 | std::cout << "end of interaction loop\n"; 653 | std::cout << "-------------------------------------\n"; 654 | if (pause) { 655 | std::cout << "press a key to continue\n"; 656 | getch(); 657 | } 658 | } 659 | 660 | } while (true); 661 | // ------------------------- 662 | // END OF LOOP 663 | // ------------------------- 664 | 665 | //if (!verbose) { 666 | if (print_final_result) { 667 | std::cout << "aps:\n"; 668 | print_equations(aps_L, aps_R); 669 | std::cout << "tlvs:\n"; 670 | print_equations(tlvs_L, tlvs_R); 671 | } 672 | ////compute result for addition tests 673 | //int s = thrust::count_if(result_rhs.begin(), result_rhs.end(), has_name('S')); 674 | int s_part = thrust::count_if(tlvs_R.begin(), tlvs_R.end(), has_name('S')); 675 | 676 | //highest index: 677 | std::cout << "maximum index used: " << maximum_index << std::endl; 678 | // stop and destroy timer 679 | float int_time = StopWatch::get(interaction_watch).getTime() / 1000.0; 680 | float com_time = StopWatch::get(communication_watch).getTime() / 1000.0; 681 | printf ("total interaction time %.5f seconds.\n", int_time ); 682 | printf ("total communication time %.5f seconds.\n", com_time ); 683 | StopWatch::destroy(communication_watch); 684 | StopWatch::destroy(interaction_watch); 685 | 686 | //free index memory 687 | thrust::device_free(dev_ptr); 688 | 689 | return result_info(s_part, num_loops, total_interactions_partition, com_time, int_time); 690 | 691 | } 692 | 693 | 694 | //testing function 695 | result_info test_interaction_step(const int ruleset, 696 | thrust::host_vector& in_lhs_host, thrust::host_vector& in_rhs_host, const bool verbose, const bool print_final_result, const bool pause) 697 | { 698 | // --------- 699 | // constants 700 | // --------- 701 | //input size 702 | int input_size = in_lhs_host.size(); 703 | 704 | //make a device pointer for tracking agent indices 705 | //------------------------------------------ 706 | const size_t ptr_size = 1; 707 | //create a dev ptr 708 | thrust::device_ptr dev_ptr = thrust::device_malloc(ptr_size); 709 | //TODO: ugly hardcoded intial index again! 710 | dev_ptr[0] = 100; 711 | int maximum_index = 100; 712 | 713 | std::cout << "ruleset: " << ruleset << std::endl; 714 | std::cout << "done allocating\n"; 715 | //extract the raw pointer 716 | int * index_ptr = thrust::raw_pointer_cast(dev_ptr); 717 | 718 | 719 | // transfer the input to the device 720 | //--------------------------------- 721 | thrust::device_vector in_lhs(in_lhs_host); 722 | thrust::device_vector in_rhs(in_rhs_host); 723 | //aux vectors for communication 724 | thrust::device_vector aux_lhs(input_size); 725 | thrust::device_vector aux_rhs(input_size); 726 | 727 | 728 | //track whether an interaction step was made 729 | thrust::device_vector normal(input_size); 730 | 731 | //result vectors 732 | thrust::host_vector result_lhs(in_lhs.size()); 733 | thrust::host_vector result_rhs(in_rhs.size()); 734 | 735 | // build the additional results equation array 736 | // -------------------------------------- 737 | if (verbose) { 738 | std::cout << "input (size " << input_size << " ) \n--------\n"; 739 | } 740 | thrust::device_vector a_lhs(input_size); 741 | thrust::device_vector a_rhs(input_size); 742 | thrust::device_vector b_lhs(input_size); 743 | thrust::device_vector b_rhs(input_size); 744 | thrust::device_vector c_lhs(input_size); 745 | thrust::device_vector c_rhs(input_size); 746 | 747 | if (verbose) { 748 | print_equations(in_lhs, in_rhs); 749 | } 750 | 751 | //loop variable 752 | int num_interactions = 0; 753 | int num_loops = 0; 754 | int total_interactions = 0; 755 | int total_interactions_partition = 0; 756 | 757 | //functor 758 | ackermann_functor ack_functor(index_ptr); 759 | //add_functor functor; 760 | //ic_functor functor2; 761 | fibonacci_functor fib_functor(index_ptr); 762 | algae_functor alg_functor(index_ptr); 763 | 764 | //dummy test 765 | valid_tuple_functor dummy_test; 766 | //sort by key functor 767 | get_tlv_single_functor key_functor; 768 | //clearing auxiliary vectors 769 | clear_functor clear; 770 | 771 | //stopwatches 772 | const unsigned int interaction_watch = StopWatch::create(); 773 | const unsigned int communication_watch = StopWatch::create(); 774 | 775 | //result info 776 | result_info info(0,0,0); 777 | 778 | // --------------- 779 | // start of loop 780 | // --------------- 781 | do { 782 | if (verbose) { 783 | std::cout << "regular input " << input_size << ":\n"; 784 | print_equations(in_lhs, in_rhs); 785 | } 786 | 787 | //original int start position 788 | //StopWatch::get(interaction_watch).start(); 789 | // ------------------------------------------- 790 | // apply interaction step to list of equations 791 | // ------------------------------------------- 792 | 793 | //if (verbose) { 794 | // print_range("normal_before", normal.begin(), normal.end()); 795 | //} 796 | switch (ruleset) { 797 | case 1: 798 | thrust::for_each( 799 | thrust::make_zip_iterator(thrust::make_tuple(in_lhs.begin(), in_rhs.begin(), a_lhs.begin(), a_rhs.begin(), b_lhs.begin(), b_rhs.begin(), c_lhs.begin(), c_rhs.begin(), normal.begin() ) ), 800 | thrust::make_zip_iterator(thrust::make_tuple(in_lhs.end(), in_rhs.end(), a_lhs.end(), a_rhs.end(), b_lhs.end(), b_rhs.end(), c_lhs.end(), c_rhs.end(), normal.end() ) ), 801 | ack_functor 802 | ); 803 | break; 804 | case 2: 805 | thrust::for_each( 806 | thrust::make_zip_iterator(thrust::make_tuple(in_lhs.begin(), in_rhs.begin(), a_lhs.begin(), a_rhs.begin(), b_lhs.begin(), b_rhs.begin(), c_lhs.begin(), c_rhs.begin(), normal.begin() ) ), 807 | thrust::make_zip_iterator(thrust::make_tuple(in_lhs.end(), in_rhs.end(), a_lhs.end(), a_rhs.end(), b_lhs.end(), b_rhs.end(), c_lhs.end(), c_rhs.end(), normal.end() ) ), 808 | alg_functor 809 | ); 810 | break; 811 | case 3: 812 | thrust::for_each( 813 | thrust::make_zip_iterator(thrust::make_tuple(in_lhs.begin(), in_rhs.begin(), a_lhs.begin(), a_rhs.begin(), b_lhs.begin(), b_rhs.begin(), c_lhs.begin(), c_rhs.begin(), normal.begin() ) ), 814 | thrust::make_zip_iterator(thrust::make_tuple(in_lhs.end(), in_rhs.end(), a_lhs.end(), a_rhs.end(), b_lhs.end(), b_rhs.end(), c_lhs.end(), c_rhs.end(), normal.end() ) ), 815 | fib_functor 816 | ); 817 | break; 818 | } 819 | 820 | //------------------------------------------------ 821 | // end of interaction step 822 | //------------------------------------------------ 823 | //StopWatch::get(interaction_watch).start(); 824 | //StopWatch::get(interaction_watch).stop(); 825 | //check if we performed one or more interactions 826 | //int_normal_form = thrust::any_of(normal.begin(), normal.end(), thrust::identity()); 827 | //StopWatch::get(interaction_watch).start(); 828 | num_interactions = thrust::count(normal.begin(), normal.end(), true); 829 | if (num_interactions > 0) { 830 | num_loops++; 831 | if (verbose) { 832 | //print_range("normal_after", normal.begin(), normal.end()); 833 | std::cout << "interactions: " << num_interactions << "\n"; 834 | } 835 | } 836 | //else { 837 | // if (verbose) { 838 | // std::cout << "equations are in int normal form\n\n"; 839 | // } 840 | // break; 841 | //} 842 | 843 | // merge equation arrays 844 | // TODO less copy operations 845 | // --------------------- 846 | 847 | in_lhs.resize(input_size * 4); 848 | in_rhs.resize(input_size * 4); 849 | 850 | equation_iter orient_begin = thrust::make_zip_iterator( thrust::make_tuple(in_lhs.begin(), in_rhs.begin() ) ); 851 | equation_iter orient_end = thrust::make_zip_iterator( thrust::make_tuple(in_lhs.end(), in_rhs.end() ) ); 852 | 853 | // append A to IN 854 | orient_end = thrust::copy_if(thrust::make_zip_iterator( thrust::make_tuple(a_lhs.begin(), a_rhs.begin() ) ), 855 | thrust::make_zip_iterator( thrust::make_tuple(a_lhs.end(), a_rhs.end() ) ), 856 | orient_begin + input_size, dummy_test); 857 | //thrust::copy(a_lhs.begin(), a_lhs.end(), in_lhs.begin() + input_size); 858 | //thrust::copy(a_rhs.begin(), a_rhs.end(), in_rhs.begin() + input_size); 859 | 860 | // append B to IN 861 | orient_end = thrust::copy_if(thrust::make_zip_iterator( thrust::make_tuple(b_lhs.begin(), b_rhs.begin() ) ), 862 | thrust::make_zip_iterator( thrust::make_tuple(b_lhs.end(), b_rhs.end() ) ), 863 | orient_end, dummy_test); 864 | //thrust::copy(b_lhs.begin(), b_lhs.end(), in_lhs.begin() + input_size*2); 865 | //thrust::copy(b_rhs.begin(), b_rhs.end(), in_rhs.begin() + input_size*2); 866 | // append C to IN 867 | orient_end = thrust::copy_if(thrust::make_zip_iterator( thrust::make_tuple(c_lhs.begin(), c_rhs.begin() ) ), 868 | thrust::make_zip_iterator( thrust::make_tuple(c_lhs.end(), c_rhs.end() ) ), 869 | orient_end, dummy_test); 870 | //thrust::copy(c_lhs.begin(), c_lhs.end(), in_lhs.begin() + input_size*3); 871 | //thrust::copy(c_rhs.begin(), c_rhs.end(), in_rhs.begin() + input_size*3); 872 | 873 | //std::cout << "\n oriented result\n-----------\n"; 874 | 875 | //remove dummy equations 876 | //equation_iter new_end = thrust::remove_if( 877 | // orient_begin, 878 | // orient_end, 879 | // dummy_test_functor_tuple() 880 | // ); 881 | 882 | input_size = orient_end - orient_begin; 883 | in_lhs.resize(input_size); 884 | in_rhs.resize(input_size); 885 | 886 | //if (new_end != orient_end) { 887 | // input_size = new_end - orient_begin; 888 | // orient_end = new_end; 889 | // in_lhs.resize(input_size); 890 | // in_rhs.resize(input_size); 891 | //} 892 | 893 | 894 | if (verbose) { 895 | std::cout << "after dummy removal:\n---------------\n"; 896 | print_equations(in_lhs, in_rhs); 897 | } 898 | 899 | //StopWatch::get(interaction_watch).stop(); 900 | 901 | StopWatch::get(interaction_watch).start(); 902 | // only perform communication on tlv equations 903 | //auto tlv_iter = thrust::partition(orient_begin, orient_end, is_active_functor()); 904 | equation_iter tlv_iter = orient_begin; 905 | //aps generated by the int step 906 | int num_aps = tlv_iter - orient_begin; 907 | //number of tlvs 908 | int num_tlvs = orient_end - tlv_iter; 909 | 910 | 911 | thrust::transform_iterator keys_begin(in_lhs.begin() + num_aps, key_functor); 912 | thrust::transform_iterator keys_end(in_lhs.end(), key_functor); 913 | 914 | //get the permutation 915 | thrust::device_vector permutation(num_tlvs); 916 | thrust::sequence(permutation.begin(), permutation.end()); 917 | 918 | thrust::sort_by_key(keys_begin, keys_end, permutation.begin()); 919 | 920 | aux_lhs.resize(num_tlvs); 921 | aux_rhs.resize(num_tlvs); 922 | equation_iter aux_begin = thrust::make_zip_iterator( thrust::make_tuple(aux_lhs.begin(), aux_rhs.begin() ) ); 923 | equation_iter aux_end = thrust::make_zip_iterator( thrust::make_tuple(aux_lhs.end(), aux_rhs.end() ) ); 924 | 925 | thrust::gather(permutation.begin(), permutation.end(), orient_begin + num_aps, aux_begin); 926 | 927 | //thrust::stable_sort_by_key(keys_begin, keys_end, orient_begin) 928 | 929 | if (verbose) { 930 | result_lhs = in_lhs; 931 | result_rhs = in_rhs; 932 | std::cout << "\n sorted and oriented result\n-----------\n"; 933 | print_equations(result_lhs, result_rhs); 934 | print_equations(aux_begin, aux_end); 935 | } 936 | 937 | //original int watch position 938 | StopWatch::get(interaction_watch).stop(); 939 | 940 | /*------------------------- 941 | / communication starts here 942 | ---------------------------*/ 943 | 944 | // parallel communication 945 | 946 | StopWatch::get(communication_watch).start(); 947 | //aux vectors to remove in-place udpate 948 | 949 | //one iteration of parallel communication 950 | int steps = comm_step_parallel( aux_begin, aux_end, tlv_iter, orient_end, num_tlvs, num_loops, communication_watch); 951 | // normal form condition 952 | if ((steps == 0) && (num_interactions == 0)) { 953 | if (verbose) { 954 | std::cout << "no more communications, normal form reached\n"; 955 | } 956 | break; 957 | } 958 | int comm_size = orient_end - orient_begin; 959 | if (comm_size < input_size) { 960 | in_lhs.resize(comm_size); 961 | in_rhs.resize(comm_size); 962 | input_size = comm_size; 963 | } 964 | if (verbose) { 965 | result_lhs = in_lhs; 966 | result_rhs = in_rhs; 967 | std::cout << "\n parallel communication result ( "<< steps << " steps) \n-----------\n"; 968 | print_equations(result_lhs, result_rhs); 969 | 970 | print_equations(orient_begin, orient_end); 971 | } 972 | 973 | StopWatch::get(communication_watch).stop(); 974 | /*------------------------- 975 | / communication ends here 976 | ---------------------------*/ 977 | 978 | //maximum index update 979 | int new_maximum_index = dev_ptr[0]; 980 | if (new_maximum_index < maximum_index) { 981 | std::cout << "error: index overflow: " << new_maximum_index << " " << maximum_index << std::endl; 982 | break; 983 | } 984 | //maximum_index = new_maximum_index; 985 | 986 | //clear result vectors 987 | //TODO this is probably slow, can it be done in one for_each transform? 988 | //a_lhs.clear(); a_rhs.clear(); 989 | a_lhs.resize(input_size); a_rhs.resize(input_size); 990 | //b_lhs.clear(); b_rhs.clear(); 991 | b_lhs.resize(input_size); b_rhs.resize(input_size); 992 | //c_lhs.clear(); c_rhs.clear(); 993 | c_lhs.resize(input_size); c_rhs.resize(input_size); 994 | //normal.clear(); 995 | normal.resize(input_size); 996 | thrust::for_each( 997 | thrust::make_zip_iterator(thrust::make_tuple(a_lhs.begin(), a_rhs.begin(), b_lhs.begin(), b_rhs.begin(), c_lhs.begin(), c_rhs.begin(), normal.begin() ) ), 998 | thrust::make_zip_iterator(thrust::make_tuple(a_lhs.end(), a_rhs.end(), b_lhs.end(), b_rhs.end(), c_lhs.end(), c_rhs.end(), normal.end() ) ), 999 | clear_functor() 1000 | ); 1001 | 1002 | //interaction statisitics 1003 | total_interactions += num_interactions; 1004 | //store interactions per loop 1005 | //info.loops_per_step.push_back(num_interactions); 1006 | 1007 | if (verbose) { 1008 | std::cout << "\n-------------------------------------\n"; 1009 | std::cout << "end of interaction loop " << num_loops <<"\n"; 1010 | std::cout << "-------------------------------------\n"; 1011 | if (pause) { 1012 | std::cout << "press a key to continue\n"; 1013 | getch(); 1014 | } 1015 | } 1016 | } while (true); 1017 | 1018 | //if (!verbose) { 1019 | if (print_final_result) { 1020 | result_lhs = in_lhs; 1021 | result_rhs = in_rhs; 1022 | std::cout << "\n result\n-----------\n"; 1023 | print_equations(result_lhs, result_rhs); 1024 | } 1025 | //} 1026 | //std::cout << "total loops: " << num_loops << std::endl; 1027 | //std::cout << "total interactions: " << total_interactions << std::endl; 1028 | //const float avg_interactions = static_cast(total_interactions) / static_cast(num_loops); 1029 | //std::cout << "average interactions per loop: " << avg_interactions << std::endl; 1030 | // 1031 | ////compute result for addition tests 1032 | int s = 0; 1033 | s = thrust::count_if(in_rhs.begin(), in_rhs.end(), has_name('S')); 1034 | std::cout << "total interactions: " << total_interactions_partition << std::endl; 1035 | 1036 | //highest index: 1037 | std::cout << "maximum index used: " << dev_ptr[0] << std::endl; 1038 | // stop and destroy timer 1039 | float int_time = StopWatch::get(interaction_watch).getTime() / 1000.0; 1040 | float com_time = StopWatch::get(communication_watch).getTime() / 1000.0; 1041 | printf ("total interaction time %.5f seconds.\n", int_time ); 1042 | printf ("total communication time %.5f seconds.\n", com_time ); 1043 | StopWatch::destroy(communication_watch); 1044 | StopWatch::destroy(interaction_watch); 1045 | 1046 | //free index memory 1047 | thrust::device_free(dev_ptr); 1048 | 1049 | info.result = s; 1050 | info.num_loops = num_loops; 1051 | info.total_interactions = total_interactions; 1052 | info.com_time = com_time; 1053 | info.int_time = int_time; 1054 | 1055 | return info; 1056 | 1057 | } --------------------------------------------------------------------------------