Skip to content

get_vtx_patches without kokkos - #231

Merged
cwsmith merged 3 commits into
SCOREC:masterfrom
Fuad-HH:patches_wo_kokkos
Aug 14, 2026
Merged

get_vtx_patches without kokkos#231
cwsmith merged 3 commits into
SCOREC:masterfrom
Fuad-HH:patches_wo_kokkos

Conversation

@Fuad-HH

@Fuad-HH Fuad-HH commented Aug 6, 2026

Copy link
Copy Markdown

This function was enabled only when kokkos was linked. Now with the alternative implementation, it can work without kokkos.
There are two assumptions here:

  1. Device code is only supported through kokkos -> without kokkos, it is always CPU only.
  2. Using std::sort which needs Omega_h to be compiled with c++17 or higher.

Fixes issue #230

@Fuad-HH
Fuad-HH marked this pull request as ready for review August 11, 2026 14:05
- all other code in the file works without kokkos excect this.
- moved the kokkos linking guards only wrapping this.
- passes all tests locally (including python)
- fixes issue SCOREC#230
@Fuad-HH
Fuad-HH force-pushed the patches_wo_kokkos branch from 8cab4a9 to 91b1cd2 Compare August 11, 2026 14:23
@Fuad-HH

Fuad-HH commented Aug 11, 2026

Copy link
Copy Markdown
Author

@jacobmerson @cwsmith @Sichao25 , Could you please review this? I cannot find the review request button for this PR.

@cwsmith

cwsmith commented Aug 11, 2026

Copy link
Copy Markdown

/runtests

@github-actions

Copy link
Copy Markdown

Test Results:

  • Kokkos CUDA: success
  • No Kokkos: success
  • Kokkos Serial: success
  • Kokkos OpenMP: success
  • Kokkos CUDA Warnings as Errors: success
  • Kokkos CUDA Python: success

(details)

@cwsmith cwsmith left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks @Fuad-HH . Below are a few comments towards tweaking the code to make it clearer that it is intended to only run in serial.

With this change I assume test_patches should no longer be within the if(Omega_h_USE_Kokkos) conditional.

omega_h/src/CMakeLists.txt

Lines 412 to 421 in 96463bb

if (Omega_h_USE_Kokkos)
osh_add_exe(bbox_reduce_test)
osh_add_exe(initKokkosAndLib)
osh_add_exe(test_patches)
if(Omega_h_USE_MPI)
test_func(run_test_patches_par 4 ./test_patches)
else()
test_func(run_test_patches 1 ./test_patches)
endif()
endif()

Comment thread src/Omega_h_patches.cpp Outdated
[[nodiscard]] Graph adj_segment_sort(Graph& g) {
auto offsets = g.a2ab;
auto elms_r = Read(g.ab2b); //read only
Write<LO> elms(elms_r.size(), "elms");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

even though this is outside the kokkos block, I think this should still use a HostWrite to make the intention clear

Comment thread src/Omega_h_patches.cpp Outdated
Comment on lines +38 to +45
auto copyFn = OMEGA_H_LAMBDA(LO i) {
elms[i] = elms_r[i];
};
parallel_for(elms.size(), copyFn);
auto sortFn = OMEGA_H_LAMBDA(LO i) {
std::sort(elms.begin() + offsets[i], elms.begin() + offsets[i+1]);
};
parallel_for(g.nnodes(), sortFn);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

likewise, since this is outside the kokkos block, I think it would be easier to read/understand if these were serial for loops instead of parallel_for(...)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I was thinking that in the future, omega_h parallel for may use the ranges or something else for host parallelism without kokkos and we don't want to manage it here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hmmm. Is std::sort expected to be thread safe is that context? I guess I'd rather do the conservative thing that we know won't break if someone does eventually implement a non-kokkos parallel backend. Note, the plan for the foreseeable future is to only support on-device parallelism via kokkos.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Okay, I will replace this. Thanks.

removed parallel_for and Read/Write
moved test_patch out of kokkos condition
@Fuad-HH
Fuad-HH force-pushed the patches_wo_kokkos branch from b532295 to 18fb8c4 Compare August 12, 2026 19:19
@cwsmith

cwsmith commented Aug 12, 2026

Copy link
Copy Markdown

/runtests

@github-actions

Copy link
Copy Markdown

Test Results:

  • Kokkos CUDA: success
  • No Kokkos: failure
  • Kokkos Serial: skipped
  • Kokkos OpenMP: skipped
  • Kokkos CUDA Warnings as Errors: skipped
  • Kokkos CUDA Python: skipped

(details)

@Fuad-HH

Fuad-HH commented Aug 12, 2026

Copy link
Copy Markdown
Author

The test_patches is failing with MPI on 2 ranks where it is expected to fail but here it is getting a segfault. It is failing at this line in a Write::size() call:

return alloc->size;

Do you have any suggestion how to can I fix this?

@Fuad-HH

Fuad-HH commented Aug 12, 2026

Copy link
Copy Markdown
Author

I am not sure if this is the intended behavior of SharedAlloc. But all the tests pass with this change.

@cwsmith

cwsmith commented Aug 13, 2026

Copy link
Copy Markdown

/runtests

@github-actions

Copy link
Copy Markdown

Test Results:

  • Kokkos CUDA: success
  • No Kokkos: success
  • Kokkos Serial: success
  • Kokkos OpenMP: success
  • Kokkos CUDA Warnings as Errors: success
  • Kokkos CUDA Python: success

(details)

@cwsmith

cwsmith commented Aug 14, 2026

Copy link
Copy Markdown

@Fuad-HH The fix for SharedAlloc is valid. Thank you. This took some digging to understand and hopefully the following summary is correct. In short, SharedAlloc was designed to support serial execution -or- host parallelism via openmp without kokkos. When kokkos is enabled kokkos view's are used by read/write arrays instead of SharedAlloc. When a host-based parallel for loop captured a write/read array by value the following logic relied on the Alloc pointer having the size of the allocation directly encoded/packed into it instead of being an actual pointer to heap memory. See

if (entering_parallel) {
alloc = reinterpret_cast<Alloc*>(
(std::uintptr_t(alloc->size) << 3) | IN_PARALLEL);

As you gathered, the problem comes when alloc is set to nullptr but the call to size() didn't distinguish between the IN_PARALLEL mask not being set (i.e., alloc is all zeros) versus nullptr:

OMEGA_H_INLINE std::size_t size() const noexcept {
#ifndef __CUDA_ARCH__
if (!(reinterpret_cast<std::uintptr_t>(alloc) & IN_PARALLEL)) {
#if defined(__GNUC__) && (__GNUC__ >= 7) && (!defined(__clang__))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnull-dereference"
#endif
return alloc->size;
#if defined(__GNUC__) && (__GNUC__ >= 7) && (!defined(__clang__))
#pragma GCC diagnostic pop
#endif
}
#endif
return reinterpret_cast<std::uintptr_t>(alloc) >> 3;
}

@cwsmith
cwsmith merged commit d5489aa into SCOREC:master Aug 14, 2026
17 checks passed
@Fuad-HH

Fuad-HH commented Aug 14, 2026

Copy link
Copy Markdown
Author

Thanks @cwsmith. I also had the similar idea looking at the stack trace.

@Fuad-HH
Fuad-HH deleted the patches_wo_kokkos branch August 14, 2026 15:05
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.

2 participants