Code Monkey home page Code Monkey logo

hblas's Introduction

Wellposed

About hblas

hblas is an open source component of the Wellposed® mathematical software suite.

Members of the numerical haskell open source community can be found on irc at #numerical-haskell on freenode, and via the numericalhaskell mailing list.

Build Status

hblas is a self contained full (well, not quite yet) BLAS and LAPACK binding that provides the full BLAS and LAPACKE APIs in a simple, unopinionated, Haskell wrapper.

This library is NOT meant to be used by end users, it is designed to be an unopinionated, simple, portable, easy to install BLAS/LAPACK substrate for higher level numerical computing libraries to build upon. Morever, this library is strictly a wrapper, and simply makes using the functionality of BLAS and LAPACK more accessible.

This library is NOT meant to be used a standalone array library (except in desperation), but rather should be used by a higher level numerical array library to provide high performance linear algebra routines.

Install

By default, hblas will assume you have BLAS and LAPACK built and installed.

OSX

On OS X systems, things will just work.

$ cabal install

Linux

On linux and bsd systems, you will need to manually install the BLAS and LAPACK libraries beforehand.

$ sudo apt-get install libblas liblapack
$ cabal install

Testing

To run the test suite execute:

$ cabal test

Linking

If you get an error like undefined reference to 'cblas_sdsdot' when building or running an HBLAS program, you might be on a system that builds BLAS and CBLAS separately, such as Arch Linux.

In which case, be sure to install CBLAS and invoke cabal install hblas -fCBLAS to make sure hblas links to CBLAS properly.

Usage

API is subject to change.

import Foreign.Storable
import Numerical.HBLAS.BLAS
import Numerical.HBLAS.MatrixTypes

-- Generate the constant mutable square matrix of the given type and dimensions.
constMatrix :: Storable a => Int -> a -> IO (IODenseMatrix Row a)
constMatrix n k = generateMutableDenseMatrix SRow (n,n) (const k)

example_dgemm :: IO ()
example_dgemm = do
    left  <- constMatrix 2 (2 :: Double)
    right <- constMatrix 2 (3 :: Double)
    out   <- constMatrix 2 (0 :: Double)

    dgemm NoTranspose NoTranspose 1.0 1.0 left right out

    resulting <- mutableVectorToList $ _bufferDenMutMat out
    print resulting

Getting Involved

Patches, bug reports, tests, and other contributions welcome.

If you want to add a new routine, check out the ones listed in the lapack section of the Intel MKL manual to get some human readable documentation.

Commercial Support

I have > 32bit size arrays, help!

Congrats, you have ``big compute on big data'', contact Carter and we'll try to help you out.

hblas's People

Contributors

archblob avatar cartazio avatar phadej avatar sdiehl avatar tclv avatar tomasmcz avatar yangjueji avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hblas's Issues

