Skip to content

Add partial workgroup local-memory regression#460

Merged
maleadt merged 1 commit into
mainfrom
tb/test-pocl-fix
Jul 16, 2026
Merged

Add partial workgroup local-memory regression#460
maleadt merged 1 commit into
mainfrom
tb/test-pocl-fix

Conversation

@maleadt

@maleadt maleadt commented Jul 15, 2026

Copy link
Copy Markdown
Member

Distilled from @christiangnrd's MWE:

# MWE: a KernelAbstractions kernel that resets a workgroup-shared @localmem
# cell, conditionally writes to it, and reads it back across two
# @synchronize() barriers returns a wrong result on PoCL when the launched
# workgroup is only partially active (ndrange not a multiple of block_size).
#
# Depends only on OpenCL, pocl_jll (or pocl_next_jll), KernelAbstractions.
#
# See pocl_localmem_barrier_bug_report.md for the full writeup, ruled-out
# causes, and links to related upstream pocl/pocl issues.
#
# Trigger conditions:
#   - the kernel must NOT suppress bounds checking on `v[i]` (this reproducer
#     intentionally omits `@inbounds`/`inbounds=true`, so it fails under
#     Julia's default `--check-bounds=auto`; adding `inbounds=true` to the
#     `@kernel` declaration makes it pass every time)
#   - `ndrange` (here 16) must not be a multiple of the static workgroup
#     size (here 256), so only some launched threads are "active"
#   - PoCL's default work-group codegen ("loopvec") is used; setting
#     `POCL_WORK_GROUP_METHOD=cbs` in the environment avoids the bug entirely
#
# Expected output: failures: 0 / 100 (expected 0)
# Actual output:   failures: ~50-98 / 100 (expected 0), depending on PoCL version

# using pocl_jll, OpenCL, KernelAbstractions
using pocl_next_jll, OpenCL, KernelAbstractions

@kernel cpu=false function reduce_any!(out, pred, @Const(v))
    temp = @localmem Int8 (1,)
    i = @index(Global, Linear)

    temp[0x1] = 0x0
    @synchronize()

    if pred(v[i])
        temp[0x1] = 0x1
    end

    @synchronize()
    if temp[0x1] != 0x0
        out[0x1] = 0x1
    end
end

backend = OpenCLBackend()
block_size = 256
n = 16              # not a multiple of block_size -> only 16/256 threads active

function main()
    fails = 0
    trials = 100
    for _ in 1:trials
        v = CLArray(zeros(Float32, n))          # all-zero: `x < 0` is false for every element
        out = KernelAbstractions.zeros(backend, Int8, 1)
        reduce_any!(backend, block_size)(out, x -> x < 0, v, ndrange=n)
        KernelAbstractions.synchronize(backend)
        Array(out)[1] != 0 && (fails += 1)
    end
    println("failures: $fails / $trials (expected 0)")
end

main()

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.74%. Comparing base (25bb8be) to head (12c906f).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #460   +/-   ##
=======================================
  Coverage   80.74%   80.74%           
=======================================
  Files          13       13           
  Lines         909      909           
=======================================
  Hits          734      734           
  Misses        175      175           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@maleadt
maleadt merged commit 8e3ff32 into main Jul 16, 2026
14 checks passed
@maleadt
maleadt deleted the tb/test-pocl-fix branch July 16, 2026 04:58
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.

1 participant