Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
RunCommandEnumerate.h
Go to the documentation of this file.
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* RunCommandEnumerate.h (C) 2000-2026 */
9/* */
10/* Macros for iterating over a list of entities. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_ACCELERATOR_RUNCOMMANDENUMERATE_H
13#define ARCANE_ACCELERATOR_RUNCOMMANDENUMERATE_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arccore/common/accelerator/RunCommand.h"
18#include "arcane/accelerator/KernelLauncher.h"
19
21#include "arcane/core/ItemGroup.h"
23
24#include "arccore/common/HostKernelRemainingArgsHelper.h"
25
26#include <concepts>
27
28#if defined(ARCCORE_EXPERIMENTAL_GRID_STRIDE)
29#include "arccore/common/StridedLoopRanges.h"
30#endif
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
35namespace Arcane::Accelerator::Impl
36{
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41/*!
42 * \brief Information for the accelerator loop over entities.
43 */
44template <typename TraitsType_>
45class ItemLocalIdsLoopRanges
46{
47 public:
48
49 using TraitsType = TraitsType_;
50 using BuilderType = TraitsType::BuilderType;
51
52 public:
53
54 explicit ItemLocalIdsLoopRanges(SmallSpan<const Int32> ids)
55 : m_ids(ids)
56 {}
57 constexpr SmallSpan<const Int32> ids() const { return m_ids; }
58 constexpr Int64 nbElement() const { return m_ids.size(); }
59
60 public:
61
63};
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
69
70template <typename LoopBoundsType, typename Lambda, typename... RemainingArgs> __global__ void
71doIndirectGPULambda2(LoopBoundsType bounds, Lambda func, RemainingArgs... remaining_args)
72{
73 // TODO: to be removed when old reductions are no longer needed
74 auto privatizer = privatize(func);
75 auto& body = privatizer.privateCopy();
76
77 Int32 i = blockDim.x * blockIdx.x + threadIdx.x;
78
80
81 if constexpr (requires { bounds.nbStride(); }) {
82 // Experimental test to use a stride of the grid size. The number of
83 // strides is given by bounds.nbStride().
84 using BuilderType = LoopBoundsType::LoopBoundType::BuilderType;
85 using LocalIdType = BuilderType::ValueType;
86 Int32 nb_grid_stride = bounds.nbStride();
87 Int32 offset = blockDim.x * gridDim.x;
88 Int64 nb_item = bounds.nbOriginalElement();
89 SmallSpan<const Int32> ids = bounds.originalLoop().ids();
90#pragma unroll 4
91 for (Int32 k = 0; k < nb_grid_stride; ++k) {
92 Int32 true_i = i + (offset * k);
93 if (true_i < nb_item) {
94 LocalIdType lid(ids[true_i]);
95 body(BuilderType::create(true_i, lid), remaining_args...);
96 }
97 }
98 }
99 else {
100 using BuilderType = LoopBoundsType::BuilderType;
101 using LocalIdType = BuilderType::ValueType;
102
103 SmallSpan<const Int32> ids = bounds.ids();
104 if (i < ids.size()) {
105 LocalIdType lid(ids[i]);
106 body(BuilderType::create(i, lid), remaining_args...);
107 }
108 }
109
111}
112
113/*---------------------------------------------------------------------------*/
114/*---------------------------------------------------------------------------*/
115
116#endif // ARCCORE_COMPILING_CUDA_OR_HIP
117
118/*---------------------------------------------------------------------------*/
119/*---------------------------------------------------------------------------*/
120
121#if defined(ARCCORE_COMPILING_SYCL)
122
123//! 1D loop with indirection
124template <typename TraitsType, typename Lambda, typename... RemainingArgs>
125class DoIndirectSYCLLambda
126{
127 public:
128
129 void operator()(sycl::nd_item<1> x, SmallSpan<std::byte> shared_memory,
130 SmallSpan<const Int32> ids, Lambda func,
131 RemainingArgs... remaining_args) const
132 {
133 using BuilderType = TraitsType::BuilderType;
134 using LocalIdType = BuilderType::ValueType;
135 auto privatizer = privatize(func);
136 auto& body = privatizer.privateCopy();
137
138 Int32 i = static_cast<Int32>(x.get_global_id(0));
139 SyclKernelRemainingArgsHelper::applyAtBegin(x, shared_memory, remaining_args...);
140 if (i < ids.size()) {
141 LocalIdType lid(ids[i]);
142 body(BuilderType::create(i, lid), remaining_args...);
143 }
144 SyclKernelRemainingArgsHelper::applyAtEnd(x, shared_memory, remaining_args...);
145 }
146 void operator()(sycl::id<1> x, SmallSpan<const Int32> ids, Lambda func) const
147 {
148 using BuilderType = TraitsType::BuilderType;
149 using LocalIdType = BuilderType::ValueType;
150 auto privatizer = privatize(func);
151 auto& body = privatizer.privateCopy();
152
153 Int32 i = static_cast<Int32>(x);
154 if (i < ids.size()) {
155 LocalIdType lid(ids[i]);
156 body(BuilderType::create(i, lid));
157 }
158 }
159};
160
161#endif
162
163} // namespace Arcane::Accelerator::Impl
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
167
168namespace Arcane
169{
170
171/*---------------------------------------------------------------------------*/
172/*---------------------------------------------------------------------------*/
173
175{
176};
177
178/*---------------------------------------------------------------------------*/
179/*---------------------------------------------------------------------------*/
180
181/*!
182 * \brief Base class for an iterator that preserves the iteration index.
183 */
184template <typename T>
185class IteratorWithIndex
187{
188 public:
189
190 constexpr ARCCORE_HOST_DEVICE IteratorWithIndex(Int32 i, T v)
191 : m_index(i)
192 , m_value(v)
193 {}
194
195 public:
196
197 constexpr ARCCORE_HOST_DEVICE Int32 index() const { return m_index; }
198 constexpr ARCCORE_HOST_DEVICE T value() const { return m_value; }
199
200 private:
201
202 Int32 m_index;
203 T m_value;
204};
205
206} // namespace Arcane
207
208/*---------------------------------------------------------------------------*/
209/*---------------------------------------------------------------------------*/
210
211namespace Arcane::impl
212{
213
214template <typename T>
216{
217 public:
218
219 using ValueType = T;
220
221 public:
222
223 constexpr ARCCORE_HOST_DEVICE static IteratorWithIndex<T> create(Int32 index, T value)
224 {
225 return IteratorWithIndex<T>(index, value);
226 }
227};
228
229template <typename T>
231{
232 public:
233
234 using ValueType = T;
235
236 public:
237
238 constexpr ARCCORE_HOST_DEVICE static T create(Int32, T value)
239 {
240 return value;
241 }
242};
243
244} // namespace Arcane::impl
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
249namespace Arcane::Accelerator::impl
250{
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
255/*!
256 * \brief Concept to constrain values in RUNCOMMAND_ENUMERATE.
257 *
258 * The type must be an entity type (Cell, Node, ...) or a
259 * local ID type (CellLocalId, NodeLocalId, ...)
260 */
261template <typename T>
262concept RunCommandEnumerateIteratorConcept = std::derived_from<T, Item> || std::derived_from<T, ItemLocalId> || std::derived_from<T, IteratorWithIndexBase>;
263
264//! Template to know the entity type associated with T
265template <typename T>
267{
268 public:
269
270 using ItemType = T;
271 using ValueType = typename ItemTraitsT<ItemType>::LocalIdType;
273};
274
275//! Specialization for ItemLocalIdT.
276template <typename T>
278{
279 public:
280
281 using ItemType = typename ItemLocalIdT<T>::ItemType;
282 using ValueType = ItemLocalIdT<T>;
284};
285
286//! Specialization for IteratorWithIndex<T>
287template <typename T>
288requires std::derived_from<T, ItemLocalId> class RunCommandItemEnumeratorSubTraitsT<IteratorWithIndex<T>>
289{
290 public:
291
292 using ItemType = typename T::ItemType;
293 using ValueType = IteratorWithIndex<T>;
294 using BuilderType = Arcane::impl::IterBuilderWithIndex<T>;
295};
296
297/*---------------------------------------------------------------------------*/
298/*---------------------------------------------------------------------------*/
299
300/*!
301 * \brief Container for RunCommandEnumerate.
302 *
303 * The container can be either an ItemVectorView or an ItemGroup.
304 *
305 * The purpose of this container is to avoid SIMD padding for an
306 * ItemGroup if it is used on an accelerator. Since padding is
307 * done on the CPU, this would induce memory transfers when using
308 * unified memory (which is the default).
309 */
310template <typename ItemType>
311class RunCommandItemContainer
312{
313 public:
314
315 explicit RunCommandItemContainer(const ItemGroupT<ItemType>& group)
316 : m_item_group(group)
317 , m_unpadded_vector_view(group._unpaddedView())
318 {}
319 explicit RunCommandItemContainer(const ItemVectorViewT<ItemType>& item_vector_view)
320 : m_item_vector_view(item_vector_view)
321 , m_unpadded_vector_view(item_vector_view)
322 {
323 }
324
325 public:
326
327 Int32 size() const { return m_unpadded_vector_view.size(); }
328 SmallSpan<const Int32> localIds() const { return m_unpadded_vector_view.localIds(); }
329 ItemVectorView paddedView() const
330 {
331 if (!m_item_group.null())
332 return m_item_group._paddedView();
333 return m_item_vector_view;
334 }
335
336 private:
337
338 ItemVectorViewT<ItemType> m_item_vector_view;
339 ItemGroupT<ItemType> m_item_group;
340 ItemVectorViewT<ItemType> m_unpadded_vector_view;
341};
342
343/*---------------------------------------------------------------------------*/
344/*---------------------------------------------------------------------------*/
345
346/*!
347 * \brief Characteristics of an enumerator for a command on entities.
348 *
349 * This class must be specialized and define a \a ValueType
350 * that corresponds to the return type of 'operator*' of the enumerator.
351 *
352 * \a IteratorValueType_ must be an entity type (Cell, Node, ...) or a
353 * local ID type (CellLocalId, NodeLocalId, ...)
354 */
355template <RunCommandEnumerateIteratorConcept IteratorValueType_>
356class RunCommandItemEnumeratorTraitsT
357{
358 public:
359
361 using ItemType = typename SubTraitsType::ItemType;
362 using LocalIdType = typename ItemTraitsT<ItemType>::LocalIdType;
363 using ValueType = typename SubTraitsType::ValueType;
364 using ContainerType = RunCommandItemContainer<ItemType>;
365 using BuilderType = typename SubTraitsType::BuilderType;
366
367 public:
368
369 explicit RunCommandItemEnumeratorTraitsT(const ItemGroupT<ItemType>& group)
370 : m_item_container(group)
371 {}
372 explicit RunCommandItemEnumeratorTraitsT(const ItemVectorViewT<ItemType>& vector_view)
373 : m_item_container(vector_view)
374 {
375 }
376
377 public:
378
379 RunCommandItemContainer<ItemType> m_item_container;
380};
381
382/*---------------------------------------------------------------------------*/
383/*---------------------------------------------------------------------------*/
384
385template <typename TraitsType, typename ContainerType, typename Lambda, typename... RemainingArgs>
386void _doItemsLambda(Int32 base_index, ContainerType sub_items, const Lambda& func, RemainingArgs... remaining_args)
387{
388 using ItemType = TraitsType::ItemType;
389 using BuilderType = TraitsType::BuilderType;
390 using LocalIdType = BuilderType::ValueType;
391 auto privatizer = Impl::privatize(func);
392 auto& body = privatizer.privateCopy();
393
395 ENUMERATE_NO_TRACE_(ItemType, iitem, sub_items)
396 {
397 body(BuilderType::create(iitem.index() + base_index, LocalIdType(iitem.itemLocalId())), remaining_args...);
398 }
400}
401
402/*---------------------------------------------------------------------------*/
403/*---------------------------------------------------------------------------*/
404
405/*!
406 * \brief Applies the enumeration \a func on the entity list \a items.
407 */
408template <typename TraitsType, typename Lambda, typename... RemainingArgs> void
409_applyItems(RunCommand& command, typename TraitsType::ContainerType items,
410 const Lambda& func, const RemainingArgs&... remaining_args)
411{
412 // TODO: merge the common part with 'applyLoop'
413 Integer vsize = items.size();
414 if (vsize == 0)
415 return;
416 using ItemType = typename TraitsType::ItemType;
417 using LoopBoundType = Impl::ItemLocalIdsLoopRanges<TraitsType>;
418 [[maybe_unused]] SmallSpan<const Int32> ids = items.localIds();
419 [[maybe_unused]] LoopBoundType bounds(ids);
420
421#if defined(ARCCORE_EXPERIMENTAL_GRID_STRIDE) && defined(ARCCORE_COMPILING_CUDA_OR_HIP)
422 using TrueLoopBoundType = Impl::StridedLoopRanges<LoopBoundType>;
423 TrueLoopBoundType bounds2(command.nbStride(), bounds);
424 Impl::RunCommandLaunchInfo launch_info(command, bounds2.strideValue());
425#else
426 using TrueLoopBoundType = LoopBoundType;
427 [[maybe_unused]] const TrueLoopBoundType& bounds2 = bounds;
428 Impl::RunCommandLaunchInfo launch_info(command, vsize);
429#endif
430
431 const eExecutionPolicy exec_policy = launch_info.executionPolicy();
432
433 launch_info.beginExecute();
434 switch (exec_policy) {
436 ARCCORE_KERNEL_CUDA_FUNC((Impl::doIndirectGPULambda2<TrueLoopBoundType, Lambda, RemainingArgs...>),
437 launch_info, func, bounds2, remaining_args...);
438 break;
440 ARCCORE_KERNEL_HIP_FUNC((Impl::doIndirectGPULambda2<TrueLoopBoundType, Lambda, RemainingArgs...>),
441 launch_info, func, bounds2, remaining_args...);
442 break;
444 ARCCORE_KERNEL_SYCL_FUNC((Impl::DoIndirectSYCLLambda<TraitsType, Lambda, RemainingArgs...>{}),
445 launch_info, func, ids, remaining_args...);
446 break;
448 impl::_doItemsLambda<TraitsType>(0, items.paddedView(), func, remaining_args...);
449 break;
451 arcaneParallelForeach(items.paddedView(), launch_info.loopRunInfo(),
452 [&](ItemVectorViewT<ItemType> sub_items, Int32 base_index) {
453 impl::_doItemsLambda<TraitsType>(base_index, sub_items, func, remaining_args...);
454 });
455 break;
456 default:
457 ARCCORE_FATAL("Invalid execution policy '{0}'", exec_policy);
458 }
459 launch_info.endExecute();
460}
461
462/*---------------------------------------------------------------------------*/
463/*---------------------------------------------------------------------------*/
464
465template <typename TraitsType, typename... RemainingArgs>
466class ItemRunCommandArgs
467{
468 public:
469
470 ItemRunCommandArgs(const TraitsType& traits, const RemainingArgs&... remaining_args)
471 : m_traits(traits)
472 , m_remaining_args(remaining_args...)
473 {
474 }
475
476 public:
477
478 TraitsType m_traits;
479 std::tuple<RemainingArgs...> m_remaining_args;
480};
481
482/*---------------------------------------------------------------------------*/
483/*---------------------------------------------------------------------------*/
484
485} // namespace Arcane::Accelerator::impl
486
487namespace Arcane::Accelerator
488{
489
490/*---------------------------------------------------------------------------*/
491/*---------------------------------------------------------------------------*/
492
493template <typename TraitsType, typename Lambda> void
494run(RunCommand& command, const TraitsType& traits, const Lambda& func)
495{
496 impl::_applyItems<TraitsType>(command, traits.m_item_container, func);
497}
498
499/*---------------------------------------------------------------------------*/
500/*---------------------------------------------------------------------------*/
501
502template <typename TraitsType, typename... RemainingArgs>
503class ItemRunCommand
504{
505 public:
506
507 ItemRunCommand(RunCommand& command, const TraitsType& traits)
508 : m_command(command)
509 , m_traits(traits)
510 {
511 }
512
513 ItemRunCommand(RunCommand& command, const TraitsType& traits, const std::tuple<RemainingArgs...>& remaining_args)
514 : m_command(command)
515 , m_traits(traits)
516 , m_remaining_args(remaining_args)
517 {
518 }
519
520 public:
521
522 RunCommand& m_command;
523 TraitsType m_traits;
524 std::tuple<RemainingArgs...> m_remaining_args;
525};
526
527/*---------------------------------------------------------------------------*/
528/*---------------------------------------------------------------------------*/
529
530template <typename ItemType> auto
531operator<<(RunCommand& command, const impl::RunCommandItemEnumeratorTraitsT<ItemType>& traits)
532{
534 return ItemRunCommand<TraitsType>(command, traits);
535}
536
537/*---------------------------------------------------------------------------*/
538/*---------------------------------------------------------------------------*/
539
540// This method is kept for compatibility with existing code.
541// To be deprecated mid-2024
542template <typename ItemType> auto
543operator<<(RunCommand& command, const ItemVectorViewT<ItemType>& items)
544{
545 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
546 return ItemRunCommand<TraitsType>(command, TraitsType(items));
547}
548
549// This method is kept for compatibility with existing code.
550// To be deprecated mid-2024
551template <typename ItemType> auto
552operator<<(RunCommand& command, const ItemGroupT<ItemType>& items)
553{
554 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
555 return ItemRunCommand<TraitsType>(command, TraitsType(items));
556}
557
558template <typename TraitsType, typename Lambda>
559void operator<<(ItemRunCommand<TraitsType>& nr, const Lambda& f)
560{
561 run(nr.m_command, nr.m_traits, f);
562}
563
564template <typename TraitsType, typename... RemainingArgs> auto
566{
567 return ItemRunCommand<TraitsType, RemainingArgs...>(command, args.m_traits, args.m_remaining_args);
568}
569
570template <typename TraitsType, typename Lambda, typename... RemainingArgs>
571void operator<<(ItemRunCommand<TraitsType, RemainingArgs...>&& nr, const Lambda& f)
572{
573 if constexpr (sizeof...(RemainingArgs) > 0) {
574 std::apply([&](auto... vs) { impl::_applyItems<TraitsType>(nr.m_command, nr.m_traits.m_item_container, f, vs...); }, nr.m_remaining_args);
575 }
576 else
577 run(nr.m_command, nr.m_traits, f);
578}
579
580/*---------------------------------------------------------------------------*/
581/*---------------------------------------------------------------------------*/
582
583} // namespace Arcane::Accelerator
584
585namespace Arcane::Accelerator::impl
586{
587
588/*---------------------------------------------------------------------------*/
589/*---------------------------------------------------------------------------*/
590
591template <typename ItemTypeName, typename ItemContainerType, typename... RemainingArgs> auto
592makeExtendedItemEnumeratorLoop(const ItemContainerType& container_type,
593 const RemainingArgs&... remaining_args)
594{
596 return ItemRunCommandArgs<TraitsType, RemainingArgs...>(TraitsType(container_type), remaining_args...);
597}
598
599/*---------------------------------------------------------------------------*/
600/*---------------------------------------------------------------------------*/
601
602} // namespace Arcane::Accelerator::impl
603
604/*---------------------------------------------------------------------------*/
605/*---------------------------------------------------------------------------*/
606
607/*!
608 * \brief Macro to iterate over an accelerator on a group of entities.
609 *
610 * Conceptually, this is equivalent to the following loop:
611 *
612 * \code
613 * for( ItemTypeName iter_name : item_group ){
614 * ...
615 * }
616 * \endcode
617 *
618 * \a ItemTypeName must be a local ID type (CellLocalId, NodeLocalId).
619 * Using the entity type name (Cell, Node, ...) is possible but is
620 * obsolete and is equivalent to using the local ID type (for example,
621 * you must replace \a Cell with \a CellLocalId).
622 * \a iter_name is the name of the variable containing the current iterator value.
623 * \a item_group is the name of the ItemGroup or ItemVectorView associated
624 * Additional arguments are used to specify potential reductions
625 */
626#define RUNCOMMAND_ENUMERATE(ItemTypeName, iter_name, item_group, ...) \
627 A_FUNCINFO << ::Arcane::Accelerator::impl::makeExtendedItemEnumeratorLoop<ItemTypeName>(item_group __VA_OPT__(, __VA_ARGS__)) \
628 << [=] ARCCORE_HOST_DEVICE(::Arcane::Accelerator::impl::RunCommandItemEnumeratorTraitsT<ItemTypeName>::ValueType iter_name \
629 __VA_OPT__(ARCCORE_RUNCOMMAND_REMAINING_FOR_EACH(__VA_ARGS__)))
630
631/*---------------------------------------------------------------------------*/
632/*---------------------------------------------------------------------------*/
633
634#endif
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
Classes, Types, and macros for managing concurrency.
#define ENUMERATE_NO_TRACE_(type, name, group)
Generic enumerator for an entity group.
Declarations of types on entities.
void _applyItems(RunCommand &command, typename TraitsType::ContainerType items, const Lambda &func, const RemainingArgs &... remaining_args)
Applies the enumeration func on the entity list items.
static ARCCORE_DEVICE void applyAtEnd(Int32 index, RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the end of the kernel.
static ARCCORE_DEVICE void applyAtBegin(Int32 index, RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the beginning of the kernel.
Information for the accelerator loop over entities.
void beginExecute()
Indicates that command execution is starting.
Class to manage the decomposition of a loop into multiple parts.
Int32 nbStride() const
Number of loop decomposition strides.
Template to know the entity type associated with T.
Characteristics of an enumerator for a command on entities.
static void applyAtEnd(RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the end of the iteration.
static void applyAtBegin(RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the beginning of the iteration.
Reference to a group of a given kind.
Definition ItemGroup.h:420
ItemVectorView _unpaddedView() const
View of the group entities without padding for vectorization.
Definition ItemGroup.cc:598
Index of an ItemType entity in a variable.
Definition ItemLocalId.h:92
View on a typed array of entities.
View on a vector of entities.
Base class for an iterator that preserves the iteration index.
View of an array of elements of type T.
Definition Span.h:805
Concept to constrain values in RUNCOMMAND_ENUMERATE.
void arcaneParallelForeach(const ItemVectorView &items_view, const ForLoopRunInfo &run_info, InstanceType *instance, void(InstanceType::*function)(ItemVectorViewT< ItemType > items))
Applies the method function of the instance instance concurrently on the view items_view with the opt...
Definition Concurrency.h:57
Namespace for accelerator usage.
eExecutionPolicy
Execution policy for a Runner.
@ SYCL
Execution policy using the SYCL environment.
@ HIP
Execution policy using the HIP environment.
@ CUDA
Execution policy using the CUDA environment.
@ Thread
Multi-threaded execution policy.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
Int32 LocalIdType
Type of integers used to store local identifiers of entities.
std::ostream & operator<<(std::ostream &ostr, eItemKind item_kind)
Output operator for a stream.
std::int32_t Int32
Signed integer type of 32 bits.