Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert DG-RePlAce algorithm to Kokkos #5352

Open
wants to merge 21 commits into
base: master
Choose a base branch
from

Conversation

kamilrakoczy
Copy link
Contributor

@kamilrakoczy kamilrakoczy commented Jul 8, 2024

This MR converts DG-RePlAce algorithm that was originally written for CUDA to Kokkos.

Kokkos provides abstraction for writing parallel code that can be translated into several backends including CUDA, OpenMP and C++ threads.

Tested on single run with RTX 3090 and i7-8700 CPU @ 3.20GHz using ariane133 design.

original placer CUDA implementation Kokkos (CUDA backend) Kokkos (OpenMP backend) Kokkos (Threads backend)
ariane133 global place time 11:27.39 0:57.70 1:33.49 3:24.12 6:08.94

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 52. Check the log or trigger a new build to see more.

// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
///////////////////////////////////////////////////////////////////////////////

#include "gpl2/MakeDgReplace.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'gpl2/MakeDgReplace.h' file not found [clang-diagnostic-error]

#include "gpl2/MakeDgReplace.h"
         ^

//
///////////////////////////////////////////////////////////////////////////////

#include <Kokkos_Core.hpp>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'Kokkos_Core.hpp' file not found [clang-diagnostic-error]

#include <Kokkos_Core.hpp>
         ^

//
//
///////////////////////////////////////////////////////////////////////////////
#include <Kokkos_Core.hpp>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'Kokkos_Core.hpp' file not found [clang-diagnostic-error]

#include <Kokkos_Core.hpp>
         ^

///////////////////////////////////////////////////////////////////////////////
#include <Kokkos_Core.hpp>

