Skip to content

Commit c871fde

Browse files
authored
Merge pull request #1684 from NeuralFault/win-rocm-onetrainer
feat: Integrate OneTrainer into Windows ROCm Helper [Windows/AMD]
2 parents 3960193 + 4a50834 commit c871fde

3 files changed

Lines changed: 133 additions & 10 deletions

File tree

StabilityMatrix.Core/Helper/Factory/PackageFactory.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ public BasePackage GetNewBasePackage(InstalledPackage installedPackage)
120120
downloadService,
121121
prerequisiteHelper,
122122
pyInstallationManager,
123-
pipWheelService
123+
pipWheelService,
124+
rocmPackageHelper
124125
),
125126
"RuinedFooocus" => new RuinedFooocus(
126127
githubApiCache,

StabilityMatrix.Core/Models/Packages/OneTrainer.cs

Lines changed: 92 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
using StabilityMatrix.Core.Helper.HardwareInfo;
66
using StabilityMatrix.Core.Models.FileInterfaces;
77
using StabilityMatrix.Core.Models.Progress;
8+
using StabilityMatrix.Core.Models.Rocm;
89
using StabilityMatrix.Core.Processes;
910
using StabilityMatrix.Core.Python;
1011
using StabilityMatrix.Core.Services;
12+
using StabilityMatrix.Core.Services.Rocm;
1113

1214
namespace StabilityMatrix.Core.Models.Packages;
1315

@@ -18,7 +20,8 @@ public class OneTrainer(
1820
IDownloadService downloadService,
1921
IPrerequisiteHelper prerequisiteHelper,
2022
IPyInstallationManager pyInstallationManager,
21-
IPipWheelService pipWheelService
23+
IPipWheelService pipWheelService,
24+
IRocmPackageHelper rocmPackageHelper
2225
)
2326
: BaseGitPackage(
2427
githubApi,
@@ -36,7 +39,7 @@ IPipWheelService pipWheelService
3639
"OneTrainer is a one-stop solution for all your stable diffusion training needs";
3740
public override string LicenseType => "AGPL-3.0";
3841
public override string LicenseUrl => "https://github.com/Nerogar/OneTrainer/blob/master/LICENSE.txt";
39-
public override string LaunchCommand => "scripts/train_ui.py";
42+
public override string LaunchCommand => "scripts/train_ui_ctk.py";
4043

4144
public override Uri PreviewImageUri =>
4245
new("https://github.com/Nerogar/OneTrainer/blob/master/resources/icons/icon.png?raw=true");
@@ -52,6 +55,17 @@ IPipWheelService pipWheelService
5255
public override bool ShouldIgnoreReleases => true;
5356
public override IEnumerable<PackagePrerequisite> Prerequisites =>
5457
base.Prerequisites.Concat([PackagePrerequisite.Tkinter]);
58+
public override PyVersion RecommendedPythonVersion => Python.PyInstallationManager.Python_3_12_10;
59+
60+
public override TorchIndex GetRecommendedTorchVersion()
61+
{
62+
if (Compat.IsWindows && rocmPackageHelper.GetCompatibility().IsCompatible)
63+
{
64+
return TorchIndex.Rocm;
65+
}
66+
67+
return base.GetRecommendedTorchVersion();
68+
}
5569

5670
public override async Task InstallPackage(
5771
string installLocation,
@@ -69,17 +83,66 @@ public override async Task InstallPackage(
6983
)
7084
.ConfigureAwait(false);
7185

72-
progress?.Report(new ProgressReport(-1f, "Installing requirements", isIndeterminate: true));
7386
var torchVersion = options.PythonOptions.TorchIndex ?? GetRecommendedTorchVersion();
74-
var requirementsFileName = torchVersion switch
87+
var pyVersion = options.PythonOptions.PythonVersion ?? RecommendedPythonVersion;
88+
89+
// Windows ROCm path
90+
var isWindowsRocm =
91+
Compat.IsWindows
92+
&& torchVersion == TorchIndex.Rocm
93+
&& rocmPackageHelper.GetCompatibility().IsCompatible;
94+
95+
if (isWindowsRocm)
96+
{
97+
var config = rocmPackageHelper.BuildWindowsNativeInstallConfig(
98+
OneTrainerWindowsRocmProfile.Default
99+
);
100+
101+
await StandardPipInstallProcessAsync(
102+
venvRunner,
103+
options,
104+
installedPackage,
105+
config with
106+
{
107+
RequirementsFilePaths = ["requirements-default.txt"],
108+
},
109+
onConsoleOutput,
110+
progress,
111+
cancellationToken
112+
)
113+
.ConfigureAwait(false);
114+
115+
progress?.Report(
116+
new ProgressReport(-1f, "Installing Windows ROCm torch...", isIndeterminate: true)
117+
);
118+
119+
await rocmPackageHelper
120+
.InstallWindowsNativeTorchAsync(
121+
venvRunner,
122+
installedPackage,
123+
OneTrainerWindowsRocmProfile.CreateInstallProfile(pyVersion),
124+
progress,
125+
onConsoleOutput,
126+
cancellationToken
127+
)
128+
.ConfigureAwait(false);
129+
}
130+
else
75131
{
76-
TorchIndex.Cuda => "requirements-cuda.txt",
77-
TorchIndex.Rocm => "requirements-rocm.txt",
78-
_ => "requirements-default.txt",
79-
};
132+
// Original path (CUDA / Linux ROCm)
133+
progress?.Report(new ProgressReport(-1f, "Installing requirements", isIndeterminate: true));
80134

81-
await venvRunner.PipInstall(["-r", requirementsFileName], onConsoleOutput).ConfigureAwait(false);
135+
var requirementsFileName = torchVersion switch
136+
{
137+
TorchIndex.Cuda => "requirements-cuda.txt",
138+
TorchIndex.Rocm => "requirements-rocm.txt",
139+
_ => "requirements-default.txt",
140+
};
82141

142+
await venvRunner.PipInstall(["-r", requirementsFileName], onConsoleOutput).ConfigureAwait(false);
143+
}
144+
145+
// Shared requirements-global.txt (both paths)
83146
var requirementsGlobal = new FilePath(installLocation, "requirements-global.txt");
84147
var pipArgs = new PipInstallArgs().WithParsedFromRequirementsTxt(
85148
(await requirementsGlobal.ReadAllTextAsync(cancellationToken).ConfigureAwait(false)).Replace(
@@ -108,13 +171,33 @@ public override async Task RunPackage(
108171
await SetupVenv(installLocation, pythonVersion: PyVersion.Parse(installedPackage.PythonVersion))
109172
.ConfigureAwait(false);
110173

174+
var selectedTorchIndex = installedPackage.PreferredTorchIndex ?? GetRecommendedTorchVersion();
175+
176+
if (rocmPackageHelper.ShouldApplyWindowsLaunchEnvironment(selectedTorchIndex))
177+
{
178+
VenvRunner.UpdateEnvironmentVariables(env =>
179+
env.SetItems(rocmPackageHelper.BuildLaunchEnvironment(OneTrainerWindowsRocmProfile.Default))
180+
);
181+
}
182+
183+
foreach (var line in GetLaunchNoticeLines(installedPackage))
184+
{
185+
onConsoleOutput?.Invoke(ProcessOutput.FromStdOutLine($"{line}{Environment.NewLine}"));
186+
}
187+
111188
VenvRunner.RunDetached(
112189
[Path.Combine(installLocation, options.Command ?? LaunchCommand), .. options.Arguments],
113190
onConsoleOutput,
114191
OnExit
115192
);
116193
}
117194

195+
private IReadOnlyList<string> GetLaunchNoticeLines(InstalledPackage installedPackage)
196+
{
197+
var selectedTorchIndex = installedPackage.PreferredTorchIndex ?? GetRecommendedTorchVersion();
198+
return rocmPackageHelper.GetWindowsLaunchNoticeLines(selectedTorchIndex);
199+
}
200+
118201
public override List<LaunchOptionDefinition> LaunchOptions => [LaunchOptionDefinition.Extras];
119202
public override Dictionary<SharedFolderType, IReadOnlyList<string>>? SharedFolders { get; }
120203
public override Dictionary<SharedOutputType, IReadOnlyList<string>>? SharedOutputFolders { get; }
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using StabilityMatrix.Core.Models.Packages;
2+
using StabilityMatrix.Core.Python;
3+
4+
namespace StabilityMatrix.Core.Models.Rocm;
5+
6+
/// <summary>
7+
/// Shared Windows ROCm profile for OneTrainer.
8+
/// Python 3.12 only - required by compatible bitsandbytes wheel.
9+
/// </summary>
10+
public class OneTrainerWindowsRocmProfile : RocmPackageProfile
11+
{
12+
public static RocmPackageProfile Default { get; } = new OneTrainerWindowsRocmProfile();
13+
14+
// Restores flop counter functionality requiring triton module
15+
private const string TritonWindowsPackage = "triton-windows";
16+
17+
// Replace upstream bitsandbytes with ROCm-aware bitsandbytes for ROCm Technical Preview on Windows
18+
private const string BitsAndBytesWheelUrl =
19+
"https://github.com/0xDELUXA/bitsandbytes_win_rocm/releases/download/0.50.0.dev0-py3.12-rocm7.15-win_amd64_all/bitsandbytes-0.50.0.dev0-cp312-cp312-win_amd64.whl";
20+
21+
public static RocmPackageProfile CreateInstallProfile(PyVersion pyVersion)
22+
{
23+
if (pyVersion.Major == 3 && pyVersion.Minor == 12)
24+
{
25+
return new RocmPackageProfile
26+
{
27+
InstallConfig = new PipInstallConfig
28+
{
29+
PostTorchInstallPipArgs = [TritonWindowsPackage, BitsAndBytesWheelUrl],
30+
},
31+
};
32+
}
33+
34+
return new RocmPackageProfile
35+
{
36+
InstallConfig = new PipInstallConfig { PostTorchInstallPipArgs = [TritonWindowsPackage] },
37+
};
38+
}
39+
}

0 commit comments

Comments
 (0)