add basic bindings to provide basic functionality

  • Linear Systems Solvers - Dense General Matrices - simple driver LAPACKE_?gesv
  • Least Square Systems solver - Dense General matrices - simple driver LAPACKE_?gelsd that does recursive SVD based least squares. (because its fast, and doesn't make any assumptions about rank)
  • more things! some of the factorizations, and perhaps some of the "expert" routines

HBLAS.BLAS.FFI types

The types of the functions (i.e. cblas_sdot_unsafe) are Float and Double, when they are really CFloat and CDouble.

Also cblas_isamax_unsafe / cblas_idamax_unsafe is returning a CInt, when really it returns a CUInt.

Also, cblas_idamax_unsafe's 2nd argument takes a Float, when it should take a Double?

Bindings to DSYEVR and ZHEEVR

These are the driver routines for the double-precision relatively robust representation symmetric eigenproblem solver. They are said to be faster and use less space than the default solver (except for a few corner cases).

gemv result

I'm not getting the result I expect for [d,s]gemv. I only just started using the library though so I could be using it incorrectly?

#include <mkl.h>
#include <stdio.h>

int main()
{
  double A[] = { 1, 2, 3
               , 4, 5, 6 };
  double x[] = { 10, 20, 30 };
  double y[2];

  cblas_dgemv(CblasRowMajor, CblasNoTrans, 2, 3, 1.0, A, 3, x, 1, 0, y, 1);

  printf("y = [%lf, %lf]\n", y[0], y[1]);

  return 0;
}
> icc -I$MKLROOT/include $MKLROOT/lib/libmkl_intel_lp64.a $MKLROOT/lib/libmkl_sequential.a $MKLROOT/lib/libmkl_core.a -lpthread -lm -ldl test.c
> ./a.out
y = [140.000000, 320.000000]
import Numerical.HBLAS.BLAS.Level2
import Numerical.HBLAS.MatrixTypes

import qualified Data.Vector.Storable         as S
import qualified Data.Vector.Storable.Mutable as SM


main :: IO ()
main = do
  let m = S.fromList [1,2,3, 4,5,6]
      x = S.fromList [10,20,30]

  m' <- S.unsafeThaw m
  x' <- S.unsafeThaw x
  y' <- SM.new 2

  let mat   = MutableDenseMatrix SRow 3 2 3 m'
      xvec  = MutableDenseVector SDirect 3 1 x'
      yvec  = MutableDenseVector SDirect 2 1 y'

  dgemv NoTranspose 1 0 mat xvec yvec

  y  <- S.unsafeFreeze y'
  print y
ghci> :main
[50.0,140.0]

have good way to automatically rederive api bindings when needed

perhaps using a cleaned up version of this clever thing by max!

{-# LANGUAGE TemplateHaskell #-}
import System.Environment (getArgs)
import Control.Monad (mapM)
import Text.PrettyPrint.Mainland
import qualified Data.ByteString.Char8 as B
import qualified Language.C.Syntax as C
import qualified Language.C.Parser as P
import Data.Loc
import Language.Haskell.TH
import Foreign.Ptr
import Foreign.C.Types
import Data.Char

-- | Parse the file in the argument, transform it, then pretty print it.
main :: IO ()
main = do
    args <- getArgs
    let fname = head args
    x <- parseFile fname
    writeFile (take (length fname - 1) fname ++ "hs")
              $ (++) required
              $ pprint
              $ x >>= transform fname

-- | Parses C headers
parseFile :: String -> IO [C.Definition]
parseFile filename = do
    let start = startPos filename
    let exts = []
    s <- B.readFile filename
    case P.parse exts [] P.parseUnit s start of
      Left err   -> error $ show err
      Right defs -> return defs

required :: String
required = "{-# LANGUAGE GeneralizedNewtypeDeriving #-}\nmodule Numerical.OpenBLAS.FFI where\nimport Foreign.Ptr\nimport Foreign.C.Types\nimport Data.Complex\n"

-- wow! 1-1 mapping
transform :: String -> C.Definition -> [Dec]
transform headerName (C.DecDef (C.InitGroup (C.DeclSpec _ _ retType _) _ [C.Init (C.Id functionName _) (C.Proto _ (C.Params argsDecl _ _) _) _ _ _ _] _) sd)
  = let ty = case argsDecl of
              [(C.Param _ (C.DeclSpec _ _ (C.Tvoid _) _) _ _)] -> (AppT (ConT (mkName "IO")) $ tyco retType)
              xs -> foldnconquer (AppT (ConT (mkName "IO")) $ tyco retType) $ paramify xs
        f = ForeignD
          $ ImportF CCall Unsafe (headerName ++ " " ++ functionName)
            (mkName functionName) ty
    in [f]
transform headerName (C.DecDef (C.TypedefGroup (C.DeclSpec _ _ (C.Tenum (Just (C.Id name _)) vals _ _) _) _ _ _) _)
  = let tname = name ++ "T"
        unname = "un" ++ tname
        fnName = "encode" ++ (caps . drop 1 . dropWhile (/= '_') $ name)
        nt = NewtypeD
             [] (mkName tname) []
             (RecC (mkName tname)
               [(mkName unname, NotStrict, ConT (mkName "CUChar"))])
             [mkName "Eq", mkName "Show"]
        da = DataD [] (mkName name) [] 
             (map (\(C.CEnum (C.Id n _) (Just (C.Const (C.IntConst _ _ _v _) _)) _) ->
               NormalC (mkName n) []) vals)
             [mkName "Eq", mkName "Show"]
        fty = SigD (mkName fnName)
              (AppT (AppT ArrowT (ConT (mkName name))) (ConT (mkName tname)))
        fun = FunD (mkName fnName) 
            $ map mkCls vals
        mkCls (C.CEnum (C.Id n _) (Just (C.Const (C.IntConst _ _ v _) _)) _)
            = Clause [ConP (mkName n) []] 
              (NormalB (AppE (ConE (mkName tname)) (LitE (IntegerL v))))
              []
    in [nt, da, fty, fun]


transform _ _ = []

foldnconquer :: Type -> [Type] -> Type
foldnconquer = foldr (\x y -> AppT (AppT ArrowT x) y)

paramify :: [C.Param] -> [Type]
paramify = map (\(C.Param _ (C.DeclSpec _ _ ty _) d _) -> tyco' d ty)

tyco' :: C.Decl -> C.TypeSpec -> Type
tyco' (C.Ptr _ d _) x = AppT (ConT (mkName "Ptr")) $ tyco' d x
tyco' _ x = tyco x

tyco :: C.TypeSpec -> Type
tyco (C.Tvoid _)               = ConT $ mkName "()"
tyco (C.Tint _ _)              = ConT $ mkName "CInt" -- TODO: the first arg is if it is signed
tyco (C.Tchar _ _)             = ConT $ mkName "CChar"
tyco (C.Tfloat _)              = ConT $ mkName "CFloat"
tyco (C.Tdouble _)             = ConT $ mkName "CDouble"
tyco (C.Tenum (Just (C.Id s _)) _ _ _)  = ConT $ mkName (s ++ "T")
tyco (C.Tnamed (C.Id "size_t" _) _ _)   = ConT $ mkName "CUInt"
tyco (C.Tnamed (C.Id "blasint" _) _ _)  = ConT $ mkName "CInt"
tyco (C.Tnamed (C.Id "openblas_complex_float" _) _ _)   = ConT $ mkName "(Ptr (Complex Float))"
tyco (C.Tnamed (C.Id "openblas_complex_double" _) _ _)  = ConT $ mkName "(Ptr (Complex Double))"
tyco x = error $ "tyco: unimplemented: " ++ show x

caps (x:xs) = toUpper x : map toLower xs

Expanding into support for gemv

So I'm looking into modifying/tweaking the current gemmAbstraction from BLAS.hs and adapting it for gemv; any sort of pointers on what aspects are likely to need changing?

Add -dev suffix to requirements on README

The readme page suggests installing libblas and liblapack. But there are no such packages! I assume you probably meant to have a -dev suffix on each of these. Yes?

cblas vs blas

Test suite requires -lcblas library to link on Arch Linux.

thinkpad% cabal test                                                                                                                             
Building hblas-0.3.0.1...
Preprocessing library hblas-0.3.0.1...
In-place registering hblas-0.3.0.1...
Preprocessing test suite 'unit-testsuite' for hblas-0.3.0.1...
Linking dist/build/unit-testsuite/unit-testsuite ...
/home/stephen/Git/hblas/dist/build/libHShblas-0.3.0.1.a(FFI.o): In function `rkxx_info':
(.text+0x111): undefined reference to `cblas_sdsdot'
/home/stephen/Git/hblas/dist/build/libHShblas-0.3.0.1.a(FFI.o): In function `slT4_info':
(.text+0x381): undefined reference to `cblas_dsdot'
/home/stephen/Git/hblas/dist/build/libHShblas-0.3.0.1.a(FFI.o): In function `slV5_info':
collect2: error: ld returned 1 exit status

Relevant information:

thinkpad% cabal --version                                                                                                                   
cabal-install version 1.18.0.1
using version 1.18.0 of the Cabal library 
thinkpad% ghc --version                                                                                                                    
The Glorious Glasgow Haskell Compilation System, version 7.6.3
thinkpad% ldconfig -p | grep blas                                                                                                                          
    libgslcblas.so.0 (libc6,x86-64) => /usr/lib/libgslcblas.so.0
    libgslcblas.so (libc6,x86-64) => /usr/lib/libgslcblas.so
    libcublas.so.5.0 (libc6,x86-64) => /opt/cuda/lib64/libcublas.so.5.0
    libcublas.so.5.0 (libc6) => /opt/cuda/lib/libcublas.so.5.0
    libcublas.so (libc6,x86-64) => /opt/cuda/lib64/libcublas.so
    libcublas.so (libc6) => /opt/cuda/lib/libcublas.so
    libcblas.so (libc6,x86-64) => /usr/lib/libcblas.so
    libblas.so (libc6,x86-64) => /usr/lib/libblas.so
thinkpad% ldconfig -p | grep cblas                                                                                                          
    libgslcblas.so.0 (libc6,x86-64) => /usr/lib/libgslcblas.so.0
    libgslcblas.so (libc6,x86-64) => /usr/lib/libgslcblas.so
    libcblas.so (libc6,x86-64) => /usr/lib/libcblas.so

This is the providing package should be blas 3.5.0-1:

https://www.archlinux.org/packages/extra/x86_64/blas/

Low-level Blas interface

Here's a complete low-level Blas FFI that contains everything defined in the official Blas standard. It's a 1-to-1 map to the C interface, using Ptr, IO, etc, but with ordinary Haskell types (Int, Float, etc). It contains both safe and unsafe foreign calls.

For better or worse, it makes use of c2hs, which saves some effort with the marshaling of data types. The generated Haskell code is not portable partly because c2hs doesn't handle size_t properly, but also because the underlying Blas implementation is free to choose a different type for CBLAS_INDEX (most implementations do use size_t though).

Would you be interested in this? It could save you some of the more tedious work.

add rank 1 real matrix update / outer product

sger and dger

http://software.intel.com/sites/products/documentation/hpc/mkl/mklman/GUID-BD2E87B3-5FA7-4E0C-88E2-1982AB0773A2.htm

https://github.com/wellposed/hblas/blob/master/src/Numerical/HBLAS/BLAS/FFI.hs#L247-L250

-- perform the rank 1 operation   A := alpha*x*y' + A,

--void cblas_sger (  enum CBLAS_ORDER order,   CInt M,   CInt N,   Float   alpha,   Float  *X,   CInt incX,   Float  *Y,   CInt incY, Float  *A,   CInt lda);
--void cblas_dger (  enum CBLAS_ORDER order,   CInt M,   CInt N,   Double  alpha,   Double *X,   CInt incX,   Double *Y,   CInt incY, Double *A,   CInt lda);

the haskelly high level version would look like (assuming you punt on dealing with modelling the vectors properly because i've not added strided vector support to hblas yet, and you assume inx and incy are set to 1)

sger ::( PrimMonad s) =>Float -> Float 
   -> Mvector (PrimState s) Float -> MVector (PrimState s) Float 
  ->  MutDenseMatrix (PrimState m) orient Float -> m () 

note this would actually be done slightly differently once I add strided vector support

a mini explanation of some of the API stuff I do currently is on this other ticket #13

don't hesitate to ask for help

clean up the ROTG, ROTM, and ROTMG code

currently it exposes the complex storable by reference style interface, which i'm removing for now, because I dont think it makes sense,

likewise, I think those calls could/should always be unsafe calls, which would further make them super performant, because they a) always take ~ constant time that should be at most a few micro seconds, and b) that probably would relax any allocation overheads, unless the underlying code has stronger alignment assumptions that word based alignment

Add padded matrix types and packed analogues

Re: our conversation in #n-h the other day:

  • Padded symmetric
  • Padded triangular
  • Padded Hermetian

and the packed analogues. I'll then get to work on their versions of gemm. I may also have a go at writing the types myself if I have time tomorrow.

doesn't work in ghci

i think we're hitting a problem wrt linking.

maybe the linking works fine with ghci 7.7 / HEAD?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.