Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
cooperative_groups.h1731 linesDownload Raw Back to include
1/*
2 * Copyright 1993-2021 NVIDIA Corporation.  All rights reserved.
3 *
4 * NOTICE TO LICENSEE:
5 *
6 * This source code and/or documentation ("Licensed Deliverables") are
7 * subject to NVIDIA intellectual property rights under U.S. and
8 * international Copyright laws.
9 *
10 * These Licensed Deliverables contained herein is PROPRIETARY and
11 * CONFIDENTIAL to NVIDIA and is being provided under the terms and
12 * conditions of a form of NVIDIA software license agreement by and
13 * between NVIDIA and Licensee ("License Agreement") or electronically
14 * accepted by Licensee.  Notwithstanding any terms or conditions to
15 * the contrary in the License Agreement, reproduction or disclosure
16 * of the Licensed Deliverables to any third party without the express
17 * written consent of NVIDIA is prohibited.
18 *
19 * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE
20 * LICENSE AGREEMENT, NVIDIA MAKES NO REPRESENTATION ABOUT THE
21 * SUITABILITY OF THESE LICENSED DELIVERABLES FOR ANY PURPOSE.  IT IS
22 * PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.
23 * NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE LICENSED
24 * DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY,
25 * NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
26 * NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE
27 * LICENSE AGREEMENT, IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY
28 * SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
29 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
30 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
31 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
32 * OF THESE LICENSED DELIVERABLES.
33 *
34 * U.S. Government End Users.  These Licensed Deliverables are a
35 * "commercial item" as that term is defined at 48 C.F.R. 2.101 (OCT
36 * 1995), consisting of "commercial computer software" and "commercial
37 * computer software documentation" as such terms are used in 48
38 * C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government
39 * only as a commercial end item.  Consistent with 48 C.F.R.12.212 and
40 * 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all
41 * U.S. Government End Users acquire the Licensed Deliverables with
42 * only those rights set forth herein.
43 *
44 * Any use of the Licensed Deliverables in individual and commercial
45 * software must include, in the user documentation and internal
46 * comments to the code, the above Disclaimer and U.S. Government End
47 * Users Notice.
48 */
49
50#ifndef _COOPERATIVE_GROUPS_H_
51#define _COOPERATIVE_GROUPS_H_
52
53#if defined(__cplusplus) && defined(__CUDACC__)
54
55#include "cooperative_groups/details/info.h"
56#include "cooperative_groups/details/driver_abi.h"
57#include "cooperative_groups/details/helpers.h"
58#include "cooperative_groups/details/memory.h"
59
60#if defined(_CG_HAS_STL_ATOMICS)
61#include <cuda/atomic>
62#define _CG_THREAD_SCOPE(scope) _CG_STATIC_CONST_DECL cuda::thread_scope thread_scope = scope;
63#else
64#define _CG_THREAD_SCOPE(scope)
65#endif
66
67_CG_BEGIN_NAMESPACE
68
69namespace details {
70    _CG_CONST_DECL unsigned int coalesced_group_id = 1;
71    _CG_CONST_DECL unsigned int multi_grid_group_id = 2;
72    _CG_CONST_DECL unsigned int grid_group_id = 3;
73    _CG_CONST_DECL unsigned int thread_block_id = 4;
74    _CG_CONST_DECL unsigned int multi_tile_group_id = 5;
75    _CG_CONST_DECL unsigned int cluster_group_id = 6;
76}
77
78/**
79 * class thread_group;
80 *
81 * Generic thread group type, into which all groups are convertible.
82 * It acts as a container for all storage necessary for the derived groups,
83 * and will dispatch the API calls to the correct derived group. This means
84 * that all derived groups must implement the same interface as thread_group.
85 */
86class thread_group
87{
88protected:
89    struct group_data {
90        unsigned int _unused : 1;
91        unsigned int type : 7, : 0;
92    };
93
94    struct gg_data  {
95        details::grid_workspace *gridWs;
96    };
97
98#if defined(_CG_CPP11_FEATURES) && defined(_CG_ABI_EXPERIMENTAL)
99    struct mg_data  {
100        unsigned long long _unused : 1;
101        unsigned long long type    : 7;
102        unsigned long long handle  : 56;
103        const details::multi_grid::multi_grid_functions *functions;
104    };
105#endif
106
107    struct tg_data {
108        unsigned int is_tiled : 1;
109        unsigned int type : 7;
110        unsigned int size : 24;
111        // packed to 4b
112        unsigned int metaGroupSize : 16;
113        unsigned int metaGroupRank : 16;
114        // packed to 8b
115        unsigned int mask;
116        // packed to 12b
117        unsigned int _res;
118    };
119
120    friend _CG_QUALIFIER thread_group tiled_partition(const thread_group& parent, unsigned int tilesz);
121    friend class thread_block;
122
123    union __align__(8) {
124        group_data  group;
125        tg_data     coalesced;
126        gg_data     grid;
127#if defined(_CG_CPP11_FEATURES) && defined(_CG_ABI_EXPERIMENTAL)
128        mg_data     multi_grid;
129#endif
130    } _data;
131
132    _CG_QUALIFIER thread_group operator=(const thread_group& src);
133
134    _CG_QUALIFIER thread_group(unsigned int type) {
135        _data.group.type = type;
136        _data.group._unused = false;
137    }
138
139#ifdef _CG_CPP11_FEATURES
140    static_assert(sizeof(tg_data) <= 16, "Failed size check");
141    static_assert(sizeof(gg_data) <= 16, "Failed size check");
142#  ifdef _CG_ABI_EXPERIMENTAL
143    static_assert(sizeof(mg_data) <= 16, "Failed size check");
144#  endif
145#endif
146
147public:
148    _CG_THREAD_SCOPE(cuda::thread_scope::thread_scope_device)
149
150    _CG_QUALIFIER unsigned long long size() const;
151    _CG_QUALIFIER unsigned long long num_threads() const;
152    _CG_QUALIFIER unsigned long long thread_rank() const;
153    _CG_QUALIFIER void sync() const;
154    _CG_QUALIFIER unsigned int get_type() const {
155        return _data.group.type;
156    }
157
158};
159
160template <unsigned int TyId>
161struct thread_group_base : public thread_group {
162    _CG_QUALIFIER thread_group_base() : thread_group(TyId) {}
163    _CG_STATIC_CONST_DECL unsigned int id = TyId;
164};
165
166#if defined(_CG_HAS_MULTI_GRID_GROUP)
167
168/**
169 * class multi_grid_group;
170 *
171 * Threads within this this group are guaranteed to be co-resident on the
172 * same system, on multiple devices within the same launched kernels.
173 * To use this group, the kernel must have been launched with
174 * cuLaunchCooperativeKernelMultiDevice (or the CUDA Runtime equivalent),
175 * and the device must support it (queryable device attribute).
176 *
177 * Constructed via this_multi_grid();
178 */
179
180
181# if defined(_CG_CPP11_FEATURES) && defined(_CG_ABI_EXPERIMENTAL)
182class multi_grid_group;
183
184// Multi grid group requires these functions to be templated to prevent ptxas from trying to use CG syscalls
185template <typename = void>
186__device__ _CG_DEPRECATED multi_grid_group this_multi_grid();
187
188class multi_grid_group : public thread_group_base<details::multi_grid_group_id>
189{
190private:
191    template <typename = void>
192    _CG_QUALIFIER multi_grid_group() {
193        _data.multi_grid.functions = details::multi_grid::load_grid_intrinsics();
194        _data.multi_grid.handle = _data.multi_grid.functions->get_intrinsic_handle();
195    }
196
197    friend multi_grid_group this_multi_grid<void>();
198
199public:
200    _CG_THREAD_SCOPE(cuda::thread_scope::thread_scope_system)
201
202    _CG_QUALIFIER bool is_valid() const {
203        return (_data.multi_grid.handle != 0);
204    }
205
206    _CG_QUALIFIER void sync() const {
207        if (!is_valid()) {
208            _CG_ABORT();
209        }
210        _data.multi_grid.functions->sync(_data.multi_grid.handle);
211    }
212
213    _CG_QUALIFIER unsigned long long num_threads() const {
214        _CG_ASSERT(is_valid());
215        return _data.multi_grid.functions->size(_data.multi_grid.handle);
216    }
217
218    _CG_QUALIFIER unsigned long long size() const {
219        return num_threads();
220    }
221
222    _CG_QUALIFIER unsigned long long thread_rank() const {
223        _CG_ASSERT(is_valid());
224        return _data.multi_grid.functions->thread_rank(_data.multi_grid.handle);
225    }
226
227    _CG_QUALIFIER unsigned int grid_rank() const {
228        _CG_ASSERT(is_valid());
229        return (_data.multi_grid.functions->grid_rank(_data.multi_grid.handle));
230    }
231
232    _CG_QUALIFIER unsigned int num_grids() const {
233        _CG_ASSERT(is_valid());
234        return (_data.multi_grid.functions->num_grids(_data.multi_grid.handle));
235    }
236};
237# else
238class multi_grid_group
239{
240private:
241    unsigned long long _handle;
242    unsigned int _size;
243    unsigned int _rank;
244
245    friend _CG_QUALIFIER multi_grid_group this_multi_grid();
246
247    _CG_QUALIFIER multi_grid_group() {
248        _handle = details::multi_grid::get_intrinsic_handle();
249        _size = details::multi_grid::size(_handle);
250        _rank = details::multi_grid::thread_rank(_handle);
251    }
252
253public:
254    _CG_THREAD_SCOPE(cuda::thread_scope::thread_scope_system)
255
256    _CG_QUALIFIER _CG_DEPRECATED bool is_valid() const {
257        return (_handle != 0);
258    }
259
260    _CG_QUALIFIER _CG_DEPRECATED void sync() const {
261        if (!is_valid()) {
262            _CG_ABORT();
263        }
264        details::multi_grid::sync(_handle);
265    }
266
267    _CG_QUALIFIER _CG_DEPRECATED unsigned long long num_threads() const {
268        _CG_ASSERT(is_valid());
269        return _size;
270    }
271
272    _CG_QUALIFIER _CG_DEPRECATED unsigned long long size() const {
273        return num_threads();
274    }
275
276    _CG_QUALIFIER _CG_DEPRECATED unsigned long long thread_rank() const {
277        _CG_ASSERT(is_valid());
278        return _rank;
279    }
280
281    _CG_QUALIFIER _CG_DEPRECATED unsigned int grid_rank() const {
282        _CG_ASSERT(is_valid());
283        return (details::multi_grid::grid_rank(_handle));
284    }
285
286    _CG_QUALIFIER _CG_DEPRECATED unsigned int num_grids() const {
287        _CG_ASSERT(is_valid());
288        return (details::multi_grid::num_grids(_handle));
289    }
290};
291# endif
292
293/**
294 * multi_grid_group this_multi_grid()
295 *
296 * Constructs a multi_grid_group
297 */
298# if defined(_CG_CPP11_FEATURES) && defined(_CG_ABI_EXPERIMENTAL)
299template <typename>
300__device__
301#else
302_CG_QUALIFIER
303# endif
304_CG_DEPRECATED
305multi_grid_group this_multi_grid()
306{
307    return multi_grid_group();
308}
309#endif
310
311/**
312 * class grid_group;
313 *
314 * Threads within this this group are guaranteed to be co-resident on the
315 * same device within the same launched kernel. To use this group, the kernel
316 * must have been launched with cuLaunchCooperativeKernel (or the CUDA Runtime equivalent),
317 * and the device must support it (queryable device attribute).
318 *
319 * Constructed via this_grid();
320 */
321class grid_group : public thread_group_base<details::grid_group_id>
322{
323    _CG_STATIC_CONST_DECL unsigned int _group_id = details::grid_group_id;
324    friend _CG_QUALIFIER grid_group this_grid();
325
326private:
327    _CG_QUALIFIER grid_group(details::grid_workspace *gridWs) {
328        _data.grid.gridWs = gridWs;
329    }
330
331 public:
332    _CG_THREAD_SCOPE(cuda::thread_scope::thread_scope_device)
333
334    _CG_QUALIFIER bool is_valid() const {
335        return (_data.grid.gridWs != NULL);
336    }
337
338    _CG_QUALIFIER void sync() const {
339        if (!is_valid()) {
340            _CG_ABORT();
341        }
342        details::grid::sync(&_data.grid.gridWs->barrier);
343    }
344
345#if defined(_CG_CPP11_FEATURES)
346    using arrival_token = unsigned int;
347
348    _CG_QUALIFIER arrival_token barrier_arrive() const {
349        if (!is_valid()) {
350            _CG_ABORT();
351        }
352        return details::grid::barrier_arrive(&_data.grid.gridWs->barrier);
353    }
354
355    _CG_QUALIFIER void barrier_wait(arrival_token&& token) const {
356        details::grid::barrier_wait(token, &_data.grid.gridWs->barrier);
357    }
358#endif
359
360    _CG_STATIC_QUALIFIER unsigned long long size() {
361        return details::grid::size();
362    }
363
364    _CG_STATIC_QUALIFIER dim3 group_dim() {
365        return details::grid::grid_dim();
366    }
367
368    _CG_STATIC_QUALIFIER dim3 dim_threads() {
369        return details::grid::dim_threads();
370    }
371
372    _CG_STATIC_QUALIFIER unsigned long long num_threads() {
373        return details::grid::num_threads();
374    }
375
376    _CG_STATIC_QUALIFIER dim3 thread_index() {
377        return details::grid::thread_index();
378    }
379
380    _CG_STATIC_QUALIFIER unsigned long long thread_rank() {
381        return details::grid::thread_rank();
382    }
383
384    _CG_STATIC_QUALIFIER dim3 dim_blocks() {
385        return details::grid::dim_blocks();
386    }
387
388    _CG_STATIC_QUALIFIER unsigned long long num_blocks() {
389        return details::grid::num_blocks();
390    }
391
392    _CG_STATIC_QUALIFIER dim3 block_index() {
393        return details::grid::block_index();
394    }
395
396    _CG_STATIC_QUALIFIER unsigned long long block_rank() {
397        return details::grid::block_rank();
398    }
399
400# if defined(_CG_HAS_CLUSTER_GROUP)
401    _CG_STATIC_QUALIFIER dim3 dim_clusters() {
402        return details::grid::dim_clusters();
403    }
404
405    _CG_STATIC_QUALIFIER unsigned long long num_clusters() {
406        return details::grid::num_clusters();
407    }
408
409    _CG_STATIC_QUALIFIER dim3 cluster_index() {
410        return details::grid::cluster_index();
411    }
412
413    _CG_STATIC_QUALIFIER unsigned long long cluster_rank() {
414        return details::grid::cluster_rank();
415    }
416# endif
417};
418
419_CG_QUALIFIER grid_group this_grid() {
420    // Load a workspace from the driver
421    grid_group gg(details::get_grid_workspace());
422#ifdef _CG_DEBUG
423    // *all* threads must be available to synchronize
424    gg.sync();
425#endif // _CG_DEBUG
426    return gg;
427}
428
429#if defined(_CG_HAS_CLUSTER_GROUP)
430/**
431 * class cluster_group
432 *
433 * Every GPU kernel is executed by a grid of thread blocks. A grid can be evenly
434 * divided along all dimensions to form groups of blocks, each group of which is
435 * a block cluster. Clustered grids are subject to various restrictions and
436 * limitations. Primarily, a cluster consists of at most 8 blocks by default
437 * (although the user is allowed to opt-in to non-standard sizes,) and clustered
438 * grids are subject to additional occupancy limitations due to per-cluster
439 * hardware resource consumption. In exchange, a block cluster is guaranteed to
440 * be a cooperative group, with access to all cooperative group capabilities, as
441 * well as cluster specific capabilities and accelerations. A cluster_group
442 * represents a block cluster.
443 *
444 * Constructed via this_cluster_group();
445 */
446class cluster_group : public thread_group_base<details::cluster_group_id>
447{
448    // Friends
449    friend _CG_QUALIFIER cluster_group this_cluster();
450
451    // Disable constructor
452    _CG_QUALIFIER cluster_group()
453    {
454    }
455
456 public:
457    //_CG_THREAD_SCOPE(cuda::thread_scope::thread_scope_cluster)
458
459    using arrival_token = struct {};
460
461    // Functionality exposed by the group
462    _CG_STATIC_QUALIFIER void sync()
463    {
464        return details::cluster::sync();
465    }
466
467    _CG_STATIC_QUALIFIER arrival_token barrier_arrive()
468    {
469        details::cluster::barrier_arrive();
470        return arrival_token();
471    }
472
473    _CG_STATIC_QUALIFIER void barrier_wait()
474    {
475        return details::cluster::barrier_wait();
476    }
477
478    _CG_STATIC_QUALIFIER void barrier_wait(arrival_token&&)
479    {
480        return details::cluster::barrier_wait();
481    }
482
483    _CG_STATIC_QUALIFIER unsigned int query_shared_rank(const void *addr)
484    {
485        return details::cluster::query_shared_rank(addr);
486    }
487
488    template <typename T>
489    _CG_STATIC_QUALIFIER T* map_shared_rank(T *addr, int rank)
490    {
491        return details::cluster::map_shared_rank(addr, rank);
492    }
493
494    _CG_STATIC_QUALIFIER dim3 block_index()
495    {
496        return details::cluster::block_index();
497    }
498
499    _CG_STATIC_QUALIFIER unsigned int block_rank()
500    {
501        return details::cluster::block_rank();
502    }
503
504    _CG_STATIC_QUALIFIER dim3 thread_index()
505    {
506        return details::cluster::thread_index();
507    }
508
509    _CG_STATIC_QUALIFIER unsigned int thread_rank()
510    {
511        return details::cluster::thread_rank();
512    }
513
514    _CG_STATIC_QUALIFIER dim3 dim_blocks()
515    {
516        return details::cluster::dim_blocks();
517    }
518
519    _CG_STATIC_QUALIFIER unsigned int num_blocks()
520    {
521        return details::cluster::num_blocks();
522    }
523
524    _CG_STATIC_QUALIFIER dim3 dim_threads()
525    {
526        return details::cluster::dim_threads();
527    }
528
529    _CG_STATIC_QUALIFIER unsigned int num_threads()
530    {
531        return details::cluster::num_threads();
532    }
533
534    // Legacy aliases
535    _CG_STATIC_QUALIFIER unsigned int size()
536    {
537        return num_threads();
538    }
539};
540
541/*
542 * cluster_group this_cluster()
543 *
544 * Constructs a cluster_group
545 */
546_CG_QUALIFIER cluster_group this_cluster()
547{
548    cluster_group cg;
549#ifdef _CG_DEBUG
550    cg.sync();
551#endif
552    return cg;
553}
554#endif
555
556#if defined(_CG_CPP11_FEATURES)
557class thread_block;
558template <unsigned int MaxBlockSize>
559_CG_QUALIFIER thread_block this_thread_block(block_tile_memory<MaxBlockSize>& scratch);
560#endif
561
562/**
563 * class thread_block
564 *
565 * Every GPU kernel is executed by a grid of thread blocks, and threads within
566 * each block are guaranteed to reside on the same streaming multiprocessor.
567 * A thread_block represents a thread block whose dimensions are not known until runtime.
568 *
569 * Constructed via this_thread_block();
570 */
571class thread_block : public thread_group_base<details::thread_block_id>
572{
573    // Friends
574    friend _CG_QUALIFIER thread_block this_thread_block();
575    friend _CG_QUALIFIER thread_group tiled_partition(const thread_group& parent, unsigned int tilesz);
576    friend _CG_QUALIFIER thread_group tiled_partition(const thread_block& parent, unsigned int tilesz);
577
578#if defined(_CG_CPP11_FEATURES)
579    template <unsigned int MaxBlockSize>
580    friend _CG_QUALIFIER thread_block this_thread_block(block_tile_memory<MaxBlockSize>& scratch);
581    template <unsigned int Size>
582    friend class __static_size_multi_warp_tile_base;
583
584    details::multi_warp_scratch* const tile_memory;
585
586    template <unsigned int MaxBlockSize>
587    _CG_QUALIFIER thread_block(block_tile_memory<MaxBlockSize>& scratch) :
588        tile_memory(details::get_scratch_ptr(&scratch)) {
589#ifdef _CG_DEBUG
590        if (num_threads() > MaxBlockSize) {
591            details::abort();
592        }
593#endif
594#if !defined(_CG_HAS_RESERVED_SHARED)
595        tile_memory->init_barriers(thread_rank());
596        sync();
597#endif
598    }
599#endif
600
601    // Disable constructor
602    _CG_QUALIFIER thread_block()
603#if defined(_CG_CPP11_FEATURES)
604    : tile_memory(details::get_scratch_ptr(NULL))
605#endif
606    { }
607
608    // Internal Use
609    _CG_QUALIFIER thread_group _get_tiled_threads(unsigned int tilesz) const {
610        const bool pow2_tilesz = ((tilesz & (tilesz - 1)) == 0);
611
612        // Invalid, immediately fail
613        if (tilesz == 0 || (tilesz > 32) || !pow2_tilesz) {
614            details::abort();
615            return (thread_block());
616        }
617
618        unsigned int mask;
619        unsigned int base_offset = thread_rank() & (~(tilesz - 1));
620        unsigned int masklength = min((unsigned int)size() - base_offset, tilesz);
621
622        mask = (unsigned int)(-1) >> (32 - masklength);
623        mask <<= (details::laneid() & ~(tilesz - 1));
624        thread_group tile = thread_group(details::coalesced_group_id);
625        tile._data.coalesced.mask = mask;
626        tile._data.coalesced.size = __popc(mask);
627        tile._data.coalesced.metaGroupSize = (details::cta::size() + tilesz - 1) / tilesz;
628        tile._data.coalesced.metaGroupRank = details::cta::thread_rank() / tilesz;
629        tile._data.coalesced.is_tiled = true;
630        return (tile);
631    }
632
633 public:
634    _CG_STATIC_CONST_DECL unsigned int _group_id = details::thread_block_id;
635    _CG_THREAD_SCOPE(cuda::thread_scope::thread_scope_block)
636
637    _CG_STATIC_QUALIFIER void sync() {
638        details::cta::sync();
639    }
640
641#if defined(_CG_CPP11_FEATURES)
642    struct arrival_token {};
643
644    _CG_QUALIFIER arrival_token barrier_arrive() const {
645        return arrival_token();
646    }
647
648    _CG_QUALIFIER void barrier_wait(arrival_token&&) const {
649        details::cta::sync();
650    }
651#endif
652
653    _CG_STATIC_QUALIFIER unsigned int size() {
654        return details::cta::size();
655    }
656
657    _CG_STATIC_QUALIFIER unsigned int thread_rank() {
658        return details::cta::thread_rank();
659    }
660
661    // Additional functionality exposed by the group
662    _CG_STATIC_QUALIFIER dim3 group_index() {
663        return details::cta::group_index();
664    }
665
666    _CG_STATIC_QUALIFIER dim3 thread_index() {
667        return details::cta::thread_index();
668    }
669
670    _CG_STATIC_QUALIFIER dim3 group_dim() {
671        return details::cta::block_dim();
672    }
673
674    _CG_STATIC_QUALIFIER dim3 dim_threads() {
675        return details::cta::dim_threads();
676    }
677
678    _CG_STATIC_QUALIFIER unsigned int num_threads() {
679        return details::cta::num_threads();
680    }
681
682};
683
684/**
685 * thread_block this_thread_block()
686 *
687 * Constructs a thread_block group
688 */
689_CG_QUALIFIER thread_block this_thread_block()
690{
691    return (thread_block());
692}
693
694#if defined(_CG_CPP11_FEATURES)
695template <unsigned int MaxBlockSize>
696_CG_QUALIFIER thread_block this_thread_block(block_tile_memory<MaxBlockSize>& scratch) {
697    return (thread_block(scratch));
698}
699#endif
700
701/**
702 * class coalesced_group
703 *
704 * A group representing the current set of converged threads in a warp.
705 * The size of the group is not guaranteed and it may return a group of
706 * only one thread (itself).
707 *
708 * This group exposes warp-synchronous builtins.
709 * Constructed via coalesced_threads();
710 */
711class coalesced_group : public thread_group_base<details::coalesced_group_id>
712{
713private:
714    friend _CG_QUALIFIER coalesced_group coalesced_threads();
715    friend _CG_QUALIFIER thread_group tiled_partition(const thread_group& parent, unsigned int tilesz);
716    friend _CG_QUALIFIER coalesced_group tiled_partition(const coalesced_group& parent, unsigned int tilesz);
717    friend class details::_coalesced_group_data_access;
718
719    _CG_QUALIFIER unsigned int _packLanes(unsigned laneMask) const {
720        unsigned int member_pack = 0;
721        unsigned int member_rank = 0;
722        for (int bit_idx = 0; bit_idx < 32; bit_idx++) {
723            unsigned int lane_bit = _data.coalesced.mask & (1 << bit_idx);
724            if (lane_bit) {
725                if (laneMask & lane_bit)
726                    member_pack |= 1 << member_rank;
727                member_rank++;
728            }
729        }
730        return (member_pack);
731    }
732
733    // Internal Use
734    _CG_QUALIFIER coalesced_group _get_tiled_threads(unsigned int tilesz) const {
735        const bool pow2_tilesz = ((tilesz & (tilesz - 1)) == 0);
736
737        // Invalid, immediately fail
738        if (tilesz == 0 || (tilesz > 32) || !pow2_tilesz) {
739            details::abort();
740            return (coalesced_group(0));
741        }
742        if (size() <= tilesz) {
743            return (*this);
744        }
745
746        if ((_data.coalesced.is_tiled == true) && pow2_tilesz) {
747            unsigned int base_offset = (thread_rank() & (~(tilesz - 1)));
748            unsigned int masklength = min((unsigned int)size() - base_offset, tilesz);
749            unsigned int mask = (unsigned int)(-1) >> (32 - masklength);
750
751            mask <<= (details::laneid() & ~(tilesz - 1));
752            coalesced_group coalesced_tile = coalesced_group(mask);
753            coalesced_tile._data.coalesced.metaGroupSize = size() / tilesz;
754            coalesced_tile._data.coalesced.metaGroupRank = thread_rank() / tilesz;
755            coalesced_tile._data.coalesced.is_tiled = true;
756            return (coalesced_tile);
757        }
758        else if ((_data.coalesced.is_tiled == false) && pow2_tilesz) {
759            unsigned int mask = 0;
760            unsigned int member_rank = 0;
761            int seen_lanes = (thread_rank() / tilesz) * tilesz;
762            for (unsigned int bit_idx = 0; bit_idx < 32; bit_idx++) {
763                unsigned int lane_bit = _data.coalesced.mask & (1 << bit_idx);
764                if (lane_bit) {
765                    if (seen_lanes <= 0 && member_rank < tilesz) {
766                        mask |= lane_bit;
767                        member_rank++;
768                    }
769                    seen_lanes--;
770                }
771            }
772            coalesced_group coalesced_tile = coalesced_group(mask);
773            // Override parent with the size of this group
774            coalesced_tile._data.coalesced.metaGroupSize = (size() + tilesz - 1) / tilesz;
775            coalesced_tile._data.coalesced.metaGroupRank = thread_rank() / tilesz;
776            return coalesced_tile;
777        }
778        else {
779            // None in _CG_VERSION 1000
780            details::abort();
781        }
782
783        return (coalesced_group(0));
784    }
785
786 protected:
787    _CG_QUALIFIER coalesced_group(unsigned int mask) {
788        _data.coalesced.mask = mask;
789        _data.coalesced.size = __popc(mask);
790        _data.coalesced.metaGroupRank = 0;
791        _data.coalesced.metaGroupSize = 1;
792        _data.coalesced.is_tiled = false;
793    }
794
795    _CG_QUALIFIER unsigned int get_mask() const {
796        return (_data.coalesced.mask);
797    }
798
799 public:
800    _CG_STATIC_CONST_DECL unsigned int _group_id = details::coalesced_group_id;
801    _CG_THREAD_SCOPE(cuda::thread_scope::thread_scope_block)
802
803    _CG_QUALIFIER unsigned int num_threads() const {
804        return _data.coalesced.size;
805    }
806
807    _CG_QUALIFIER unsigned int size() const {
808        return num_threads();
809    }
810
811    _CG_QUALIFIER unsigned int thread_rank() const {
812        return (__popc(_data.coalesced.mask & details::lanemask32_lt()));
813    }
814
815    // Rank of this group in the upper level of the hierarchy
816    _CG_QUALIFIER unsigned int meta_group_rank() const {
817        return _data.coalesced.metaGroupRank;
818    }
819
820    // Total num partitions created out of all CTAs when the group was created
821    _CG_QUALIFIER unsigned int meta_group_size() const {
822        return _data.coalesced.metaGroupSize;
823    }
824
825    _CG_QUALIFIER void sync() const {
826        __syncwarp(_data.coalesced.mask);
827    }
828
829#ifdef _CG_CPP11_FEATURES
830    template <typename TyElem, typename TyRet = details::remove_qual<TyElem>>
831    _CG_QUALIFIER TyRet shfl(TyElem&& elem, int srcRank) const {
832        unsigned int lane = (srcRank == 0) ? __ffs(_data.coalesced.mask) - 1 :
833            (size() == 32) ? srcRank : __fns(_data.coalesced.mask, 0, (srcRank + 1));
834
835        return details::tile::shuffle_dispatch<TyElem>::shfl(
836            _CG_STL_NAMESPACE::forward<TyElem>(elem), _data.coalesced.mask, lane, 32);
837    }
838
839    template <typename TyElem, typename TyRet = details::remove_qual<TyElem>>
840    _CG_QUALIFIER TyRet shfl_down(TyElem&& elem, unsigned int delta) const {
841        if (size() == 32) {
842            return details::tile::shuffle_dispatch<TyElem>::shfl_down(
843                _CG_STL_NAMESPACE::forward<TyElem>(elem), 0xFFFFFFFF, delta, 32);
844        }
845
846        unsigned int lane = __fns(_data.coalesced.mask, details::laneid(), delta + 1);
847
848        if (lane >= 32)
849            lane = details::laneid();
850
851        return details::tile::shuffle_dispatch<TyElem>::shfl(
852            _CG_STL_NAMESPACE::forward<TyElem>(elem), _data.coalesced.mask, lane, 32);
853    }
854
855    template <typename TyElem, typename TyRet = details::remove_qual<TyElem>>
856    _CG_QUALIFIER TyRet shfl_up(TyElem&& elem, int delta) const {
857        if (size() == 32) {
858            return details::tile::shuffle_dispatch<TyElem>::shfl_up(
859                _CG_STL_NAMESPACE::forward<TyElem>(elem), 0xFFFFFFFF, delta, 32);
860        }
861
862        unsigned lane = __fns(_data.coalesced.mask, details::laneid(), -(delta + 1));
863        if (lane >= 32)
864            lane = details::laneid();
865
866        return details::tile::shuffle_dispatch<TyElem>::shfl(
867            _CG_STL_NAMESPACE::forward<TyElem>(elem), _data.coalesced.mask, lane, 32);
868    }
869#else
870    template <typename TyIntegral>
871    _CG_QUALIFIER TyIntegral shfl(TyIntegral var, unsigned int src_rank) const {
872        details::assert_if_not_arithmetic<TyIntegral>();
873        unsigned int lane = (src_rank == 0) ? __ffs(_data.coalesced.mask) - 1 :
874            (size() == 32) ? src_rank : __fns(_data.coalesced.mask, 0, (src_rank + 1));
875        return (__shfl_sync(_data.coalesced.mask, var, lane, 32));
876    }
877
878    template <typename TyIntegral>
879    _CG_QUALIFIER TyIntegral shfl_up(TyIntegral var, int delta) const {
880        details::assert_if_not_arithmetic<TyIntegral>();
881        if (size() == 32) {
882            return (__shfl_up_sync(0xFFFFFFFF, var, delta, 32));
883        }
884        unsigned lane = __fns(_data.coalesced.mask, details::laneid(), -(delta + 1));
885        if (lane >= 32) lane = details::laneid();
886        return (__shfl_sync(_data.coalesced.mask, var, lane, 32));
887    }
888
889    template <typename TyIntegral>
890    _CG_QUALIFIER TyIntegral shfl_down(TyIntegral var, int delta) const {
891        details::assert_if_not_arithmetic<TyIntegral>();
892        if (size() == 32) {
893            return (__shfl_down_sync(0xFFFFFFFF, var, delta, 32));
894        }
895        unsigned int lane = __fns(_data.coalesced.mask, details::laneid(), delta + 1);
896        if (lane >= 32) lane = details::laneid();
897        return (__shfl_sync(_data.coalesced.mask, var, lane, 32));
898    }
899#endif
900
901    _CG_QUALIFIER int any(int predicate) const {
902        return (__ballot_sync(_data.coalesced.mask, predicate) != 0);
903    }
904    _CG_QUALIFIER int all(int predicate) const {
905        return (__ballot_sync(_data.coalesced.mask, predicate) == _data.coalesced.mask);
906    }
907    _CG_QUALIFIER unsigned int ballot(int predicate) const {
908        if (size() == 32) {
909            return (__ballot_sync(0xFFFFFFFF, predicate));
910        }
911        unsigned int lane_ballot = __ballot_sync(_data.coalesced.mask, predicate);
912        return (_packLanes(lane_ballot));
913    }
914
915#ifdef _CG_HAS_MATCH_COLLECTIVE
916
917    template <typename TyIntegral>
918    _CG_QUALIFIER unsigned int match_any(TyIntegral val) const {
919        details::assert_if_not_arithmetic<TyIntegral>();
920        if (size() == 32) {
921            return (__match_any_sync(0xFFFFFFFF, val));
922        }
923        unsigned int lane_match = __match_any_sync(_data.coalesced.mask, val);
924        return (_packLanes(lane_match));
925    }
926
927    template <typename TyIntegral>
928    _CG_QUALIFIER unsigned int match_all(TyIntegral val, int &pred) const {
929        details::assert_if_not_arithmetic<TyIntegral>();
930        if (size() == 32) {
931            return (__match_all_sync(0xFFFFFFFF, val, &pred));
932        }
933        unsigned int lane_match = __match_all_sync(_data.coalesced.mask, val, &pred);
934        return (_packLanes(lane_match));
935    }
936
937#endif /* !_CG_HAS_MATCH_COLLECTIVE */
938
939};
940
941_CG_QUALIFIER coalesced_group coalesced_threads()
942{
943    return (coalesced_group(__activemask()));
944}
945
946namespace details {
947    template <unsigned int Size> struct verify_thread_block_tile_size;
948    template <> struct verify_thread_block_tile_size<32> { typedef void OK; };
949    template <> struct verify_thread_block_tile_size<16> { typedef void OK; };
950    template <> struct verify_thread_block_tile_size<8>  { typedef void OK; };
951    template <> struct verify_thread_block_tile_size<4>  { typedef void OK; };
952    template <> struct verify_thread_block_tile_size<2>  { typedef void OK; };
953    template <> struct verify_thread_block_tile_size<1>  { typedef void OK; };
954
955#ifdef _CG_CPP11_FEATURES
956    template <unsigned int Size>
957    using _is_power_of_2 = _CG_STL_NAMESPACE::integral_constant<bool, (Size & (Size - 1)) == 0>;
958
959    template <unsigned int Size>
960    using _is_single_warp = _CG_STL_NAMESPACE::integral_constant<bool, Size <= 32>;
961    template <unsigned int Size>
962    using _is_multi_warp =
963    _CG_STL_NAMESPACE::integral_constant<bool, (Size > 32) && (Size <= 1024)>;
964
965    template <unsigned int Size>
966    using _is_valid_single_warp_tile =
967        _CG_STL_NAMESPACE::integral_constant<bool, _is_power_of_2<Size>::value && _is_single_warp<Size>::value>;
968    template <unsigned int Size>
969    using _is_valid_multi_warp_tile =
970        _CG_STL_NAMESPACE::integral_constant<bool, _is_power_of_2<Size>::value && _is_multi_warp<Size>::value>;
971#else
972    template <unsigned int Size>
973    struct _is_multi_warp {
974        static const bool value = false;
975    };
976#endif
977}
978
979template <unsigned int Size>
980class __static_size_tile_base
981{
982protected:
983    _CG_STATIC_CONST_DECL unsigned int numThreads = Size;
984
985public:
986    _CG_THREAD_SCOPE(cuda::thread_scope::thread_scope_block)
987
988    // Rank of thread within tile
989    _CG_STATIC_QUALIFIER unsigned int thread_rank() {
990        return (details::cta::thread_rank() & (numThreads - 1));
991    }
992
993    // Number of threads within tile
994    _CG_STATIC_CONSTEXPR_QUALIFIER unsigned int num_threads() {
995        return numThreads;
996    }
997
998    _CG_STATIC_CONSTEXPR_QUALIFIER unsigned int size() {
999        return num_threads();
1000    }
1001};
1002
1003template <unsigned int Size>
1004class __static_size_thread_block_tile_base : public __static_size_tile_base<Size>
1005{
1006    friend class details::_coalesced_group_data_access;
1007    typedef details::tile::tile_helpers<Size> th;
1008
1009#ifdef _CG_CPP11_FEATURES
1010    static_assert(details::_is_valid_single_warp_tile<Size>::value, "Size must be one of 1/2/4/8/16/32");
1011#else
1012    typedef typename details::verify_thread_block_tile_size<Size>::OK valid;
1013#endif
1014    using __static_size_tile_base<Size>::numThreads;
1015    _CG_STATIC_CONST_DECL unsigned int fullMask = 0xFFFFFFFF;
1016
1017 protected:
1018    _CG_STATIC_QUALIFIER unsigned int build_mask() {
1019        unsigned int mask = fullMask;
1020        if (numThreads != 32) {
1021            // [0,31] representing the current active thread in the warp
1022            unsigned int laneId = details::laneid();
1023            // shift mask according to the partition it belongs to
1024            mask = th::tileMask << (laneId & ~(th::laneMask));
1025        }
1026        return (mask);
1027    }
1028
1029public:
1030    _CG_STATIC_CONST_DECL unsigned int _group_id = details::coalesced_group_id;
1031
1032    _CG_STATIC_QUALIFIER void sync() {
1033        __syncwarp(build_mask());
1034    }
1035
1036#ifdef _CG_CPP11_FEATURES
1037    // PTX supported collectives
1038    template <typename TyElem, typename TyRet = details::remove_qual<TyElem>>
1039    _CG_QUALIFIER TyRet shfl(TyElem&& elem, int srcRank) const {
1040        return details::tile::shuffle_dispatch<TyElem>::shfl(
1041            _CG_STL_NAMESPACE::forward<TyElem>(elem), build_mask(), srcRank, numThreads);
1042    }
1043
1044    template <typename TyElem, typename TyRet = details::remove_qual<TyElem>>
1045    _CG_QUALIFIER TyRet shfl_down(TyElem&& elem, unsigned int delta) const {
1046        return details::tile::shuffle_dispatch<TyElem>::shfl_down(
1047            _CG_STL_NAMESPACE::forward<TyElem>(elem), build_mask(), delta, numThreads);
1048    }
1049
1050    template <typename TyElem, typename TyRet = details::remove_qual<TyElem>>
1051    _CG_QUALIFIER TyRet shfl_up(TyElem&& elem, unsigned int delta) const {
1052        return details::tile::shuffle_dispatch<TyElem>::shfl_up(
1053            _CG_STL_NAMESPACE::forward<TyElem>(elem), build_mask(), delta, numThreads);
1054    }
1055
1056    template <typename TyElem, typename TyRet = details::remove_qual<TyElem>>
1057    _CG_QUALIFIER TyRet shfl_xor(TyElem&& elem, unsigned int laneMask) const {
1058        return details::tile::shuffle_dispatch<TyElem>::shfl_xor(
1059            _CG_STL_NAMESPACE::forward<TyElem>(elem), build_mask(), laneMask, numThreads);
1060    }
1061#else
1062    template <typename TyIntegral>
1063    _CG_QUALIFIER TyIntegral shfl(TyIntegral var, int srcRank) const {
1064        details::assert_if_not_arithmetic<TyIntegral>();
1065        return (__shfl_sync(build_mask(), var, srcRank, numThreads));
1066    }
1067
1068    template <typename TyIntegral>
1069    _CG_QUALIFIER TyIntegral shfl_down(TyIntegral var, unsigned int delta) const {
1070        details::assert_if_not_arithmetic<TyIntegral>();
1071        return (__shfl_down_sync(build_mask(), var, delta, numThreads));
1072    }
1073
1074    template <typename TyIntegral>
1075    _CG_QUALIFIER TyIntegral shfl_up(TyIntegral var, unsigned int delta) const {
1076        details::assert_if_not_arithmetic<TyIntegral>();
1077        return (__shfl_up_sync(build_mask(), var, delta, numThreads));
1078    }
1079
1080    template <typename TyIntegral>
1081    _CG_QUALIFIER TyIntegral shfl_xor(TyIntegral var, unsigned int laneMask) const {
1082        details::assert_if_not_arithmetic<TyIntegral>();
1083        return (__shfl_xor_sync(build_mask(), var, laneMask, numThreads));
1084    }
1085#endif //_CG_CPP11_FEATURES
1086
1087    _CG_QUALIFIER int any(int predicate) const {
1088        unsigned int lane_ballot = __ballot_sync(build_mask(), predicate);
1089        return (lane_ballot != 0);
1090    }
1091    _CG_QUALIFIER int all(int predicate) const {
1092        unsigned int lane_ballot = __ballot_sync(build_mask(), predicate);
1093        return (lane_ballot == build_mask());
1094    }
1095    _CG_QUALIFIER unsigned int ballot(int predicate) const {
1096        unsigned int lane_ballot = __ballot_sync(build_mask(), predicate);
1097        return (lane_ballot >> (details::laneid() & (~(th::laneMask))));
1098    }
1099
1100#ifdef _CG_HAS_MATCH_COLLECTIVE
1101    template <typename TyIntegral>
1102    _CG_QUALIFIER unsigned int match_any(TyIntegral val) const {
1103        details::assert_if_not_arithmetic<TyIntegral>();
1104        unsigned int lane_match = __match_any_sync(build_mask(), val);
1105        return (lane_match >> (details::laneid() & (~(th::laneMask))));
1106    }
1107
1108    template <typename TyIntegral>
1109    _CG_QUALIFIER unsigned int match_all(TyIntegral val, int &pred) const {
1110        details::assert_if_not_arithmetic<TyIntegral>();
1111        unsigned int lane_match = __match_all_sync(build_mask(), val, &pred);
1112        return (lane_match >> (details::laneid() & (~(th::laneMask))));
1113    }
1114#endif
1115
1116};
1117
1118template <unsigned int Size, typename ParentT>
1119class __static_parent_thread_block_tile_base
1120{
1121public:
1122    // Rank of this group in the upper level of the hierarchy
1123    _CG_STATIC_QUALIFIER unsigned int meta_group_rank() {
1124        return ParentT::thread_rank() / Size;
1125    }
1126
1127    // Total num partitions created out of all CTAs when the group was created
1128    _CG_STATIC_QUALIFIER unsigned int meta_group_size() {
1129        return (ParentT::size() + Size - 1) / Size;
1130    }
1131};
1132
1133/**
1134 * class thread_block_tile<unsigned int Size, ParentT = void>
1135 *
1136 * Statically-sized group type, representing one tile of a thread block.
1137 * The only specializations currently supported are those with native
1138 * hardware support (1/2/4/8/16/32)
1139 *
1140 * This group exposes warp-synchronous builtins.
1141 * Can only be constructed via tiled_partition<Size>(ParentT&)
1142 */
1143
1144template <unsigned int Size, typename ParentT = void>
1145class __single_warp_thread_block_tile :
1146    public __static_size_thread_block_tile_base<Size>,
1147    public __static_parent_thread_block_tile_base<Size, ParentT>
1148{
1149    typedef __static_parent_thread_block_tile_base<Size, ParentT> staticParentBaseT;
1150    friend class details::_coalesced_group_data_access;
1151
1152protected:
1153    _CG_QUALIFIER __single_warp_thread_block_tile() { };
1154    _CG_QUALIFIER __single_warp_thread_block_tile(unsigned int, unsigned int) { };
1155
1156    _CG_STATIC_QUALIFIER unsigned int get_mask() {
1157        return __static_size_thread_block_tile_base<Size>::build_mask();
1158    }
1159};
1160
1161template <unsigned int Size>
1162class __single_warp_thread_block_tile<Size, void> :
1163    public __static_size_thread_block_tile_base<Size>,
1164    public thread_group_base<details::coalesced_group_id>
1165{
1166    _CG_STATIC_CONST_DECL unsigned int numThreads = Size;
1167
1168    template <unsigned int, typename ParentT> friend class __single_warp_thread_block_tile;
1169    friend class details::_coalesced_group_data_access;
1170
1171    typedef __static_size_thread_block_tile_base<numThreads> staticSizeBaseT;
1172
1173protected:
1174    _CG_QUALIFIER __single_warp_thread_block_tile(unsigned int meta_group_rank = 0, unsigned int meta_group_size = 1) {
1175        _data.coalesced.mask = staticSizeBaseT::build_mask();
1176        _data.coalesced.size = numThreads;
1177        _data.coalesced.metaGroupRank = meta_group_rank;
1178        _data.coalesced.metaGroupSize = meta_group_size;
1179        _data.coalesced.is_tiled = true;
1180    }
1181
1182    _CG_QUALIFIER unsigned int get_mask() const {
1183        return (_data.coalesced.mask);
1184    }
1185
1186public:
1187    using staticSizeBaseT::sync;
1188    using staticSizeBaseT::size;
1189    using staticSizeBaseT::num_threads;
1190    using staticSizeBaseT::thread_rank;
1191
1192    _CG_QUALIFIER unsigned int meta_group_rank() const {
1193        return _data.coalesced.metaGroupRank;
1194    }
1195
1196    _CG_QUALIFIER unsigned int meta_group_size() const {
1197        return _data.coalesced.metaGroupSize;
1198    }
1199};
1200

Showing the first 1,200 of 1731 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai