{"id":21766362,"url":"https://github.com/drilonaliu/parallel-fractal-tree","last_synced_at":"2026-05-19T06:37:13.218Z","repository":{"id":251379332,"uuid":"837230679","full_name":"drilonaliu/Parallel-Fractal-Tree","owner":"drilonaliu","description":"GPU-accelerated fractal tree generation with CUDA and OpenGL interoperability.","archived":false,"fork":false,"pushed_at":"2024-08-12T12:39:03.000Z","size":825,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-21T05:27:22.282Z","etag":null,"topics":["cuda","fractal-tree","fractals","gpu"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drilonaliu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-02T13:44:11.000Z","updated_at":"2024-10-10T22:08:39.000Z","dependencies_parsed_at":"2024-08-02T16:05:29.427Z","dependency_job_id":"2b2c38fb-51ef-4662-805b-7f82dc5a340a","html_url":"https://github.com/drilonaliu/Parallel-Fractal-Tree","commit_stats":null,"previous_names":["drilonaliu/parallel-fractal-tree"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/drilonaliu/Parallel-Fractal-Tree","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Fractal-Tree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Fractal-Tree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Fractal-Tree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Fractal-Tree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drilonaliu","download_url":"https://codeload.github.com/drilonaliu/Parallel-Fractal-Tree/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Fractal-Tree/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33204730,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T09:27:30.708Z","status":"online","status_checked_at":"2026-05-19T02:00:06.763Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cuda","fractal-tree","fractals","gpu"],"created_at":"2024-11-26T13:16:57.239Z","updated_at":"2026-05-19T06:37:13.200Z","avatar_url":"https://github.com/drilonaliu.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Parallel-Fractal-Tree\n GPU-accelerated fractal tree generation with CUDA and OpenGL interoperability.\n \n# Fractal Tree\n\nThe Fractal Tree is a well-known fractal that visually represents the concept of recursion in nature. The construction of this fractal begins with a single trunk, which then splits into two branches at a certain angle. Each of these branches further splits into two smaller branches, continuing this process recursively.  The initial iterations of this fractal are shown below.\n\n\u003cdiv\u003e\n  \u003cp\u003e\n    \u003cimg src=\"images/tree_1.png\" width=\"200\" height=\"200\" alt=\"Tree 1\"\u003e\n    \u003cimg src=\"images/tree_2.png\" width=\"200\" height=\"200\" alt=\"Tree 2\"\u003e\n    \u003cimg src=\"images/tree_3.png\" width=\"200\" height=\"200\" alt=\"Tree 3\"\u003e\n    \u003cimg src=\"images/tree_4.png\" width=\"200\" height=\"200\" alt=\"Tree 4\"\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n## Constructing branches\n\nLet the points $A(x_1, y_1)$ and $B(x_2, y_2)$ be given. We have to find the point\n$C(c_1, c_2)$ such that\n$\\overrightarrow{AB} = \\lambda \\overrightarrow{BC}$, and the points $C'$ and\n$C''$ such that $\\angle CBC' = \\alpha = \\angle CBC''$. \n\n\u003cp\u003e\n   \u003cimg src=\"images/tree_5.png\"\u003e\n\u003c/p\u003e\n\n\\\nFrom the equation $\\overrightarrow{AB} = \\lambda \\overrightarrow{BC}$ we get\n\n$$(x_2 - x_1, y_2 - y_1) = \\lambda (c_1 - x_2, c_2 - y_2)$$\n\n\\\nBy equating the corresponding coordinates of the pairs listed on both sides\nof the equation we get\n\n$$x_2 - x_1 = \\lambda (c_1 - x_2)$$ \n\n$$y_2 - y_1 = \\lambda (c_2 - y_2)$$\n\n\\\nSolving for $c_1$, $c_2$ we get:\n\n$$c_1 = \\frac{x_2 (1 + \\lambda) - x_1}{\\lambda}$$\n\n$$c_2 = \\frac{y_2 (1 + \\lambda) - y_1}{\\lambda}$$\n\n\\\nWe rotate the point $C$ around the point $B$ by the angle $\\alpha$ and get\npoint $C''$ with coordinates:\n\n$$c_1'' = (c_1 - x_2) \\cos(\\alpha) - (c_2 - y_2) \\sin(\\alpha) + x_2$$\n\n$$c_2'' = (c_1 - x_2) \\sin(\\alpha) + (c_2 - y_2) \\cos(\\alpha) + y_2$$\n\n\\\nSimilarly, point $C'$ is obtained by rotating point $C$ around point $B$\nfor the $-\\alpha$ angle.\n\n## Number of vertices \n\\\nLet $f(n)$ be the number of edges of the fractal in $n$ iteration. After\neach iteration, the number of edges doubles and we have:\n\n$$f(n) = 2^0 + 2^1 + 2^2 + \\cdots + 2^n = 2^{n+1} - 1.$$\n\n\\\nEach edge has two points and the number of points will be $2 \\cdot f(n)$,\nand we use this expression to connect the points as segments in part \nvisualization.\n\n```\n void renderTreeFromBuffer() {\n  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);\n  glEnableVertexAttribArray(0);\n  glColor3f(0.0f, 0.0f, 0.0f);\n  int numberOfVertices = 2 * (pow(2, iteration + 1) - 1);\n  glDrawArrays(GL_LINES, 0, numberOfVertices2(iterations));\n  glutSwapBuffers();\n }\n```\n\n## Parallelization\n\nParallelization occurs in a hierarchical manner, where in each iteration they will be\nactive a certain number of threads. Each active thread will get \nthe $i$ -th branch of the picture, and thread $i$ will construct the right branch or\nleft depending on the index. The newly acquired branch is inserted into the array of\nall branches. The size of this array will be $f(n)$.\n\n\\\nFor each iteration there will be $2^n$ active threads. With the increase of\niterations, the number of active threads will rise exponentially:\n\n1. Iteration 0: Only the thread with id 0 is active. This thread initializes the\n initial branch.\n\n2. Iteration 1: Threads 2 and 3 are active. Thread 2 constructs the left branch from the initial branch and inserts it into the branch array at position 2. Thread 3 constructs the right branch and inserts it into the branch array at position 3.\n\n3. Iteration 2: Threads 4, 5, 6, and 7 are active. Threads 4 and 5 construct the left and right branches, respectively, of the branch at position 2 in the array. Threads 6 and 7 construct the left and right branches, respectively, of the branch at position 3 in the array. The created branches are inserted into the branch array for the next iteration.\n\n4. Iteration $n$: Threads $2^n$ to $2^{n+1}-1$ will be active.\nThese threads take the respective branches and, depending on the index, construct the left or right branch.\n\n\u003cp\u003e\n   \u003cimg src=\"images/tree_6.png\"\u003e\n\u003c/p\u003e\n\n\\\nParallelization and data insertion are modeled in a binary graph . Each node in the graph represents a thread that constructs a branch, while the edges of the graph represent the branching in future iterations. \nEach thread $i$ takes the branch from the parent position $i/2$ in the branch array, constructs the right or the\nleft branch, and the newly constructed branch is inserted at position $i$ in the array.\nEach level of the graph represents the threads that are working in parallel.\n\n\\\nThe leftmost index at the level n of the graph is:\n\n$$\\text{leftMost}(n) = 2^n$$ \n\nThe rightmost index at the level n of the graph is:\n\n$$\\text{rightMost}(n) = \\text{leftMost}(n+1) - 1 = 2^{n+1} - 1$$ \n\nNumber of of threads working in parallel at level n is:\n\n$$\\text{leftMost}(n+1) - \\text{leftMost}(n) = 2^{n+1} - 2^n = 2^n$$\n\n## The kernel\n\nThe following kernel generates the fractal through parallel computation. Initially, the thread with index 0 handles the initial branch. For each iteration, threads within the interval start_at to end_at are active and construct new branches. Threads with even index numbers construct the left branches, while threads with odd index numbers construct the right branches. The constructed branches are stored in the branch array, which will be branched in the next iteration. The two endpoints of the branch are added to the points array. Synchronization ensures that all threads complete their tasks before proceeding to the next iteration.\n\n```\n__global__ void branchDivide(float* points, Branch branch, Branch* branches, float angle_left, float angle_right, int start_iteration, int max_iterations, int threadShiftIndex) {\n\n    int idx = threadIdx.x + blockIdx.x * blockDim.x;;\n    idx += threadShiftIndex;\n    \n    Branch childBranch,parentBranch;\n    float angle;\n    auto g = cg::this_grid();\n    \n    if (idx == 0) {\n        points[0] = branch.start.x;\n        points[1] = branch.start.y;\n        points[2] = branch.end.x;\n        points[3] = branch.end.y;\n        branches[1] = branch;\n    }\n    \n    for (int iteration = start_iteration; iteration \u003c= max_iterations; iteration++) {\n        float start_at = round(pow(2, iteration));\n        int end_at = round((pow(2, iteration + 1))) - 1;\n    \n        if (idx \u003e= start_at \u0026\u0026 idx \u003c= end_at) {\n            int parentNode = idx / 2;\n            parentBranch = branches[parentNode];\n            int t = idx % 2;\n            \n            if (t == 0) {\n                angle = angle_left;\n            }\n            else {\n                angle = angle_right;\n            }\n            \n            childBranch = makeChildBranch(parentBranch,angle);\n            branches[idx] = childBranch;\n            //add points to points array;\n            int offset = 2 * 2 * (idx - 1);\n            points[offset] = childBranch.start.x;\n            points[offset + 1] = childBranch.start.y;\n            points[offset + 2] = childBranch.end.x;\n            points[offset + 3] = childBranch.end.y;\n        }\n    g.sync();\n    }\n}\n```\n\n## Comparisons\n\nThe table below compares the execution time in microseconds of the fractal between the sequential version and the parallel version. The CUDA implementation was done using cooperative groups, with 23,040 threads per kernel call. \n\n\u003ctable\u003e\n  \u003ccaption\u003eKTime comparison.\u003c/caption\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003eIterimi\u003c/th\u003e\n      \u003cth\u003eC++\u003c/th\u003e\n      \u003cth\u003eCUDA\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003e23\u003c/td\u003e\u003ctd\u003e27\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003e40\u003c/td\u003e\u003ctd\u003e25\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e2\u003c/td\u003e\u003ctd\u003e47\u003c/td\u003e\u003ctd\u003e23\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e3\u003c/td\u003e\u003ctd\u003e39\u003c/td\u003e\u003ctd\u003e28\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e4\u003c/td\u003e\u003ctd\u003e40\u003c/td\u003e\u003ctd\u003e27\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e5\u003c/td\u003e\u003ctd\u003e58\u003c/td\u003e\u003ctd\u003e27\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e6\u003c/td\u003e\u003ctd\u003e332\u003c/td\u003e\u003ctd\u003e29\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e7\u003c/td\u003e\u003ctd\u003e288\u003c/td\u003e\u003ctd\u003e28\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e8\u003c/td\u003e\u003ctd\u003e105\u003c/td\u003e\u003ctd\u003e26\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e9\u003c/td\u003e\u003ctd\u003e155\u003c/td\u003e\u003ctd\u003e26\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e10\u003c/td\u003e\u003ctd\u003e436\u003c/td\u003e\u003ctd\u003e27\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e11\u003c/td\u003e\u003ctd\u003e541\u003c/td\u003e\u003ctd\u003e24\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e12\u003c/td\u003e\u003ctd\u003e733\u003c/td\u003e\u003ctd\u003e29\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e13\u003c/td\u003e\u003ctd\u003e1563\u003c/td\u003e\u003ctd\u003e29\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e14\u003c/td\u003e\u003ctd\u003e2576\u003c/td\u003e\u003ctd\u003e43\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e15\u003c/td\u003e\u003ctd\u003e4861\u003c/td\u003e\u003ctd\u003e47\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e16\u003c/td\u003e\u003ctd\u003e9027\u003c/td\u003e\u003ctd\u003e89\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e17\u003c/td\u003e\u003ctd\u003e22230\u003c/td\u003e\u003ctd\u003e148\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e18\u003c/td\u003e\u003ctd\u003e37435\u003c/td\u003e\u003ctd\u003e253\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e19\u003c/td\u003e\u003ctd\u003e75886\u003c/td\u003e\u003ctd\u003e382\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e20\u003c/td\u003e\u003ctd\u003e145146\u003c/td\u003e\u003ctd\u003e745\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e21\u003c/td\u003e\u003ctd\u003e294950\u003c/td\u003e\u003ctd\u003e1268\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e22\u003c/td\u003e\u003ctd\u003e584644\u003c/td\u003e\u003ctd\u003e2560\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e23\u003c/td\u003e\u003ctd\u003e1184101\u003c/td\u003e\u003ctd\u003e5265\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e24\u003c/td\u003e\u003ctd\u003e2347734\u003c/td\u003e\u003ctd\u003e142678\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e25\u003c/td\u003e\u003ctd\u003e4705941\u003c/td\u003e\u003ctd\u003e439919\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003e26\u003c/td\u003e\u003ctd\u003e9416423\u003c/td\u003e\u003ctd\u003e789610\u003c/td\u003e\u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\n\u003cp\u003e\n   \u003cimg src=\"images/tree_7.png\"\u003e\n\u003c/p\u003e****\n\n[\\[fig:tree_graph\\]](#fig:tree_graph){reference-type=\"ref\"\nreference=\"fig:tree_graph\"}.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrilonaliu%2Fparallel-fractal-tree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrilonaliu%2Fparallel-fractal-tree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrilonaliu%2Fparallel-fractal-tree/lists"}