LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
fj_respt_bulk.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_FJ_RESPT_BULK_H
6#define LINE_API_FJ_RESPT_BULK_H
7
8/**
9 * @file
10 * @ingroup api_fj
11 * Centralized splitting analysed as an M[K]/M/c bulk arrival system.
12 *
13 * Templated port of matlab/src/api/fj/fj_respt_bulk.m.
14 *
15 * A request forks into K tasks held in a single central queue and served by c
16 * identical servers, so the same server may serve several tasks of the same
17 * request: an M[K]/M/c queue with fixed batch size K. Its level chain is solved
18 * by truncation, which is exact up to the tail mass discarded.
19 *
20 * The request response time is the completion of the LAST of the K tasks. By
21 * PASTA the batch finds n tasks in system, its last task is the (n+K)-th in
22 * line, and under first come first served with c exponential servers it starts
23 * service after max(0, n+K-c) departures, each an exponential of rate c mu:
24 *
25 * E[R_request] = sum_n p_n [ max(0, n+K-c)/(c mu) + 1/mu ].
26 *
27 * This lower bounds the distributed splitting fork-join system, because no task
28 * is bound to a particular server.
29 */
30
31#include <cstddef>
32#include <vector>
33
36#include "line/num/number.h"
37#include "line/util/error.h"
38#include "line/util/matrix.h"
39
40namespace line {
41namespace fj {
42
43/** [Rreq, Rtask, Q, p] of fj_respt_bulk. */
44template <class T>
48 T Q;
49 std::vector<T> p;
50};
51
52/**
53 * @brief Centralized splitting analysed as an M[K]/M/c bulk arrival system.
54 *
55 * @param K batch size, that is the number of tasks per request
56 * @param lambda arrival rate of requests
57 * @param mu per-server task service rate
58 * @param c number of servers
59 * @param nmax truncation level of the task-count chain, 0 for the default
60 * @return the request and task response times, the mean queue and the distribution
61 */
62template <class T>
63FJResptBulkResult<T> fj_respt_bulk(unsigned K, const T& lambda, const T& mu, unsigned c,
64 std::size_t nmax = 0) {
65 detail::require_positive_K(K, "fj_respt_bulk");
66 if (c < 1) throw InputError("fj_respt_bulk: c must be a positive integer");
67 const T zero = num_traits<T>::from_int(0), one = num_traits<T>::from_int(1);
68 if (!(lambda > zero) || !(mu > zero))
69 throw InputError("fj_respt_bulk: lambda and mu must be positive");
70
71 const T Kt = num_traits<T>::from_int(static_cast<long>(K));
72 const T ct = num_traits<T>::from_int(static_cast<long>(c));
73 const T rho = lambda * Kt / (ct * mu);
74 if (rho >= one)
75 throw NumericError("fj_respt_bulk: unstable system, rho = lambda*K/(c*mu) >= 1");
76
77 if (nmax == 0) {
78 const double rd = num_traits<T>::to_double(rho);
79 const double want = static_cast<double>(K) + 40.0 * static_cast<double>(c) / (1.0 - rd);
80 nmax = static_cast<std::size_t>(want > 200.0 ? want : 200.0);
81 }
82 const std::size_t ns = nmax + 1;
83
84 // Generator of the task-count chain: batch arrivals of K, service min(n,c) mu
85 Matrix<T> Q(ns, ns, zero);
86 for (std::size_t i = 0; i < ns; ++i) {
87 if (i > 0) {
88 const std::size_t busy = (i < c) ? i : c;
89 const T srv = num_traits<T>::from_int(static_cast<long>(busy)) * mu;
90 Q(i, i - 1) = Q(i, i - 1) + srv;
91 Q(i, i) = Q(i, i) - srv;
92 }
93 const std::size_t j = i + K;
94 if (j < ns) {
95 Q(i, j) = Q(i, j) + lambda;
96 Q(i, i) = Q(i, i) - lambda;
97 }
98 }
99
101 out.p = mc::ctmc_solve(Q);
102
103 out.Q = zero;
104 for (std::size_t n = 0; n < ns; ++n)
105 out.Q += num_traits<T>::from_int(static_cast<long>(n)) * out.p[n];
106 out.Rtask = out.Q / (lambda * Kt);
107
108 // Last of the K tasks of a tagged batch: the (n+K)-th in line on arrival
109 out.Rreq = zero;
110 for (std::size_t n = 0; n < ns; ++n) {
111 const std::size_t ahead = n + K;
112 const T wait = (ahead > c) ? num_traits<T>::from_int(static_cast<long>(ahead - c)) /
113 (ct * mu)
114 : zero;
115 out.Rreq += out.p[n] * (wait + one / mu);
116 }
117 return out;
118}
119
120} // namespace fj
121} // namespace line
122
123#endif // LINE_API_FJ_RESPT_BULK_H
InputError(const std::string &what)
Definition error.h:39
NumericError(const std::string &what)
Definition error.h:45
Steady-state distribution of a continuous-time Markov chain.
The exception types the port throws.
Shared return types and arithmetic helpers for the templated fork-join port.
Dense matrix and non-owning view.
FJResptBulkResult< T > fj_respt_bulk(unsigned K, const T &lambda, const T &mu, unsigned c, std::size_t nmax=0)
Centralized splitting analysed as an M[K]/M/c bulk arrival system.
std::vector< T > ctmc_solve(const Matrix< T > &Qin)
Steady-state distribution of a continuous-time Markov chain.
Definition ctmc_solve.h:122
Number-type abstraction for the templated API port.
[Rreq, Rtask, Q, p] of fj_respt_bulk.