acprof 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acprof/__init__.py +3 -0
- acprof/__main__.py +5 -0
- acprof/_bundle/.dockerignore +20 -0
- acprof/_bundle/LICENSE +202 -0
- acprof/_bundle/NOTICE +43 -0
- acprof/_bundle/acprof/__init__.py +3 -0
- acprof/_bundle/acprof/__main__.py +5 -0
- acprof/_bundle/acprof/analysis/__init__.py +1 -0
- acprof/_bundle/acprof/analysis/audit.py +276 -0
- acprof/_bundle/acprof/analysis/comparison.py +364 -0
- acprof/_bundle/acprof/analysis/compatibility.py +223 -0
- acprof/_bundle/acprof/analysis/conditions.py +185 -0
- acprof/_bundle/acprof/analysis/independent_comparison.py +191 -0
- acprof/_bundle/acprof/analysis/latency_model.py +1106 -0
- acprof/_bundle/acprof/analysis/latency_report.py +577 -0
- acprof/_bundle/acprof/analysis/model.py +276 -0
- acprof/_bundle/acprof/analysis/precision.py +51 -0
- acprof/_bundle/acprof/analysis/uncertainty.py +144 -0
- acprof/_bundle/acprof/application/__init__.py +1 -0
- acprof/_bundle/acprof/application/download.py +14 -0
- acprof/_bundle/acprof/application/errors.py +5 -0
- acprof/_bundle/acprof/application/notifications.py +302 -0
- acprof/_bundle/acprof/application/preparation.py +333 -0
- acprof/_bundle/acprof/application/resources.py +66 -0
- acprof/_bundle/acprof/application/run.py +462 -0
- acprof/_bundle/acprof/application/terminal_log.py +136 -0
- acprof/_bundle/acprof/artifact_layout.py +261 -0
- acprof/_bundle/acprof/artifacts.py +161 -0
- acprof/_bundle/acprof/capabilities.py +404 -0
- acprof/_bundle/acprof/cli/__init__.py +1 -0
- acprof/_bundle/acprof/cli/audit.py +74 -0
- acprof/_bundle/acprof/cli/auto.py +41 -0
- acprof/_bundle/acprof/cli/backfill_compute.py +498 -0
- acprof/_bundle/acprof/cli/compare.py +34 -0
- acprof/_bundle/acprof/cli/coverage.py +70 -0
- acprof/_bundle/acprof/cli/doctor.py +47 -0
- acprof/_bundle/acprof/cli/inspect.py +101 -0
- acprof/_bundle/acprof/cli/load.py +190 -0
- acprof/_bundle/acprof/cli/main.py +64 -0
- acprof/_bundle/acprof/cli/model_store.py +22 -0
- acprof/_bundle/acprof/cli/plot.py +211 -0
- acprof/_bundle/acprof/cli/posthoc.py +113 -0
- acprof/_bundle/acprof/cli/probe.py +186 -0
- acprof/_bundle/acprof/cli/report.py +35 -0
- acprof/_bundle/acprof/cli/results.py +37 -0
- acprof/_bundle/acprof/cli/run.py +54 -0
- acprof/_bundle/acprof/cli/stats.py +94 -0
- acprof/_bundle/acprof/cli/tui.py +65 -0
- acprof/_bundle/acprof/config.py +177 -0
- acprof/_bundle/acprof/container/__init__.py +1 -0
- acprof/_bundle/acprof/container/compat/__init__.py +1 -0
- acprof/_bundle/acprof/container/compat/transformers_dynamic.py +54 -0
- acprof/_bundle/acprof/container/compat/transformers_model_types.json +1091 -0
- acprof/_bundle/acprof/container/compute_profile_runner.py +392 -0
- acprof/_bundle/acprof/container/download_model.py +165 -0
- acprof/_bundle/acprof/container/execution.py +73 -0
- acprof/_bundle/acprof/container/handlers/__init__.py +298 -0
- acprof/_bundle/acprof/container/handlers/audio.py +743 -0
- acprof/_bundle/acprof/container/handlers/custom_pipeline.py +74 -0
- acprof/_bundle/acprof/container/handlers/cv.py +321 -0
- acprof/_bundle/acprof/container/handlers/diffusion.py +728 -0
- acprof/_bundle/acprof/container/handlers/moss.py +64 -0
- acprof/_bundle/acprof/container/handlers/multimodal.py +609 -0
- acprof/_bundle/acprof/container/handlers/nlp.py +747 -0
- acprof/_bundle/acprof/container/handlers/onnx_tasks.py +231 -0
- acprof/_bundle/acprof/container/handlers/onnxruntime.py +90 -0
- acprof/_bundle/acprof/container/handlers/structured.py +185 -0
- acprof/_bundle/acprof/container/handlers/timeseries.py +178 -0
- acprof/_bundle/acprof/container/load_policy.py +81 -0
- acprof/_bundle/acprof/container/loading_quality.py +48 -0
- acprof/_bundle/acprof/container/local_pipeline.py +31 -0
- acprof/_bundle/acprof/container/model_files.py +280 -0
- acprof/_bundle/acprof/container/model_probe.py +80 -0
- acprof/_bundle/acprof/container/onnx_session.py +150 -0
- acprof/_bundle/acprof/container/runtime_manifest.py +150 -0
- acprof/_bundle/acprof/container/runtime_validate.py +156 -0
- acprof/_bundle/acprof/container/server.py +209 -0
- acprof/_bundle/acprof/container/torch_execution.py +55 -0
- acprof/_bundle/acprof/container/validation.py +172 -0
- acprof/_bundle/acprof/cpu_affinity.py +35 -0
- acprof/_bundle/acprof/dependency_locks.py +129 -0
- acprof/_bundle/acprof/experiment.py +356 -0
- acprof/_bundle/acprof/extensions/__init__.py +294 -0
- acprof/_bundle/acprof/extensions/builtin/manifest.json +3591 -0
- acprof/_bundle/acprof/extensions/onnxruntime/manifest.json +191 -0
- acprof/_bundle/acprof/extensions/schema.py +238 -0
- acprof/_bundle/acprof/extensions/transformers/4.57.6.json +1639 -0
- acprof/_bundle/acprof/extensions/transformers/5.10.4.json +1812 -0
- acprof/_bundle/acprof/failures.py +115 -0
- acprof/_bundle/acprof/hardware_conditions.py +18 -0
- acprof/_bundle/acprof/hf_download.py +143 -0
- acprof/_bundle/acprof/hf_endpoints.py +62 -0
- acprof/_bundle/acprof/hf_transport.py +238 -0
- acprof/_bundle/acprof/host/__init__.py +1 -0
- acprof/_bundle/acprof/host/automation.py +161 -0
- acprof/_bundle/acprof/host/client.py +520 -0
- acprof/_bundle/acprof/host/collection_history.py +77 -0
- acprof/_bundle/acprof/host/collection_workflow.py +285 -0
- acprof/_bundle/acprof/host/command.py +119 -0
- acprof/_bundle/acprof/host/container_lifecycle.py +225 -0
- acprof/_bundle/acprof/host/container_state.py +128 -0
- acprof/_bundle/acprof/host/coverage_state.py +259 -0
- acprof/_bundle/acprof/host/detect.py +669 -0
- acprof/_bundle/acprof/host/docker_runtime.py +359 -0
- acprof/_bundle/acprof/host/doctor.py +158 -0
- acprof/_bundle/acprof/host/env_utils.py +233 -0
- acprof/_bundle/acprof/host/execution_conditions.py +87 -0
- acprof/_bundle/acprof/host/gpu_device.py +66 -0
- acprof/_bundle/acprof/host/hardware_conditions.py +130 -0
- acprof/_bundle/acprof/host/images/__init__.py +1 -0
- acprof/_bundle/acprof/host/images/dependencies.py +169 -0
- acprof/_bundle/acprof/host/images/environment.py +313 -0
- acprof/_bundle/acprof/host/images/graph.py +143 -0
- acprof/_bundle/acprof/host/images/identity.py +6 -0
- acprof/_bundle/acprof/host/images/inventory.py +445 -0
- acprof/_bundle/acprof/host/images/runtime.py +457 -0
- acprof/_bundle/acprof/host/images/scan.py +154 -0
- acprof/_bundle/acprof/host/input_plan.py +1056 -0
- acprof/_bundle/acprof/host/interface_probe.py +141 -0
- acprof/_bundle/acprof/host/largest_scale_probe.py +566 -0
- acprof/_bundle/acprof/host/matrix_plan.py +98 -0
- acprof/_bundle/acprof/host/measurement/__init__.py +1 -0
- acprof/_bundle/acprof/host/measurement/boundary.py +162 -0
- acprof/_bundle/acprof/host/measurement/capture.py +139 -0
- acprof/_bundle/acprof/host/measurement/checkpoint.py +275 -0
- acprof/_bundle/acprof/host/measurement/config.py +212 -0
- acprof/_bundle/acprof/host/measurement/diagnostics.py +247 -0
- acprof/_bundle/acprof/host/measurement/energy_validation.py +172 -0
- acprof/_bundle/acprof/host/measurement/errors.py +25 -0
- acprof/_bundle/acprof/host/measurement/execution.py +396 -0
- acprof/_bundle/acprof/host/measurement/load.py +237 -0
- acprof/_bundle/acprof/host/measurement/metrics.py +975 -0
- acprof/_bundle/acprof/host/measurement/monitors.py +143 -0
- acprof/_bundle/acprof/host/measurement/publication.py +171 -0
- acprof/_bundle/acprof/host/measurement/requests.py +97 -0
- acprof/_bundle/acprof/host/measurement/types.py +82 -0
- acprof/_bundle/acprof/host/model_coverage.py +337 -0
- acprof/_bundle/acprof/host/model_errors.py +116 -0
- acprof/_bundle/acprof/host/model_inspection.py +107 -0
- acprof/_bundle/acprof/host/model_schema.py +35 -0
- acprof/_bundle/acprof/host/model_store.py +733 -0
- acprof/_bundle/acprof/host/network_preflight.py +229 -0
- acprof/_bundle/acprof/host/orchestrator.py +1133 -0
- acprof/_bundle/acprof/host/permissions.py +117 -0
- acprof/_bundle/acprof/host/platform_metadata.py +63 -0
- acprof/_bundle/acprof/host/posthoc/__init__.py +12 -0
- acprof/_bundle/acprof/host/posthoc/backfill.py +415 -0
- acprof/_bundle/acprof/host/posthoc/context.py +400 -0
- acprof/_bundle/acprof/host/posthoc/plans.py +597 -0
- acprof/_bundle/acprof/host/posthoc/service.py +303 -0
- acprof/_bundle/acprof/host/posthoc/storage.py +491 -0
- acprof/_bundle/acprof/host/preflight.py +370 -0
- acprof/_bundle/acprof/host/profiling/__init__.py +1 -0
- acprof/_bundle/acprof/host/profiling/compute.py +436 -0
- acprof/_bundle/acprof/host/profiling/compute_plan.py +261 -0
- acprof/_bundle/acprof/host/profiling/execution.py +547 -0
- acprof/_bundle/acprof/host/profiling/execution_plan.py +576 -0
- acprof/_bundle/acprof/host/profiling/progress.py +83 -0
- acprof/_bundle/acprof/host/profiling/support.py +252 -0
- acprof/_bundle/acprof/host/profiling/tools/__init__.py +1 -0
- acprof/_bundle/acprof/host/profiling/tools/advisor.py +164 -0
- acprof/_bundle/acprof/host/profiling/tools/compute_parsers.py +409 -0
- acprof/_bundle/acprof/host/profiling/tools/execution_environment.py +135 -0
- acprof/_bundle/acprof/host/profiling/tools/execution_parsers.py +364 -0
- acprof/_bundle/acprof/host/profiling/tools/massif.py +418 -0
- acprof/_bundle/acprof/host/profiling/tools/ncu.py +696 -0
- acprof/_bundle/acprof/host/profiling/tools/nsys.py +326 -0
- acprof/_bundle/acprof/host/profiling/tools/tool_discovery.py +229 -0
- acprof/_bundle/acprof/host/profiling/tools/torch.py +158 -0
- acprof/_bundle/acprof/host/result_cleanup.py +65 -0
- acprof/_bundle/acprof/host/run_state.py +639 -0
- acprof/_bundle/acprof/host/runtime_settings.py +10 -0
- acprof/_bundle/acprof/host/runtime_validation.py +302 -0
- acprof/_bundle/acprof/host/source_bundle.py +96 -0
- acprof/_bundle/acprof/host/startup_probe.py +95 -0
- acprof/_bundle/acprof/host/static_metadata.py +936 -0
- acprof/_bundle/acprof/host/task_support.py +121 -0
- acprof/_bundle/acprof/installation.py +26 -0
- acprof/_bundle/acprof/latency_slo.py +62 -0
- acprof/_bundle/acprof/messages.py +26 -0
- acprof/_bundle/acprof/metric_registry.py +315 -0
- acprof/_bundle/acprof/model_candidates.py +297 -0
- acprof/_bundle/acprof/model_contract.py +234 -0
- acprof/_bundle/acprof/model_dependencies.py +93 -0
- acprof/_bundle/acprof/model_dependency_domain.py +45 -0
- acprof/_bundle/acprof/model_dependency_eval.py +438 -0
- acprof/_bundle/acprof/model_dependency_flow.py +200 -0
- acprof/_bundle/acprof/model_evidence.py +115 -0
- acprof/_bundle/acprof/model_metadata_analysis.py +156 -0
- acprof/_bundle/acprof/model_repository.py +149 -0
- acprof/_bundle/acprof/model_resolution.py +129 -0
- acprof/_bundle/acprof/model_review.py +155 -0
- acprof/_bundle/acprof/model_source_analysis.py +299 -0
- acprof/_bundle/acprof/model_spec.py +204 -0
- acprof/_bundle/acprof/model_support.py +105 -0
- acprof/_bundle/acprof/model_transforms.py +81 -0
- acprof/_bundle/acprof/monitors/__init__.py +1 -0
- acprof/_bundle/acprof/monitors/common.py +63 -0
- acprof/_bundle/acprof/monitors/energy_cpu.py +651 -0
- acprof/_bundle/acprof/monitors/energy_nvml.py +381 -0
- acprof/_bundle/acprof/monitors/gpu_metrics.py +123 -0
- acprof/_bundle/acprof/monitors/interfaces.py +74 -0
- acprof/_bundle/acprof/monitors/perf_mips.py +617 -0
- acprof/_bundle/acprof/monitors/rapl_topology.py +100 -0
- acprof/_bundle/acprof/monitors/resource_metrics.py +472 -0
- acprof/_bundle/acprof/monitors/resource_readers.py +435 -0
- acprof/_bundle/acprof/monitors/resource_usage.py +450 -0
- acprof/_bundle/acprof/monitors/sampling.py +79 -0
- acprof/_bundle/acprof/network_policy.py +182 -0
- acprof/_bundle/acprof/notifications.py +279 -0
- acprof/_bundle/acprof/packet/__init__.py +1 -0
- acprof/_bundle/acprof/packet/merge_packet_latency.py +369 -0
- acprof/_bundle/acprof/packet/sniff_parse_pcap.py +240 -0
- acprof/_bundle/acprof/pixel_metrics.py +103 -0
- acprof/_bundle/acprof/platform.py +180 -0
- acprof/_bundle/acprof/plotting/__init__.py +1 -0
- acprof/_bundle/acprof/plotting/config.py +487 -0
- acprof/_bundle/acprof/plotting/data.py +236 -0
- acprof/_bundle/acprof/plotting/diagnostics.py +747 -0
- acprof/_bundle/acprof/plotting/latency.py +638 -0
- acprof/_bundle/acprof/plotting/metrics.py +648 -0
- acprof/_bundle/acprof/plotting/plotly-LICENSE.txt +21 -0
- acprof/_bundle/acprof/plotting/report.py +66 -0
- acprof/_bundle/acprof/plotting/styles.py +111 -0
- acprof/_bundle/acprof/precision.py +42 -0
- acprof/_bundle/acprof/preparation_events.py +78 -0
- acprof/_bundle/acprof/progress_events.py +105 -0
- acprof/_bundle/acprof/quality.py +153 -0
- acprof/_bundle/acprof/resource_budget.py +29 -0
- acprof/_bundle/acprof/result_csv.py +263 -0
- acprof/_bundle/acprof/result_layers.py +365 -0
- acprof/_bundle/acprof/run_args.py +223 -0
- acprof/_bundle/acprof/run_options.py +225 -0
- acprof/_bundle/acprof/runtime_dependencies.py +195 -0
- acprof/_bundle/acprof/runtime_profiles.py +258 -0
- acprof/_bundle/acprof/runtime_settings.py +72 -0
- acprof/_bundle/acprof/source_identity.py +68 -0
- acprof/_bundle/acprof/telemetry.py +225 -0
- acprof/_bundle/acprof/testing/__init__.py +1 -0
- acprof/_bundle/acprof/testing/evidence.py +117 -0
- acprof/_bundle/acprof/testing/plugin.py +126 -0
- acprof/_bundle/acprof/testing/provenance.py +53 -0
- acprof/_bundle/acprof/testing/sharding.py +14 -0
- acprof/_bundle/acprof/tui/__init__.py +1 -0
- acprof/_bundle/acprof/tui/app.py +934 -0
- acprof/_bundle/acprof/tui/app_contracts.py +43 -0
- acprof/_bundle/acprof/tui/catalog_controller.py +120 -0
- acprof/_bundle/acprof/tui/commands.py +209 -0
- acprof/_bundle/acprof/tui/configuration_controller.py +436 -0
- acprof/_bundle/acprof/tui/diagnostics.py +340 -0
- acprof/_bundle/acprof/tui/downloads.py +56 -0
- acprof/_bundle/acprof/tui/environment.py +248 -0
- acprof/_bundle/acprof/tui/experiment_catalog.py +279 -0
- acprof/_bundle/acprof/tui/experiment_controller.py +132 -0
- acprof/_bundle/acprof/tui/experiment_picker.py +273 -0
- acprof/_bundle/acprof/tui/field_validation.py +62 -0
- acprof/_bundle/acprof/tui/i18n.py +57 -0
- acprof/_bundle/acprof/tui/image_controller.py +525 -0
- acprof/_bundle/acprof/tui/images.py +737 -0
- acprof/_bundle/acprof/tui/input.py +191 -0
- acprof/_bundle/acprof/tui/localization_controller.py +110 -0
- acprof/_bundle/acprof/tui/log.py +310 -0
- acprof/_bundle/acprof/tui/model_candidates.py +278 -0
- acprof/_bundle/acprof/tui/model_controller.py +111 -0
- acprof/_bundle/acprof/tui/model_input.py +12 -0
- acprof/_bundle/acprof/tui/model_store.py +166 -0
- acprof/_bundle/acprof/tui/preflight_controller.py +271 -0
- acprof/_bundle/acprof/tui/preparation.py +269 -0
- acprof/_bundle/acprof/tui/presentation.py +46 -0
- acprof/_bundle/acprof/tui/process.py +111 -0
- acprof/_bundle/acprof/tui/process_controller.py +218 -0
- acprof/_bundle/acprof/tui/profile_controller.py +109 -0
- acprof/_bundle/acprof/tui/progress.py +195 -0
- acprof/_bundle/acprof/tui/recovery.py +114 -0
- acprof/_bundle/acprof/tui/recovery_controller.py +169 -0
- acprof/_bundle/acprof/tui/rendering.py +75 -0
- acprof/_bundle/acprof/tui/reports.py +303 -0
- acprof/_bundle/acprof/tui/result_controller.py +279 -0
- acprof/_bundle/acprof/tui/review_inputs.py +54 -0
- acprof/_bundle/acprof/tui/run_form.py +125 -0
- acprof/_bundle/acprof/tui/run_planning.py +97 -0
- acprof/_bundle/acprof/tui/run_results.py +175 -0
- acprof/_bundle/acprof/tui/scrollbar.py +65 -0
- acprof/_bundle/acprof/tui/settings.py +203 -0
- acprof/_bundle/acprof/tui/slash_controller.py +95 -0
- acprof/_bundle/acprof/tui/stages.py +97 -0
- acprof/_bundle/acprof/tui/storage.py +150 -0
- acprof/_bundle/acprof/tui/table.py +213 -0
- acprof/_bundle/acprof/tui/themes.py +112 -0
- acprof/_bundle/acprof/tui/translation_catalog.py +1861 -0
- acprof/_bundle/acprof/tui/tui.tcss +373 -0
- acprof/_bundle/acprof/tui/views.py +706 -0
- acprof/_bundle/acprof/window_records.py +165 -0
- acprof/_bundle/acprof/workloads/__init__.py +222 -0
- acprof/_bundle/acprof/workloads/audio.py +621 -0
- acprof/_bundle/acprof/workloads/contract.py +116 -0
- acprof/_bundle/acprof/workloads/cv.py +240 -0
- acprof/_bundle/acprof/workloads/diffusion.py +410 -0
- acprof/_bundle/acprof/workloads/multimodal.py +329 -0
- acprof/_bundle/acprof/workloads/nlp.py +151 -0
- acprof/_bundle/acprof/workloads/structured.py +151 -0
- acprof/_bundle/acprof/workloads/timeseries.py +69 -0
- acprof/_bundle/assets/audio/librispeech-clean-test-en-30s/audio.wav +0 -0
- acprof/_bundle/assets/audio/librispeech-clean-test-en-30s/source.json +81 -0
- acprof/_bundle/dockerfiles/environment_tools.py +314 -0
- acprof/_bundle/dockerfiles/locks/audio-cpu.artifacts.json +503 -0
- acprof/_bundle/dockerfiles/locks/audio-cpu.txt +143 -0
- acprof/_bundle/dockerfiles/locks/audio-cu124.artifacts.json +600 -0
- acprof/_bundle/dockerfiles/locks/audio-cu124.txt +171 -0
- acprof/_bundle/dockerfiles/locks/audio-cu128.artifacts.json +544 -0
- acprof/_bundle/dockerfiles/locks/audio-cu128.txt +155 -0
- acprof/_bundle/dockerfiles/locks/custom-multimodal-cpu.artifacts.json +510 -0
- acprof/_bundle/dockerfiles/locks/custom-multimodal-cpu.txt +145 -0
- acprof/_bundle/dockerfiles/locks/custom-multimodal-cu124.artifacts.json +607 -0
- acprof/_bundle/dockerfiles/locks/custom-multimodal-cu124.txt +173 -0
- acprof/_bundle/dockerfiles/locks/custom-multimodal-cu128.artifacts.json +642 -0
- acprof/_bundle/dockerfiles/locks/custom-multimodal-cu128.txt +183 -0
- acprof/_bundle/dockerfiles/locks/cv-cpu.artifacts.json +279 -0
- acprof/_bundle/dockerfiles/locks/cv-cpu.txt +79 -0
- acprof/_bundle/dockerfiles/locks/cv-cu124.artifacts.json +376 -0
- acprof/_bundle/dockerfiles/locks/cv-cu124.txt +107 -0
- acprof/_bundle/dockerfiles/locks/cv-cu128.artifacts.json +411 -0
- acprof/_bundle/dockerfiles/locks/cv-cu128.txt +117 -0
- acprof/_bundle/dockerfiles/locks/diffusion-cpu.artifacts.json +335 -0
- acprof/_bundle/dockerfiles/locks/diffusion-cpu.txt +95 -0
- acprof/_bundle/dockerfiles/locks/diffusion-cu124.artifacts.json +432 -0
- acprof/_bundle/dockerfiles/locks/diffusion-cu124.txt +123 -0
- acprof/_bundle/dockerfiles/locks/diffusion-cu128.artifacts.json +467 -0
- acprof/_bundle/dockerfiles/locks/diffusion-cu128.txt +133 -0
- acprof/_bundle/dockerfiles/locks/moss-transformers5104.artifacts.json +621 -0
- acprof/_bundle/dockerfiles/locks/moss-transformers5104.txt +177 -0
- acprof/_bundle/dockerfiles/locks/multimodal-transformers4576.artifacts.json +635 -0
- acprof/_bundle/dockerfiles/locks/multimodal-transformers4576.txt +181 -0
- acprof/_bundle/dockerfiles/locks/nlp-cpu.artifacts.json +363 -0
- acprof/_bundle/dockerfiles/locks/nlp-cpu.txt +103 -0
- acprof/_bundle/dockerfiles/locks/nlp-cu124.artifacts.json +460 -0
- acprof/_bundle/dockerfiles/locks/nlp-cu124.txt +131 -0
- acprof/_bundle/dockerfiles/locks/nlp-cu128.artifacts.json +495 -0
- acprof/_bundle/dockerfiles/locks/nlp-cu128.txt +141 -0
- acprof/_bundle/dockerfiles/locks/onnxruntime-cpu.artifacts.json +261 -0
- acprof/_bundle/dockerfiles/locks/onnxruntime-cpu.txt +73 -0
- acprof/_bundle/dockerfiles/locks/platform-cpu.artifacts.json +99 -0
- acprof/_bundle/dockerfiles/locks/platform-cpu.txt +27 -0
- acprof/_bundle/dockerfiles/locks/platform-cu124.artifacts.json +196 -0
- acprof/_bundle/dockerfiles/locks/platform-cu124.txt +55 -0
- acprof/_bundle/dockerfiles/locks/platform-cu128.artifacts.json +231 -0
- acprof/_bundle/dockerfiles/locks/platform-cu128.txt +65 -0
- acprof/_bundle/dockerfiles/locks/platform-python-cpu.artifacts.json +37 -0
- acprof/_bundle/dockerfiles/locks/platform-python-cpu.txt +9 -0
- acprof/_bundle/dockerfiles/locks/structured-cpu.artifacts.json +279 -0
- acprof/_bundle/dockerfiles/locks/structured-cpu.txt +79 -0
- acprof/_bundle/dockerfiles/locks/structured-cu124.artifacts.json +376 -0
- acprof/_bundle/dockerfiles/locks/structured-cu124.txt +107 -0
- acprof/_bundle/dockerfiles/locks/structured-cu128.artifacts.json +411 -0
- acprof/_bundle/dockerfiles/locks/structured-cu128.txt +117 -0
- acprof/_bundle/dockerfiles/locks/system-trixie-amd64.json +620 -0
- acprof/_bundle/dockerfiles/locks/timeseries-cpu.artifacts.json +314 -0
- acprof/_bundle/dockerfiles/locks/timeseries-cpu.txt +89 -0
- acprof/_bundle/dockerfiles/locks/timeseries-cu124.artifacts.json +411 -0
- acprof/_bundle/dockerfiles/locks/timeseries-cu124.txt +117 -0
- acprof/_bundle/dockerfiles/locks/timeseries-cu128.artifacts.json +446 -0
- acprof/_bundle/dockerfiles/locks/timeseries-cu128.txt +127 -0
- acprof/_bundle/dockerfiles/locks/transformers5104-cpu.artifacts.json +594 -0
- acprof/_bundle/dockerfiles/locks/transformers5104-cpu.txt +169 -0
- acprof/_bundle/dockerfiles/locks/transformers5104-cu124.artifacts.json +691 -0
- acprof/_bundle/dockerfiles/locks/transformers5104-cu124.txt +197 -0
- acprof/_bundle/dockerfiles/locks/transformers5104-cu128.artifacts.json +726 -0
- acprof/_bundle/dockerfiles/locks/transformers5104-cu128.txt +207 -0
- acprof/_bundle/dockerfiles/platform.Dockerfile +22 -0
- acprof/_bundle/dockerfiles/requirements/audio.in +5 -0
- acprof/_bundle/dockerfiles/requirements/custom-multimodal.in +2 -0
- acprof/_bundle/dockerfiles/requirements/cv.in +4 -0
- acprof/_bundle/dockerfiles/requirements/diffusion.in +6 -0
- acprof/_bundle/dockerfiles/requirements/moss-transformers5104.in +9 -0
- acprof/_bundle/dockerfiles/requirements/multimodal-transformers4576.in +3 -0
- acprof/_bundle/dockerfiles/requirements/nlp.in +7 -0
- acprof/_bundle/dockerfiles/requirements/onnxruntime.in +9 -0
- acprof/_bundle/dockerfiles/requirements/service.in +8 -0
- acprof/_bundle/dockerfiles/requirements/structured.in +4 -0
- acprof/_bundle/dockerfiles/requirements/timeseries.in +2 -0
- acprof/_bundle/dockerfiles/requirements/timm.in +1 -0
- acprof/_bundle/dockerfiles/requirements/transformers5104.in +4 -0
- acprof/_bundle/dockerfiles/runtime-final.Dockerfile +34 -0
- acprof/_bundle/dockerfiles/runtime-model.Dockerfile +19 -0
- acprof/_bundle/dockerfiles/runtime.Dockerfile +23 -0
- acprof/_bundle/examples/coverage/regression.json +17 -0
- acprof/_bundle/examples/hardware-validation.json +19 -0
- acprof/_bundle/examples/multimodal/ultravox.model.json +29 -0
- acprof/_bundle/examples/nlp/smoke.py +111 -0
- acprof/_bundle/examples/onnxruntime/fixtures.py +164 -0
- acprof/_bundle/examples/onnxruntime/iris.json +16 -0
- acprof/_bundle/examples/onnxruntime/iris.model.json +7 -0
- acprof/_bundle/examples/onnxruntime/real_models.py +155 -0
- acprof/_bundle/examples/onnxruntime/smoke.py +68 -0
- acprof/_bundle/examples/structured/chronos_smoke.py +56 -0
- acprof/_bundle/examples/structured/export_models.py +71 -0
- acprof/_bundle/examples/structured/smoke.py +71 -0
- acprof/_bundle/licenses/CC-BY-4.0.txt +156 -0
- acprof/analysis/__init__.py +1 -0
- acprof/analysis/audit.py +276 -0
- acprof/analysis/comparison.py +364 -0
- acprof/analysis/compatibility.py +223 -0
- acprof/analysis/conditions.py +185 -0
- acprof/analysis/independent_comparison.py +191 -0
- acprof/analysis/latency_model.py +1106 -0
- acprof/analysis/latency_report.py +577 -0
- acprof/analysis/model.py +276 -0
- acprof/analysis/precision.py +51 -0
- acprof/analysis/uncertainty.py +144 -0
- acprof/application/__init__.py +1 -0
- acprof/application/download.py +14 -0
- acprof/application/errors.py +5 -0
- acprof/application/notifications.py +302 -0
- acprof/application/preparation.py +333 -0
- acprof/application/resources.py +66 -0
- acprof/application/run.py +462 -0
- acprof/application/terminal_log.py +136 -0
- acprof/artifact_layout.py +261 -0
- acprof/artifacts.py +161 -0
- acprof/capabilities.py +404 -0
- acprof/cli/__init__.py +1 -0
- acprof/cli/audit.py +74 -0
- acprof/cli/auto.py +41 -0
- acprof/cli/backfill_compute.py +498 -0
- acprof/cli/compare.py +34 -0
- acprof/cli/coverage.py +70 -0
- acprof/cli/doctor.py +47 -0
- acprof/cli/inspect.py +101 -0
- acprof/cli/load.py +190 -0
- acprof/cli/main.py +64 -0
- acprof/cli/model_store.py +22 -0
- acprof/cli/plot.py +211 -0
- acprof/cli/posthoc.py +113 -0
- acprof/cli/probe.py +186 -0
- acprof/cli/report.py +35 -0
- acprof/cli/results.py +37 -0
- acprof/cli/run.py +54 -0
- acprof/cli/stats.py +94 -0
- acprof/cli/tui.py +65 -0
- acprof/config.py +177 -0
- acprof/container/__init__.py +1 -0
- acprof/container/compat/__init__.py +1 -0
- acprof/container/compat/transformers_dynamic.py +54 -0
- acprof/container/compat/transformers_model_types.json +1091 -0
- acprof/container/compute_profile_runner.py +392 -0
- acprof/container/download_model.py +165 -0
- acprof/container/execution.py +73 -0
- acprof/container/handlers/__init__.py +298 -0
- acprof/container/handlers/audio.py +743 -0
- acprof/container/handlers/custom_pipeline.py +74 -0
- acprof/container/handlers/cv.py +321 -0
- acprof/container/handlers/diffusion.py +728 -0
- acprof/container/handlers/moss.py +64 -0
- acprof/container/handlers/multimodal.py +609 -0
- acprof/container/handlers/nlp.py +747 -0
- acprof/container/handlers/onnx_tasks.py +231 -0
- acprof/container/handlers/onnxruntime.py +90 -0
- acprof/container/handlers/structured.py +185 -0
- acprof/container/handlers/timeseries.py +178 -0
- acprof/container/load_policy.py +81 -0
- acprof/container/loading_quality.py +48 -0
- acprof/container/local_pipeline.py +31 -0
- acprof/container/model_files.py +280 -0
- acprof/container/model_probe.py +80 -0
- acprof/container/onnx_session.py +150 -0
- acprof/container/runtime_manifest.py +150 -0
- acprof/container/runtime_validate.py +156 -0
- acprof/container/server.py +209 -0
- acprof/container/torch_execution.py +55 -0
- acprof/container/validation.py +172 -0
- acprof/cpu_affinity.py +35 -0
- acprof/dependency_locks.py +129 -0
- acprof/experiment.py +356 -0
- acprof/extensions/__init__.py +294 -0
- acprof/extensions/builtin/manifest.json +3591 -0
- acprof/extensions/onnxruntime/manifest.json +191 -0
- acprof/extensions/schema.py +238 -0
- acprof/extensions/transformers/4.57.6.json +1639 -0
- acprof/extensions/transformers/5.10.4.json +1812 -0
- acprof/failures.py +115 -0
- acprof/hardware_conditions.py +18 -0
- acprof/hf_download.py +143 -0
- acprof/hf_endpoints.py +62 -0
- acprof/hf_transport.py +238 -0
- acprof/host/__init__.py +1 -0
- acprof/host/automation.py +161 -0
- acprof/host/client.py +520 -0
- acprof/host/collection_history.py +77 -0
- acprof/host/collection_workflow.py +285 -0
- acprof/host/command.py +119 -0
- acprof/host/container_lifecycle.py +225 -0
- acprof/host/container_state.py +128 -0
- acprof/host/coverage_state.py +259 -0
- acprof/host/detect.py +669 -0
- acprof/host/docker_runtime.py +359 -0
- acprof/host/doctor.py +158 -0
- acprof/host/env_utils.py +233 -0
- acprof/host/execution_conditions.py +87 -0
- acprof/host/gpu_device.py +66 -0
- acprof/host/hardware_conditions.py +130 -0
- acprof/host/images/__init__.py +1 -0
- acprof/host/images/dependencies.py +169 -0
- acprof/host/images/environment.py +313 -0
- acprof/host/images/graph.py +143 -0
- acprof/host/images/identity.py +6 -0
- acprof/host/images/inventory.py +445 -0
- acprof/host/images/runtime.py +457 -0
- acprof/host/images/scan.py +154 -0
- acprof/host/input_plan.py +1056 -0
- acprof/host/interface_probe.py +141 -0
- acprof/host/largest_scale_probe.py +566 -0
- acprof/host/matrix_plan.py +98 -0
- acprof/host/measurement/__init__.py +1 -0
- acprof/host/measurement/boundary.py +162 -0
- acprof/host/measurement/capture.py +139 -0
- acprof/host/measurement/checkpoint.py +275 -0
- acprof/host/measurement/config.py +212 -0
- acprof/host/measurement/diagnostics.py +247 -0
- acprof/host/measurement/energy_validation.py +172 -0
- acprof/host/measurement/errors.py +25 -0
- acprof/host/measurement/execution.py +396 -0
- acprof/host/measurement/load.py +237 -0
- acprof/host/measurement/metrics.py +975 -0
- acprof/host/measurement/monitors.py +143 -0
- acprof/host/measurement/publication.py +171 -0
- acprof/host/measurement/requests.py +97 -0
- acprof/host/measurement/types.py +82 -0
- acprof/host/model_coverage.py +337 -0
- acprof/host/model_errors.py +116 -0
- acprof/host/model_inspection.py +107 -0
- acprof/host/model_schema.py +35 -0
- acprof/host/model_store.py +733 -0
- acprof/host/network_preflight.py +229 -0
- acprof/host/orchestrator.py +1133 -0
- acprof/host/permissions.py +117 -0
- acprof/host/platform_metadata.py +63 -0
- acprof/host/posthoc/__init__.py +12 -0
- acprof/host/posthoc/backfill.py +415 -0
- acprof/host/posthoc/context.py +400 -0
- acprof/host/posthoc/plans.py +597 -0
- acprof/host/posthoc/service.py +303 -0
- acprof/host/posthoc/storage.py +491 -0
- acprof/host/preflight.py +370 -0
- acprof/host/profiling/__init__.py +1 -0
- acprof/host/profiling/compute.py +436 -0
- acprof/host/profiling/compute_plan.py +261 -0
- acprof/host/profiling/execution.py +547 -0
- acprof/host/profiling/execution_plan.py +576 -0
- acprof/host/profiling/progress.py +83 -0
- acprof/host/profiling/support.py +252 -0
- acprof/host/profiling/tools/__init__.py +1 -0
- acprof/host/profiling/tools/advisor.py +164 -0
- acprof/host/profiling/tools/compute_parsers.py +409 -0
- acprof/host/profiling/tools/execution_environment.py +135 -0
- acprof/host/profiling/tools/execution_parsers.py +364 -0
- acprof/host/profiling/tools/massif.py +418 -0
- acprof/host/profiling/tools/ncu.py +696 -0
- acprof/host/profiling/tools/nsys.py +326 -0
- acprof/host/profiling/tools/tool_discovery.py +229 -0
- acprof/host/profiling/tools/torch.py +158 -0
- acprof/host/result_cleanup.py +65 -0
- acprof/host/run_state.py +639 -0
- acprof/host/runtime_settings.py +10 -0
- acprof/host/runtime_validation.py +302 -0
- acprof/host/source_bundle.py +96 -0
- acprof/host/startup_probe.py +95 -0
- acprof/host/static_metadata.py +936 -0
- acprof/host/task_support.py +121 -0
- acprof/installation.py +26 -0
- acprof/latency_slo.py +62 -0
- acprof/messages.py +26 -0
- acprof/metric_registry.py +315 -0
- acprof/model_candidates.py +297 -0
- acprof/model_contract.py +234 -0
- acprof/model_dependencies.py +93 -0
- acprof/model_dependency_domain.py +45 -0
- acprof/model_dependency_eval.py +438 -0
- acprof/model_dependency_flow.py +200 -0
- acprof/model_evidence.py +115 -0
- acprof/model_metadata_analysis.py +156 -0
- acprof/model_repository.py +149 -0
- acprof/model_resolution.py +129 -0
- acprof/model_review.py +155 -0
- acprof/model_source_analysis.py +299 -0
- acprof/model_spec.py +204 -0
- acprof/model_support.py +105 -0
- acprof/model_transforms.py +81 -0
- acprof/monitors/__init__.py +1 -0
- acprof/monitors/common.py +63 -0
- acprof/monitors/energy_cpu.py +651 -0
- acprof/monitors/energy_nvml.py +381 -0
- acprof/monitors/gpu_metrics.py +123 -0
- acprof/monitors/interfaces.py +74 -0
- acprof/monitors/perf_mips.py +617 -0
- acprof/monitors/rapl_topology.py +100 -0
- acprof/monitors/resource_metrics.py +472 -0
- acprof/monitors/resource_readers.py +435 -0
- acprof/monitors/resource_usage.py +450 -0
- acprof/monitors/sampling.py +79 -0
- acprof/network_policy.py +182 -0
- acprof/notifications.py +279 -0
- acprof/packet/__init__.py +1 -0
- acprof/packet/merge_packet_latency.py +369 -0
- acprof/packet/sniff_parse_pcap.py +240 -0
- acprof/pixel_metrics.py +103 -0
- acprof/platform.py +180 -0
- acprof/plotting/__init__.py +1 -0
- acprof/plotting/config.py +487 -0
- acprof/plotting/data.py +236 -0
- acprof/plotting/diagnostics.py +747 -0
- acprof/plotting/latency.py +638 -0
- acprof/plotting/metrics.py +648 -0
- acprof/plotting/plotly-LICENSE.txt +21 -0
- acprof/plotting/report.css +61 -0
- acprof/plotting/report.html +68 -0
- acprof/plotting/report.js +295 -0
- acprof/plotting/report.py +66 -0
- acprof/plotting/styles.py +111 -0
- acprof/plotting/view_model.js +145 -0
- acprof/precision.py +42 -0
- acprof/preparation_events.py +78 -0
- acprof/progress_events.py +105 -0
- acprof/quality.py +153 -0
- acprof/resource_budget.py +29 -0
- acprof/result_csv.py +263 -0
- acprof/result_layers.py +365 -0
- acprof/run_args.py +223 -0
- acprof/run_options.py +225 -0
- acprof/runtime_dependencies.py +195 -0
- acprof/runtime_profiles.py +258 -0
- acprof/runtime_settings.py +72 -0
- acprof/source_identity.py +68 -0
- acprof/telemetry.py +225 -0
- acprof/testing/__init__.py +1 -0
- acprof/testing/evidence.py +117 -0
- acprof/testing/plugin.py +126 -0
- acprof/testing/provenance.py +53 -0
- acprof/testing/sharding.py +14 -0
- acprof/tui/__init__.py +1 -0
- acprof/tui/app.py +934 -0
- acprof/tui/app_contracts.py +43 -0
- acprof/tui/catalog_controller.py +120 -0
- acprof/tui/commands.py +209 -0
- acprof/tui/configuration_controller.py +436 -0
- acprof/tui/diagnostics.py +340 -0
- acprof/tui/downloads.py +56 -0
- acprof/tui/environment.py +248 -0
- acprof/tui/experiment_catalog.py +279 -0
- acprof/tui/experiment_controller.py +132 -0
- acprof/tui/experiment_picker.py +273 -0
- acprof/tui/field_validation.py +62 -0
- acprof/tui/i18n.py +57 -0
- acprof/tui/image_controller.py +525 -0
- acprof/tui/images.py +737 -0
- acprof/tui/input.py +191 -0
- acprof/tui/localization_controller.py +110 -0
- acprof/tui/log.py +310 -0
- acprof/tui/model_candidates.py +278 -0
- acprof/tui/model_controller.py +111 -0
- acprof/tui/model_input.py +12 -0
- acprof/tui/model_store.py +166 -0
- acprof/tui/preflight_controller.py +271 -0
- acprof/tui/preparation.py +269 -0
- acprof/tui/presentation.py +46 -0
- acprof/tui/process.py +111 -0
- acprof/tui/process_controller.py +218 -0
- acprof/tui/profile_controller.py +109 -0
- acprof/tui/progress.py +195 -0
- acprof/tui/recovery.py +114 -0
- acprof/tui/recovery_controller.py +169 -0
- acprof/tui/rendering.py +75 -0
- acprof/tui/reports.py +303 -0
- acprof/tui/result_controller.py +279 -0
- acprof/tui/review_inputs.py +54 -0
- acprof/tui/run_form.py +125 -0
- acprof/tui/run_planning.py +97 -0
- acprof/tui/run_results.py +175 -0
- acprof/tui/scrollbar.py +65 -0
- acprof/tui/settings.py +203 -0
- acprof/tui/slash_controller.py +95 -0
- acprof/tui/stages.py +97 -0
- acprof/tui/storage.py +150 -0
- acprof/tui/table.py +213 -0
- acprof/tui/themes.py +112 -0
- acprof/tui/translation_catalog.py +1861 -0
- acprof/tui/tui.tcss +373 -0
- acprof/tui/views.py +706 -0
- acprof/window_records.py +165 -0
- acprof/workloads/__init__.py +222 -0
- acprof/workloads/audio.py +621 -0
- acprof/workloads/contract.py +116 -0
- acprof/workloads/cv.py +240 -0
- acprof/workloads/diffusion.py +410 -0
- acprof/workloads/multimodal.py +329 -0
- acprof/workloads/nlp.py +151 -0
- acprof/workloads/structured.py +151 -0
- acprof/workloads/timeseries.py +69 -0
- acprof-0.3.0.dist-info/METADATA +117 -0
- acprof-0.3.0.dist-info/RECORD +704 -0
- acprof-0.3.0.dist-info/WHEEL +4 -0
- acprof-0.3.0.dist-info/entry_points.txt +2 -0
- acprof-0.3.0.dist-info/licenses/LICENSE +202 -0
- acprof-0.3.0.dist-info/licenses/NOTICE +43 -0
- acprof-0.3.0.dist-info/licenses/licenses/CC-BY-4.0.txt +156 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""Small helpers for local project environment bootstrap."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import re
|
|
8
|
+
import stat
|
|
9
|
+
import tempfile
|
|
10
|
+
from collections.abc import Iterable, Mapping, MutableMapping
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from acprof.config import (
|
|
14
|
+
CONTAINER_HF_HOME,
|
|
15
|
+
CONTAINER_MODEL_LOCAL_PATH,
|
|
16
|
+
)
|
|
17
|
+
from acprof.hf_endpoints import hf_endpoints
|
|
18
|
+
|
|
19
|
+
CONFIGURABLE_ENV_KEYS = (
|
|
20
|
+
"HF_TOKEN", "HF_ENDPOINT", "HF_FALLBACK_ENDPOINTS", "HF_DOWNLOAD_MODE",
|
|
21
|
+
"ACPROF_MAX_DOWNLOAD", "ACPROF_MODEL_MAX_DOWNLOAD",
|
|
22
|
+
"ACPROF_MODEL_STORE", "ACPROF_MODEL_STORE_MAX",
|
|
23
|
+
"ACPROF_WECOM_WEBHOOK_URL",
|
|
24
|
+
)
|
|
25
|
+
_ENV_ALIASES = {
|
|
26
|
+
"HF_TOKEN": "HUGGING_FACE_HUB_TOKEN", "HF_ENDPOINT": "HF_HUB_ENDPOINT",
|
|
27
|
+
}
|
|
28
|
+
_RETIRED_PROXY_KEYS = frozenset({"http_proxy", "https_proxy", "all_proxy", "no_proxy"})
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _parse_env_line(raw_line: str) -> tuple[str, str] | None:
|
|
32
|
+
line = raw_line.strip()
|
|
33
|
+
if line.startswith("export "):
|
|
34
|
+
line = line[7:].lstrip()
|
|
35
|
+
if not line or line.startswith("#") or "=" not in line:
|
|
36
|
+
return None
|
|
37
|
+
key, value = line.split("=", 1)
|
|
38
|
+
key, value = key.strip(), value.strip()
|
|
39
|
+
if not re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*", key):
|
|
40
|
+
return None
|
|
41
|
+
if len(value) >= 2 and value[0] == value[-1] and value[0] in "\"'":
|
|
42
|
+
quote, value = value[0], value[1:-1]
|
|
43
|
+
if quote == '"':
|
|
44
|
+
value = re.sub(r'\\([\\"])', r'\1', value)
|
|
45
|
+
return key, value
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _read_env_values(path: Path) -> dict[str, str]:
|
|
49
|
+
if not path.exists():
|
|
50
|
+
return {}
|
|
51
|
+
return dict(item for line in path.read_text(encoding="utf-8").splitlines()
|
|
52
|
+
if (item := _parse_env_line(line)) is not None)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def project_env_values(project_dir: str | os.PathLike[str]) -> dict[str, str]:
|
|
56
|
+
"""Read local values without changing the process; .env.local has priority."""
|
|
57
|
+
values: dict[str, str] = {}
|
|
58
|
+
for path in _iter_env_files(project_dir):
|
|
59
|
+
values.update(_read_env_values(path))
|
|
60
|
+
return values
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def configurable_env_values(project_dir, *, environ=None) -> dict[str, str]:
|
|
64
|
+
values = project_env_values(project_dir)
|
|
65
|
+
values.update(os.environ if environ is None else environ)
|
|
66
|
+
return {key: values.get(key, values.get(_ENV_ALIASES.get(key, ""), ""))
|
|
67
|
+
for key in CONFIGURABLE_ENV_KEYS}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _private_env_text(path: Path) -> str:
|
|
71
|
+
if path.is_symlink() or (path.exists() and not path.is_file()):
|
|
72
|
+
raise ValueError("Local configuration must be a regular file, not a symbolic link")
|
|
73
|
+
return path.read_text(encoding="utf-8") if path.exists() else ""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _atomic_private_text(path: Path, text: str) -> None:
|
|
77
|
+
_private_env_text(path)
|
|
78
|
+
fd, name = tempfile.mkstemp(prefix=".env.local.", suffix=".tmp", dir=path.parent)
|
|
79
|
+
try:
|
|
80
|
+
with os.fdopen(fd, "w", encoding="utf-8") as stream:
|
|
81
|
+
os.fchmod(stream.fileno(), stat.S_IRUSR | stat.S_IWUSR)
|
|
82
|
+
stream.write(text)
|
|
83
|
+
stream.flush()
|
|
84
|
+
os.fsync(stream.fileno())
|
|
85
|
+
os.replace(name, path)
|
|
86
|
+
if os.name == "posix":
|
|
87
|
+
directory_fd = os.open(path.parent, os.O_RDONLY | os.O_DIRECTORY)
|
|
88
|
+
try:
|
|
89
|
+
os.fsync(directory_fd)
|
|
90
|
+
finally:
|
|
91
|
+
os.close(directory_fd)
|
|
92
|
+
finally:
|
|
93
|
+
if os.path.exists(name):
|
|
94
|
+
os.unlink(name)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def save_project_env(
|
|
98
|
+
project_dir: str | os.PathLike[str], values: Mapping[str, str], *,
|
|
99
|
+
environ: MutableMapping[str, str] | None = None, expected_text: str | None = None,
|
|
100
|
+
) -> Path:
|
|
101
|
+
"""Save explicit TUI edits privately, preserving other settings and a backup.
|
|
102
|
+
|
|
103
|
+
No shell evaluation or variable interpolation is performed. Only an explicit
|
|
104
|
+
save updates the current process and its children; ordinary bootstrap still
|
|
105
|
+
gives inherited environment variables priority.
|
|
106
|
+
"""
|
|
107
|
+
if set(values) - set(CONFIGURABLE_ENV_KEYS):
|
|
108
|
+
raise ValueError("Unsupported environment setting")
|
|
109
|
+
updates = {}
|
|
110
|
+
for key, value in values.items():
|
|
111
|
+
if not isinstance(value, str) or any(ord(char) < 32 or ord(char) == 127 for char in value):
|
|
112
|
+
raise ValueError(f"{key}: enter a single line without control characters")
|
|
113
|
+
updates[key] = value.strip()
|
|
114
|
+
hf_endpoints({**os.environ, **updates})
|
|
115
|
+
from acprof.network_policy import parse_bytes
|
|
116
|
+
for key in ("ACPROF_MAX_DOWNLOAD", "ACPROF_MODEL_MAX_DOWNLOAD", "ACPROF_MODEL_STORE_MAX"):
|
|
117
|
+
parse_bytes(updates.get(key))
|
|
118
|
+
if updates.get("ACPROF_WECOM_WEBHOOK_URL"):
|
|
119
|
+
from acprof.notifications import NotificationConfigError, validate_wecom_webhook_url
|
|
120
|
+
try:
|
|
121
|
+
validate_wecom_webhook_url(updates["ACPROF_WECOM_WEBHOOK_URL"])
|
|
122
|
+
except (ValueError, NotificationConfigError):
|
|
123
|
+
raise ValueError("ACPROF_WECOM_WEBHOOK_URL: invalid WeCom webhook URL") from None
|
|
124
|
+
for key, alias in _ENV_ALIASES.items():
|
|
125
|
+
if key in updates:
|
|
126
|
+
updates[alias] = updates[key]
|
|
127
|
+
path = Path(project_dir) / ".env.local"
|
|
128
|
+
original = _private_env_text(path)
|
|
129
|
+
if expected_text is not None and original != expected_text:
|
|
130
|
+
raise ValueError(".env.local changed since this form opened; close and reopen before saving")
|
|
131
|
+
remaining = dict(updates)
|
|
132
|
+
lines = []
|
|
133
|
+
for line in original.splitlines(keepends=True):
|
|
134
|
+
item = _parse_env_line(line)
|
|
135
|
+
if item is not None and item[0] in updates:
|
|
136
|
+
key = item[0]
|
|
137
|
+
if key in remaining:
|
|
138
|
+
lines.append(f"{key}={json.dumps(remaining.pop(key), ensure_ascii=False)}\n")
|
|
139
|
+
else:
|
|
140
|
+
lines.append(line)
|
|
141
|
+
if lines and not lines[-1].endswith("\n"):
|
|
142
|
+
lines[-1] += "\n"
|
|
143
|
+
lines.extend(f"{key}={json.dumps(value, ensure_ascii=False)}\n" for key, value in remaining.items())
|
|
144
|
+
if path.exists():
|
|
145
|
+
_atomic_private_text(path.with_name(".env.local.bak"), original)
|
|
146
|
+
_atomic_private_text(path, "".join(lines))
|
|
147
|
+
(os.environ if environ is None else environ).update(updates)
|
|
148
|
+
return path
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _iter_env_files(project_dir: str | os.PathLike[str]) -> Iterable[Path]:
|
|
152
|
+
root = Path(project_dir)
|
|
153
|
+
yield root / ".env"
|
|
154
|
+
yield root / ".env.local"
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def load_project_env(
|
|
158
|
+
project_dir: str | os.PathLike[str],
|
|
159
|
+
*,
|
|
160
|
+
environ: MutableMapping[str, str] | None = None,
|
|
161
|
+
) -> None:
|
|
162
|
+
"""Load local KEY=VALUE pairs into the process or an isolated environment."""
|
|
163
|
+
target_environ = os.environ if environ is None else environ
|
|
164
|
+
retired_setting = "ACPROF_SUDO_PASSWORD"
|
|
165
|
+
migration = f"{retired_setting} is no longer supported; remove it and follow docs/getting_started/installation.md#最小权限安装"
|
|
166
|
+
if retired_setting in target_environ:
|
|
167
|
+
raise ValueError(migration)
|
|
168
|
+
values = project_env_values(project_dir)
|
|
169
|
+
if retired_setting in values:
|
|
170
|
+
raise ValueError(migration)
|
|
171
|
+
for key, value in values.items():
|
|
172
|
+
# Historical TUI proxy fields remain untouched on disk. Only the user's
|
|
173
|
+
# inherited system environment configures HTTP clients now.
|
|
174
|
+
if key.lower() not in _RETIRED_PROXY_KEYS:
|
|
175
|
+
target_environ.setdefault(key, value)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _set_default_if_blank(key: str, value: str) -> None:
|
|
179
|
+
if not os.environ.get(key, "").strip():
|
|
180
|
+
os.environ[key] = value
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def configure_hf_network() -> str:
|
|
184
|
+
"""Normalize the selected endpoint while preserving the user's proxy policy."""
|
|
185
|
+
endpoint = hf_endpoints()[0]
|
|
186
|
+
os.environ["HF_ENDPOINT"] = endpoint
|
|
187
|
+
_set_default_if_blank("HF_HUB_ENDPOINT", endpoint)
|
|
188
|
+
from acprof.hf_transport import configure_hf_transport
|
|
189
|
+
configure_hf_transport()
|
|
190
|
+
return endpoint
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def resolve_hf_token() -> str | None:
|
|
194
|
+
"""Populate HF_TOKEN from env or local Hugging Face login when available."""
|
|
195
|
+
token = (
|
|
196
|
+
os.environ.get("HF_TOKEN", "").strip()
|
|
197
|
+
or os.environ.get("HUGGING_FACE_HUB_TOKEN", "").strip()
|
|
198
|
+
)
|
|
199
|
+
if not token:
|
|
200
|
+
try:
|
|
201
|
+
from huggingface_hub.utils import get_token
|
|
202
|
+
|
|
203
|
+
token = (get_token() or "").strip()
|
|
204
|
+
except Exception:
|
|
205
|
+
token = ""
|
|
206
|
+
|
|
207
|
+
if not token:
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
_set_default_if_blank("HF_TOKEN", token)
|
|
211
|
+
_set_default_if_blank("HUGGING_FACE_HUB_TOKEN", token)
|
|
212
|
+
return token
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def bootstrap_project_env(project_dir: str | os.PathLike[str]) -> str | None:
|
|
216
|
+
"""Load project env files and normalize Hugging Face auth env vars."""
|
|
217
|
+
load_project_env(project_dir)
|
|
218
|
+
configure_hf_network()
|
|
219
|
+
return resolve_hf_token()
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def hf_offline_docker_env_args() -> list[str]:
|
|
223
|
+
"""Return the shared Docker environment for network-free model loading."""
|
|
224
|
+
return [
|
|
225
|
+
"-e", "HF_HUB_DISABLE_TELEMETRY=1",
|
|
226
|
+
"-e", "HF_HUB_OFFLINE=1",
|
|
227
|
+
"-e", "HF_HUB_DISABLE_XET=1",
|
|
228
|
+
"-e", "TRANSFORMERS_OFFLINE=1",
|
|
229
|
+
"-e", f"HF_HOME={CONTAINER_HF_HOME}",
|
|
230
|
+
"-e", f"HF_HUB_CACHE={CONTAINER_HF_HOME}",
|
|
231
|
+
"-e", f"TRANSFORMERS_CACHE={CONTAINER_HF_HOME}",
|
|
232
|
+
"-e", f"MODEL_LOCAL_PATH={CONTAINER_MODEL_LOCAL_PATH}",
|
|
233
|
+
]
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Restore recorded execution conditions outside measurement windows."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import math
|
|
5
|
+
import os
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from contextlib import contextmanager
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
|
|
10
|
+
from acprof.cpu_affinity import normalize_cpu_set, parse_cpu_set
|
|
11
|
+
from acprof.host.gpu_device import gpu_device_scope, pin_gpu_device
|
|
12
|
+
from acprof.runtime_settings import RUNTIME_ENV_NAMES
|
|
13
|
+
|
|
14
|
+
MEASUREMENT_ENV_NAMES = (
|
|
15
|
+
"AUTO_WARMUP_REQUESTS", "SLOW_LATENCY_THRESHOLD_S", "IDLE_DEBUG_TRACE_INTERVAL_S",
|
|
16
|
+
"DEVICE_INDEX", "CUDA_VISIBLE_DEVICES", "OMP_NUM_THREADS", "MKL_NUM_THREADS",
|
|
17
|
+
)
|
|
18
|
+
DEVICE_ENV_NAMES = ("ACPROF_GPU_DEVICE", "GPU_DEVICE_UUID", "NVIDIA_VISIBLE_DEVICES")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def measurement_environment() -> dict:
|
|
22
|
+
return {**{name: os.environ.get(name) for name in MEASUREMENT_ENV_NAMES},
|
|
23
|
+
**{name: os.environ[name] for name in RUNTIME_ENV_NAMES if name in os.environ}}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@contextmanager
|
|
27
|
+
def source_runtime_environment(recorded: Mapping):
|
|
28
|
+
"""Clear unrecorded overrides and restore the caller's environment on every exit."""
|
|
29
|
+
names = (*MEASUREMENT_ENV_NAMES, *RUNTIME_ENV_NAMES, *DEVICE_ENV_NAMES)
|
|
30
|
+
previous = {name: os.environ.get(name) for name in names}
|
|
31
|
+
try:
|
|
32
|
+
for name in names:
|
|
33
|
+
value = recorded.get(name)
|
|
34
|
+
if value is None:
|
|
35
|
+
os.environ.pop(name, None)
|
|
36
|
+
else:
|
|
37
|
+
os.environ[name] = str(value)
|
|
38
|
+
yield
|
|
39
|
+
finally:
|
|
40
|
+
for name, value in previous.items():
|
|
41
|
+
if value is None:
|
|
42
|
+
os.environ.pop(name, None)
|
|
43
|
+
else:
|
|
44
|
+
os.environ[name] = value
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class ExecutionConditions:
|
|
49
|
+
gpu_mode: str
|
|
50
|
+
gpu_uuid: str
|
|
51
|
+
cpuset_cpus: str
|
|
52
|
+
request_timeout_seconds: float
|
|
53
|
+
environment: dict
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def from_options(cls, options: Mapping, *, gpu: str) -> ExecutionConditions:
|
|
57
|
+
if gpu not in {"off", "on"} or gpu not in options.get("gpus", "").split(","):
|
|
58
|
+
raise ValueError("source does not include the requested GPU mode")
|
|
59
|
+
environment = options.get("measurement_environment")
|
|
60
|
+
if not isinstance(environment, dict):
|
|
61
|
+
raise ValueError("source measurement_environment is missing")
|
|
62
|
+
uuid = str(options.get("gpu_device", "")) if gpu == "on" else ""
|
|
63
|
+
if gpu == "on" and not uuid.startswith("GPU-"):
|
|
64
|
+
raise ValueError("source GPU UUID is missing; refusing index-based replay")
|
|
65
|
+
timeout = float(options["request_timeout_seconds"])
|
|
66
|
+
if not math.isfinite(timeout) or timeout <= 0:
|
|
67
|
+
raise ValueError("source request timeout must be finite and positive")
|
|
68
|
+
return cls(gpu, uuid, normalize_cpu_set(options.get("cpuset_cpus", "")), timeout, dict(environment))
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def container_options(self) -> dict:
|
|
72
|
+
return {"cpuset_cpus": self.cpuset_cpus, "request_timeout_seconds": self.request_timeout_seconds}
|
|
73
|
+
|
|
74
|
+
@contextmanager
|
|
75
|
+
def activate(self):
|
|
76
|
+
with source_runtime_environment(self.environment), gpu_device_scope():
|
|
77
|
+
requested = parse_cpu_set(self.cpuset_cpus)
|
|
78
|
+
if requested and not requested <= os.sched_getaffinity(0):
|
|
79
|
+
raise ValueError("source CPU affinity is unavailable on this host")
|
|
80
|
+
device = {}
|
|
81
|
+
if self.gpu_mode == "on":
|
|
82
|
+
device = pin_gpu_device(self.gpu_uuid)
|
|
83
|
+
if device["uuid"] != self.gpu_uuid:
|
|
84
|
+
raise ValueError("resolved GPU UUID differs from the source")
|
|
85
|
+
os.environ.update(ACPROF_GPU_DEVICE=self.gpu_uuid, GPU_DEVICE_UUID=self.gpu_uuid,
|
|
86
|
+
DEVICE_INDEX=str(device["index"]))
|
|
87
|
+
yield device
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""在测量窗口外解析物理 GPU;容器与主机采集器共享同一 UUID。"""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import csv
|
|
5
|
+
import os
|
|
6
|
+
from contextlib import contextmanager
|
|
7
|
+
from contextvars import ContextVar
|
|
8
|
+
|
|
9
|
+
from acprof.host.command import run_command
|
|
10
|
+
|
|
11
|
+
_SELECTED: ContextVar[dict | None] = ContextVar("acprof_gpu_device", default=None)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@contextmanager
|
|
15
|
+
def gpu_device_scope():
|
|
16
|
+
"""Limit a pinned selection to one CLI invocation, including embedded callers."""
|
|
17
|
+
token = _SELECTED.set(None)
|
|
18
|
+
try:
|
|
19
|
+
yield
|
|
20
|
+
finally:
|
|
21
|
+
_SELECTED.reset(token)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def selected_gpu_device() -> dict:
|
|
25
|
+
return dict(_SELECTED.get() or {})
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def resolve_gpu_device(selector: str | None = None) -> dict:
|
|
29
|
+
if selector is None and _SELECTED.get() is not None:
|
|
30
|
+
return selected_gpu_device()
|
|
31
|
+
selector = str(selector if selector is not None else
|
|
32
|
+
os.environ.get("ACPROF_GPU_DEVICE", os.environ.get("DEVICE_INDEX", "0"))).strip()
|
|
33
|
+
if not (selector.isdecimal() or selector.startswith("GPU-")) or any(c in selector for c in ",\n\r "):
|
|
34
|
+
raise ValueError("GPU selector must be one physical GPU index or UUID; all and MIG are unsupported")
|
|
35
|
+
result = run_command(
|
|
36
|
+
["nvidia-smi", f"--id={selector}",
|
|
37
|
+
"--query-gpu=uuid,index,pci.bus_id,name,memory.total,mig.mode.current",
|
|
38
|
+
"--format=csv,noheader,nounits"],
|
|
39
|
+
capture_output=True, text=True, check=False, timeout=10,
|
|
40
|
+
)
|
|
41
|
+
if result.returncode:
|
|
42
|
+
raise RuntimeError(f"Cannot resolve GPU {selector}: {result.stderr.strip()}")
|
|
43
|
+
rows = list(csv.reader(result.stdout.strip().splitlines(), skipinitialspace=True))
|
|
44
|
+
if len(rows) != 1 or len(rows[0]) != 6:
|
|
45
|
+
raise RuntimeError(f"Expected exactly one physical GPU for {selector}")
|
|
46
|
+
uuid, index, bus, name, memory_mib, mig = (value.strip() for value in rows[0])
|
|
47
|
+
if not uuid.startswith("GPU-") or mig.lower() == "enabled":
|
|
48
|
+
raise RuntimeError("MIG devices cannot be attributed using physical-device NVML energy")
|
|
49
|
+
return {"uuid": uuid, "index": int(index), "pci_bus_id": bus, "name": name,
|
|
50
|
+
"memory_total_bytes": int(float(memory_mib) * 1024 ** 2)}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def pin_gpu_device(selector: str | None = None) -> dict:
|
|
54
|
+
device = resolve_gpu_device(selector)
|
|
55
|
+
_SELECTED.set(device)
|
|
56
|
+
return dict(device)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def gpu_docker_args(device: dict | None = None) -> list[str]:
|
|
60
|
+
device = resolve_gpu_device() if device is None else device
|
|
61
|
+
return ["--gpus", f"device={device['uuid']}",
|
|
62
|
+
"-e", f"NVIDIA_VISIBLE_DEVICES={device['uuid']}", "-e", "CUDA_VISIBLE_DEVICES=0"]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def normalize_gpu_mode(gpu: str) -> str:
|
|
66
|
+
return "on" if str(gpu).lower() == "on" else "off"
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""Observe comparison conditions before capture; never poll in measurement windows."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import csv
|
|
5
|
+
import hashlib
|
|
6
|
+
import os
|
|
7
|
+
import re
|
|
8
|
+
import subprocess
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from acprof.artifact_layout import ArtifactLayout
|
|
12
|
+
from acprof.artifacts import atomic_write_json, read_json_object
|
|
13
|
+
from acprof.cpu_affinity import normalize_cpu_set, parse_cpu_set
|
|
14
|
+
from acprof.hardware_conditions import HARDWARE_FIELDS, conditions_path
|
|
15
|
+
from acprof.host.command import run_command
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _read(path) -> str | None:
|
|
19
|
+
try:
|
|
20
|
+
return Path(path).read_text().strip() or None
|
|
21
|
+
except OSError:
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _run(command) -> str | None:
|
|
26
|
+
try:
|
|
27
|
+
result = run_command(command, capture_output=True, text=True, timeout=10, check=False)
|
|
28
|
+
return result.stdout.strip() if result.returncode == 0 else None
|
|
29
|
+
except (OSError, subprocess.TimeoutExpired):
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def observe_conditions(session) -> dict:
|
|
34
|
+
record = dict.fromkeys(HARDWARE_FIELDS)
|
|
35
|
+
errors = []
|
|
36
|
+
machine_id = _read("/etc/machine-id")
|
|
37
|
+
record["host_id"] = hashlib.sha256(machine_id.encode()).hexdigest() if machine_id else None
|
|
38
|
+
cpuinfo = _read("/proc/cpuinfo") or ""
|
|
39
|
+
record["cpu_model"] = sorted(set(re.findall(r"^model name\s*:\s*(.+)$", cpuinfo, re.M))) or None
|
|
40
|
+
if not re.fullmatch(r"[0-9a-f]{64}", str(getattr(session, "container_id", ""))):
|
|
41
|
+
return {**record, "errors": ["container identity unavailable"]}
|
|
42
|
+
raw = _run(["docker", "top", session.container_id, "-eo", "pid"])
|
|
43
|
+
try:
|
|
44
|
+
pids = [int(value.strip()) for value in (raw or "").splitlines()[1:]]
|
|
45
|
+
masks = set()
|
|
46
|
+
allowed = set()
|
|
47
|
+
for pid in pids:
|
|
48
|
+
try:
|
|
49
|
+
tasks = Path(f"/proc/{pid}/task").iterdir()
|
|
50
|
+
for task in tasks:
|
|
51
|
+
try:
|
|
52
|
+
affinity = os.sched_getaffinity(int(task.name))
|
|
53
|
+
except ProcessLookupError:
|
|
54
|
+
# Threads may exit between /proc enumeration and the
|
|
55
|
+
# affinity read. A vanished thread cannot participate in
|
|
56
|
+
# the later measurement window, so keep evidence from
|
|
57
|
+
# the live siblings instead of discarding the snapshot.
|
|
58
|
+
continue
|
|
59
|
+
allowed.update(affinity)
|
|
60
|
+
masks.add(normalize_cpu_set(",".join(str(cpu) for cpu in sorted(affinity))))
|
|
61
|
+
except FileNotFoundError:
|
|
62
|
+
# docker top is a snapshot; a process can legitimately exit
|
|
63
|
+
# before its task directory is opened.
|
|
64
|
+
continue
|
|
65
|
+
record["cpu_affinity"] = sorted(masks) or None
|
|
66
|
+
governors = {str(cpu): _read(f"/sys/devices/system/cpu/cpu{cpu}/cpufreq/scaling_governor")
|
|
67
|
+
for cpu in sorted(allowed)}
|
|
68
|
+
policy = {
|
|
69
|
+
"governors": governors or None,
|
|
70
|
+
"boost": _read("/sys/devices/system/cpu/cpufreq/boost"),
|
|
71
|
+
"intel_no_turbo": _read("/sys/devices/system/cpu/intel_pstate/no_turbo"),
|
|
72
|
+
}
|
|
73
|
+
# Only one of the boost interfaces may apply; absent interfaces are
|
|
74
|
+
# reported distinctly from missing evidence for every applicable one.
|
|
75
|
+
if policy["boost"] is not None:
|
|
76
|
+
policy.pop("intel_no_turbo")
|
|
77
|
+
elif policy["intel_no_turbo"] is not None:
|
|
78
|
+
policy.pop("boost")
|
|
79
|
+
record["cpu_policy"] = policy
|
|
80
|
+
except (OSError, ValueError, AttributeError) as exc:
|
|
81
|
+
errors.append(f"CPU affinity: {exc}")
|
|
82
|
+
gpu = session.gpu_device
|
|
83
|
+
if gpu:
|
|
84
|
+
raw = _run(["nvidia-smi", f"--id={gpu.get('uuid', '')}",
|
|
85
|
+
"--query-gpu=driver_version,power.limit,persistence_mode", "--format=csv,noheader,nounits"])
|
|
86
|
+
raw_values = next(csv.reader([raw], skipinitialspace=True), []) if raw else []
|
|
87
|
+
values: list[str | None] = [None if value.strip().lower() in {"", "n/a", "[n/a]", "not supported", "[not supported]"}
|
|
88
|
+
else value.strip() for value in raw_values]
|
|
89
|
+
record["gpu"] = {"model": gpu.get("name"), "uuid": gpu.get("uuid"),
|
|
90
|
+
"driver": values[0] if len(values) == 3 else None,
|
|
91
|
+
"power_limit_w": values[1] if len(values) == 3 else None,
|
|
92
|
+
"persistence_mode": values[2] if len(values) == 3 else None}
|
|
93
|
+
else:
|
|
94
|
+
record["gpu"] = "not_applicable"
|
|
95
|
+
import requests
|
|
96
|
+
try:
|
|
97
|
+
response = requests.get(session.base_url + "/meta", timeout=5, headers={"Connection": "close"})
|
|
98
|
+
response.raise_for_status()
|
|
99
|
+
observed = response.json().get("runtime_parameters", {}).get("effective", {}).get("threads")
|
|
100
|
+
record["runtime_threads"] = observed if type(observed) is int and observed > 0 else None
|
|
101
|
+
except (requests.RequestException, ValueError, AttributeError, TypeError) as exc:
|
|
102
|
+
errors.append(f"runtime threads: {exc}")
|
|
103
|
+
return {**record, "errors": errors}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def record_case_conditions(output_dir, case_id, session, *, cpuset_cpus="") -> None:
|
|
107
|
+
cpuset_cpus = normalize_cpu_set(cpuset_cpus)
|
|
108
|
+
path = conditions_path(ArtifactLayout.discover(output_dir))
|
|
109
|
+
payload = (
|
|
110
|
+
read_json_object(path, label="hardware conditions")
|
|
111
|
+
if path.exists()
|
|
112
|
+
else {"schema_version": 1, "cases": {}}
|
|
113
|
+
)
|
|
114
|
+
if not isinstance(payload, dict) or payload.get("schema_version") != 1 or not isinstance(payload.get("cases"), dict):
|
|
115
|
+
raise ValueError("unsupported hardware conditions schema")
|
|
116
|
+
observed = observe_conditions(session)
|
|
117
|
+
observed["requested_cpuset"] = cpuset_cpus or "unrestricted"
|
|
118
|
+
# Runtimes may pin individual workers more narrowly than Docker's CPU set.
|
|
119
|
+
# Every observed thread must stay inside the requested boundary.
|
|
120
|
+
affinities = observed["cpu_affinity"]
|
|
121
|
+
requested = parse_cpu_set(cpuset_cpus)
|
|
122
|
+
verified = bool(affinities) and all(
|
|
123
|
+
parse_cpu_set(mask) and parse_cpu_set(mask) <= requested for mask in affinities
|
|
124
|
+
) if cpuset_cpus else True
|
|
125
|
+
if not verified:
|
|
126
|
+
observed["errors"].append("thread affinities are unknown or outside the requested CPU set")
|
|
127
|
+
payload["cases"][case_id] = observed
|
|
128
|
+
atomic_write_json(path, payload)
|
|
129
|
+
if not verified:
|
|
130
|
+
raise RuntimeError("cannot verify requested CPU set on the running container")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Host image planning, dependency evidence, inventory and runtime assembly."""
|