Skip to content

Hydra 3.0.0

Compare
Choose a tag to compare
@AAAlvesJr AAAlvesJr released this 27 Jun 22:28
· 179 commits to master since this release

Hydra 3.0.0

It is the first release of the long-awaited 3 series. Overall, this release is expected to be faster
or at least to have similar performance to the previous releases.
There are many bug fixes and other changes across. The most significant ones are summarized below:

C++14 compiliant release

This release is the first C++14 compatible release. So, move the versions of NVCC, GCC, CLANG and so on, acordinaly.
Also, set the "--std" compiler flags to "--std=c++14" for both CUDA and host compilers.
The first the minimal CUDA version has now been moved to 9.2.
The support for extended C++ lambdas in CUDA is not complete. The restrictions are discussed in the page:

https://docs.nvidia.com/cuda/archive/10.2/cuda-c-programming-guide/index.html#extended-lambda

Hydra3 can not wrap generic lambdas in host code. If this feature is necessary, use host-only uwrapped lambdas.

Function call interface

This is probably the most impacting change in this release, making Hydra3 series backward incompatible with the previous series.

  1. New interface for calling functors and lambdas.

    a) Extensive statically-bound named parameter idiom support. This new idiom for specification of function call interfaces makes the definition callable objects in Hydra3 much more safe, straight forward, transparent and user friendly, without compromise performance. In many cases enhancing performance, indeed. From Hydra3, users will be able to define new types, with ad hoc names wrapping around primary types, using the macro declarg(NewVar, Type).
    These new types are searched in compile time to bind the function call, if the type
    is not found a compile error is emitted, avoiding the generation of invalid or error prone code.
    See how it works:

    ...
    #include <hydra/functions/Gaussian.h>
    ...
    
    declarg(Angle, double)
    
    int main(int argv, char** argc)
    {
    ...
    
    auto gauss = hydra::Gaussian<Angle>(mean, signa);
    ...
    }

    in the previous code snippet, wherever the object gauss is called, if the argument consists of one or tuples, which are the entry type of all multidimensional dataset classes in Hydra, the Angletype identifier will be searched among the elements, if not found, code will not compile. If the argument is a non-tuple type, conversion will be tried. Multidimensional datasets can be defined using named parameters like in the snippet below:

    ...
    #include <hydra/multivector.h>
    ...
     
    declarg(X, double)
    declarg(Y, double)
    declarg(Z, double)
    
    int main(int argv, char** argc)
    {
    //3D device buffer
    hydra::multivector< hydra::tuple<X,Y,Z>,  hydra::device::sys_t> data(nentries);
    
    ...
    
    for(auto x: hydra::column<X>(data)
        std::cout << x << std::endl;
    }

    b) Functors: as usual, it should derive from hydra::BaseFunctor, defined in hydra/Function.h, but now the must inform their argument type, signature and number of parameters (hydra::Parameter) at template instantiation time. It is also necessary to implement the ResultType Evaluate(ArgType...) method. Default constructors should be deleted, non-default and copy constructors, as well as assignments operators should be implemented as well. See how this works for hydra::Gaussian:

    //implementations omited, for complete details
    //see: hydra/functions/Gaussian.h
    
    template<typename ArgType, typename Signature=double(ArgType) >
    class Gaussian: public BaseFunctor<Gaussian<ArgType>, Signature, 2>
    {
    
    public:
    
        Gaussian()=delete;
    
        Gaussian(Parameter const& mean, Parameter const& sigma );
    
        __hydra_host__ __hydra_device__
        Gaussian(Gaussian<ArgType> const& other );
    
        __hydra_host__ __hydra_device__
        Gaussian<ArgType>& operator=(Gaussian<ArgType> const& other );
    
        __hydra_host__ __hydra_device__
        inline double Evaluate(ArgType x)  const;
    
    };

    c) Lambdas: Support for lambdas was updated to adhere the new interface. The new interface is implemented in `hydra/Lambda.h

    ...
    #include <hydra/multivector.h>
    #include <hydra/Lambda.h>
    ...
    
    declarg(X, double)
    declarg(Y, double)
    declarg(Z, double)
    
    int main(int argv, char** argc)
    {
        //3D device buffer
        hydra::multivector< hydra::tuple<X,Y,Z>,  hydra::device::sys_t> data(nentries);
    
        //Lambda
        auto printer = hydra::wrap_lambda( []__hydra_dual__(X x, Y y){
    
           print("x = %f y = %f", x(), y());
    
        } );
    
        for(auto entry: data) printer(entry);           
    }
    

Random number generation

  1. Support for analytical pseudo-random number generation (APRNG) added for many functors added via hydra::Distribution<FunctorType> specializations (see example example/random/basic_distributions.inl).

  2. Parallel filling of containers with random numbers (see example example/random/fill_basic_distributions.inl). In particular, there are some convenience functions in order to deploy in a generic and simple way the parallel filling of containers transparently, independently of the back-end. For a given instance of the functor of interest, the framework is informed of the presence of the APRNG method in compile time. If the APRNG
    is not found a compile error is emitted, informing and suggesting the user to use the hydra::sample interface, which implements a different filling strategy. The facility is decoupled from the underlying PRNG engine, in order to be compatible with the current pseudo-random engines already imlemented in Hydra, and future algorithms that will be made available over the time. If the user needs to use a specific PRNG engine, its type can be passed as template parameter to the convenience function, otherwise the hydra_thrust::default_random_engine is used. As an example of filling of containers with random numbers see the snippet below:

    ...
    #include <hydra/functions/Gaussian.h>
    ...
    
    declarg(Xvar, double)
    
    int main(int argv, char** argc)
    {
    ...
    
    auto gauss  = hydra::Gaussian<Xvar>(mean, signa);
    
    auto data_d = hydra::device::vector<Xvar>(nentries);
    
    hydra::fill_random(data_d , gauss);
    
    ...
    }

The filling functions can be called also with a specific backend policy and with iterators instead of the whole container. The seed used by the PRNG engine can be also passed to the function as last parameter. The collection of all the convenience functions can be found in hydra/RandomFill.h.

Phase-space generation

  1. Updated hydra::Decays container for supporting named variable idiom.
  2. Changes in hydra::PhaseSpaceand hydra::Decays.
  3. hydra::Chain not supported any more.
  4. New Meld(...) method in hydra::Decays for building mixed datasets and decay chains.
  5. Re-implemented logics for generation of events and associated weights.

Data fitting

  1. Added support to multi-layered simultaneous fit of different models, over different datasets, deploying different parallelization strategies for each model. No categorization of the dataset is needed, but just to set up preliminarly the different component FCNs, that can be optimized in isolation or in the context of the simultaneous FCN. Simultaneous FCNs can be created via direct instantiation or using the convenience function hydra::make_simultaneous_fcn(...), as shown in the following snippet.

    ...
    #include <hydra/LogLikelihoodFCN.h>
    ...
    
    int main(int argv, char** argc)
    {
     ...
     //=====================================================================================
     //                                                           +----< fcn(model-x) 
     //                           +----< simultaneous fcn 1 ----- |
     //                           |                               +----< fcn(model-y)  
     //   simultaneous fcn   <----+
     //                           |                               +----< fcn(model-w)
     //                           +----< simultaneous fcn 2 ------|
     //                           |                               +----< fcn(model-z) 
     //                           +----< fcn(model-v)
     //=====================================================================================        
     auto fcnX    = hydra::make_loglikehood_fcn(modelX, dataX);
     auto fcnY    = hydra::make_loglikehood_fcn(modelY, dataY);
     auto fcnW    = hydra::make_loglikehood_fcn(modelY, dataY);
     auto fcnZ    = hydra::make_loglikehood_fcn(modelZ, dataZ);    
     auto fcnV    = hydra::make_loglikehood_fcn(modelv, datav);
     
     auto sim_fcn1 = hydra::make_simultaneous_fcn(fcnx, fcny);
     auto sim_fcn2 = hydra::make_simultaneous_fcn(fcnw, fcnz);
     auto sim_fcn  = hydra::make_simultaneous_fcn(sim_fcn1, sim_fcn2, fcnV);
     ...
    }

    Moreover, the generic interface allows to build up a simultaneous FCN object by composing usual FCNs and simultaneous FCNs. An example of such new method can be found in examples/fit/simultaneous_fit.inl.

  2. Fitting of convoluted PDFs.

General

Many issues solved and bugs fixed across the tree:

1. https://github.com/MultithreadCorner/Hydra/issues/91#issue-631032116
2. https://github.com/MultithreadCorner/Hydra/issues/90
3. https://github.com/MultithreadCorner/Hydra/pull/89
4. https://github.com/MultithreadCorner/Hydra/issues/87
5. https://github.com/MultithreadCorner/Hydra/issues/86
6. https://github.com/MultithreadCorner/Hydra/issues/82
7. https://github.com/MultithreadCorner/Hydra/issues/77

and many others.

Acknowledgment note: Hydra's author is very thankful to all the people that in one way or another contributed to this release. In particular, Hydra's author would like to thanks Davide Brundu (@dbrundu) , for his generous contributions reporting bugs, sending some code and helping to expand the framework functionality.