Skip to content

Commit 212cf3d

Browse files
committed
feat(FR-1448): allow user to select multi agents when creating multi-node session
1 parent 72a98ab commit 212cf3d

27 files changed

+108
-39
lines changed

react/src/components/AgentSelect.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import React, { useDeferredValue, useState } from 'react';
99
import { useTranslation } from 'react-i18next';
1010
import { graphql, useLazyLoadQuery } from 'react-relay';
1111

12-
interface Props extends SelectProps {
12+
interface Props extends Omit<SelectProps, 'options'> {
1313
autoSelectDefault?: boolean;
1414
fetchKey?: string;
1515
resourceGroup?: string | null;
@@ -122,19 +122,33 @@ const AgentSelect: React.FC<Props> = ({
122122
: undefined;
123123
return (
124124
<Select
125-
onChange={(value, option) => {
126-
setValue(value, option);
127-
}}
128125
loading={searchStr !== deferredSearchStr}
129126
filterOption={false}
130127
showSearch
131128
searchValue={searchStr}
132129
onSearch={(v) => {
133130
setSearchStr(v);
134131
}}
135-
{...selectProps}
136-
value={value}
137132
options={filterOutEmpty([autoSelectIfMatch, ...agentOptions])}
133+
//override props.onChange and props.value, it is handled by useControllableValue
134+
{..._.omit(selectProps, ['value', 'onChange'])}
135+
onChange={(value: unknown, option) => {
136+
if (
137+
selectProps.mode === 'multiple' &&
138+
_.isArray(value) &&
139+
_.isArray(option)
140+
) {
141+
if (_.last(value) === 'auto' || value.length === 0) {
142+
value = ['auto'];
143+
option = _.last(option);
144+
} else if (value[0] === 'auto' && value.length > 1) {
145+
value = value.slice(1);
146+
option = option.slice(1);
147+
}
148+
}
149+
setValue(value, option);
150+
}}
151+
value={value}
138152
/>
139153
);
140154
};

react/src/components/SessionFormItems/ResourceAllocationFormItems.tsx

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export const RESOURCE_ALLOCATION_INITIAL_FORM_VALUES: DeepPartial<ResourceAlloca
4646
cluster_mode: 'single-node',
4747
cluster_size: 1,
4848
enabledAutomaticShmem: true,
49-
agent: 'auto',
49+
agent: ['auto'],
5050
};
5151

5252
export const isMinOversMaxValue = (min: number, max: number) => {
@@ -67,7 +67,7 @@ export interface ResourceAllocationFormValue {
6767
cluster_size: number;
6868
enabledAutomaticShmem: boolean;
6969
allocationPreset?: string;
70-
agent?: string;
70+
agent?: string[] | string;
7171
}
7272

7373
export type MergedResourceAllocationFormValue = ResourceAllocationFormValue &
@@ -95,6 +95,7 @@ const ResourceAllocationFormItems: React.FC<
9595
const { token } = theme.useToken();
9696

9797
const baiClient = useSuspendedBackendaiClient();
98+
const supportMultiAgents = baiClient.supports('multi-agents');
9899

99100
const [{ keypairResourcePolicy, sessionLimitAndRemaining }] =
100101
useCurrentKeyPairResourcePolicyLazyLoadQuery();
@@ -1225,22 +1226,40 @@ const ResourceAllocationFormItems: React.FC<
12251226
<Form.Item
12261227
label={t('session.launcher.SelectAgent')}
12271228
required
1228-
tooltip={<Trans i18nKey={'session.launcher.DescSelectAgent'} />}
1229+
tooltip={
1230+
<Trans
1231+
i18nKey={
1232+
supportMultiAgents
1233+
? 'session.launcher.DescSelectAgent'
1234+
: 'session.launcher.DescSelectAgentBefore2516'
1235+
}
1236+
/>
1237+
}
12291238
>
12301239
<BAIFlex gap={'xs'}>
12311240
<Suspense>
12321241
<Form.Item required noStyle style={{ flex: 1 }} name="agent">
12331242
<AgentSelect
12341243
resourceGroup={currentResourceGroupInForm}
12351244
fetchKey={agentFetchKey}
1245+
mode={supportMultiAgents ? 'multiple' : undefined}
1246+
labelRender={
1247+
supportMultiAgents
1248+
? ({ label, value }) => {
1249+
return value === 'auto' ? label : value;
1250+
}
1251+
: undefined
1252+
}
12361253
onChange={(value) => {
1237-
if (value !== 'auto') {
1254+
if (
1255+
!supportMultiAgents &&
1256+
!_.isEqual(_.castArray(value), ['auto'])
1257+
) {
12381258
form.setFieldsValue({
12391259
cluster_mode: 'single-node',
12401260
cluster_size: 1,
12411261
});
12421262
}
1243-
// TODO: set cluster mode to single node and cluster size to 1 when agent value is not "auto"
12441263
}}
12451264
></AgentSelect>
12461265
</Form.Item>
@@ -1286,7 +1305,12 @@ const ResourceAllocationFormItems: React.FC<
12861305
onChange={() => {
12871306
form.validateFields().catch(() => {});
12881307
}}
1289-
disabled={getFieldValue('agent') !== 'auto'}
1308+
disabled={
1309+
!supportMultiAgents &&
1310+
!_.isEqual(_.castArray(getFieldValue('agent')), [
1311+
'auto',
1312+
])
1313+
}
12901314
>
12911315
<Radio.Button value="single-node">
12921316
{t('session.launcher.SingleNode')}
@@ -1351,7 +1375,11 @@ const ResourceAllocationFormItems: React.FC<
13511375
}
13521376
disabled={
13531377
derivedClusterSizeMaxLimit === 1 ||
1354-
getFieldValue('agent') !== 'auto'
1378+
(!supportMultiAgents &&
1379+
!_.isEqual(
1380+
_.castArray(getFieldValue('agent')),
1381+
['auto'],
1382+
))
13551383
}
13561384
sliderProps={{
13571385
marks: {

react/src/components/SessionLauncherPreview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ const SessionLauncherPreview: React.FC<{
523523
{baiClient.supports('agent-select') &&
524524
!baiClient?._config?.hideAgents && (
525525
<Descriptions.Item label={t('session.launcher.AgentNode')}>
526-
{form.getFieldValue('agent') ||
526+
{_.castArray(form.getFieldValue('agent')).join(', ') ||
527527
t('session.launcher.AutoSelect')}
528528
</Descriptions.Item>
529529
)}

react/src/hooks/useStartSession.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,14 @@ export const useStartSession = () => {
255255
// Agent selection (optional)
256256
...(baiClient.supports('agent-select') &&
257257
!baiClient?._config?.hideAgents &&
258-
values.agent !== 'auto'
258+
values.agent !== undefined &&
259+
!_.isEqual(values.agent, ['auto'])
259260
? {
260261
// Filter out undefined values
261-
agent_list: [values.agent].filter(
262-
(agent): agent is string => !!agent,
263-
),
262+
agent_list: _.chain(values.agent)
263+
.castArray()
264+
.filter((agent): agent is string => !!agent)
265+
.value(),
264266
}
265267
: undefined),
266268
},

react/src/pages/SessionLauncherPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1276,7 +1276,7 @@ const SessionLauncherPage = () => {
12761276
command: undefined,
12771277
scheduleDate: undefined,
12781278
},
1279-
agent: 'auto', // Add the missing 'agent' property
1279+
agent: ['auto'], // Add the missing 'agent' property
12801280
} as SessionLauncherFormData,
12811281
formValue,
12821282
);

resources/i18n/de.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1468,7 +1468,8 @@
14681468
"DescMemory": " <p> Der Computerspeicher ist ein temporärer Speicherbereich. </p> <p> Es enthält die Daten und Anweisungen, die die Central Processing Unit (CPU) benötigt. </p> <p> Wenn Sie eine GPU in einem Machine Learning-Workload verwenden, müssen Sie dem Arbeitsspeicher mindestens den doppelten Arbeitsspeicher der GPU zuweisen. Andernfalls erhöht sich die Leerlaufzeit der GPU, was zu einer Leistungseinbuße führt. </p>",
14691469
"DescMultiNode": " <p> Beim Ausführen einer Sitzung werden ein verwalteter Knoten und ein oder mehrere Worker-Knoten auf mehrere physische Knoten oder virtuelle Maschinen aufgeteilt. </p>",
14701470
"DescOpenMPOptimization": "<p>Dieser Wert legt die Anzahl der Threads fest, die für parallele Regionen verwendet werden sollen, indem er den Anfangswert der internen Steuervariablen nthreads-var festlegt.</p><p>Backend.AI setzt diesen Wert gleich der Anzahl der CPU-Kerne, was zur Folge hat, dass typische High-Performance-Computing-Workloads beschleunigt werden. Bei einigen Multi-Thread-Workloads werden jedoch mehrere Prozesse, die OpenMP verwenden, gleichzeitig verwendet, was zu einer abnormal großen Anzahl von Threads und einer erheblichen Leistungsverschlechterung führt. In diesem Fall stellen Sie diesen Wert bitte auf 1 oder 2 ein.</p>>",
1471-
"DescSelectAgent": "Die auf der rechten Seite des Agenten angezeigten Ressourcen stellen die tatsächliche Menge der verfügbaren Ressourcen dar. \nDerzeit ist die Agentenauswahl nur in einer Single-Node-Single-Container-Umgebung verfügbar. \nDie Standardeinstellung ist die Agentenzuteilung durch den Scheduler.",
1471+
"DescSelectAgent": "Die rechts neben einem Agenten angezeigten Ressourcen geben die tatsächlich verfügbaren Mengen an. Ausgewählte Agenten stellen die Kandidaten für eine Zuweisung dar; auch wenn mehrere ausgewählt sind, kann nur einem Agenten zugewiesen werden. Die Standardeinstellung ist die automatische Zuweisung durch den Scheduler.",
1472+
"DescSelectAgentBefore2516": "Die rechts beim Agenten angezeigten Ressourcen entsprechen der tatsächlich verfügbaren Menge. Derzeit ist die Agentenauswahl nur in einer Einzelknoten-/Einzelcontainer-Umgebung verfügbar. Standardmäßig erfolgt die Agentenzuweisung durch den Scheduler.",
14721473
"DescSession": " <p> Eine Sitzung ist eine Einheit einer Rechenumgebung, die gemäß einer bestimmten Umgebung und Ressourcen erstellt wird. </p> <p> Wenn dieser Wert auf einen Wert größer als 1 gesetzt ist, werden mehrere Sitzungen erstellt, die dem oben genannten Ressourcensatz entsprechen. </p> <p> Wenn nicht genügend Ressourcen verfügbar sind, werden Anforderungen zum Erstellen von Sitzungen, die nicht erstellt werden können, in die Warteschlange gestellt. </p>",
14731474
"DescSetEnv": " <p> Wenn Sie eine Standardumgebungsvariable im Container setzen und auch eine Umgebungsvariable mit demselben Namen auf der Backend.AI setzen, hat der auf der Backend.AI festgelegte Wert Vorrang. </p> <p style='color:var(--paper-red-400);'> Jeder Eingabewert wird nach dem Start des Sitzungsstarters initialisiert. <br /> Außerdem werden diese Umgebungen nur übergeben, wenn sowohl die Variable als auch der Wert nicht leer sind. </p>",
14741475
"DescSetPreOpenPort": "Preopen Ports\" bezieht sich auf einen bestimmten <span style='color:var(--paper-red-400);'>internen Container-Port</span>, der eingehende Verbindungen von externen Geräten oder Computern auf einem Netzwerkgerät oder Computer erlaubt.",

resources/i18n/el.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1467,7 +1467,8 @@
14671467
"DescMemory": " <p> Η μνήμη του υπολογιστή είναι μια προσωρινή περιοχή αποθήκευσης. </p> <p> Διατηρεί τα δεδομένα και τις οδηγίες που χρειάζεται η κεντρική μονάδα επεξεργασίας (CPU). </p> <p> Όταν χρησιμοποιείτε GPU σε φόρτο εργασίας μηχανικής εκμάθησης, πρέπει να εκχωρήσετε τουλάχιστον δύο φορές τη μνήμη της GPU στη μνήμη. Διαφορετικά, ο χρόνος αδράνειας της GPU θα αυξηθεί, οδηγώντας σε ποινή απόδοσης. </p>",
14681468
"DescMultiNode": " <p> Κατά την εκτέλεση μιας περιόδου σύνδεσης, ένας διαχειριζόμενος κόμβος και ένας ή περισσότεροι κόμβοι εργαζομένων χωρίζονται σε πολλούς φυσικούς κόμβους ή εικονικές μηχανές. </p>",
14691469
"DescOpenMPOptimization": "<p>Αυτή η τιμή καθορίζει τον αριθμό των νημάτων που θα χρησιμοποιηθούν για τις παράλληλες περιοχές, θέτοντας την αρχική τιμή της εσωτερικής μεταβλητής ελέγχου nthreads-var.</p><p>Το Backend.AI θέτει αυτή την τιμή ίση με τον αριθμό των πυρήνων της CPU, γεγονός που έχει ως αποτέλεσμα την επιτάχυνση τυπικών υπολογιστικών φόρτων εργασίας υψηλών επιδόσεων. Ωστόσο, για ορισμένα φορτία εργασίας με πολλά νήματα, χρησιμοποιούνται ταυτόχρονα πολλές διεργασίες που χρησιμοποιούν OpenMP, με αποτέλεσμα να δημιουργείται ασυνήθιστα μεγάλος αριθμός νημάτων και σημαντική υποβάθμιση των επιδόσεων. Σε αυτή την περίπτωση, παρακαλούμε προσαρμόστε αυτή την τιμή σε 1 ή 2.</p>",
1470-
"DescSelectAgent": "Οι πόροι που εμφανίζονται στη δεξιά πλευρά του πράκτορα αντιπροσωπεύουν την πραγματική ποσότητα των διαθέσιμων πόρων. \nΠρος το παρόν, η επιλογή πράκτορα είναι διαθέσιμη μόνο σε περιβάλλον ενός κοντέινερ ενός κόμβου. \nΗ προεπιλεγμένη ρύθμιση είναι η κατανομή πράκτορα από τον προγραμματιστή.",
1470+
"DescSelectAgent": "Οι πόροι στα δεξιά του agent δείχνουν την πραγματικά διαθέσιμη ποσότητα. Οι επιλεγμένοι agent αντιπροσωπεύουν υποψήφιους προς ανάθεση — ακόμα κι αν επιλεγούν πολλοί, η ανάθεση μπορεί να γίνει μόνο σε έναν agent. Η προεπιλεγμένη ρύθμιση είναι η αυτόματη ανάθεση από τον scheduler.",
1471+
"DescSelectAgentBefore2516": "Οι πόροι που εμφανίζονται στη δεξιά πλευρά του agent αντιπροσωπεύουν την πραγματική ποσότητα διαθέσιμων πόρων. Προς το παρόν, η επιλογή agent είναι διαθέσιμη μόνο σε περιβάλλον με έναν κόμβο και ένα κοντέινερ. Η προεπιλεγμένη ρύθμιση είναι η ανάθεση των agent από τον scheduler.",
14711472
"DescSession": " <p> Η περίοδος σύνδεσης είναι μια μονάδα υπολογιστικού περιβάλλοντος που δημιουργείται σύμφωνα με ένα καθορισμένο περιβάλλον και πόρους. </p> <p> Εάν αυτή η τιμή έχει οριστεί σε μια τιμή μεγαλύτερη από 1, δημιουργούνται πολλές συνεδρίες που αντιστοιχούν στον παραπάνω πόρο. </p> <p> Εάν δεν υπάρχουν αρκετοί διαθέσιμοι πόροι, τα αιτήματα για δημιουργία περιόδων σύνδεσης που δεν μπορούν να δημιουργηθούν τίθενται στην ουρά αναμονής. </p>",
14721473
"DescSetEnv": " <p> Εάν ορίσετε μια προεπιλεγμένη μεταβλητή περιβάλλοντος στο κοντέινερ και επίσης ορίσετε μια μεταβλητή περιβάλλοντος με το ίδιο όνομα στο Backend.AI, υπερισχύει η τιμή που έχει οριστεί στο Backend.AI. </p> <p style='color:var(--paper-red-400);'> Κάθε τιμή εισόδου θα αρχικοποιηθεί μετά την έναρξη της εκκίνησης περιόδου λειτουργίας. <br /> Επίσης, αυτά τα περιβάλλοντα θα περάσουν μόνο αν και η μεταβλητή και η τιμή δεν είναι κενά. </p>",
14731474
"DescSetPreOpenPort": "Οι \"Προανοιχτές θύρες\" αναφέρονται σε μια συγκεκριμένη <span style='color:var(--paper-red-400);'>εσωτερική θύρα εμπορευματοκιβωτίου</span> που επιτρέπει εισερχόμενες συνδέσεις από εξωτερικές συσκευές ή υπολογιστές σε μια συσκευή ή έναν υπολογιστή δικτύου.",

resources/i18n/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,8 @@
14761476
"DescMemory": "<p>Computer memory is a temporary storage area.</p><p>It holds the data and instructions that the Central Processing Unit (CPU) needs.</p><p>When using a GPU in a machine learning workload, you must allocate at least twice the memory of the GPU to memory. Otherwise, the GPU's idle time will increase, resulting in a performance penalty.</p>",
14771477
"DescMultiNode": "<p>When running a session, one managed node and one or more worker nodes are split across multiple physical nodes or virtual machines.</p>",
14781478
"DescOpenMPOptimization": "<p>This value sets the number of threads to use for parallel regions by setting the initial value of the nthreads-var internal control variable.</p><p>Backend.AI sets this value equal to the number of CPU cores, which has the effect of accelerating typical high-performance computing workloads. However, for some multi-threaded workloads, multiple processes using OpenMP are used at the same time, resulting in an abnormally large number of threads and significant performance degradation. In this case, please adjust this value to 1 or 2.</p>",
1479-
"DescSelectAgent": "The resources displayed on the right side of the agent represent the actual amount of available resources. Currently, agent selection is only available in a single-node single-container environment. The default setting is agent allocation by the scheduler.",
1479+
"DescSelectAgent": "The resources shown on the right side of each agent represent the actual available capacity. The selected agents indicate the candidates that can be allocated, and even if multiple agents are selected, the allocation may be made to only one agent. By default, the scheduler automatically handles the allocation.",
1480+
"DescSelectAgentBefore2516": "The resources displayed on the right side of the agent represent the actual amount of available resources. Currently, agent selection is only available in a single-node single-container environment. The default setting is agent allocation by the scheduler.",
14801481
"DescSession": "<p>A session is a unit of computational environment that is created according to a specified environment and resources.</p><p>If this value is set to a value greater than 1, multiple sessions corresponding to the resource set above are created.</p><p>If there are not enough resources available, requests to create sessions that cannot be created are put on the waiting queue.</p>",
14811482
"DescSetEnv": "<p>If you set a default environment variable in the container and also set an environment variable with the same name on the Backend.AI, the value set on the Backend.AI takes precedence.</p><p style='color:var(--paper-red-400);'>Every input value will be initialized after starting session launcher.<br />Also, those environment will be passed only if both variable and value are not empty.</p>",
14821483
"DescSetPreOpenPort": "'Preopen Ports' refers to a specific <span style='color:var(--paper-red-400);'>internal container port</span> that allows incoming connections from external devices or computers on a network device or computer.",

0 commit comments

Comments
 (0)