fix(tiny): repaired cuda side-runtime install
Downloaded missing ONNX Runtime CUDA provider sidecars when the compiled tiny-model side runtime is used with PI_TINY_DEVICE=cuda. Preserved actionable CUDA worker diagnostics in tiny-models text output and added focused regression coverage. Fixes #4475
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed Linux x64 `PI_TINY_DEVICE=cuda` tiny-model side runtimes missing ONNX Runtime CUDA provider binaries by repairing the `onnxruntime-node` CUDA sidecar install and preserving actionable CUDA diagnostics in `omp tiny-models download` output ([#4475](https://github.com/can1357/oh-my-pi/issues/4475)).
|
||||
|
||||
## [16.3.4] - 2026-07-03
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -35,12 +35,19 @@ function writeLine(text = ""): void {
|
||||
process.stdout.write(`${text}\n`);
|
||||
}
|
||||
|
||||
const ACTIONABLE_DOWNLOAD_ERROR_LINE = /PI_TINY_|CUDA|cuDNN|cudnn|libcudnn|tiny-title-runtime|onnxruntime-node/i;
|
||||
|
||||
function downloadErrorSummary(error: string | undefined): string | undefined {
|
||||
return error
|
||||
?.split(/\r?\n/)
|
||||
.map(line => line.trim())
|
||||
.find(line => line.length > 0)
|
||||
?.replace(/^Error:\s*/, "");
|
||||
const lines =
|
||||
error
|
||||
?.split(/\r?\n/)
|
||||
.map(line => line.trim().replace(/^Error:\s*/, ""))
|
||||
.filter(line => line.length > 0) ?? [];
|
||||
const first = lines[0];
|
||||
if (!first) return undefined;
|
||||
const details = lines.slice(1).filter(line => ACTIONABLE_DOWNLOAD_ERROR_LINE.test(line));
|
||||
if (details.length === 0) return first;
|
||||
return [first, ...details].join("\n");
|
||||
}
|
||||
|
||||
export function resolveModels(model: string | undefined): TinyLocalModelKey[] {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as fsp from "node:fs/promises";
|
||||
import { createRequire } from "node:module";
|
||||
import * as path from "node:path";
|
||||
import type { ProgressInfo } from "@huggingface/transformers";
|
||||
@@ -27,6 +28,15 @@ import packageJson from "../../package.json" with { type: "json" };
|
||||
|
||||
export const TRANSFORMERS_PACKAGE = "@huggingface/transformers";
|
||||
const COMPILED_TRANSFORMERS_VERSION = process.env.PI_TINY_TRANSFORMERS_VERSION;
|
||||
const ONNX_RUNTIME_NODE_PACKAGE = "onnxruntime-node";
|
||||
const ONNX_RUNTIME_CUDA_INSTALL = "cuda12";
|
||||
const ONNX_RUNTIME_CUDA_PROVIDER_FILES = [
|
||||
"libonnxruntime_providers_cuda.so",
|
||||
"libonnxruntime_providers_shared.so",
|
||||
"libonnxruntime_providers_tensorrt.so",
|
||||
] as const;
|
||||
const LINUX_X64_ONNX_RUNTIME_CUDA_PROVIDER_DIR = path.join("bin", "napi-v6", "linux", "x64");
|
||||
|
||||
const sourceRequire = createRequire(import.meta.url);
|
||||
|
||||
// ── Error serialization ─────────────────────────────────────────────
|
||||
@@ -162,6 +172,82 @@ export async function installSharpStubResolver(runtimeDir: string): Promise<stri
|
||||
return nodeModules;
|
||||
}
|
||||
|
||||
function shouldInstallOnnxRuntimeCudaProviders(device: string | undefined): boolean {
|
||||
return process.platform === "linux" && process.arch === "x64" && device?.trim().toLowerCase() === "cuda";
|
||||
}
|
||||
|
||||
async function missingOnnxRuntimeCudaProviderFiles(binDir: string): Promise<string[]> {
|
||||
const missing: string[] = [];
|
||||
for (const file of ONNX_RUNTIME_CUDA_PROVIDER_FILES) {
|
||||
try {
|
||||
await fsp.access(path.join(binDir, file));
|
||||
} catch {
|
||||
missing.push(file);
|
||||
}
|
||||
}
|
||||
return missing;
|
||||
}
|
||||
|
||||
async function readPipe(stream: ReadableStream<Uint8Array> | null): Promise<string> {
|
||||
if (!stream) return "";
|
||||
return new Response(stream).text();
|
||||
}
|
||||
|
||||
async function installOnnxRuntimeCudaProviders(packageDir: string, runtimeDir: string, binDir: string): Promise<void> {
|
||||
const script = path.join(packageDir, "script", "install.js");
|
||||
try {
|
||||
await fsp.access(script);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`ONNX Runtime CUDA provider binaries are missing from ${binDir}, and ${script} is unavailable. Remove the tiny-model side runtime cache at ${runtimeDir} and retry.`,
|
||||
);
|
||||
}
|
||||
|
||||
const proc = Bun.spawn([process.execPath, script], {
|
||||
cwd: runtimeDir,
|
||||
env: { ...Bun.env, BUN_BE_BUN: "1", ONNXRUNTIME_NODE_INSTALL: ONNX_RUNTIME_CUDA_INSTALL },
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
readPipe(proc.stdout as ReadableStream<Uint8Array> | null),
|
||||
readPipe(proc.stderr as ReadableStream<Uint8Array> | null),
|
||||
proc.exited,
|
||||
]);
|
||||
if (exitCode !== 0) {
|
||||
const output = `${stdout}\n${stderr}`.trim();
|
||||
throw new Error(
|
||||
`Failed to install ONNX Runtime CUDA provider binaries into ${binDir} with ${process.execPath} ${script} (exit ${exitCode}). Remove the tiny-model side runtime cache at ${runtimeDir} and retry with network access. ${output}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repairs the compiled Transformers side runtime when CUDA was requested and
|
||||
* Bun skipped `onnxruntime-node`'s NuGet sidecar install.
|
||||
*/
|
||||
export async function ensureOnnxRuntimeCudaProviders(
|
||||
runtimeDir: string,
|
||||
device = process.env.PI_TINY_DEVICE,
|
||||
): Promise<void> {
|
||||
if (!shouldInstallOnnxRuntimeCudaProviders(device)) return;
|
||||
const nodeModules = path.join(runtimeDir, "node_modules");
|
||||
const manifest = resolveRuntimeModule(nodeModules, `${ONNX_RUNTIME_NODE_PACKAGE}/package.json`);
|
||||
if (!manifest)
|
||||
throw new Error(`Unable to resolve ${ONNX_RUNTIME_NODE_PACKAGE} in compiled runtime at ${nodeModules}`);
|
||||
const packageDir = path.dirname(manifest);
|
||||
const binDir = path.join(packageDir, LINUX_X64_ONNX_RUNTIME_CUDA_PROVIDER_DIR);
|
||||
const missing = await missingOnnxRuntimeCudaProviderFiles(binDir);
|
||||
if (missing.length === 0) return;
|
||||
|
||||
await installOnnxRuntimeCudaProviders(packageDir, runtimeDir, binDir);
|
||||
const stillMissing = await missingOnnxRuntimeCudaProviderFiles(binDir);
|
||||
if (stillMissing.length === 0) return;
|
||||
throw new Error(
|
||||
`ONNX Runtime CUDA provider install completed but ${stillMissing.join(", ")} are still missing from ${binDir}. Remove the tiny-model side runtime cache at ${runtimeDir} and retry.`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a freshly-installed compiled runtime for loading and return the
|
||||
* absolute entrypoint of `packageName` to `require`.
|
||||
@@ -211,6 +297,98 @@ interface ConfigurableTransformers {
|
||||
LogLevel: { ERROR: unknown };
|
||||
}
|
||||
|
||||
export interface TransformersRuntimeMetadata {
|
||||
__ompRuntimeNodeModules?: string;
|
||||
__ompTransformersEntry?: string;
|
||||
}
|
||||
|
||||
function attachTransformersRuntimeMetadata<T extends ConfigurableTransformers>(
|
||||
transformers: T,
|
||||
metadata: TransformersRuntimeMetadata,
|
||||
): T {
|
||||
const runtime = transformers as T & TransformersRuntimeMetadata;
|
||||
runtime.__ompRuntimeNodeModules = metadata.__ompRuntimeNodeModules;
|
||||
runtime.__ompTransformersEntry = metadata.__ompTransformersEntry;
|
||||
return runtime;
|
||||
}
|
||||
|
||||
const TRANSITIVE_CUDA_LIBRARY_RE =
|
||||
/\b(lib(?:cu|nv)[A-Za-z0-9_.+-]*\.so(?:\.[0-9]+)*)\b[^:\n]*:\s*cannot open shared object file/iu;
|
||||
const CUDA_DEVICE_UNAVAILABLE_RE = /\bCUDA failure 100\b|no CUDA-capable device is detected|cudaSetDevice|GPU=-1/iu;
|
||||
|
||||
function cudaDeviceUnavailable(error: unknown): boolean {
|
||||
return CUDA_DEVICE_UNAVAILABLE_RE.test(errorText(error));
|
||||
}
|
||||
|
||||
function missingCudaLibrary(error: unknown): string | undefined {
|
||||
return TRANSITIVE_CUDA_LIBRARY_RE.exec(errorText(error))?.[1];
|
||||
}
|
||||
|
||||
function cudaFailureCause(error: unknown, missingFiles: readonly string[]): string {
|
||||
if (missingFiles.length > 0) return `missing ONNX Runtime CUDA provider file(s): ${missingFiles.join(", ")}`;
|
||||
const missingLibrary = missingCudaLibrary(error);
|
||||
if (missingLibrary) return `${missingLibrary}: cannot open shared object file`;
|
||||
if (cudaDeviceUnavailable(error)) {
|
||||
return "CUDA provider files are present; CUDA runtime reports no CUDA-capable device";
|
||||
}
|
||||
return "CUDA provider files are present; inspect the original ONNX Runtime CUDA error";
|
||||
}
|
||||
|
||||
function cudaFailureHint(error: unknown, missingFiles: readonly string[]): string {
|
||||
if (missingFiles.length > 0) return "reinstall the tiny side runtime with ONNX Runtime postinstall enabled";
|
||||
if (missingCudaLibrary(error)) {
|
||||
return "install the matching CUDA/cuDNN shared libraries and expose them on the dynamic loader path";
|
||||
}
|
||||
if (cudaDeviceUnavailable(error)) {
|
||||
return "make the NVIDIA GPU visible to this process/session, or use providers.tinyModelDevice=default/cpu";
|
||||
}
|
||||
return "check the host CUDA driver, device visibility, and ONNX Runtime CUDA compatibility";
|
||||
}
|
||||
|
||||
function resolveOnnxRuntimePackageDir(metadata: TransformersRuntimeMetadata): string | null {
|
||||
const entry = metadata.__ompTransformersEntry;
|
||||
if (entry) {
|
||||
try {
|
||||
return path.dirname(createRequire(entry).resolve(`${ONNX_RUNTIME_NODE_PACKAGE}/package.json`));
|
||||
} catch {
|
||||
// Fall through to the side-runtime resolver below.
|
||||
}
|
||||
}
|
||||
const nodeModules = metadata.__ompRuntimeNodeModules;
|
||||
if (!nodeModules) return null;
|
||||
const manifest = resolveRuntimeModule(nodeModules, `${ONNX_RUNTIME_NODE_PACKAGE}/package.json`);
|
||||
return manifest ? path.dirname(manifest) : null;
|
||||
}
|
||||
|
||||
export async function formatOnnxRuntimeCudaDiagnostics(
|
||||
metadata: TransformersRuntimeMetadata,
|
||||
requestedDevice: string,
|
||||
error: unknown,
|
||||
): Promise<string | null> {
|
||||
const device = requestedDevice.trim().toLowerCase();
|
||||
if (device !== "cuda" && device !== "gpu" && device !== "auto") return null;
|
||||
if (process.platform !== "linux" || process.arch !== "x64") return null;
|
||||
const packageDir = resolveOnnxRuntimePackageDir(metadata);
|
||||
if (!packageDir) {
|
||||
return [
|
||||
"ONNX Runtime CUDA diagnostics:",
|
||||
` PI_TINY_DEVICE=${requestedDevice} requested CUDAExecutionProvider`,
|
||||
" cause: unable to resolve onnxruntime-node in the tiny-model runtime",
|
||||
].join("\n");
|
||||
}
|
||||
const binDir = path.join(packageDir, LINUX_X64_ONNX_RUNTIME_CUDA_PROVIDER_DIR);
|
||||
const missingFiles = await missingOnnxRuntimeCudaProviderFiles(binDir);
|
||||
const sideRuntime = metadata.__ompRuntimeNodeModules;
|
||||
const lines = [
|
||||
"ONNX Runtime CUDA diagnostics:",
|
||||
` PI_TINY_DEVICE=${requestedDevice} requested CUDAExecutionProvider`,
|
||||
sideRuntime ? ` side runtime: ${sideRuntime}` : ` onnxruntime-node: ${packageDir}`,
|
||||
` cause: ${cudaFailureCause(error, missingFiles)}`,
|
||||
];
|
||||
lines.push(` hint: ${cudaFailureHint(error, missingFiles)}`);
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
function configureTransformers<T extends ConfigurableTransformers>(transformers: T): T {
|
||||
transformers.env.cacheDir = getTinyModelsCacheDir();
|
||||
transformers.env.allowLocalModels = false;
|
||||
@@ -251,7 +429,12 @@ export function loadTransformersRuntime<T extends ConfigurableTransformers, K>(
|
||||
runtimeDir: () => string,
|
||||
): Promise<T> {
|
||||
return holder.load(async () => {
|
||||
if (!isCompiledBinary()) return configureTransformers(sourceRequire(TRANSFORMERS_PACKAGE) as T);
|
||||
if (!isCompiledBinary()) {
|
||||
const entry = sourceRequire.resolve(TRANSFORMERS_PACKAGE);
|
||||
return attachTransformersRuntimeMetadata(configureTransformers(sourceRequire(entry) as T), {
|
||||
__ompTransformersEntry: entry,
|
||||
});
|
||||
}
|
||||
const installedDir = await ensureRuntimeInstalled({
|
||||
runtimeDir: runtimeDir(),
|
||||
install: {
|
||||
@@ -270,8 +453,12 @@ export function loadTransformersRuntime<T extends ConfigurableTransformers, K>(
|
||||
},
|
||||
}),
|
||||
});
|
||||
await ensureOnnxRuntimeCudaProviders(installedDir);
|
||||
const entry = await prepareCompiledRuntime(installedDir, TRANSFORMERS_PACKAGE);
|
||||
const require_ = createRequire(entry);
|
||||
return configureTransformers(require_(entry) as T);
|
||||
return attachTransformersRuntimeMetadata(configureTransformers(require_(entry) as T), {
|
||||
__ompRuntimeNodeModules: path.join(installedDir, "node_modules"),
|
||||
__ompTransformersEntry: entry,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,12 +10,14 @@ import tinyTitleSystemPrompt from "../prompts/system/tiny-title-system.md" with
|
||||
import {
|
||||
errorMessage,
|
||||
errorText,
|
||||
formatOnnxRuntimeCudaDiagnostics,
|
||||
getTransformersVersionSpec,
|
||||
loadTransformersRuntime,
|
||||
MemoizedRuntime,
|
||||
replayCachedReady,
|
||||
sendLog,
|
||||
sendProgress,
|
||||
type TransformersRuntimeMetadata,
|
||||
} from "../subprocess/worker-runtime";
|
||||
import { resolveTinyModelDevicePreference, type TinyModelDevice, tinyModelDeviceLoadOrder } from "./device";
|
||||
import { resolveTinyModelDtypeOverride, type TinyModelDtype } from "./dtype";
|
||||
@@ -39,7 +41,7 @@ const TINY_TITLE_SYSTEM_PROMPT = prompt.render(tinyTitleSystemPrompt);
|
||||
const tinyModelDevicePreference = resolveTinyModelDevicePreference();
|
||||
const tinyModelDtypeOverride = resolveTinyModelDtypeOverride();
|
||||
|
||||
interface TransformersRuntime {
|
||||
interface TransformersRuntime extends TransformersRuntimeMetadata {
|
||||
env: {
|
||||
cacheDir?: string;
|
||||
allowLocalModels?: boolean;
|
||||
@@ -136,6 +138,7 @@ async function loadPipelineWithDeviceFallback(
|
||||
device: devices[0],
|
||||
});
|
||||
}
|
||||
let cudaDiagnostics: string | null = null;
|
||||
for (let i = 0; i < devices.length; i += 1) {
|
||||
const device = devices[i]!;
|
||||
try {
|
||||
@@ -144,15 +147,22 @@ async function loadPipelineWithDeviceFallback(
|
||||
device,
|
||||
};
|
||||
} catch (error) {
|
||||
if (i === devices.length - 1) throw error;
|
||||
const deviceDiagnostics = await formatOnnxRuntimeCudaDiagnostics(transformers, device, error);
|
||||
if (deviceDiagnostics) cudaDiagnostics = deviceDiagnostics;
|
||||
if (i === devices.length - 1) {
|
||||
if (cudaDiagnostics) throw new Error(`${errorText(error)}\n${cudaDiagnostics}`);
|
||||
throw error;
|
||||
}
|
||||
const fallbackDevice = devices[i + 1]!;
|
||||
sendLog(transport, "warn", "tiny-model: accelerated device failed; falling back", {
|
||||
const meta: Record<string, unknown> = {
|
||||
modelKey,
|
||||
repo: spec.repo,
|
||||
device,
|
||||
fallbackDevice,
|
||||
error: errorMessage(error),
|
||||
});
|
||||
};
|
||||
if (deviceDiagnostics) meta.cudaDiagnostics = deviceDiagnostics;
|
||||
sendLog(transport, "warn", "tiny-model: accelerated device failed; falling back", meta);
|
||||
}
|
||||
}
|
||||
throw new Error("No tiny model devices configured");
|
||||
|
||||
@@ -75,4 +75,40 @@ describe("tiny-models download model resolution", () => {
|
||||
|
||||
expect(output.join("")).toContain("Failed to download LFM2 700M: runtime install failed.");
|
||||
});
|
||||
|
||||
it("prints actionable CUDA provider diagnostics from worker errors", async () => {
|
||||
const output: string[] = [];
|
||||
const isTtyDescriptor = Object.getOwnPropertyDescriptor(process.stdout, "isTTY");
|
||||
const diagnostic = [
|
||||
"Error: Failed to load ONNX Runtime CUDA execution provider",
|
||||
"ONNX Runtime CUDA diagnostics:",
|
||||
" PI_TINY_DEVICE=cuda requested CUDAExecutionProvider",
|
||||
" side runtime: /home/user/.omp/cache/tiny-title-runtime/transformers-test/node_modules",
|
||||
" cause: libcudnn.so.9: cannot open shared object file",
|
||||
].join("\n");
|
||||
Object.defineProperty(process.stdout, "isTTY", { configurable: true, value: false });
|
||||
spyOn(process.stdout, "write").mockImplementation((chunk: string | Uint8Array) => {
|
||||
output.push(typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk));
|
||||
return true;
|
||||
});
|
||||
spyOn(tinyTitleClient, "downloadModel").mockResolvedValue({
|
||||
ok: false,
|
||||
error: diagnostic,
|
||||
});
|
||||
|
||||
try {
|
||||
await expect(runTinyModelsCommand({ action: "download", model: "lfm2-700m", flags: {} })).rejects.toThrow(
|
||||
"One or more tiny title models failed to download",
|
||||
);
|
||||
} finally {
|
||||
if (isTtyDescriptor) Object.defineProperty(process.stdout, "isTTY", isTtyDescriptor);
|
||||
else Reflect.deleteProperty(process.stdout, "isTTY");
|
||||
}
|
||||
|
||||
const text = output.join("");
|
||||
expect(text).toContain("Failed to download LFM2 700M:");
|
||||
expect(text).toContain("PI_TINY_DEVICE=cuda");
|
||||
expect(text).toContain("libcudnn.so.9");
|
||||
expect(text).toContain("tiny-title-runtime");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { afterEach, describe, expect, it } from "bun:test";
|
||||
import * as fs from "node:fs/promises";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
import { ensureOnnxRuntimeCudaProviders, formatOnnxRuntimeCudaDiagnostics } from "../src/subprocess/worker-runtime";
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
const CUDA_PROVIDER_FILES = [
|
||||
"libonnxruntime_providers_cuda.so",
|
||||
"libonnxruntime_providers_shared.so",
|
||||
"libonnxruntime_providers_tensorrt.so",
|
||||
];
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(tempDirs.splice(0).map(dir => fs.rm(dir, { recursive: true, force: true })));
|
||||
});
|
||||
|
||||
async function makeRuntimeWithOnnxInstallScript(): Promise<string> {
|
||||
const runtimeDir = await fs.mkdtemp(path.join(os.tmpdir(), "omp-tiny-runtime-install-"));
|
||||
tempDirs.push(runtimeDir);
|
||||
const packageDir = path.join(runtimeDir, "node_modules", "onnxruntime-node");
|
||||
await Bun.write(
|
||||
path.join(packageDir, "package.json"),
|
||||
JSON.stringify({ name: "onnxruntime-node", version: "1.24.3", main: "dist/index.js" }),
|
||||
);
|
||||
await Bun.write(path.join(packageDir, "dist", "index.js"), "module.exports = {};\n");
|
||||
await Bun.write(
|
||||
path.join(packageDir, "script", "install.js"),
|
||||
[
|
||||
"const fs = require('node:fs');",
|
||||
"const path = require('node:path');",
|
||||
"if (process.env.ONNXRUNTIME_NODE_INSTALL !== 'cuda12') process.exit(2);",
|
||||
"const dir = path.join(__dirname, '..', 'bin', 'napi-v6', 'linux', 'x64');",
|
||||
"fs.mkdirSync(dir, { recursive: true });",
|
||||
`for (const file of ${JSON.stringify(CUDA_PROVIDER_FILES)}) fs.writeFileSync(path.join(dir, file), '');`,
|
||||
].join("\n"),
|
||||
);
|
||||
return runtimeDir;
|
||||
}
|
||||
|
||||
describe("tiny runtime CUDA provider repair", () => {
|
||||
it("runs onnxruntime-node's cuda12 installer when compiled runtime sidecars are missing", async () => {
|
||||
if (process.platform !== "linux" || process.arch !== "x64") return;
|
||||
const runtimeDir = await makeRuntimeWithOnnxInstallScript();
|
||||
|
||||
await ensureOnnxRuntimeCudaProviders(runtimeDir, "cuda");
|
||||
|
||||
const binDir = path.join(runtimeDir, "node_modules", "onnxruntime-node", "bin", "napi-v6", "linux", "x64");
|
||||
for (const file of CUDA_PROVIDER_FILES) {
|
||||
expect(await Bun.file(path.join(binDir, file)).exists()).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("reports CUDA device visibility failures after provider sidecars exist", async () => {
|
||||
if (process.platform !== "linux" || process.arch !== "x64") return;
|
||||
const runtimeDir = await makeRuntimeWithOnnxInstallScript();
|
||||
await ensureOnnxRuntimeCudaProviders(runtimeDir, "cuda");
|
||||
|
||||
const diagnostic = await formatOnnxRuntimeCudaDiagnostics(
|
||||
{ __ompRuntimeNodeModules: path.join(runtimeDir, "node_modules") },
|
||||
"cuda",
|
||||
new Error(
|
||||
"CUDA failure 100: no CUDA-capable device is detected ; GPU=-1 ; expr=cudaSetDevice(info_.device_id);",
|
||||
),
|
||||
);
|
||||
|
||||
expect(diagnostic).toContain("CUDA runtime reports no CUDA-capable device");
|
||||
expect(diagnostic).toContain("make the NVIDIA GPU visible to this process/session");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user