-
Notifications
You must be signed in to change notification settings - Fork 676
[Refactor] Move AtomicAdd Vectorization to VectorizeLoop Pass #1677
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
Changes from 3 commits
639e8e4
dcff47e
53f4a5d
94370c3
f1bf450
173fe4d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -327,8 +327,8 @@ TL_DEVICE T1 AtomicAddRet(T1 *address, T2 val, | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| // TODO add memory_order for vectorized atomic add | ||||||
| TL_DEVICE void AtomicAddx2(half_t *ref, half_t *val, | ||||||
| template <typename src_type> | ||||||
| TL_DEVICE void AtomicAddx2(half_t *ref, src_type *val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| atomicAdd(reinterpret_cast<half2 *>(ref), | ||||||
|
|
@@ -374,8 +374,9 @@ TL_DEVICE void AtomicAddx2(half_t *ref, half_t *val, | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| template <typename src_type> | ||||||
| TL_DEVICE half2 | ||||||
| AtomicAddx2Ret(half_t *ref, half_t *val, | ||||||
| AtomicAddx2Ret(half_t *ref, src_type *val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| return atomicAdd(reinterpret_cast<half2 *>(ref), | ||||||
|
|
@@ -419,7 +420,8 @@ AtomicAddx2Ret(half_t *ref, half_t *val, | |||||
| } | ||||||
|
|
||||||
| #if (defined(__CUDA_ARCH_LIST__) && (__CUDA_ARCH_LIST__ > 750)) | ||||||
| TL_DEVICE void AtomicAddx2(bfloat16_t *ref, bfloat16_t *val, | ||||||
| template <typename src_type> | ||||||
| TL_DEVICE void AtomicAddx2(bfloat16_t *ref, src_type *val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| atomicAdd( | ||||||
|
|
@@ -458,8 +460,9 @@ TL_DEVICE void AtomicAddx2(bfloat16_t *ref, bfloat16_t *val, | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| template <typename src_type> | ||||||
| TL_DEVICE __nv_bfloat162 | ||||||
| AtomicAddx2Ret(bfloat16_t *ref, bfloat16_t *val, | ||||||
| AtomicAddx2Ret(bfloat16_t *ref, src_type *val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| return atomicAdd( | ||||||
|
|
@@ -502,7 +505,8 @@ AtomicAddx2Ret(bfloat16_t *ref, bfloat16_t *val, | |||||
| #endif | ||||||
|
|
||||||
| #if (defined(__CUDA_ARCH_LIST__) && (__CUDA_ARCH_LIST__ >= 900)) | ||||||
| TL_DEVICE void AtomicAddx2(float *ref, float *val, | ||||||
| template <typename src_type> | ||||||
| TL_DEVICE void AtomicAddx2(float *ref, src_type *val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| atomicAdd(reinterpret_cast<float2 *>(ref), | ||||||
|
|
@@ -532,8 +536,37 @@ TL_DEVICE void AtomicAddx2(float *ref, float *val, | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| TL_DEVICE void AtomicAddx2(float *ref, float2 val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| atomicAdd(reinterpret_cast<float2 *>(ref), val); | ||||||
| } else { | ||||||
| unsigned long long ref_addr = reinterpret_cast<unsigned long long>(ref); | ||||||
| float2 ret_val; | ||||||
| if (memory_order == int(cuda::memory_order_release) || | ||||||
| memory_order == int(cuda::memory_order_consume)) { | ||||||
| asm volatile("atom.release.gpu.global.add.v2.f32 {%0,%1}, [%2], {%3,%4};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y) | ||||||
| : "memory"); | ||||||
| } else if (memory_order == int(cuda::memory_order_acquire)) { | ||||||
| asm volatile("atom.acquire.gpu.global.add.v2.f32 {%0,%1}, [%2], {%3,%4};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y) | ||||||
| : "memory"); | ||||||
| } else if (memory_order == int(cuda::memory_order_acq_rel) || | ||||||
| memory_order == int(cuda::memory_order_seq_cst)) { | ||||||
| asm volatile("atom.acq_rel.gpu.global.add.v2.f32 {%0,%1}, [%2], {%3,%4};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y) | ||||||
| : "memory"); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| template <typename src_type> | ||||||
| TL_DEVICE float2 | ||||||
| AtomicAddx2Ret(float *ref, float *val, | ||||||
| AtomicAddx2Ret(float *ref, src_type *val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| return atomicAdd(reinterpret_cast<float2 *>(ref), | ||||||
|
|
@@ -564,7 +597,39 @@ AtomicAddx2Ret(float *ref, float *val, | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| TL_DEVICE void AtomicAddx4(float *ref, float *val, | ||||||
| template <typename src_type> | ||||||
| TL_DEVICE float2 | ||||||
| AtomicAddx2Ret(float *ref, float2 val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| return atomicAdd(reinterpret_cast<float2 *>(ref), static_cast<float2>(val)); | ||||||
| } else { | ||||||
| unsigned long long ref_addr = reinterpret_cast<unsigned long long>(ref); | ||||||
| float2 ret_val; | ||||||
| if (memory_order == int(cuda::memory_order_release) || | ||||||
| memory_order == int(cuda::memory_order_consume)) { | ||||||
| asm volatile("atom.release.gpu.global.add.v2.f32 {%0,%1}, [%2], {%3,%4};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y) | ||||||
| : "memory"); | ||||||
| } else if (memory_order == int(cuda::memory_order_acquire)) { | ||||||
| asm volatile("atom.acquire.gpu.global.add.v2.f32 {%0,%1}, [%2], {%3,%4};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y) | ||||||
| : "memory"); | ||||||
| } else if (memory_order == int(cuda::memory_order_acq_rel) || | ||||||
| memory_order == int(cuda::memory_order_seq_cst)) { | ||||||
| asm volatile("atom.acq_rel.gpu.global.add.v2.f32 {%0,%1}, [%2], {%3,%4};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y) | ||||||
| : "memory"); | ||||||
| } | ||||||
| return ret_val; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| template <typename src_dtype, typename dst_dtype> | ||||||
| TL_DEVICE void AtomicAddx4(dst_dtype *ref, src_dtype *val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| atomicAdd(reinterpret_cast<float4 *>(ref), | ||||||
|
|
@@ -606,8 +671,47 @@ TL_DEVICE void AtomicAddx4(float *ref, float *val, | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| template <typename dst_dtype> | ||||||
| TL_DEVICE void AtomicAddx4(dst_dtype *ref, float4 val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| atomicAdd(reinterpret_cast<float4 *>(ref), val); | ||||||
| } else { | ||||||
| // Since atomicAdd does not support memory order, atomic_ref does not | ||||||
| // support vectorized atomic operation we can only inline ptx code here | ||||||
| // Note: Vectorized atomic operations only support global space | ||||||
| unsigned long long ref_addr = reinterpret_cast<unsigned long long>(ref); | ||||||
| float4 ret_val; | ||||||
| if (memory_order == int(cuda::memory_order_release) || | ||||||
| memory_order == int(cuda::memory_order_consume)) { | ||||||
| asm volatile( | ||||||
| "atom.release.gpu.global.add.v4.f32 {%0,%1,%2,%3}, [%4], " | ||||||
| "{%5,%6,%7,%8};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y), "=f"(ret_val.z), "=f"(ret_val.w) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y), "f"(val.z), "f"(val.w) | ||||||
| : "memory"); | ||||||
| } else if (memory_order == int(cuda::memory_order_acquire)) { | ||||||
| asm volatile( | ||||||
| "atom.acquire.gpu.global.add.v4.f32 {%0,%1,%2,%3}, [%4], " | ||||||
| "{%5,%6,%7,%8};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y), "=f"(ret_val.z), "=f"(ret_val.w) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y), "f"(val.z), "f"(val.w) | ||||||
| : "memory"); | ||||||
| } else if (memory_order == int(cuda::memory_order_acq_rel) || | ||||||
| memory_order == int(cuda::memory_order_seq_cst)) { | ||||||
| asm volatile( | ||||||
| "atom.acq_rel.gpu.global.add.v4.f32 {%0,%1,%2,%3}, [%4], " | ||||||
| "{%5,%6,%7,%8};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y), "=f"(ret_val.z), "=f"(ret_val.w) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y), "f"(val.z), "f"(val.w) | ||||||
| : "memory"); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| template <typename src_dtype, typename dst_dtype> | ||||||
| TL_DEVICE float4 | ||||||
| AtomicAddx4Ret(float *ref, float *val, | ||||||
| AtomicAddx4Ret(dst_dtype *ref, src_dtype *val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| return atomicAdd(reinterpret_cast<float4 *>(ref), | ||||||
|
|
@@ -646,17 +750,56 @@ AtomicAddx4Ret(float *ref, float *val, | |||||
| return ret_val; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| template <typename dst_dtype> | ||||||
| TL_DEVICE float4 | ||||||
| AtomicAddx4Ret(dst_dtype *ref, float4 val, | ||||||
| int memory_order = int(cuda::memory_order_relaxed)) { | ||||||
| if (memory_order == int(cuda::memory_order_relaxed)) { | ||||||
| return atomicAdd(reinterpret_cast<float4 *>(ref), val); | ||||||
| } else { | ||||||
| unsigned long long ref_addr = reinterpret_cast<unsigned long long>(ref); | ||||||
| float4 ret_val; | ||||||
| if (memory_order == int(cuda::memory_order_release) || | ||||||
| memory_order == int(cuda::memory_order_consume)) { | ||||||
| asm volatile( | ||||||
| "atom.global.gpu.release.add.v4.f32 {%0,%1,%2,%3}, [%4], " | ||||||
|
||||||
| "{%5,%6,%7,%8};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y), "=f"(ret_val.z), "=f"(ret_val.w) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y), "f"(val.z), "f"(val.w) | ||||||
| : "memory"); | ||||||
| } else if (memory_order == int(cuda::memory_order_acquire)) { | ||||||
| asm volatile( | ||||||
| "atom.global.gpu.acquire.add.v4.f32 {%0,%1,%2,%3}, [%4], " | ||||||
|
||||||
| "{%5,%6,%7,%8};" | ||||||
| : "=f"(ret_val.x), "=f"(ret_val.y), "=f"(ret_val.z), "=f"(ret_val.w) | ||||||
| : "l"(ref_addr), "f"(val.x), "f"(val.y), "f"(val.z), "f"(val.w) | ||||||
| : "memory"); | ||||||
| } else if (memory_order == int(cuda::memory_order_acq_rel) || | ||||||
| memory_order == int(cuda::memory_order_seq_cst)) { | ||||||
| asm volatile( | ||||||
| "atom.global.gpu.acq_rel.add.v4.f32 {%0,%1,%2,%3}, [%4], " | ||||||
|
||||||
| "atom.global.gpu.acq_rel.add.v4.f32 {%0,%1,%2,%3}, [%4], " | |
| "atom.acq_rel.gpu.global.add.v4.f32 {%0,%1,%2,%3}, [%4], " |
Uh oh!
There was an error while loading. Please reload this page.