From 971dab56b55d3ac6e874e52d061b0dddbcaa75e3 Mon Sep 17 00:00:00 2001 From: cianciosa Date: Mon, 9 Mar 2026 14:08:30 -0400 Subject: [PATCH] Add a case study on kernel performance for PIC code field solve like kernel. This case study shows the affects of loop unrolling on run time performance on the kernels. Partial loop unrolling on the GPU shows a significant performance imporvement on GPU. This may be an effective way to impliment the field solve on the GPU without needing to create a loop or sum nodes in the graph. However, we may need to impliment MAX, MIN nodes or If/Else nodes to deal with functionality involving grid bounds and particle reinjection. --- .gitignore | 4 + graph_docs/kernel_optimization.dox | 141 ++++++++++++++++++++++ graph_docs/kernel_optimization.png | Bin 0 -> 62628 bytes graph_docs/main.dox | 1 + graph_framework.xcodeproj/project.pbxproj | 2 + graph_framework/cuda_context.hpp | 11 ++ graph_framework/metal_context.hpp | 11 ++ 7 files changed, 170 insertions(+) create mode 100644 graph_docs/kernel_optimization.dox create mode 100644 graph_docs/kernel_optimization.png diff --git a/.gitignore b/.gitignore index 3094469..0b22c14 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ .DS_Store build +LLVM +graph_framework.xcodeproj/project.xcworkspace/xcuserdata/ +graph_framework.xcodeproj/xcshareddata/xcschemes/graph_playground.xcscheme +graph_framework.xcodeproj/xcuserdata diff --git a/graph_docs/kernel_optimization.dox b/graph_docs/kernel_optimization.dox new file mode 100644 index 0000000..971619a --- /dev/null +++ b/graph_docs/kernel_optimization.dox @@ -0,0 +1,141 @@ +/*! + * @page kernel_optimization Kernel Optimization + * @brief Notes on optimizing kernel performance. + * @tableofcontents + * @section kernel_optimization_introduction Introduction + * There is a balance kernel run time, compile time, and kernel source code + * size. To discuss these issues we can explore a case study for a simple field + * solve of a Particle In Cell (PIC) code. The field solve involves computing + * the contribution of a every particle to fields. Fields are typically + * discretized onto a grid which will have a smaller size compared to the number + * of particles. + * + * @section kernel_optimization_source Source Code + * Take the example case. + * @code +template +void field_solve_example() { + timing::measure_diagnostic init("Init"); + const size_t batch = 1; + const size_t num_particles = 1000000; + auto particle_positions = graph::variable (num_particles, "x"); + + const size_t num_grid = 1000; + auto grid_value = graph::variable (num_grid, "g"); + auto particle_index = graph::variable (num_grid, "i"); + auto gird_position = graph::variable (num_grid, "gx"); + + std::vector buffer(1000, static_cast (0.0)); + grid_value->set(buffer); + particle_index->set(buffer); + + for (size_t index = 0; index < num_grid; index++) { + buffer[index] = static_cast (2*index)/static_cast (999) + - static_cast (1); + } + gx->set(buffer); + + auto indexed_particle = graph::index_1D(particle_positions, + particle_index, + static_cast (1), + static_cast (0)); + auto next_index = particle_index + static_cast (1.0); + auto arg = indexed_particle - gird_position; + auto next_grid_value = grid_value + + graph::exp(static_cast (-1)*arg*arg/static_cast (10)); + +// Unroll kernel call loop by running multiple iterations in a single kernel +// call. + for (size_t i = 1; i < batch; i++) { + indexed_particle = graph::index_1D(particle_positions, + particle_index, + static_cast (1), + static_cast (0)); + next_index = next_index + static_cast (1.0); + arg = indexed_particle - gird_position; + next_grid_value = next_grid_value + + graph::exp(static_cast (-1)*arg*arg/static_cast (10)); + } + + auto state = graph::random_state (jit::context::random_state_size, 0); + auto random = graph::random (graph::random_state_cast(state)); + const T max = 1.0; + const T min = -1.0; + auto random_real = (max - min)/graph::random_scale ()*random + min; + + init.print(); + + timing::measure_diagnostic compile("compile"); + + workflow::manager work(0); + work.add_preitem({ + graph::variable_cast(particle_positions) + }, {}, { + {random_real, variable_cast(particle_positions)} + }, graph::random_state_cast(state), "Initialize_x", num_particles); + + work.add_item({ + graph::variable_cast(particle_positions), + graph::variable_cast(indexed_particle), + graph::variable_cast(grid_value), + graph::variable_cast(gird_position) + }, {}, { + {next_index, graph::variable_cast(indexed_particle)}, + {next_grid_value, graph::variable_cast(grid_value)} + }, NULL, "Set_Grid", num_grid); + + work.compile(); + + compile.print(); + + work.pre_run(); + timing::measure_diagnostic field_solve("field_solve"); + for (size_t index = 0, ie = num_particles/batch; index < ie; index++) { + work.run(); + } + work.wait(); + field_solve.print(); +} + @endcode + * + * In this example we build two kernels. The Initialize_x kernel set + * random values between @f$1@f$ and @f$-1@f$ for particle positions to + * represent a particle state after a particle push step. This kernel is applied + * over each of the @f$1\times10^{6}@f$ particles. + * + * The Set_Grid kernel mimics a simple field. For a given particle + * position @f$x@f$, the contribution to grid point is defined as + * @f{equation}{g_{next}=g+e^{-\frac{\left(x\left[i\right]-gx\right)^{2}}{10}}@f} + * where @f$i@f$ is the particle index, @f$g@f$ is the current grid value, + * @f$gx@f$ is the grid position, and @f$g_{next}@f$ is the updated value. After + * each kernel call, the particle index is incremented. This kernel is applied + * over each of the @f$1\times10^{3}@f$ gird points. + * + * @section kernel_optimization_performance Kernel Performance + * @image{} html kernel_optimization.png "Wall time scaling comparing compile time and run time for the number of loop unroll iterations." + * In this section we focus on the Set_Grid kernel and the + * batch. When batch = 1, the kernel only adds the kernel + * contribution for a single particle. To compute the full field, we would need + * to call this kernel @f$1\times10^{6}@f$. Setting batch > 1 + * allows us to unroll the kernel call loop. This reduces the number of times we + * need to call the kernel but comes at the expense of a larger kernel and an + * associated compile penalty. If we were to set batch = 1000000 + * then we would fully unroll the loop resulting in only needing to call the + * kernel once. However it would come at the expense of the generated kernel + * source having over @f$1\times10^{6}@f$ lines of code. In testing, loop + * unrolling beyond @f$1\times10^{5}@f$ resulted in a segmentation fault. + * + * The figure above, shows the scaling of the setup time for the graphs, the + * compile time for the kernel and the resulting run time. A benchmark was + * performed on a Apple M1 Pro for both float and double precision. Note that + * the GPU on the M1 Pro only support single precision. CPU benchmark was + * performed on a single core. + * + * Unrolling the loop up to @f$500@f$ iterations shows a significant reduction + * in the GPU kernel run time with a negligible affect on the initialization and + * kernel compile time. Beyond @f$1000@f$ iterations, the improvement to kernel + * runtime becomes negligible. However, any gaines we made in runtime + * improvement is lost due to penalty to kernel compiling. For CPU execution + * there is little to no noticeable performance improvement when unrolling + * kernel call loops. + */ diff --git a/graph_docs/kernel_optimization.png b/graph_docs/kernel_optimization.png new file mode 100644 index 0000000000000000000000000000000000000000..03172cd05dcaa01a040443c18fd182065a267f3c GIT binary patch literal 62628 zcmeAS@N?(olHy`uVBq!ia0y~yVD@2PV9erRV_;y={C;aI0|TRarn7TEwzIo)eolT- za6w{ns$)uiQfiR9lcA-h1p|Y|#N>p8AP*gl6Ny3z2`A2KYjPEp2X%Dx1SQlTJ#gm0 z$pfbqPAE*A5fk%3Lg2w+1{MP;(VE@I4sa~ef8BKE(3IocJA#6`CpUhPS2*XVr=gXY zkZ^`!)6~=6Tn=yK6rxo$rO(7MB#AT1a-`%lZoI7cMmWJ#;G67*SrZh}6@D{MI6Ivs z&A9Q+Bk%SNtPVLV_9`g6m@#SolvNC$_O>lty0lfTvrd7-D@fbRVM}qHV`^Ypm0M?% zvcZxdQJc?`zLtpe@bsLKkZ^d&7x>pwKxSS~Qo2AAM}xp@<%0(v?4Q!u_>|x2%#!Ji ziH&^B%>P4LX3SD#Zf>w+KD^KJ3<{eC+oKW)VHor_se4(zPfkr=i3p z(9wZq%00y|LQxG*-pwnoQ=DJCSyh)GgaGR`V<91S^DJd z{jRPKU+%5H*JRZ%)wzO9P6}om9j%%TpG#g`P`tITcK7```~Uy5et7&w@VR-m-rQn3 zAAFX5eSQ7%w%pq~FJE6<`#J0J^ZE7Lo}BEQyVQI7rHhN*4`*dPKGwS>_4Krc*A_KD z4E}z-9v}H^zHPPH&KSMo!>XX<~vI=`8n|I(+Yr*&`g%UCRk511ib zJJnSFeBax%v(1J79h#`@-Y2jx_@IYEGOO{1&+7kP-PoMY|M2$%&3$!;#q{HR)cxiZ zq#xbdn60w>=>3SMm&fPV|MS$;)MOOr{9>-NdEdi*8*^?N&Ck_~*)ieV9Lr?Ow))-farVr~P1T1csd^vEGcu0br^T;g|L*LL`d`8^n}6Ir^!`+zto5JN$t9pz za9GB2=jZ3wxhC%4_wZj&@%#6#ee26qeL=b9 zfu}+uM|b+7H_@CA-b%@dWnEvFYg3F(!i(!6b0G*7WBG(@LJ=a zee06XZ!26k;r#RmHd8bL4;AG~|E&4S{_~^Lp$ZN2PgTpF9xG?8<$h*m_ABq7i)?_x z=3U#)rq&c1$sad+SnG*ZhB*BJXoaeS3up#+G(Jn>Eju z{E+rGs6DWQdFQrXtBLj#iswh(4`|Ldfto}+q^-TS{3k#jEwJJ?`ymtG&MRv8nTo$OUR0?6Lc-+1Hh;Gytj;∓*3n6 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 * @section framework_developer Framework developer guides diff --git a/graph_framework.xcodeproj/project.pbxproj b/graph_framework.xcodeproj/project.pbxproj index 57c3d13..5558843 100644 --- a/graph_framework.xcodeproj/project.pbxproj +++ b/graph_framework.xcodeproj/project.pbxproj @@ -364,6 +364,7 @@ C75C42952E5CC80B00B0950B /* tutorial.dox */ = {isa = PBXFileReference; lastKnownFileType = text; path = tutorial.dox; sourceTree = ""; }; C760B1AB2BC6D760001737A3 /* get_includes.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = get_includes.py; sourceTree = ""; }; C7678FBD2B45C2850025F37E /* bin.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = bin.py; sourceTree = ""; }; + C77707F62F5F288B00BA4E87 /* kernel_optimization.dox */ = {isa = PBXFileReference; lastKnownFileType = text; path = kernel_optimization.dox; sourceTree = ""; }; C77E6DF522DD64E700469621 /* trigonometry.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = trigonometry.hpp; sourceTree = ""; }; C78F3D872DC122B1002E3D94 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; C78F3D882DC122B1002E3D94 /* xkorc.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = xkorc.cpp; sourceTree = ""; }; @@ -627,6 +628,7 @@ C75C42952E5CC80B00B0950B /* tutorial.dox */, C7DD87D32E664B440058BA66 /* code_structure.dox */, C729B8B12ED7521A00A2559D /* discription.dox */, + C77707F62F5F288B00BA4E87 /* kernel_optimization.dox */, C729B8B22ED7536B00A2559D /* use_cases.dox */, C729B8B42ED77CA800A2559D /* code_performance.dox */, ); diff --git a/graph_framework/cuda_context.hpp b/graph_framework/cuda_context.hpp index dc660a0..741bafa 100644 --- a/graph_framework/cuda_context.hpp +++ b/graph_framework/cuda_context.hpp @@ -324,6 +324,7 @@ namespace gpu { check_error(cuModuleGetFunction(&function, module, kernel_name.c_str()), "cuModuleGetFunction"); std::vector buffers; + std::set *> needed_buffers; const size_t buffer_element_size = sizeof(T); for (auto &input : inputs) { @@ -339,6 +340,11 @@ namespace gpu { backend.size()*sizeof(T)), "cuMemcpyHtoD"); buffers.push_back(reinterpret_cast (&kernel_arguments[input.get()])); + needed_buffers.insert(input.get()); + } + if (!needed_buffers.contains(input.get())) { + buffers.push_back(kernel_arguments[input.get()]); + needed_buffers.insert(input.get()); } } for (auto &output : outputs) { @@ -349,6 +355,11 @@ namespace gpu { CU_MEM_ATTACH_GLOBAL), "cuMemAllocManaged"); buffers.push_back(reinterpret_cast (&kernel_arguments[output.get()])); + needed_buffers.insert(output.get()); + } + if (!needed_buffers.contains(output.get())) { + buffers.push_back(kernel_arguments[output.get()]); + needed_buffers.insert(output.get()); } } diff --git a/graph_framework/metal_context.hpp b/graph_framework/metal_context.hpp index 5e0bc96..fd91bee 100644 --- a/graph_framework/metal_context.hpp +++ b/graph_framework/metal_context.hpp @@ -138,6 +138,7 @@ namespace gpu { } std::vector> buffers; + std::set *> needed_buffers; const size_t buffer_element_size = sizeof(float); for (graph::shared_variable &input : inputs) { @@ -147,6 +148,11 @@ namespace gpu { length:buffer.size()*buffer_element_size options:MTLResourceStorageModeShared]; buffers.push_back(kernel_arguments[input.get()]); + needed_buffers.insert(input.get()); + } + if (!needed_buffers.contains(input.get())) { + buffers.push_back(kernel_arguments[input.get()]); + needed_buffers.insert(input.get()); } } for (graph::shared_leaf &output : outputs) { @@ -154,6 +160,11 @@ namespace gpu { kernel_arguments[output.get()] = [device newBufferWithLength:num_rays*sizeof(float) options:MTLResourceStorageModeShared]; buffers.push_back(kernel_arguments[output.get()]); + needed_buffers.insert(output.get()); + } + if (!needed_buffers.contains(output.get())) { + buffers.push_back(kernel_arguments[output.get()]); + needed_buffers.insert(output.get()); } } if (state.get()) { -- GitLab