Struct ClockCalibration
- Namespace
- DotCompute.Abstractions.Timing
- Assembly
- DotCompute.Abstractions.dll
Represents calibration data for converting between CPU and GPU time domains.
public readonly struct ClockCalibration : IEquatable<ClockCalibration>
- Implements
- Inherited Members
Remarks
Clock calibration is performed by collecting paired CPU-GPU timestamps and fitting a linear model: GPU_time = offset + drift * CPU_time. This compensates for:
- Clock Offset: Different initialization times
- Clock Drift: Frequency differences (typically 50-200 PPM)
Typical Drift Rates:
- 50 PPM: 180μs drift per hour
- 100 PPM: 360μs drift per hour
- 200 PPM: 720μs drift per hour
Recommended Usage:
// Initial calibration
var calibration = await timingProvider.CalibrateAsync(100);
// Convert GPU time to CPU time domain
long gpuTime = await timingProvider.GetGpuTimestampAsync();
long cpuTime = calibration.GpuToCpuTime(gpuTime);
// Get uncertainty bounds
var (min, max) = calibration.GetUncertaintyRange(gpuTime);
// Recalibrate periodically (every 5-10 minutes)
if (DateTime.UtcNow - lastCalibration > TimeSpan.FromMinutes(5))
{
calibration = await timingProvider.CalibrateAsync(100);
}
Properties
CalibrationTimestampNanos
Gets the timestamp when this calibration was performed (CPU time in nanoseconds).
public long CalibrationTimestampNanos { get; init; }
Property Value
- long
The calibration timestamp in nanoseconds since an implementation-defined epoch. Used to determine when recalibration is needed.
DriftPPM
Gets the clock drift rate in parts per million (PPM).
public double DriftPPM { get; init; }
Property Value
- double
The drift rate in PPM. Positive values indicate the GPU clock runs faster than the CPU clock. Typical range: 50-200 PPM.
Remarks
PPM (parts per million) represents the frequency difference between clocks:
- 50 PPM = 0.005% frequency difference = 50μs drift per second
- 100 PPM = 0.01% frequency difference = 100μs drift per second
Over time, drift accumulates. For 100 PPM drift:
- 1 minute: 6μs accumulated drift
- 1 hour: 360μs accumulated drift
- 1 day: 8.64ms accumulated drift
ErrorBoundNanos
Gets the error bound (±uncertainty) of the calibration in nanoseconds.
public long ErrorBoundNanos { get; init; }
Property Value
- long
The error bound in nanoseconds, representing ±1 standard deviation from the linear regression fit. Smaller values indicate higher calibration accuracy.
Remarks
The error bound is computed from regression residuals and represents the typical uncertainty in time conversions. For a 68% confidence interval, the actual time is within [estimated - error, estimated + error].
Factors Affecting Error:
- Sample count: More samples → lower error
- System load: Lower load → lower error
- Clock stability: Stable clocks → lower error
OffsetNanos
Gets the offset between GPU and CPU clocks in nanoseconds (GPU_time - CPU_time).
public long OffsetNanos { get; init; }
Property Value
- long
The clock offset in nanoseconds. Positive values indicate the GPU clock is ahead of the CPU clock. This offset accounts for different initialization times.
Remarks
This offset is the intercept of the linear regression: GPU_time = offset + drift * CPU_time.
SampleCount
Gets the number of timestamp pairs used for calibration.
public int SampleCount { get; init; }
Property Value
- int
The sample count. Higher counts improve accuracy but increase calibration time. Typical values: 50-200 samples.
Methods
CpuToGpuTime(long)
Converts a CPU timestamp to the GPU time domain.
public long CpuToGpuTime(long cpuTimeNanos)
Parameters
cpuTimeNanoslongThe CPU timestamp in nanoseconds.
Returns
- long
The corresponding GPU time in nanoseconds, accounting for offset and drift.
Remarks
Conversion formula: GPU_time = CPU_time * (1 + drift_ppm / 1_000_000) + offset
Example:
long cpuTime = 1_000_000_000; // 1 second in CPU time
long gpuTime = calibration.CpuToGpuTime(cpuTime);
// gpuTime ≈ 1_000_100_000 (assuming 100 PPM drift and 0 offset)
Equals(ClockCalibration)
Determines whether the specified ClockCalibration is equal to the current instance.
public bool Equals(ClockCalibration other)
Parameters
otherClockCalibrationThe ClockCalibration to compare with the current instance.
Returns
- bool
True if the specified ClockCalibration is equal to the current instance; otherwise, false.
Equals(object?)
Determines whether the specified ClockCalibration is equal to the current instance.
public override bool Equals(object? obj)
Parameters
objobjectThe object to compare with the current instance.
Returns
- bool
True if the specified object is equal to the current instance; otherwise, false.
GetHashCode()
Returns the hash code for this instance.
public override int GetHashCode()
Returns
- int
A 32-bit signed integer hash code.
GetUncertaintyRange(long)
Gets the uncertainty range for a GPU timestamp conversion.
public (long min, long max) GetUncertaintyRange(long gpuTimeNanos)
Parameters
gpuTimeNanoslongThe GPU timestamp in nanoseconds.
Returns
- (long min, long max)
A tuple containing the minimum and maximum CPU time bounds (inclusive), representing a ±1 standard deviation confidence interval.
Remarks
The uncertainty range accounts for calibration error and provides a confidence interval for time conversions. For normally distributed errors:
- 68% of measurements fall within [min, max]
- 95% of measurements fall within [min - error, max + error]
Example:
long gpuTime = 1_000_000_000;
var (min, max) = calibration.GetUncertaintyRange(gpuTime);
// With error bound of 1000ns:
// min ≈ 999_999_000, max ≈ 1_000_001_000
// True time is likely within this range (68% confidence)
GpuToCpuTime(long)
Converts a GPU timestamp to the CPU time domain.
public long GpuToCpuTime(long gpuTimeNanos)
Parameters
gpuTimeNanoslongThe GPU timestamp in nanoseconds.
Returns
- long
The corresponding CPU time in nanoseconds, accounting for offset and drift.
Remarks
Conversion formula: CPU_time = (GPU_time - offset) / (1 + drift_ppm / 1_000_000)
Example:
long gpuTime = 1_000_000_000; // 1 second in GPU time
long cpuTime = calibration.GpuToCpuTime(gpuTime);
// cpuTime ≈ 999_900_000 (assuming 100 PPM drift and 0 offset)
ShouldRecalibrate(long, double)
Determines whether this calibration should be refreshed.
public bool ShouldRecalibrate(long currentTimeNanos, double maxAgeMinutes = 5)
Parameters
currentTimeNanoslongThe current CPU time in nanoseconds (same epoch as CalibrationTimestampNanos).
maxAgeMinutesdoubleMaximum calibration age in minutes before refresh is recommended (default: 5 minutes).
Returns
- bool
True if the calibration age exceeds
maxAgeMinutes, false otherwise.
Remarks
Clock drift accumulates over time, so periodic recalibration is recommended. For typical drift rates (100 PPM):
- 5 minutes: 30μs accumulated drift
- 10 minutes: 60μs accumulated drift
- 30 minutes: 180μs accumulated drift
Usage:
long currentTime = GetCurrentCpuTimeNanos();
if (calibration.ShouldRecalibrate(currentTime, maxAgeMinutes: 5))
{
calibration = await timingProvider.CalibrateAsync(100);
}
Operators
operator ==(ClockCalibration, ClockCalibration)
Determines whether two ClockCalibration instances are equal.
public static bool operator ==(ClockCalibration left, ClockCalibration right)
Parameters
leftClockCalibrationThe first instance to compare.
rightClockCalibrationThe second instance to compare.
Returns
- bool
True if the instances are equal; otherwise, false.
operator !=(ClockCalibration, ClockCalibration)
Determines whether two ClockCalibration instances are not equal.
public static bool operator !=(ClockCalibration left, ClockCalibration right)
Parameters
leftClockCalibrationThe first instance to compare.
rightClockCalibrationThe second instance to compare.
Returns
- bool
True if the instances are not equal; otherwise, false.