Open njtierney opened 2 years ago
We could allow it to change for extra samples. But in the first instance, we could just force it to reuse what was used in the first place. I don't think many people will want to change the compute in between those.
OK cool!
I have nearly got a first pass at this working for MCMC
However I get this error
Error in py_call_impl(callable, dots$args, dots$keywords) :
RuntimeError: Visible devices cannot be modified after being initialized
Which is I believe from trying to set the device on exit...need to think about how to handle this
the_default_device <- default_device()
on.exit(
set_device(the_default_device)
)
Interesting. Maybe the solution is to run the TF code in a with()
context? Worth looking at examples of how this is used in TF code
Got it working!
library(greta)
#>
#> Attaching package: 'greta'
#> The following objects are masked from 'package:stats':
#>
#> binomial, cov2cor, poisson
#> The following objects are masked from 'package:base':
#>
#> %*%, apply, backsolve, beta, chol2inv, colMeans, colSums, diag,
#> eigen, forwardsolve, gamma, identity, rowMeans, rowSums, sweep,
#> tapply
library(tictoc)
greta_sitrep()
#> ℹ checking if python available
#> ✔ python (v3.8) available
#>
#> ℹ checking if TensorFlow available
#> ✔ TensorFlow (v2.9.2) available
#>
#> ℹ checking if TensorFlow Probability available
#> ✔ TensorFlow Probability (v0.17.0) available
#>
#> ℹ checking if greta conda environment available
#> ✔ greta conda environment available
#>
#> ℹ Initialising python and checking dependencies, this may take a moment.
#> ✔ Initialising python and checking dependencies ... done!
#>
#> ℹ greta is ready to use!
x <- normal(0,1)
m <- model(x)
#> Loaded Tensorflow version 2.9.2
tic()
draws_cpu <- mcmc(m, n_samples = 500, warmup = 500, compute_options = cpu_only())
#> running 4 chains simultaneously on up to 8 cores
#>
#> warmup 0/500 | eta: ?s warmup ==== 50/500 | eta: 6s warmup ======== 100/500 | eta: 3s warmup ============ 150/500 | eta: 2s warmup ================ 200/500 | eta: 2s warmup ==================== 250/500 | eta: 1s warmup ======================== 300/500 | eta: 1s warmup ============================ 350/500 | eta: 1s warmup ================================ 400/500 | eta: 0s warmup ==================================== 450/500 | eta: 0s warmup ======================================== 500/500 | eta: 0s
#> sampling 0/500 | eta: ?s sampling ==== 50/500 | eta: 0s sampling ======== 100/500 | eta: 0s sampling ============ 150/500 | eta: 0s sampling ================ 200/500 | eta: 0s sampling ==================== 250/500 | eta: 0s sampling ======================== 300/500 | eta: 0s sampling ============================ 350/500 | eta: 0s sampling ================================ 400/500 | eta: 0s sampling ==================================== 450/500 | eta: 0s sampling ======================================== 500/500 | eta: 0s
toc()
#> 2.795 sec elapsed
tic()
draws_gpu <- mcmc(m, n_samples = 500, warmup = 500, compute_options = gpu_only())
#> running 4 chains simultaneously on up to 8 cores
#> warmup 0/500 | eta: ?s warmup ==== 50/500 | eta: 25s warmup ======== 100/500 | eta: 21s warmup ============ 150/500 | eta: 17s warmup ================ 200/500 | eta: 14s warmup ==================== 250/500 | eta: 12s warmup ======================== 300/500 | eta: 10s warmup ============================ 350/500 | eta: 7s warmup ================================ 400/500 | eta: 5s warmup ==================================== 450/500 | eta: 2s warmup ======================================== 500/500 | eta: 0s
#> sampling 0/500 | eta: ?s sampling ==== 50/500 | eta: 22s sampling ======== 100/500 | eta: 17s sampling ============ 150/500 | eta: 16s sampling ================ 200/500 | eta: 13s sampling ==================== 250/500 | eta: 11s sampling ======================== 300/500 | eta: 9s sampling ============================ 350/500 | eta: 7s sampling ================================ 400/500 | eta: 5s sampling ==================================== 450/500 | eta: 2s sampling ======================================== 500/500 | eta: 0s
toc()
#> 45.819 sec elapsed
library(coda)
#>
#> Attaching package: 'coda'
#>
#> The following object is masked from 'package:greta':
#>
#> mcmc
plot(draws_cpu)
plot(draws_gpu)
Created on 2022-08-10 by the reprex package (v2.0.1)
Remaining tasks
OK, I got the message to display!
library(greta)
#>
#> Attaching package: 'greta'
#> The following objects are masked from 'package:stats':
#>
#> binomial, cov2cor, poisson
#> The following objects are masked from 'package:base':
#>
#> %*%, apply, backsolve, beta, chol2inv, colMeans, colSums, diag,
#> eigen, forwardsolve, gamma, identity, rowMeans, rowSums, sweep,
#> tapply
library(tictoc)
greta_sitrep()
#> ℹ checking if python available
#> ✔ python (v3.8) available
#>
#> ℹ checking if TensorFlow available
#> ✔ TensorFlow (v2.9.2) available
#>
#> ℹ checking if TensorFlow Probability available
#> ✔ TensorFlow Probability (v0.17.0) available
#>
#> ℹ checking if greta conda environment available
#> ✔ greta conda environment available
#>
#> ℹ Initialising python and checking dependencies, this may take a moment.
#> ✔ Initialising python and checking dependencies ... done!
#>
#> ℹ greta is ready to use!
x <- normal(0,1)
m <- model(x)
#> Loaded Tensorflow version 2.9.2
tic()
draws_cpu <- mcmc(m, n_samples = 500, warmup = 500, compute_options = cpu_only())
#> running 4 chains simultaneously on up to 8 CPU cores
#>
#> warmup 0/500 | eta: ?s warmup ==== 50/500 | eta: 6s warmup ======== 100/500 | eta: 3s warmup ============ 150/500 | eta: 2s warmup ================ 200/500 | eta: 2s warmup ==================== 250/500 | eta: 1s warmup ======================== 300/500 | eta: 1s warmup ============================ 350/500 | eta: 1s warmup ================================ 400/500 | eta: 0s warmup ==================================== 450/500 | eta: 0s warmup ======================================== 500/500 | eta: 0s
#> sampling 0/500 | eta: ?s sampling ==== 50/500 | eta: 0s sampling ======== 100/500 | eta: 0s sampling ============ 150/500 | eta: 0s sampling ================ 200/500 | eta: 0s sampling ==================== 250/500 | eta: 0s sampling ======================== 300/500 | eta: 0s sampling ============================ 350/500 | eta: 0s sampling ================================ 400/500 | eta: 0s sampling ==================================== 450/500 | eta: 0s sampling ======================================== 500/500 | eta: 0s
toc()
#> 2.829 sec elapsed
tic()
draws_gpu <- mcmc(m, n_samples = 500, warmup = 500, compute_options = gpu_only())
#> running 4 chains simultaneously on up to 8 GPU cores
#> warmup 0/500 | eta: ?s warmup ==== 50/500 | eta: 25s warmup ======== 100/500 | eta: 21s warmup ============ 150/500 | eta: 18s warmup ================ 200/500 | eta: 15s warmup ==================== 250/500 | eta: 12s warmup ======================== 300/500 | eta: 10s warmup ============================ 350/500 | eta: 7s warmup ================================ 400/500 | eta: 5s warmup ==================================== 450/500 | eta: 2s warmup ======================================== 500/500 | eta: 0s
#> sampling 0/500 | eta: ?s sampling ==== 50/500 | eta: 24s sampling ======== 100/500 | eta: 20s sampling ============ 150/500 | eta: 16s sampling ================ 200/500 | eta: 13s sampling ==================== 250/500 | eta: 12s sampling ======================== 300/500 | eta: 10s sampling ============================ 350/500 | eta: 8s sampling ================================ 400/500 | eta: 5s sampling ==================================== 450/500 | eta: 3s sampling ======================================== 500/500 | eta: 0s
toc()
#> 51.845 sec elapsed
Created on 2022-08-10 by the reprex package (v2.0.1)
It might be a bit of a hack, but these two are the relevant commits
https://github.com/greta-dev/greta/pull/534/commits/40b984b9f7c61dc1e2af97d4941e14771436bfc2 https://github.com/greta-dev/greta/pull/534/commits/094a5e5cff3bbd59413d8d361347df472bf13d85
Great! For GPU it shouldn't list the number of CPU cores though. So maybe just put 'on GPU '?
OK, how's this?
library(greta)
#>
#> Attaching package: 'greta'
#> The following objects are masked from 'package:stats':
#>
#> binomial, cov2cor, poisson
#> The following objects are masked from 'package:base':
#>
#> %*%, apply, backsolve, beta, chol2inv, colMeans, colSums, diag,
#> eigen, forwardsolve, gamma, identity, rowMeans, rowSums, sweep,
#> tapply
library(tictoc)
greta_sitrep()
#> ℹ checking if python available
#> ✔ python (v3.8) available
#>
#> ℹ checking if TensorFlow available
#> ✔ TensorFlow (v2.9.2) available
#>
#> ℹ checking if TensorFlow Probability available
#> ✔ TensorFlow Probability (v0.17.0) available
#>
#> ℹ checking if greta conda environment available
#> ✔ greta conda environment available
#>
#> ℹ Initialising python and checking dependencies, this may take a moment.
#> ✔ Initialising python and checking dependencies ... done!
#>
#> ℹ greta is ready to use!
x <- normal(0,1)
m <- model(x)
#> Loaded Tensorflow version 2.9.2
tic()
draws_cpu <- mcmc(m, n_samples = 500, warmup = 500, compute_options = cpu_only())
#> running 4 chains simultaneously on each on up to 8 CPU cores
#>
#> warmup 0/500 | eta: ?s warmup ==== 50/500 | eta: 6s warmup ======== 100/500 | eta: 3s warmup ============ 150/500 | eta: 2s warmup ================ 200/500 | eta: 2s warmup ==================== 250/500 | eta: 1s warmup ======================== 300/500 | eta: 1s warmup ============================ 350/500 | eta: 1s warmup ================================ 400/500 | eta: 0s warmup ==================================== 450/500 | eta: 0s warmup ======================================== 500/500 | eta: 0s
#> sampling 0/500 | eta: ?s sampling ==== 50/500 | eta: 0s sampling ======== 100/500 | eta: 0s sampling ============ 150/500 | eta: 0s sampling ================ 200/500 | eta: 0s sampling ==================== 250/500 | eta: 0s sampling ======================== 300/500 | eta: 0s sampling ============================ 350/500 | eta: 0s sampling ================================ 400/500 | eta: 0s sampling ==================================== 450/500 | eta: 0s sampling ======================================== 500/500 | eta: 0s
toc()
#> 2.798 sec elapsed
tic()
draws_gpu <- mcmc(m, n_samples = 500, warmup = 500, compute_options = gpu_only())
#> running 4 chains simultaneously on GPU
#> warmup 0/500 | eta: ?s warmup ==== 50/500 | eta: 25s warmup ======== 100/500 | eta: 20s warmup ============ 150/500 | eta: 17s warmup ================ 200/500 | eta: 15s warmup ==================== 250/500 | eta: 12s warmup ======================== 300/500 | eta: 10s warmup ============================ 350/500 | eta: 7s warmup ================================ 400/500 | eta: 5s warmup ==================================== 450/500 | eta: 2s warmup ======================================== 500/500 | eta: 0s
#> sampling 0/500 | eta: ?s sampling ==== 50/500 | eta: 22s sampling ======== 100/500 | eta: 19s sampling ============ 150/500 | eta: 16s sampling ================ 200/500 | eta: 13s sampling ==================== 250/500 | eta: 11s sampling ======================== 300/500 | eta: 9s sampling ============================ 350/500 | eta: 7s sampling ================================ 400/500 | eta: 5s sampling ==================================== 450/500 | eta: 2s sampling ======================================== 500/500 | eta: 0s
toc()
#> 47.299 sec elapsed
Created on 2022-08-10 by the reprex package (v2.0.1)
The CPU one is mangled? Should be the same as before. GPU one looks good
Blarg, here we go
library(greta)
#>
#> Attaching package: 'greta'
#> The following objects are masked from 'package:stats':
#>
#> binomial, cov2cor, poisson
#> The following objects are masked from 'package:base':
#>
#> %*%, apply, backsolve, beta, chol2inv, colMeans, colSums, diag,
#> eigen, forwardsolve, gamma, identity, rowMeans, rowSums, sweep,
#> tapply
greta_sitrep()
#> ℹ checking if python available
#> ✔ python (v3.8) available
#>
#> ℹ checking if TensorFlow available
#> ✔ TensorFlow (v2.9.2) available
#>
#> ℹ checking if TensorFlow Probability available
#> ✔ TensorFlow Probability (v0.17.0) available
#>
#> ℹ checking if greta conda environment available
#> ✔ greta conda environment available
#>
#> ℹ Initialising python and checking dependencies, this may take a moment.
#> ✔ Initialising python and checking dependencies ... done!
#>
#> ℹ greta is ready to use!
x <- normal(0,1)
m <- model(x)
#> Loaded Tensorflow version 2.9.2
draws_cpu <- mcmc(m, n_samples = 50, warmup = 50, compute_options = cpu_only())
#> running 4 chains simultaneously each on up to 8 CPU cores
#>
#> warmup 0/50 | eta: ?s warmup ========================================== 50/50 | eta: 0s
#> sampling 0/50 | eta: ?s sampling ========================================== 50/50 | eta: 0s
draws_gpu <- mcmc(m, n_samples = 50, warmup = 50, compute_options = gpu_only())
#> running 4 chains simultaneously on GPU
#> warmup 0/50 | eta: ?s warmup ========================================== 50/50 | eta: 0s
#> sampling 0/50 | eta: ?s sampling ========================================== 50/50 | eta: 0s
Created on 2022-08-10 by the reprex package (v2.0.1)
Sorry Nick, it's not 'each on up to', that's not true, has to be the same as before for CPU
Ack, sorry about that - does this look right?
library(greta)
#>
#> Attaching package: 'greta'
#> The following objects are masked from 'package:stats':
#>
#> binomial, cov2cor, poisson
#> The following objects are masked from 'package:base':
#>
#> %*%, apply, backsolve, beta, chol2inv, colMeans, colSums, diag,
#> eigen, forwardsolve, gamma, identity, rowMeans, rowSums, sweep,
#> tapply
greta_sitrep()
#> ℹ checking if python available
#> ✔ python (v3.8) available
#>
#> ℹ checking if TensorFlow available
#> ✔ TensorFlow (v2.9.2) available
#>
#> ℹ checking if TensorFlow Probability available
#> ✔ TensorFlow Probability (v0.17.0) available
#>
#> ℹ checking if greta conda environment available
#> ✔ greta conda environment available
#>
#> ℹ Initialising python and checking dependencies, this may take a moment.
#> ✔ Initialising python and checking dependencies ... done!
#>
#> ℹ greta is ready to use!
x <- normal(0,1)
m <- model(x)
#> Loaded Tensorflow version 2.9.2
draws_cpu <- mcmc(m, n_samples = 50, warmup = 50, compute_options = cpu_only())
#> running 4 chains simultaneously on up to 8 CPU cores
#>
#> warmup 0/50 | eta: ?s warmup ========================================== 50/50 | eta: 0s
#> sampling 0/50 | eta: ?s sampling ========================================== 50/50 | eta: 0s
draws_gpu <- mcmc(m, n_samples = 50, warmup = 50, compute_options = gpu_only())
#> running 4 chains simultaneously on GPU
#> warmup 0/50 | eta: ?s warmup ========================================== 50/50 | eta: 0s
#> sampling 0/50 | eta: ?s sampling ========================================== 50/50 | eta: 0s
Created on 2022-08-11 by the reprex package (v2.0.1)
That looks right to me! I guess you could check the CPU one against the snapshot?
For the time being we have the interfaces
x <- normal(0,1)
m <- model(x)
draws_cpu <- mcmc(m, n_samples = 50, warmup = 50, compute_options = cpu_only())
draws_gpu <- mcmc(m, n_samples = 50, warmup = 50, compute_options = gpu_only())
But in the future we might explore more complex interfaces discussed by @cboettig and @goldingn here https://github.com/greta-dev/greta/issues/306
As discussed by @goldingn and @cboettig in https://github.com/greta-dev/greta/issues/306
I thought it might be good to have an issue open on this discussion so I can knock it off as a task.
What we require from this are:
The default interface would be something like:
(@goldingn - I'm not sure if we need to specify this for
extra_samples
as well? )Which would have the output:
With the idea being that you could turn on the GPU like so:
And allow for finer grained use like so:
Which would have output like:
To approach this API, I think the first release should probably focus on just getting the
cpu_only()
andgpu_only()
approaches, but that we should design this so we can extend it easily - as Carl and Nick G both said.In terms of order of operations, where's what I think we need:
compute_options
argument formcmc
,calculate
,opt
, andextra_samples
device_used()
(or similar) function which returns the name and type of the current device used - e.g., CPU or GPU. We can use this to capture the device used and then set it up at the end withon.exit()
.cpu_only()
function - uses CPU and returns to default state after operationgpu_only()
function - uses GPU and returns to default state after operationReading https://www.tensorflow.org/guide/gpu
they say:
They also say:
So if we can confirm that CPU and GPU are available, then we can "safely" (I think?) return to using GPU