UNPKG

federer

Version:

Experiments in asynchronous federated learning and decentralized learning

68 lines 2.8 kB
"use strict"; 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