void dct_2d_fft(const int M,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'M' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
void dct_2d_fft(const int M,
void dct_2d_fft(int M,

#include <Kokkos_Core.hpp>

void dct_2d_fft(const int M,
const int N,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'N' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
const int N,
int N,

binCntY_ = 512;
}

binSizeX_ = ceil(static_cast<float>((ux_ - lx_)) / binCntX_);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: call to 'ceil' promotes float to double [performance-type-promotion-in-math-fn]

src/gpl2/src/placerBase.cpp:40:

- #include <cstdio>
+ #include <cmath>
+ #include <cstdio>
Suggested change
binSizeX_ = ceil(static_cast<float>((ux_ - lx_)) / binCntX_);
binSizeX_ = std::ceil(static_cast<float>((ux_ - lx_)) / binCntX_);

}

binSizeX_ = ceil(static_cast<float>((ux_ - lx_)) / binCntX_);
binSizeY_ = ceil(static_cast<float>((uy_ - ly_)) / binCntY_);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: call to 'ceil' promotes float to double [performance-type-promotion-in-math-fn]

Suggested change
binSizeY_ = ceil(static_cast<float>((uy_ - ly_)) / binCntY_);
binSizeY_ = std::ceil(static_cast<float>((uy_ - ly_)) / binCntY_);

#include <string>
#include <vector>

#include "db_sta/dbNetwork.hh"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'db_sta/dbNetwork.hh' file not found [clang-diagnostic-error]

#include "db_sta/dbNetwork.hh"
         ^

int64_t nesterovInstsArea() const
{
return stdInstsArea_
+ static_cast<int64_t>(round(macroInstsArea_ * targetDensity_));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: call to 'round' promotes float to double [performance-type-promotion-in-math-fn]

src/gpl2/src/placerBase.h:38:

- #include <memory>
+ #include <cmath>
+ #include <memory>
Suggested change
+ static_cast<int64_t>(round(macroInstsArea_ * targetDensity_));
+ static_cast<int64_t>(std::round(macroInstsArea_ * targetDensity_));

///////////////////////////////////////////////////////////////
// Instance
Instance::Instance()
: inst_(nullptr),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member initializer for 'inst_' is redundant [modernize-use-default-member-init]

Suggested change
: inst_(nullptr),
: ,

@maliberty
Copy link
Member

Earlier it was reported the runtime difference to be minimal but 0:57.70 vs 1:33.49 is more substantial. Is this expected?

@kamilrakoczy
Copy link
Contributor Author

Earlier it was reported the runtime difference to be minimal but 0:57.70 vs 1:33.49 is more substantial. Is this expected?

Earlier measurements were done when some parts was still using native CUDA and using different design (black-parrot).
This measurements are single run on local machine while using it for other things too, so they are not very accurate.

I'd expect, it should be possible to achieve similar runtime using Kokkos, This results might suggest, that there are some unnecessary memory copies between host/device, but this needs to be investigated further.

@maliberty
Copy link
Member

Please try to get a more precise measure of the runtime difference as this is important in deciding whether Kokkos is a good alternative to direct CUDA coding.

Do all the various versions produce the same result? That is also important.

@maliberty
Copy link
Member

What was the thinking behind making kokkos a dependency but kokkos-fft a submodule? It seems like they could both be build dependencies (and added to the DependencyInstaller with an option).

@QuantamHD
Copy link
Collaborator

QuantamHD commented Jul 9, 2024

Please try to get a more precise measure of the runtime difference as this is important in deciding whether Kokkos is a good alternative to direct CUDA coding.

I think I would say direct CUDA coding isn't really a viable option. I would be personally opposed to its inclusion. I think Kokkos or something like it is the only viable path forward. The runtime differences don't look significant if you compare it to the overall speedup achieved.

We're going for a pragmatic path forward, and to me this meets my bar for the goals we set out.

Do all the various versions produce the same result? That is also important.

Agree that this is important to check. We may need to order the floats to get identical/sufficiently similar results.

@maliberty
Copy link
Member

I think I would say direct CUDA coding isn't really a viable option. I would be personally opposed to its inclusion.

You personally pushed for the inclusion of gpuSolver.cu and said its was valuable as a template for future development. Shall we delete it? I was never in favor.

A 50% overhead is worth exploring to at least understand if not eliminate.

@QuantamHD
Copy link
Collaborator

QuantamHD commented Jul 9, 2024

You personally pushed for the inclusion of gpuSolver.cu and said its was valuable as a template for future development. Shall we delete it? I was never in favor.

I think that seems like the right move at this point. With more time and context I don't think it's viable for us to maintain two codebases.

A 50% overhead is worth exploring to at least understand if not eliminate.

+1 I just want to point out if this is the fastest we could go that seems fast enough for me.

@kamilrakoczy
Copy link
Contributor Author

Do all the various versions produce the same result? That is also important.

No they don't and it was quite surprising, as I expected that original code and Kokkos with CUDA backend will produce the same result.
We investigated this and it turned out that it is because Kokkos passes all files that depends on it through nvcc_wrapper. This wrapper converts host compiler options (g++) to nvcc options and uses nvcc to compile all Kokkos-dependent sources. This is done to allow device code in single .cpp file instead of separate .cu file for it.

NVCC should do pre-processing and compilation for device code and produce CUDA binary and it should leave host code for host compiler.

We checked that when nvcc is used to compile InitialPlace, Eigen solveWithGuess returns different results with exactly the same inputs comparing to using g++ directly.

I suspect that this issue isn't only related to Eigen: when I disabled initial placement, runtime of Kokkos and original code were almost the same, but results were still different (I haven't investigated reason for this).

What was the thinking behind making kokkos a dependency but kokkos-fft a submodule? It seems like they could both be build dependencies (and added to the DependencyInstaller with an option).

kokkos-fft is header only interface library that translates FFT calls into proper backend by detecting enabled backends in Kokkos, but I agree, if preferred, both kokkos and kokkos-fft could be dependencies.

A 50% overhead is worth exploring to at least understand if not eliminate.

I think this overhead is due to different initial placement, when initial placement is disabled runtime is very similar:

CUDA implementation Kokkos (CUDA backend)
ariane133 global place time without initial placement 0:55.52 0:58.25

I also did precise measurements using RTX 3080, 8 vCPU i9-12900 @ 2.42 GHz and 32GB of RAM with 10 runs using ariane133 design:

min time [min] avg time [min] med time [min] max time [min]
CUDA implementation 0:45 0:48 0:47 0:53
Kokkos (CUDA backend) 1:53 1:57 1:57 2:00
Kokkos (OpenMP backend) 1:50 2:04 1:54 2:37
Kokkos (threads backend) 3:42 3:43 3:43 3:45

@maliberty
Copy link
Member

Thanks for the analysis. It would be good to get to the bottom of the difference as it will make regression testing hard otherwise. Is nvcc calling g++ with different flags?

@kamilrakoczy
Copy link
Contributor Author

Is nvcc calling g++ with different flags?

Arguments that are passed to nvcc and that nvcc should pass to g++ are the same.
I haven't investigated yet how (with what flags) g++ is invoked from nvcc.

@maliberty
Copy link
Member

another possibility is that it is invoking a different g++ binary from another path

@maliberty maliberty marked this pull request as draft October 14, 2024 04:41
@maliberty
Copy link
Member

Converted to a draft due to no progress.

@jbylicki jbylicki force-pushed the convert-gpl2-kokkos branch 2 times, most recently from 04d428f to 925dd93 Compare January 7, 2025 13:14
@jbylicki
Copy link

jbylicki commented Jan 7, 2025

I've rebased this branch onto latest master and started resolving the mentioned issues:

  • Eigen’s solveWithGuess() behaves differently on the Kokkos branch (with a suggestion that this is caused by nvcc_wrapper, a part of Kokkos responsible for redirecting compilations, not pertaining to CUDA, to the host compiler):

I've found that to not be the case. Early, I've recreated the same condition (where Eigen was running slowly) using clang++ as the Kokkos compiler and I've confirmed that nvcc_wrapper was not used then. The problem was Eigen, when detecting CUDA availability, was trying to use it. Nevertheless, I saw no peak in GPU usage when initial_place was running, so I've disabled it and saw the numbers return to baseline (the same as in the CUDA-native implementation).

  • What is the performance difference between Kokkos and CUDA-native implementations?

To prioritize merging of GPU-accelerated placement, the focus was to get the branch issue-free before optimizing. In my testing, Kokkos-based algorithm on black-parrot spends about 10 seconds in libcuda.so, whereas the CUDA-native implementation spends around 5. All other timings are comparable, making the entire run about 5 seconds longer.

Future / subsequent work:

  • Make Kokkos a submodule: Due to varying conditions on host machines, most Kokkos libraries available as a package ship without either CUDA or OMP support. Having a dependency that has to be manually compiled and set correctly to have a functioning and fast implementation might intruduce complexity for the end user. Therefore, I suggest not migrating kokkos-fft to be a dependency and using kokkos, that is already cloned as a submodule to kokkos-fft, as an in-tree library. The issue I'm currently facing is that internal deprecations of CMake symbols are being triggered when Kokkos' compilation is triggered as a child project and not the parent.
  • Optimize memory accesses and the Kokkos implementation itself: I've confirmed that memory copying is one of the causes of the algorithm being slower, and fixes are in development, waiting for the more pressing issues to be resolved.

@jbylicki
Copy link

jbylicki commented Jan 9, 2025

I added a configuration option to etc/Build.sh, -use_gpl2 that will include the gpl2 subdirectory and launch the compilation of kokkos via kokkos-fft in CMake. I additionally assigned the -gpu flag from the build script to enable the CUDA backend in Kokkos.

@maliberty
Copy link
Member

I would prefer to see kokkos as part of the dependency installer rather than as a submodule. There should be no need to compile it for each workspace on a machine.

@jbylicki
Copy link

jbylicki commented Jan 9, 2025

With the current setup, it would be possible to support both compilation schemes, with the priority set towards the DependencyInstaller - if a system-wide Kokkos installation would be detected, it will be used during compilation. I would suggest leaving the possibility to use in-tree Kokkos and kokkos-fft (if kokkos-fft was also moved to be downloaded via DependencyInstaller), as the script is tailored only towards Ubuntu users. If a system-wide package is not detected, both dependencies can be installed via FetchContent and built in-tree.

@maliberty
Copy link
Member

If someone wants to put a local copy in-tree that's fine but I'd like to avoid having a submodule.

@jbylicki
Copy link

jbylicki commented Jan 9, 2025

I'll add support for kokkos and kokkos-fft via the DependencyInstaller then. The submodule could be deleted while keeping in-tree support - CMake would in case of a system-wide package being absent handle the download by the FetchContent directive, and the build would have conditionals in place to link correctly.

@jbylicki
Copy link

I've added nested parallelism to the most time consuming kernel - computeBCPosNegKernel. After rebasing both branches to the same base commit, the performance results are as follows for the black-parrot design with the CUDA backend:

  • CUDA-native: 24.606 seconds (total time: 114.50 s, skipped intial place: 94.49 s)
  • Kokkos: 23.614 seconds (total time: 114.42 s, skipped intial place: 95.07 s)

Additionally, a concern was raised wrt. non-deterministic results that are returned from Kokkos, depending on the compute device used for processing. To validate the flow, each variant was subjected to a run from syntheis to the final step. While it's true that those results are varying, they have minimal impact on the actual parameters of the finished flow. Additionally, the results are deterministic on a per-device basis, even when the compute device is calculating under heavy external loads (especially applicable for GPUs).

Test subjects were:

  • master branch commit 7e0fce872123, as baseline and base for other branches
  • cuda-native, the original CUDA-native implementation, rebased onto the same base as other branches
  • kokkos-cpu, the Kokkos-based flow, ran on the OpenMP backend
  • kokkos-gpu, the Kokkos-based flow, ran on the CUDA backend

Metrics collected were taken from the final report and log, and were:

  • Total Negative Slack (tns)
  • Worst Negative Slack (wns)
  • Total power
  • Design area and utilization

Results:

Branch TNS WNS Design area, utilization Total Power
master -2.42 -2.42 760397 u^2 45% utilization 2.57e-01 W
cuda-native -2.40 -2.40 753511 u^2 44% utilization 2.49e-01 W
kokkos-cpu -2.49 -2.49 753608 u^2 44% utilization 2.50e-01 W
kokkos-gpu -2.44 -2.44 753674 u^2 44% utilization 2.50e-01 W

@maliberty
Copy link
Member

Very nice! How is the cpu vs gpu runtime with your latest changes? Is this ready for review?

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 25 out of 45. Check the log or trigger a new build to see more.

///////////////////////////////////////////////////////////////////////////////
#include <Kokkos_Core.hpp>

void dct_2d_fft(const int M,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'M' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
void dct_2d_fft(const int M,
void dct_2d_fft(int M,

#include <Kokkos_Core.hpp>

void dct_2d_fft(const int M,
const int N,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'N' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
const int N,
int N,

const Kokkos::View<Kokkos::complex<float>*>& fft,
const Kokkos::View<float*>& post);

void idct_2d_fft(const int M,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'M' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
void idct_2d_fft(const int M,
void idct_2d_fft(int M,

const Kokkos::View<float*>& post);

void idct_2d_fft(const int M,
const int N,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'N' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
const int N,
int N,

const Kokkos::View<float*>& ifft,
const Kokkos::View<float*>& post);

void idxst_idct(const int M,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'M' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
void idxst_idct(const int M,
void idxst_idct(int M,

densityScale_(0.0),
haloWidth_(0),
type_(InstanceType::FILLER),
isFixed_(false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member initializer for 'isFixed_' is redundant [modernize-use-default-member-init]

Suggested change
isFixed_(false)

int lx = 0.0;
int ly = 0.0;
inst->getLocation(lx, ly);
int ux = lx + floor(bbox->getDX() / 2) * 2;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: result of integer division used in a floating point context; possible loss of precision [bugprone-integer-division]

  int ux = lx + floor(bbox->getDX() / 2) * 2;
                      ^

int ly = 0.0;
inst->getLocation(lx, ly);
int ux = lx + floor(bbox->getDX() / 2) * 2;
int uy = ly + floor(bbox->getDY() / 2) * 2;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: result of integer division used in a floating point context; possible loss of precision [bugprone-integer-division]

  int uy = ly + floor(bbox->getDY() / 2) * 2;
                      ^

}
}

void Instance::dbSetPlacementStatus(odb::dbPlacementStatus ps)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: the parameter 'ps' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]

Suggested change
void Instance::dbSetPlacementStatus(odb::dbPlacementStatus ps)
void Instance::dbSetPlacementStatus(const odb::dbPlacementStatus& ps)

src/gpl2/src/placerObjects.h:105:

-   void dbSetPlacementStatus(odb::dbPlacementStatus ps);
+   void dbSetPlacementStatus(const odb::dbPlacementStatus& ps);

////////////////////////////////////////////////////////
// Pin
Pin::Pin()
: pin_(nullptr),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member initializer for 'pin_' is redundant [modernize-use-default-member-init]

Suggested change
: pin_(nullptr),
: ,

@jbylicki
Copy link

Yes, it's ready for review. I've applied the suggested clang-tidy fixes and added the missing RockyLinux9 package.

The performance difference between CUDA and OpenMP backends on black_parrot is:

  • CUDA: 85.38 s (dg_global_place call time: 20.46 s)
  • OpenMP: 96.58 s (dg_global_place call time: 29.83 s)

The test setup is an Intel i7-8700 and a NVIDIA GTX 1080Ti

@jbylicki jbylicki force-pushed the convert-gpl2-kokkos branch from a1b101b to 1d136de Compare February 13, 2025 19:44
@maliberty maliberty marked this pull request as ready for review February 14, 2025 05:34
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

////////////////////////////////////////////////////////////////////////////////////////////////
// Net
Net::Net()
: net_(nullptr),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member initializer for 'net_' is redundant [modernize-use-default-member-init]

Suggested change
: net_(nullptr),
: ,

// Net
Net::Net()
: net_(nullptr),
netId_(-1),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member initializer for 'netId_' is redundant [modernize-use-default-member-init]

Suggested change
netId_(-1),
,

ly_(0),
ux_(0),
uy_(0),
isDontCare_(false),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member initializer for 'isDontCare_' is redundant [modernize-use-default-member-init]

Suggested change
isDontCare_(false),
,

ux_(0),
uy_(0),
isDontCare_(false),
virtualWeight_(0.0),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member initializer for 'virtualWeight_' is redundant [modernize-use-default-member-init]

Suggested change
virtualWeight_(0.0),
,

uy_(0),
isDontCare_(false),
virtualWeight_(0.0),
weight_(1.0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member initializer for 'weight_' is redundant [modernize-use-default-member-init]

Suggested change
weight_(1.0)

Kokkos::View<float*> electroForceY);

// Compute Potential Only (not Electric Force) the row-major order
void solvePoissonPotential(const Kokkos::View<float*> binDensity, Kokkos::View<float*> potential);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'binDensity' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]

Suggested change
void solvePoissonPotential(const Kokkos::View<float*> binDensity, Kokkos::View<float*> potential);
void solvePoissonPotential(Kokkos::View<float*> binDensity, Kokkos::View<float*> potential);

// RouteBase

RouteBase::RouteBase()
: rbVars_(), db_(nullptr), grouter_(nullptr), nbc_(nullptr), log_(nullptr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: initializer for member 'rbVars_' is redundant [readability-redundant-member-init]

Suggested change
: rbVars_(), db_(nullptr), grouter_(nullptr), nbc_(nullptr), log_(nullptr)
: , db_(nullptr), grouter_(nullptr), nbc_(nullptr), log_(nullptr)

RouteBase::RouteBase(RouteBaseVars rbVars,
odb::dbDatabase* db,
grt::GlobalRouter* grouter,
std::shared_ptr<PlacerBaseCommon> nbc,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: the parameter 'nbc' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]

Suggested change
std::shared_ptr<PlacerBaseCommon> nbc,
const std::shared_ptr<PlacerBaseCommon>& nbc,

nbVec_ = std::move(nbVec);
}

RouteBase::~RouteBase()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: use '= default' to define a trivial destructor [modernize-use-equals-default]

src/gpl2/src/routeBase.cpp:98:

- {
- }
+ = default;

}

TimingBase::TimingBase(std::shared_ptr<PlacerBaseCommon> nbc,
rsz::Resizer* rs,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: the parameter 'nbc' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]

Suggested change
rsz::Resizer* rs,
TimingBase::TimingBase(const std::shared_ptr<PlacerBaseCommon>&const ingBase::TimingBase(std::shared_p&tr<PlacerBaseCommon> nbc,
rsz::Resizer* rs,

Copy link
Member

@maliberty maliberty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review

Comment on lines +157 to +159
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19")
link_libraries(stdc++)
endif()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What necessitates this?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After bumping clang to version 19, it started defaulting to linking against libc++ in CUDA code. It only affected gpl2; there was a missing libstdc++ definiton when linking only this specific module. Should I add a CUDA/GPL2 conditional there as well?

@@ -121,6 +122,9 @@ while [ "$#" -gt 0 ]; do
echo "${1} requires an argument" >&2
_help
;;
-use_gpl2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a description to the usage message

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -76,6 +76,7 @@ _installCommonDev() {
gtestChecksum="a1279c6fb5bf7d4a5e0d0b2a4adb39ac"
bisonVersion=3.8.2
bisonChecksum="1e541a097cda9eca675d29dd2832921f"
kokkosfftVersion="2c616d29a7ad0c390259efeb9224115bfa6910fd"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't this using a release tag and checksum?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It accomplishes the same goal in a single defintion and eliminates the need to hash the directory. If it's preferred to keep convention, I can change it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not as there is no easy way to know what release (if any) we are using from a commit id.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to a version tag. Other dependencies managed by git were not getting hashed either, as it would require to tar the directory.

Comment on lines +186 to +187
# Older version of g++ is needed for compatibility with NVCC
ARGS_KOKKOSFFT+=" -DKokkos_ENABLE_CUDA=ON -DCMAKE_CXX_COMPILER=g++-10"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html suggests it works with many default compiler versions. Is this really necessary?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NVlabs/instant-ngp#119 presents the same issue as I have encountered. Ubuntu is using the supposedly supported gcc 11.4, but it does not compile Kokkos properly.

Comment on lines +186 to +187
# Older version of g++ is needed for compatibility with NVCC
ARGS_KOKKOSFFT+=" -DKokkos_ENABLE_CUDA=ON -DCMAKE_CXX_COMPILER=g++-10"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you enable both openmp and cuda in one build?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will default to CUDA if it's detected but both can be compiled in at once.

src/gpl2/LICENSE Outdated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need for a separate LICENSE file here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Comment on lines 84 to 86
// The three main functions
void doInitialPlace();
int doNesterovPlace(int start_iter = 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only see two

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the comment, it was here since the CUDA-native implementation, there's no clear indication what would've been the third function.

Comment on lines 150 to 151
// We should only have one placerBaseCommon, timingBase and routeBase
// But we need multiple placerBases to handle fences and multiple domains
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment seems to have become separate from its context (move down 4 lines)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you author this code?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was originally written by @ZhiangWang033 (as can be seen in the commit history), then ported to Kokkos by the other committers (including me).

int coreUx_;
int coreUy_;

// We need to store all the statictis information for each bin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: statictis

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected

@jbylicki jbylicki force-pushed the convert-gpl2-kokkos branch 5 times, most recently from 974d4c0 to e0f9b1f Compare February 20, 2025 13:20
@jbylicki
Copy link

Currently, the mainline gpl runs the global_place call for 653.90s with the total run time being 729.30s

ZhiangWang033 and others added 21 commits March 6, 2025 12:49
Signed-off-by: ZhiangWang033 <zhw033@ucsd.edu>
Co-authored-by: Kamil Rakoczy <krakoczy@antmicro.com>
Co-authored-by: Jan Bylicki <jbylicki@antmicro.com>

Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
Signed-off-by: Jan Bylicki <jbylicki@antmicro.com>
Signed-off-by: Jan Bylicki <jbylicki@antmicro.com>
Signed-off-by: Jan Bylicki <jbylicki@antmicro.com>
Signed-off-by: Jan Bylicki <jbylicki@antmicro.com>
Signed-off-by: Jan Bylicki <jbylicki@antmicro.com>
Signed-off-by: Jan Bylicki <jbylicki@antmicro.com>
…ackends

Signed-off-by: Jan Bylicki <jbylicki@antmicro.com>
Signed-off-by: Jan Bylicki <jbylicki@antmicro.com>
Removes interpretation of LayoutRight data as LayoutLeft

Fixes `input and output extents must be the same except for
the transform axis` gpl2 error caused by incomplete workaround against
differing default 2d data layouts beetween CUDA and CPU.

I considered alternative approches (such as getting rid of LayoutRight
specific code entirely) but they turned out to be unproportionaly complex.

Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
Always calculate fft on host to avoid differing results between impls

NOTE: This may have some performance repercussions.
Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
Device and host may use different implementations of math functions
giving different results which is not desirable in OpenROAD
The fix relies on (possibly wrong) assumption, that the error of
double precision built-in function is less than precision of float.

Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
Replace non-deterministic paralel reduces with serial loops that give
same result regardless of platform

NOTE: This change results in serious performance degradation
Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
computeWeightedHPWL() suffered from implicit lossy (in case of big
numbers) conversion of int64_t to float.

After fixing it, the summation can be made parallel without introducing
inconsistencies between kokkos configurations.

NOTE: the computeHPWL() never suffered from this issue, but I had
excesivly deparalelized it before.

In this fix, I added safe-guards to both computeWeightedHPWL() and
computeHPWL() for consistency.

Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
Replace dNetWith and dNetHeight with single dNetWidthPlusHeight
The time improvement is small (it could be measurement error as well)

Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
Serial code is order of magnitude slower to execute on GPU than on CPU

Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
I'm a bit suprised, but this simple change reduced time from 2m38s to 2m30s

Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
Calculate individual distances in parallel, then sum them serially

Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
Before, we executed serial reduction for X and Y separatly.
Now we have parallel calculation of view with abs(X)+abs(Y), and one
serial reduction of it.

Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
NOTE: I used static vars for storing plans. While simple and convienient,
it assumes that N and M won't change between calls (changing them would
result in runtime error)

Signed-off-by: Szymon Gizler <sgizler@antmicro.com>
@sgizler sgizler force-pushed the convert-gpl2-kokkos branch from d841e44 to 76e5a69 Compare March 6, 2025 12:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants