federer
Version:
Experiments in asynchronous federated learning and decentralized learning
68 lines • 2.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getClientDelays = void 0;
const assert = require("assert");
const common_1 = require("../common");
/**
* Converts a {@link CoordinatorClientDelayOptions} configuration to a list of
* delays that the clients should use.
*/
function getClientDelays(options, numberClients) {
assert(numberClients > 0);
checkOptions(options, numberClients);
switch (options.type) {
case "none":
return new Array(numberClients).fill(0);
case "delay-groups":
return getDelayGroupsClientDelays(options, numberClients);
}
}
exports.getClientDelays = getClientDelays;
/**
* Checks that options are valid. Returns true if valid, throws an error if not.
*
* @note
* Returning `true` is a trick to get the type checker to verify that all cases
* have been covered.
*/
function checkOptions(options, numberClients) {
switch (options.type) {
case "none":
return true;
case "delay-groups":
return checkDelayGroupsOptions(options, numberClients);
}
}
function getDelayGroupsClientDelays(options, numberClients) {
// We round the values in the cumulative sum to 10 digits after the decimal
// point. This is because of the imprecision of floats (e.g. 0.1 + 0.2
// = 0.30000000000000004), which may give unexpected results. We don't expect
// users to ever give a fraction precise to 10 digits after the decimal point,
// so we do not expect this "hack" to give unexpected results.
const cumulativeFractions = common_1.cumulativeSum(options.groups.map((entry) => entry.fraction)).map((val) => Math.round(val * 1e10) / 1e10);
let entryIndex = 0;
const result = [];
for (let i = 0; i < numberClients; ++i) {
const fraction = i / numberClients;
if (fraction >= cumulativeFractions[entryIndex]) {
entryIndex++;
}
result.push(options.groups[entryIndex].delay);
}
return result;
}
function checkDelayGroupsOptions(options, numberClients) {
assert(options.groups.length >= 1);
let sumSplits = 0;
for (const { fraction, delay } of options.groups) {
assert(fraction > 0);
assert(fraction <= 1);
assert(fraction >= 1 / numberClients, `The delay group with a delay of ${delay} ms was assigned to a ${fraction} fraction of all nodes, ` +
`but the minimum value for the fraction of clients with a given delay is 1 / numberClients = ${1 / numberClients}. The reason for this is that groups with a fraction lower than that would not include any clients.`);
assert(delay >= 0);
sumSplits += fraction;
}
assert.strictEqual(sumSplits, 1);
return true;
}
//# sourceMappingURL=delays.js.map