Showing posts with label CUDA. Show all posts
Showing posts with label CUDA. Show all posts

CUDA 4.0 RC Released to Registered Developers

Here it is, CUDA 4.0 RC just got released to NVIDIA Registered developers.

Interesting stuff from the CUDA manual:

  • Layered Textures Support (GL_TEXTURE_1D/2D_ARRAY)  : New tex.a1d/.a2d modifiers in PTX. But unfortunately the surface instruction do not support them yet, Grrrr
    Layered textures are created using cudaMalloc3DArray() with the cudaArrayLayered flag. New cudaTextureType2DLayered/ cudaTextureType2DLayered texture sampler types and tex1DLayered()/tex2DLayered() access intrinsics.
  • New .address_size PTX specifier : Allows  to specify the address size (32b/64b) used throughout a PTX module.
  • Inline PTX assembly: This feature was already present since CUDA 2.x but was not officially supported. It's now fully supported and documented :-D
  • Driver API, new thread-safe stateless launch API function cuLaunchKernel(): cuLaunchKernel(kernelObj,   blocksPerGrid, 1, 1,   threadsPerBlock, 1, 1,   0, 0, args, 0);
  • FERMI ISA documented and supported by cuobjdump.
  • Enhanced C++: Support for operators new  and  delete, virtual functions.

CUDA 4.0 announced @GDC 2011

Today NVIDIA announced CUDA 4.0 at the GDC. It will be available to registered developers on March 4th :-D
Among interesting novelties, there is the support for layered textures (GL_TEXTURE_2D_ARRAY) that I hope will also be supported for surface access !
There is also the support for direct peer-to-peer communication between GPUs and mappping multiple GPUs (and potentially other third party devices like network/infiniband) memory into the same address space in order to provide direct memory access (Unified Virtual Addressing, UVA). Virtual functions should also now be supported, along with the New and Delete functions for dynamic memory allocations from kernels.
Looking forward to test all of this !

More info : Anandtech, NVIDIA pressroom, Dr Dobbs GPGPU.org

Update: CUDA 4.0 RC released to registered developers
Slides are available there: http://bit.ly/cuda4features
Among the interesting novelties I did not see before, it seems inline PTX will be officially supported with this release ! Also the dissasembler (cuobjdump) that were previously limited to Tesla ISA now support Fermi ISA disassembly. Take a look as the manual for the list of supported instructions.

CUDA "Better Performance at Lower Occupancy" @GTC2010

A friend point me this very interesting talk at NVIDIA GTC:
Better Performance at Lower Occupancy

They deny two common fallacies that CUDA developer usually believe in:

  • Multithreading is the only way to hide latency on GPU
  • Shared memory is as fast as registers

All the GTC2010 presentations can be found there (with slides and videos !):
http://www.nvidia.com/object/gtc2010-presentation-archive.html

CUDA 3.2 Final released

Download it on NVIDIA Developer website !
http://developer.nvidia.com/object/cuda_3_2_downloads.html

Various stuff from October

I did not have much time to update this blog lately, so here are some interesting stuff I did not post during October:

CUDA 3.2 RC

Available to registered developers.

