futhark
Safe HaskellNone
LanguageGHC2021

Futhark.CodeGen.ImpGen.GPU.Base

Synopsis

Documentation

data KernelConstants Source #

Constructors

KernelConstants 

Fields

data Locks Source #

Information about the locks available for accumulators.

Constructors

Locks 

data Target Source #

Which target are we ultimately generating code for? While most of the kernels code is the same, there are some cases where we generate special code based on the ultimate low-level API we are targeting.

Constructors

CUDA 
OpenCL 
HIP 

blockReduce :: TExp Int32 -> Lambda GPUMem -> [VName] -> InKernelGen () Source #

Reduce the w first elements of the given arrays, leaving the result in element zero of each. The others are clobbered.

warpLocal :: InKernelGen () -> InKernelGen () Source #

Run code where threads within a warp communicate directly through shared memory. On OpenCL we rely on lockstep execution make all memory accesses volatile; on CUDA and HIP we explicitly synchronise the warp afterwards with WarpSync. Like a barrier, this must be reached by all threads of the warp.

blockScan :: Maybe (TExp Int32 -> TExp Int32 -> TExp Bool) -> TExp Int64 -> TExp Int64 -> Lambda GPUMem -> [VName] -> InKernelGen () Source #

Scan the w first elements of the given arrays, in place.

An array-typed element is kept twice: at index i, where the result is expected, and again at index i + arrs_full_size. It is the latter copy that a thread reads as its x operand, because the operator writes its result through its x parameter, which may well be the former. The elements from index arrs_full_size + blockScanChunkSize on are then used to save the elements of the first chunk, which are overwritten with the per-chunk carry-ins. Only the w first elements need be within the shape of the arrays, but all of the above must be backed by memory; see blockScanElems.

The callers in Futhark.CodeGen.ImpGen.GPU.SegScan.TwoPass and Futhark.CodeGen.ImpGen.GPU.SegRed pass arrays whose elements are the x and y parameters of the operator, so for them the copies that keep the two in step are redundant, but harmless.

blockScanChunkSize :: Num a => a Source #

blockScan splits the block into chunks of this size, which are scanned separately. The only requirement is that it should not be less than the square root of the block size. With 32, we will work on blocks of size 1024 or smaller, which fits every device Troels has seen. Still, it would be nicer if it were a runtime parameter. Some day.

blockLoop :: forall {k} (t :: k). IntExp t => TExp t -> (TExp t -> InKernelGen ()) -> InKernelGen () Source #

Assign iterations of a for-loop to threads in the threadblock. The passed-in function is invoked with the (symbolic) iteration. For multidimensional loops, use blockCoverSpace.

peeledKernelLoop :: forall {k} (t :: k). IntExp t => TExp t -> TExp t -> TExp t -> TExp t -> (TExp t -> InKernelGen ()) -> InKernelGen () Source #

peeledKernelLoop tid num_threads num_full_chunks n f invokes f on the iterations tid, tid+num_threads, and so on, below n, where num_full_chunks must be n quot num_threads. Only the final partial chunk is bounds checked, so the body is generated twice; see Note [Peeled block loops]. The body must contain thread-level code.

data KernelAttrs Source #

Various extra configuration of the kernel being generated.

Constructors

KernelAttrs 

Fields

defKernelAttrs :: Count NumBlocks SubExp -> Count BlockSize SubExp -> KernelAttrs Source #

The default kernel attributes.

lvlKernelAttrs :: SegLevel -> CallKernelGen KernelAttrs Source #

Compute kernel attributes from SegLevel; including synthesising block-size and thread count if no grid is provided.

virtualiseBlocks :: SegVirt -> TExp Int32 -> (TExp Int32 -> InKernelGen ()) -> InKernelGen () Source #

For many kernels, we may not have enough physical blocks to cover the logical iteration space. Some blocks thus have to perform double duty; we put an outer loop to accomplish this. The advantage over just launching a bazillion threads is that the cost of memory expansion should be proportional to the number of *physical* threads (hardware parallelism), not the amount of application parallelism.

kernelLoop :: forall {k} (t :: k). IntExp t => TExp t -> TExp t -> TExp t -> (TExp t -> InKernelGen ()) -> InKernelGen () Source #

Assign iterations of a for-loop to all threads in the kernel. The passed-in function is invoked with the (symbolic) iteration. The body must contain thread-level code. For multidimensional loops, use blockCoverSpace.

blockCoverSpace :: forall {k} (t :: k). IntExp t => [TExp t] -> ([TExp t] -> InKernelGen ()) -> InKernelGen () Source #

Iterate collectively though a multidimensional space, such that all threads in the block participate. The passed-in function is invoked with a (symbolic) point in the index space.

fenceForArrays :: [VName] -> InKernelGen Fence Source #

If we are touching these arrays, which kind of fence do we need?

genZeroes :: Name -> Int -> CallKernelGen VName Source #

Generate a constant device array of 32-bit integer zeroes with the given number of elements. Initialised with a replicate.

getSize :: Name -> SizeClass -> CallKernelGen (TV Int64) Source #

Retrieve a size of the given size class and put it in a variable with the given name.

Host-level bulk operations

sReplicate :: VName -> SubExp -> CallKernelGen () Source #

Perform a Replicate with a kernel.

sIota :: VName -> TExp Int64 -> Exp -> Exp -> IntType -> CallKernelGen () Source #

Perform an Iota with a kernel.

Atomics

type AtomicBinOp = BinOp -> Maybe (VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp) Source #

Is there an atomic BinOp corresponding to this BinOp?

atomicUpdateLocking :: AtomicBinOp -> Lambda GPUMem -> AtomicUpdate GPUMem KernelEnv Source #

Do an atomic update corresponding to a binary operator lambda.

data Locking Source #

Locking strategy used for an atomic update.

Constructors

Locking 

Fields

data AtomicUpdate rep r Source #

The mechanism that will be used for performing the atomic update. Approximates how efficient it will be. Ordered from most to least efficient.

Constructors

AtomicPrim (DoAtomicUpdate rep r)

Supported directly by primitive.

AtomicCAS (DoAtomicUpdate rep r)

Can be done by efficient swaps.

AtomicLocking (Locking -> DoAtomicUpdate rep r)

Requires explicit locking.

type DoAtomicUpdate rep r = Space -> [VName] -> [TExp Int64] -> ImpM rep r KernelOp () Source #

A function for generating code for an atomic update. Assumes that the bucket is in-bounds.

writeAtomic :: VName -> [TExp Int64] -> SubExp -> [TExp Int64] -> InKernelGen () Source #

Perform a scalar write followed by a fence.