---
title: "Executing `koma` in Parallel"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{parallel}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
    collapse = TRUE,
    comment = "#>"
)
```

```{r setup}
library(koma)
```

## Introduction

This vignette demonstrates how to use the `future::plan` function to run `koma`
package functions either sequentially or in parallel, depending on your
operating system and other preferences.

For more details, see the [future package documentation](https://CRAN.R-project.org/package=future).

## Preliminaries

Install the `future` and `parallelly` packages:

```{R install-future-parallelly, eval=FALSE}
install.packages("future")
install.packages("parallelly")
```

We will use the simulated data contained in `koma` to illustrate the use of `future::plan`. The setup is the following:

```{R model-setup}
library(koma)

equations <- "consumption ~ gdp + consumption.L(1),
investment ~ investment.L(1),
exports ~ world_gdp + exports.L(1),
imports ~ domestic_demand + imports.L(1),
prices ~ exchange_rate + oil_price + prices.L(1),
interest_rate ~ prices + interest_rate_germany + prices.L(1),
gdp == 0.6*consumption + 0.6*domestic_demand + 0.5*exports - 0.4*imports,
domestic_demand == 0.6*consumption + 0.4*investment"

exogenous_variables <- c("world_gdp", "interest_rate_germany", "exchange_rate", "oil_price")

dates <- list(
    estimation = list(start = c(1996, 1), end = c(2019, 4)),
    forecast = list(start = c(2023, 1), end = c(2023, 4))
)

sys_eq <- system_of_equations(equations, exogenous_variables)

series <- names(small_open_economy)
series <- series[!series %in% c("interest_rate", "interest_rate_germany")]

ts_data <- lapply(series, function(x) {
    as_ets(small_open_economy[[x]],
        series_type = "level", method = "diff_log"
    )
})
names(ts_data) <- series

ts_data$interest_rate <- as_ets(small_open_economy$interest_rate,
    series_type = "rate", method = "none"
)
ts_data$interest_rate_germany <- as_ets(small_open_economy$interest_rate_germany,
    series_type = "rate", method = "none"
)
```

## Sequential Execution

By default, R executes code sequentially. For example:

```{R sequential-exec, eval=FALSE}
estimates <- estimate(ts_data, sys_eq, dates)
```

## Parallel Execution with `future::plan`

To enable parallel execution, you can use `future::plan`. The type of parallel execution depends on your operating system or whether you are running the code on a cluster.

#### Worker Setup
You need to define the number of workers that your parallel job to run on. Here we use all cores except one.

```{R workers, eval=FALSE}
# Get the available workers
workers <- parallelly::availableCores(omit = 1)
```

### Windows

For Windows, you can use **multisession**:

```{R multisession, eval=FALSE}
future::plan("future::multisession", workers = workers)

estimates <- estimate(ts_data, sys_eq, dates)
```

### Linux

On Linux, you can use **multicore** (fork-based, lower overhead):

```{R multicore, eval=FALSE}
future::plan("future::multicore", workers = workers)

estimates <- estimate(ts_data, sys_eq, dates)
```

### macOS

On macOS, **do not use `multicore`**. Apple's Accelerate framework (the BLAS/LAPACK
backend used by `eigen()`) relies on Grand Central Dispatch internally, which is not
fork-safe. Forked workers will segfault with "invalid permissions" inside `eigen()`.

Use **multisession** instead — it spawns fresh R processes rather than forking:

```{R multisession-macos, eval=FALSE}
future::plan("future::multisession", workers = workers)

estimates <- estimate(ts_data, sys_eq, dates)
```