Here are the interesting new stuff I found:

  • Support for malloc() and free() in kernels: dynamic global memory allocation !
  • This is implemented with a new syscall linking mechanism that seems to allow kernel to be linked to precompiled system calls. Infos on the linking mechanism (.calltargets , .callprototype ) can be found in section 10.3 of the PTX ISA manual. I hope this mechanism will get exposed for user functions in the API !
    • 64 bits addressing support in CUDA driver AP: Allows manipulating more than 4GB of device memory.
    • New System Management Interface (nvidia-smi) for reporting various hardware counters informations
    • New stream synchronization function cudaStreamSynchronize(): allow GPU-side inter-streams synchronisation.
    • A set of new calls is available to allow the creation of CUDA devices with interoperability with Direct3D devices that use SLI in AFR (Alternate Frame Rendering) 
    • New flag to driver API texture reference (CU_TRSF_SRGB), which enables sRGB->linear conversion on a read.
    • Reference manual adds architecture information on GF10x (GF104, GF106, GF108) class hardware (compute capability 2.1)
    Changes in PTX ISA 2.2:
    • Add tld4 (fetch4) instruction for loading a component (r, g, b, or a) from the four texels compising the bilinear interpolation footprint of a given texture location.
    • Add kernel pointer parameter state space and alignment of the memory being pointed to.

    New CUDA Libraries
    • CUSPARSE, supporting sparse matrix computations.
    • CURAND, supporting random number generation for both host and device code with Sobel quasi-random and XORWOW pseudo random routines.

    Official CUDA disasembler for sm_1.x real ISA

    Yesturday NVIDIA released an official disasembler for sm_1.x (pre-Fermi) real hardware ISA. It's like an official version of DECUDA :-) (that Wladimir stopped to develop)
    It takes either an ELF CUDA binary, a cubin or even an exe file, and provides the low level assembly code of the CUDA kernels.
    It is only available for registered developer for now, but you can get a little more information the CUDA forum.

    That's something a lot of developers have been asking for for a while. That allows to see the impact of optimizations on the real microcode, and it is particularly important for register usage for instance (since registers allocations is done after the PTX level).
    Nice NVIDIA finally end up unveiling it's real hardware ISA instructions. AMD is still a little bit ahead on this since the ISA instructions and microcode is available even for the Evergreen architecture (RV870): http://developer.amd.com/gpu/ATIStreamSDK/assets/AMD_Evergreen-Family_ISA_Instructions_and_Microcode.pdf

    CUDA 3.1 Final out

    Check it there: http://developer.nvidia.com/object/cuda_3_1_downloads.html
    Did not find new features since 3.1beta, just bug fixes. 2D surface write intrinsics that were buggy in 3.1 Beta are now working for instance.
    There is also a reference to GPUDirect in the "release highlights", but I did not find any documentation for it. GPUDirect seams to allow third party devices to do direct memory acces to the GPU memory (cf the anouncement here).

    CUDA dynamic template parameters (2/2) : Emulation with metaprogramming

    Following my last post, I will describe how template metaprogramming can be used to "emulate" dynamic kernel template parameters. This approach does not prevent explosion of the amount of generated code at compile time, but provides a simple interface to "transform" runtime variable values into kernel template parameters.

    If you are not familiar with templates metaprogramming, I suggest you to read Andrei Alexandrescu's great book: Modern C++ Design: Generic Programming and Design Patterns Applied. This book comes with a small and simple metaprogramming library called Loki that is just a series of helper headers. My code relies on a few structures from it.

    Code description
    Here is what a kernel call looks like with this mechanism:

    The actual kernel call is encapsulated into a functor (here MyKernelCallFunctor) that is passed, with the runtime variables, to the call function of what I called the KernelCaller. The KernelCaller "transform" the set of runtime variables passed to the call function into a set of compile time parameters passed to the functor in the form of a typelist.
    The functor is in charge making the actual kernel call by extracting the template values from the typelist, and by passing to the __global__ function the arguments previously passed through it's constructor and stored into the structure. It has to be written for each kernel you want to launch:

    The KernelCaller is the core of the mechanism. It operates by recursively adding static values into the typelist by testing the value of the runtime variables. In reallity the compiler will generate code for all the branches and so will instanciate all possible sets of compile time parameters as typelists, the right one being selected at runtime. To ease usage, the runtime variables are passed using a variable argument list and transformed into a vector containing the values.

    The compile time recursion is stopped thanks to the number of arguments passed as a template parameter to the KernelCaller.  :

    Here it is, as is we already have a working mechanism able to deal with arbitrary number of boolean parameters !

    Extending the approach to integer parameters
    The approach as presented here works well for boolean template parameters. If we want to deal with more values than 0/1 per variable, we need to write something like this:

    But this is not very funny to write and not very scalable. So once again we can rely on templates to generate the code for us !
    In this case here is what the KernelCaller::call function looks like:

    And here is the ValueSelector mechanism:


    Loki structures
    Here are the Loki structures we rely on:


    Full source code
    A full running sample code can be downloaded here.

    Have fun, and... sorry for this crazy long post !

    [Update June 21]
    Code updated: There was 2 bugs in the code :
    • Using a reference as first parameter of a vararg is forbiden by C++ and resulted in a crash on 32bits machines -> transformed into a pointer.
    • The MaxArgValue argument to the KernelCaller was not kept by the ValueSelector, resulting in the use of the default value of 10 whatever the user specified so it was very slow to compile even for boolean values.
    I added two #defines to control the sample kernel call: SAMPLE_NUMBER_OF_PARAMS indicating the number of parameters to use and SAMPLE_NUMBER_OF_INTEGER_VALUES indicating the number of values to use for each paramater (2 for boolean parameters).
    I also added a #pragma message in order to follow the recursive compilation. 
    Dependency on cutil_inline.h removed.

    CUDA dynamic template parameters (1/2) : My dream CUDA feature

    One common problem when using templates to parametrize CUDA kernels (cf. my previous post) is to be able to dynamically select the set of template parameters to use for a call, depending on runtime variables. This usually leads to an exploding number of cascaded if/switch and a lot of code copy/paste to instantiate the whole parameters tree for each kernel call.
    This situation is illustrated by the following code for boolean parameters:


    In addition to the pain it is to write, such code results in the compilation of an exploding number of versions of the same kernel, one for each instantiated template configuration.

    Dynamic template parameters with JIT Kernels compilation
    There is a CUDA feature I am dreaming about for a few time now and that would solve both problems: dynamic template parameters. What I mean by this is the ability for a CUDA kernel to accept true C variables (containing runtime values) as integer template parameters. The syntax would simply look like this:


    This feature would be implemented by taking advantage of a C-level JIT (Just In Time) kernel compilation (current CUDA JIT compiler operates at the PTX level). It implies recompiling the kernel at runtime with a new set of template parameters each time a value changed. It requires tracking the last value of each parameters so that recompilation happens only when necessary. To be a bit more efficient, generated code could also be cached in some way so that it can be reused.
    This would change the kernel compilation paradigm to something closer to the OpenCL compiling model, but while keeping the nice CUDA-C syntax provided by nvcc.
    That feature would be very useful, and it would be great if NVIDIA makes CUDA evolves in that direction, or if someone write a JIT CUDA-C compiler that allows that !

    Emulating dynamic templates... with templates !
    While waiting for that feature, dynamic integer template parameters can be partially emulated today... with template metaprogramming ! The idea is to instantiate the whole parameters tree at compile time using templates, and to select the right one at runtime, based on the variables.

    More details coming in the next post !

    Fermi output queues and L2 write combining experiments

    A guy from Los Alamos compared the performances (between Tesla 2 and Fermi) of output queues using atomic-add on an integer index per queue. First result : 16x speedup on Fermi !
    http://forums.nvidia.com/index.php?showtopic=170125

    Its is supposedly thanks to the coalescing of atomic operation that may be done in the L2 cache.

    He also did another experiment to see if the L2 cache allows combining writes from different blocks into global memory, and it appears to be the case when you have consecutive blocks writing to the same cache line at the same time. Result: 3.25x speedup on Fermi.
    http://forums.nvidia.com/index.php?showtopic=170127

    CUDA 3.1Beta out

    NVIDIA released a beta version of the CUDA 3.1 toolkit for register developers.

    New features from the programming guide :

    • 16bits float textures supported by the runtime API. __float2half_rn() and __half2float() intrinsic added (Table C-3).
    • Surface memory interface exposed in the runtime API (Section 3.2.5, B9). Read/Write access into textures (CUDA Arrays). But limited to 1D and 2D Arrays yet.
    • Up to 16 parallel kernel launches on Fermi (it was only 4 in CUDA 3.0). Not sure how it is really implemented (one per SM ? multiple per SM ?).
    • Recursive calls supported in device function on Fermi (B.1.4). Stack size query and setting functions added (cudaThreadGetLimit(), cudaThreadSetLimit()).
    • Function pointers supported on device functions on Fermi (B.1.4). Function pointers to global functions supported on all GPUs.
    • Just noticed that a __CUDA_ARCH__ macro allowing to write different code paths depending on the architecture (or code executed on the host) is here since CUDA 3.0 (B.1.4).
    • printf support into kernels integrated into the API for sm_20 (B.14). Note that a cuprintf supporting all architectures was provided to register developers a few months ago.
    • New __byte_perm(x,y,s) intrinsic (C.2.3).
    • New __forceinline__ function qualifier to force inlining on Fermi. A __noinline__ was also present already to allow forcing function call on sm_1.x
    • New –dlcm compilation flag to specify global memory caching strategy on Fermi (G.4.2).

    Interesting new stuff in the Fermi Compatibility Guide:
    • Just-in-time kernel compilation can be used with the runtime API with R195 drivers (Section 1.2.1).
    • Details using the volatile keyword for intra-warp communications (Section 1.2.2).

    Interesting new stuff in the Best Practice Guide:
    • Uses signed integer instead of unsigned as loop counter. It allows the compiler to perform strength reduction and can provides better performances (Section 6.3).

    NVIDIA GT200 microbenchmarking

    A crazy paper from university of Toronto:
    Demystifying GPU Microarchitecture through Microbenchmarking

    This  work  develops  a  microbechmark  suite  and  measures  the CUDA-visible architectural characteristics of the Nvidia GT200 (GTX280) GPU. Various undisclosed characteristics of the processing elements and the memory hierarchies are measured.

    CUDA Template Metaprogramming

    CUDA is awesome and, for me, one of the reason I think it is better than OpenCL is because of its support of C++ templates.

    I have been using templates in CUDA for quite a long time now, and in addition to the classical "generic programming" advantages (generic types, functors...), using templates allows for a lot of optimizations in kernel functions.

    First, templated values ( template<uint i>... ) can be used as compile time constants. For instance, blockDim is very often known and fixed at compile time. Passing it through a templated value instead of relying on the built-in variable allows faster access, since its value is directly integrated as a constant in the asm. The compiler can optimize some operations, if the constant is a power of two for instance, multiplications and divisions will be transformed into bit-shifts.

    Even more interestingly, you can help the compiler in many cases where it would not optimize itself, by implementing the optimizations yourself using template evaluation. Such usage of templates is called template metaprogramming. C++ templates are turing-complete, that means you can implement any computation you want so that it will be evaluated at compile time by the template processor.
    For instance, I am not sure the compiler will detect when you are passing a constant to a function like log2(). But you can implement the compile time (recursive) evaluation of log2 very easily with templates:



    Template Metaprogramming libraries exist and provide a lot of very advanced and powerful features. I am personally using Loki that is the library written by Andrei Alexandrescu as part of his (awesome) book Modern C++ Design. I am mainly using Typelist and Type manipulation features and they compile perfectly with CUDA 2.3.

    CUDA: Beware of the structs...

    ... and unions in local variables, they eat kittens !

    PS: And in many situations, they also fall down in local memory. So if you are writing a ray tracer, do not use a Ray structure !

    CUDA "volatile trick"

    A very useful trick found on the CUDA forum.

    Very often, the CUDA compiler inline the operations needed to compute the value of a variable used at several places, instead of keeping the variable in a register. This can be a good strategy in some situations, but there is also many cases where it brings register usage up unnecessarily and duplicates instructions. To prevent this, the "volatile" keyword can be used when the variable is declared, forcing it to be really kept and reused.
    This trick also work with constant variables (and shared memory) which would otherwise get loaded into registers over and over when accessed at several places.

    It clearly reduces the number of virtual registers allocated at the PTX level, which helps a lot for the real register allocation phase that happens later during the transform to cubin. However, be careful not using it with constantly indexed arrays for instance, they would be put in local memory.

    More info there:
    http://forums.nvidia.com/index.php?showtopic=89573
    http://forums.nvidia.com/index.php?showtopic=99209

    CUDA PTX 2.0 (Fermi) specification released

    NVIDIA made available the specification of the PTX 2.0 ISA for Fermi, this can be downloaded there:

    Among interesting things I saw :
    • New Texture, Sampler and Surface types: Opaque type for manipulating texture, sampler and surface descriptor as normal variables. -> More flexible texture manipulation, allow arrays of textures for instance.
    • New syntax for abstracting an underlining ABI (Application Binary Interface): define a syntax for function definition/calls, parameter passing, variadic functions, and dynamic memory allocation in the stack ("alloca"). -> true function calls, and recursivity ! But not yet implemented in CUDA 3.0.
    • New binary instructions  popc (population count, number of one bits), clz (count leading zeros), bfind (non significant non-sign bit), brev (bit reverse), bfe/bfi (bit field extract/insert, ?), prmt (permute)
    • Cache operators (8.7.5.1): Allow to select (per operation) the level of caching in the cache hierarchy (L1/L2) of the load/store instructions.
    • Prefetch instructions (Table 84) that allows forcing the load of a page in global/local memory into a specific cache level).
    • Surface load/store (surd/sust, Tables 90/91): Read/Write (through ROPs ?) into render targets. (Support 3D R/W! Hum.. really working ?)
    • Video instructions: Vector operations on bytes/half-words/words.
    • Performance tuning directives (10.3): Allows to help the compiler to optimize the code based on bloc configurations.

    Overcoming WDDM : Tesla compute-only driver on GeForce

    One big pain with CUDA under Windows Vista or Seven is that performances suffers a lot from limits and overheads imposed by the WDDM (Windows Display Driver Model) the driver has to comply to.
    This means slower kernel launches, limit on the size of memory allocations and a lot  of constraints that prevents NVIDIA to efficiently implement a lot of features in CUDA.

    Tim Murray on the CUDA forum:

    "Welcome to WDDM. Kernel launch overhead is ~3us on non-WDDM platforms. On WDDM, it's 40 at a minimum and can potentially be much larger. Considering the number of kernels you're launching in 10ms, that's going to add up."
    "WDDM is a lot more than just a rendering interface. It manages all the memory on the device so it can page it in and out as necessary, which is a good thing for display cards. However, we get zero benefit from it in CUDA, because we have pointers! As a result, you can't really do paging in a CUDA app, so you get zero benefit from WDDM. However, because it's the memory manager, we can't just go around it for CUDA because WDDM will assume it owns the card completely, start moving memory, and whoops your CUDA app just exploded. So no, there's not really some magic workaround for cards that can also be used as display."

    To overcome this problem, NVIDIA provides a compute-only drivers for Tesla boards. But with little effort it can be also be installed on GeForce.
    How to install them on GeForce:
    http://oscarbg.blogspot.com/2010/02/about-tesla-computing-driver.html

    Copyright © Icare3D
    Designed by Templates Next | Converted into Blogger Templates by Theme Craft