Table of Contents

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

cpuTimeNanos long

The 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

other ClockCalibration

The 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

obj object

The 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

gpuTimeNanos long

The 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

gpuTimeNanos long

The 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

currentTimeNanos long

The current CPU time in nanoseconds (same epoch as CalibrationTimestampNanos).

maxAgeMinutes double

Maximum 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

left ClockCalibration

The first instance to compare.

right ClockCalibration

The 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

left ClockCalibration

The first instance to compare.

right ClockCalibration

The second instance to compare.

Returns

bool

True if the instances are not equal; otherwise, false.