|
CONVERSION ERROR
|
|
## Vectorisation for nested data parallelism
|
|
|
|
|
|
Error: HttpError (HttpExceptionRequest Request {
|
|
|
|
host = "ghc.haskell.org"
|
|
|
|
port = 443
|
|
**TODO** This material needs to be revised and we need to come up with a plan for getting some programs to quickly get some programs to compile. Also integrate the [lifted case example](data-parallel/code-vectorisation/lifted-case-example).
|
|
secure = True
|
|
|
|
requestHeaders = []
|
|
|
|
path = "/trac/ghc/wiki/DataParallel/CodeVectorisation"
|
|
|
|
queryString = "?version=3"
|
|
|
|
method = "GET"
|
|
|
|
proxy = Nothing
|
|
|
|
rawBody = False
|
|
|
|
redirectCount = 10
|
|
|
|
responseTimeout = ResponseTimeoutDefault
|
|
|
|
requestVersion = HTTP/1.1
|
|
|
|
}
|
|
|
|
(StatusCodeException (Response {responseStatus = Status {statusCode = 403, statusMessage = "Forbidden"}, responseVersion = HTTP/1.1, responseHeaders = [("Date","Sun, 10 Mar 2019 07:02:00 GMT"),("Server","Apache/2.2.22 (Debian)"),("Strict-Transport-Security","max-age=63072000; includeSubDomains"),("Vary","Accept-Encoding"),("Content-Encoding","gzip"),("Content-Length","262"),("Content-Type","text/html; charset=iso-8859-1")], responseBody = (), responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}) "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>403 Forbidden</title>\n</head><body>\n<h1>Forbidden</h1>\n<p>You don't have permission to access /trac/ghc/wiki/DataParallel/CodeVectorisation\non this server.</p>\n<hr>\n<address>Apache/2.2.22 (Debian) Server at ghc.haskell.org Port 443</address>\n</body></html>\n"))
|
|
|
|
|
|
|
|
Original source:
|
|
|
|
|
|
|
|
```trac
|
|
|
|
== Vectorisation for nested data parallelism ==
|
|
|
|
|
|
|
|
'''TODO:''' This material needs to be revised and we need to come up with a plan for getting some programs to quickly get some programs to compile. Also integrate the [wiki:DataParallel/CodeVectorisation/LiftedCaseExample lifted case example].
|
|
|
|
|
|
|
|
We will try to implement full blown vectorisation using an explicit closure representation on Core code after lambda lifting. The transformation performs closure conversion and vectorisation in one sweep. We represent scalar and array closures as follows:
|
|
We will try to implement full blown vectorisation using an explicit closure representation on Core code after lambda lifting. The transformation performs closure conversion and vectorisation in one sweep. We represent scalar and array closures as follows:
|
|
{{{
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
data a :-> b = forall env. PA env => Clo env (env -> a -> b) ([:env:] -> [:a:] -> [:b:])
|
|
data a :-> b = forall env. PA env => Clo env (env -> a -> b) ([:env:] -> [:a:] -> [:b:])
|
|
data a :=> b = forall env. PA env => AClo [:env:] (env -> a -> b) ([:env:] -> [:a:] -> [:b:])
|
|
data a :=> b = forall env. PA env => AClo [:env:] (env -> a -> b) ([:env:] -> [:a:] -> [:b:])
|
|
|
|
|
... | @@ -33,19 +18,29 @@ data a :=> b = forall env. PA env => AClo [:env:] (env -> a -> b) ([:env:] -> [: |
... | @@ -33,19 +18,29 @@ data a :=> b = forall env. PA env => AClo [:env:] (env -> a -> b) ([:env:] -> [: |
|
|
|
|
|
(##) :: (a :=> b) -> [:a:] -> [:b:]
|
|
(##) :: (a :=> b) -> [:a:] -> [:b:]
|
|
(##) (AClo envs _ fs) = fs envs
|
|
(##) (AClo envs _ fs) = fs envs
|
|
}}}
|
|
```
|
|
|
|
|
|
|
|
|
|
It is important that both kinds of closures include scalar and lifted code, as we need to move between `a :-> b` and `a :=> b` in both directions due to the functions:
|
|
It is important that both kinds of closures include scalar and lifted code, as we need to move between `a :-> b` and `a :=> b` in both directions due to the functions:
|
|
{{{
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
replicateP :: Int -> (a :-> b) -> (a :=> b)
|
|
replicateP :: Int -> (a :-> b) -> (a :=> b)
|
|
replicateP n (Clo env f fs) = AClo (replicateP n env) f fs
|
|
replicateP n (Clo env f fs) = AClo (replicateP n env) f fs
|
|
|
|
|
|
(!:) :: (a :=> b) -> Int -> (a :-> b)
|
|
(!:) :: (a :=> b) -> Int -> (a :-> b)
|
|
i !: AClo envs f fs = Clo (i !: envs) f fs
|
|
i !: AClo envs f fs = Clo (i !: envs) f fs
|
|
}}}
|
|
```
|
|
|
|
|
|
|
|
|
|
In other words, we move between the two types of closures simply by replicating and indexing into the environment.
|
|
In other words, we move between the two types of closures simply by replicating and indexing into the environment.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
We do not have any explicit type transformations. These are all encoded using associated types of the parallel array type class `PA`:
|
|
We do not have any explicit type transformations. These are all encoded using associated types of the parallel array type class `PA`:
|
|
{{{
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
class PA e where
|
|
class PA e where
|
|
data [:e:]
|
|
data [:e:]
|
|
type Vec e
|
|
type Vec e
|
... | @@ -91,44 +86,64 @@ instance (PA a, PA b) => PA (a :-> b) where |
... | @@ -91,44 +86,64 @@ instance (PA a, PA b) => PA (a :-> b) where |
|
data [: a :-> b :] = PAClo (a :=> b)
|
|
data [: a :-> b :] = PAClo (a :=> b)
|
|
type Vect (a :-> b) = a:-> b -- shouldn't happen, right?
|
|
type Vect (a :-> b) = a:-> b -- shouldn't happen, right?
|
|
PAClo (AClo envs f fs) !: i = Clo (envs!:i) f fs
|
|
PAClo (AClo envs f fs) !: i = Clo (envs!:i) f fs
|
|
}}}
|
|
```
|
|
|
|
|
|
|
|
### Mixing Vectorised and Scalar Code
|
|
|
|
|
|
|
|
|
|
=== Mixing Vectorised and Scalar Code ===
|
|
|
|
|
|
|
|
We have two types of modules: (a) modules compiled as ever, which we call 'scalar modules', and (b) 'vectorised modules'. Scalar modules export the same code as before. Vectorised modules export additional identifiers.
|
|
We have two types of modules: (a) modules compiled as ever, which we call 'scalar modules', and (b) 'vectorised modules'. Scalar modules export the same code as before. Vectorised modules export additional identifiers.
|
|
* For every variable `f :: t`, we have '''in addition'''
|
|
|
|
{{{
|
|
|
|
|
|
- For every variable `f :: t`, we have **in addition**
|
|
|
|
|
|
|
|
```wiki
|
|
f^p :: t^v
|
|
f^p :: t^v
|
|
f^p = V[[e]]
|
|
f^p = V[[e]]
|
|
}}}
|
|
```
|
|
|
|
|
|
the code for `f` is not the original scalar code. Instead, it is defined as
|
|
the code for `f` is not the original scalar code. Instead, it is defined as
|
|
{{{
|
|
|
|
|
|
```wiki
|
|
f :: t
|
|
f :: t
|
|
f = unvect f^p
|
|
f = unvect f^p
|
|
}}}
|
|
```
|
|
* For every data type `T`, we have in addition {{{T^v}}}.
|
|
- For every data type `T`, we have in addition `T^v`.
|
|
* For every function `M.f :: a -> b` imported from a scalar module `M`, we generate and use the following definition instead:
|
|
- For every function `M.f :: a -> b` imported from a scalar module `M`, we generate and use the following definition instead:
|
|
{{{
|
|
|
|
|
|
```wiki
|
|
f :: (a -> b)^v
|
|
f :: (a -> b)^v
|
|
f = vect M.f
|
|
f = vect M.f
|
|
}}}
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
The functions `vect` and `unvect` are defined in the same type classes where `t^v` is defined as an associated type. **!!TODO:** Try to define these two functions, to be sure we can actually do it.
|
|
|
|
|
|
|
|
|
|
The functions `vect` and `unvect` are defined in the same type classes where `t^v` is defined as an associated type. '''!!!TODO:''' Try to define these two functions, to be sure we can actually do it.
|
|
|
|
|
|
|
|
Moreover, we like to have a toplevel declarations of the form `derive PA (T)` that create a suitable `PA` instance of a previously defined (and possibly imported) data type `T`.
|
|
Moreover, we like to have a toplevel declarations of the form `derive PA (T)` that create a suitable `PA` instance of a previously defined (and possibly imported) data type `T`.
|
|
|
|
|
|
=== Various Ideas to Avoid Full Blown Vectorisation ===
|
|
|
|
|
|
### Various Ideas to Avoid Full Blown Vectorisation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
We discussed some approaches that would lead to a certain degree of vectorisation, but avoid dealing with issues, such as arrays of functions.
|
|
We discussed some approaches that would lead to a certain degree of vectorisation, but avoid dealing with issues, such as arrays of functions.
|
|
|
|
|
|
* We could have rewrite rules as follows (for a vectorised function):
|
|
|
|
{{{
|
|
- We could have rewrite rules as follows (for a vectorised function):
|
|
|
|
|
|
|
|
```wiki
|
|
mapP f -> f^
|
|
mapP f -> f^
|
|
mapP f^ -> inject f^
|
|
mapP f^ -> inject f^
|
|
mapP (inject f^) -> inject (mapP f^)
|
|
mapP (inject f^) -> inject (mapP f^)
|
|
}}}
|
|
```
|
|
where {{{inject}}} is the flatten/partition combination.
|
|
|
|
|
|
|
|
'''!!!TODO:''' What else was there???
|
|
where `inject` is the flatten/partition combination.
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> **!!TODO:** What else was there???
|
|
|
|
>
|
|
|
|
>
|
|
|
|
|
|
``` |
|
|