Skip to content

Commit

Permalink
Merge branch 'main' into fix/23-change-mutex-lock-conditionally
Browse files Browse the repository at this point in the history
  • Loading branch information
annereinarz authored Feb 20, 2024
2 parents 552a9cc + fba5caf commit fde5612
Show file tree
Hide file tree
Showing 12 changed files with 305 additions and 343 deletions.
44 changes: 44 additions & 0 deletions clients/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ Note that `webwrite` handles all HTTP statuses internally, and is unable to filt
The Julia integration can be installed using Julia's builtin package manager Pkg

```
import Pkg
Pkg.add("UMBridge")
```

Expand Down Expand Up @@ -519,3 +520,46 @@ The remaining arguments are the stopping tolerance (`1e-5`) and a vectorization
We can notice the total number of model evaluations as `cum#evals=449` in the printout of `greedy2_cross`, and the Tensor-Train rank `max_rank=3`. A neat reduction compared to 1089 points in the full 2D grid!

[Full example sources here.](https://github.com/UM-Bridge/umbridge/blob/main/clients/matlab/ttClient.m)


## Sparse Grids Matlab Kit client

The Sparse Grids Matlab Kit (SGMK) provides a Matlab implementation of sparse grids, and can be used for approximating high-dimensional functions and, in particular, for surrogate-model-based uncertainty quantification; for more info, see the [SGMK website](https://sites.google.com/view/sparse-grids-kit).

The SGMK integrates in a very straightforward way with the Matlab UM-Bridge client (it literally takes 1 line!), see e.g. the script [sgmkClient.m](https://github.com/UM-Bridge/umbridge/blob/main/clients/matlab/sgmkClient.m) that can be found in the folder [clients/matlab](https://github.com/UM-Bridge/umbridge/blob/main/clients/matlab).

The script begins by checking whether the SGMK is already in our path, and if not downloads it from the Github repo [here](https://github.com/lorenzo-tamellini/sparse-grids-matlab-kit) and adds it to the path:
```matlab
check_sgmk()
```
The goal of this simple script is to use the SGMK as a high-dimensional quadrature tool to compute the integral of the posterior density function (pdf) defined in the benchmark **analytic-gaussian-mixture**. The pdf in the benchmark is actually not normalized so the integral should be around 3.

To this end, create a model as before:
```matlab
uri = 'http://localhost:4243';
model = HTTPModel(uri, 'posterior','webwrite');
```
then simply wrap `model.evaluate()` in an `@-function` and **you're done**!
```matlab
f = @(y) model.evaluate(y);
```
The script then goes on creating a sparse grid and evaluating `f` over the sparse grid points:
```matlab
N=2;
w=7;
domain = [-5.5 -5;
5 5.5];
knots = {@(n) knots_CC(n,domain(1,1),domain(2,1),'nonprob'), @(n) knots_CC(n,domain(1,2),domain(2,2),'nonprob')};
S = create_sparse_grid(N,w,knots,@lev2knots_doubling);
Sr = reduce_sparse_grid(S);
f_evals = evaluate_on_sparse_grid(f,Sr);
```
and finally, computing the integral given the values of `f` just obtained. Note that the values returned by the container and stored in `f_evals` are actually the log-posterior, so we need to take their exponent before computing the integral:
```matlab
Ev = quadrature_on_sparse_grid(exp(f_evals),Sr)
```
which indeed returns `Ev = 2.9948`, i.e., close to 3 as expected. The script then ends by plotting the sparse grids interpolant of `f` and of `exp(f)`.

[Full example sources here.](https://github.com/UM-Bridge/umbridge/blob/main/clients/matlab/sgmkClient.m)


43 changes: 28 additions & 15 deletions clients/matlab/sgmkClient.m
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
clear


% Analytic-Banana benchmark. Use the sparse grids matlab kit as a high-dimensional quadrature tool to compute the
% integral of the posterior density defined in the benchmark. The problem is a bit challenging so even a poor result is
% ok, this is just for testing the client. The pdfs in the benchmark are not normalized so the integral should be
% Analytic-gaussian-mixture. Use the sparse grids matlab kit as a high-dimensional quadrature tool to compute the
% integral of the posterior density function (pdf) defined in the benchmark. The problem is a bit challenging so even a poor result is
% ok, this is just for testing the client. The pdfs in the benchmark is not normalized so the integral should be
% around 3

% add the Sparse Grids Matlab Kit and umbridge to your path
% add the Sparse Grids Matlab Kit to your path
check_sgmk()
% run these commands too if you haven't umbridge in your path
% currdir = pwd;
% cd ../../matlab/
% addpath(genpath(pwd))
% cd(currdir)

% also, start the Analytic-gaussian-mixture container
% sudo docker run -it -p 4243:4243 linusseelinger/benchmark-analytic-gaussian-mixture

% uri of the service running the server
uri = 'http://localhost:4243';

% HTTPModel is an object provided by the UM-Bridge Matlab client.
% model = HTTPModel(uri, 'posterior');
model = HTTPModel(uri, 'posterior','webwrite');
model = HTTPModel(uri, 'posterior','webwrite'); % let's use webwrite, it's much faster

% model.evaluate(y) sends a request to the server to evaluate the model at y. Wrap it in an @-function:
f = @(y) model.evaluate(y);
Expand All @@ -26,17 +33,23 @@
% as a column, so that
% D = [a c ;
% b d ];
domain = [-5 -5;
5 5];
knots={@(n) knots_CC(n,domain(1,1),domain(2,1),'nonprob'), @(n) knots_CC(n,domain(1,2),domain(2,2),'nonprob')};
S=create_sparse_grid(N,w,knots,@lev2knots_doubling);
Sr=reduce_sparse_grid(S);
f_evals=evaluate_on_sparse_grid(f,Sr);

% from here on, do whatever UQ analysis you want with the values contained in f_evals
domain = [-5.5 -5;
5 5.5];
knots = {@(n) knots_CC(n,domain(1,1),domain(2,1),'nonprob'), @(n) knots_CC(n,domain(1,2),domain(2,2),'nonprob')};
S = create_sparse_grid(N,w,knots,@lev2knots_doubling);
Sr = reduce_sparse_grid(S);
f_evals = evaluate_on_sparse_grid(f,Sr);

% from here on, do whatever UQ analysis you want with the values contained in f_evals. Here we just check that
% the pdf integrates to 3 (the benchmark is not normalized). Note that the values returned by the container
% and stored in f_evals are actually the log-posterior, so we need to take their exponent before computing the integral

Ev = quadrature_on_sparse_grid(exp(f_evals),Sr)


% We also plot the sparse grids interpolant of the function in the benchmark
figure
plot_sparse_grids_interpolant(S,Sr,domain,exp(f_evals),'nb_plot_pts',80)
figure
plot_sparse_grids_interpolant(S,Sr,domain,f_evals,'with_f_values')

Ev = quadrature_on_sparse_grid(exp(f_evals),Sr)
50 changes: 37 additions & 13 deletions hpc/LoadBalancer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,43 @@ void create_directory_if_not_existing(std::string directory) {
}
}

void clear_url(std::string directory) {
for (auto& file : std::filesystem::directory_iterator(directory)) {
if (std::regex_match(file.path().filename().string(), std::regex("url-\\d+\\.txt"))) {
std::filesystem::remove(file);
}
}
}

std::string get_hostname() {
char hostname[HOST_NAME_MAX];
gethostname(hostname, HOST_NAME_MAX);
return std::string(hostname);
}

void launch_hq_with_alloc_queue() {
std::system("hq server stop &> /dev/null");

std::system("hq server start &");
sleep(1); // Workaround: give the HQ server enough time to start.

// Create HQ allocation queue
std::system("hq_scripts/allocation_queue.sh");
}

const std::vector<std::string> get_model_names() {
HyperQueueJob hq_job("", false); // Don't start a client.

return umbridge::SupportedModels(hq_job.server_url);
}

int main(int argc, char *argv[])
{

create_directory_if_not_existing("urls");
create_directory_if_not_existing("sub-jobs");
clear_url("urls");

launch_hq_with_alloc_queue();

// Read environment variables for configuration
char const *port_cstr = std::getenv("PORT");
Expand All @@ -41,15 +67,15 @@ int main(int argc, char *argv[])
port = atoi(port_cstr);
}

// Start: Instaltialize multiple LB classes for multiple models on the regular server
char const *delay_cstr = std::getenv("HQ_SUBMIT_DELAY_MS");
if (delay_cstr != NULL)
{
hq_submit_delay_ms = atoi(delay_cstr);
}
std::cout << "HQ_SUBMIT_DELAY_MS set to " << hq_submit_delay_ms << std::endl;

// start a SLURM job for single request
const std::string job_id = submitJob("sbatch model.slurm");
const std::string server_url = readUrl("./urls/url-" + job_id + ".txt"); // read server url from txt file
// May use $SLURM_LOCALID in a .slurm file later
std::cout << "Hosting sub-server at : " << server_url << std::endl;
// List supported models
std::vector<std::string> model_names = umbridge::SupportedModels(server_url);
// Initialize load balancer for each available model on the model server.
const std::vector<std::string> model_names = get_model_names();

std::vector<LoadBalancer> LB_vector;
for (auto model_name : model_names)
Expand All @@ -58,14 +84,12 @@ int main(int argc, char *argv[])
LB_vector.emplace_back(LoadBalancer{model_name});
}

// End: Instaltialize multiple LB classes for multiple models on the regular server

// Create a new vector of pointers to LB_vector
// umbridge::serveModels currently only accepts raw pointers.
std::vector<umbridge::Model *> LB_ptr_vector(LB_vector.size());
std::transform(LB_vector.begin(), LB_vector.end(), LB_ptr_vector.begin(),
[](LoadBalancer& obj) { return &obj; });

std::cout << "Load balancer running on host " << get_hostname()
<< " and bound to 0.0.0.0:" << port << std::endl;
umbridge::serveModels(LB_ptr_vector, "0.0.0.0", port, false);
}
}
Loading

0 comments on commit fde5612

Please sign in to comment.