Skip to content

Implement DPC4 improvements #690

Open

Description

@maccoymerrell

Two improvements were made to DPC4 to facilitate the competition (ignoring the added prefetch hooks like bandwidth utilization and ipc sampling). We should consider adopting both of these changes.

  1. CPU halt during warmup
  • In multi-core, all cores continue to execute instructions until all cores' warmups are completed
  • This results in warmup performance directly impacting which instructions are executed during simulation
  • For long-running warmups like in multi-core, shifts in which instructions are executed between heterogeneous mixes can be significant, upwards of 10s of millions of instructions
  • This makes comparing performance of traces across mixes and different policies difficult

For DPC4, cpu halt stops feeding instructions to cpus which have completed warmup until the simulation begins. This has the negative outcome of shared resources (like the LLC) being cold upon exiting warmup, but the benefit of the stability of the results of the simulation.

  1. Instruction flag to cache packets
  • For a data prefetching competition, it was deemed unfair to allow prefetchers to prefetch instructions.
  • A flag was added which allows for should_prefetch() to control and filter out instruction triggers for prefetchers
  • This flag can either be set within the CPU as instruction fetches leave, or determined by a direct comparison between virtual address and ip.

Instead of a hard-coded filtering like was done in DPC4, an additional configure flag for the caches should be created to enable/disable instruction triggers. The best way to implement this is unclear (for example, LOAD could be split to LOAD_INSTR and LOAD_DATA enums so that the prefetch sensitivity list could exclude instruction or data loads using our current system).

Activity

  1. ngober commented on Feb 15, 2026

    @ngober
    Collaborator

    I think that both of these are probably good changes to make in some form.

    Considering warmup, I think the methodology here matters a lot for correctness, but I don't think that the suggestion here is correct. As you indicate, this methodology is bad for shared resources, especially the closer those resources are to the top of the hierarchy. Something that I think would be ideal is a general model of [static warmup, dynamic warmup, execution].

    Take a cache for example:

    1. We start by flashing in an image of the cache contents (there is a high error tolerance here)
    2. Then we quickly send a series of memory requests, allowing the cache to exercise and to cover any lacuna in the static warmup.
    3. Then we run the pipe for a bit (the warmup we are used to) to get the timing down. This can actually be really short, since we don't need to fill the caches.
    4. Simulation start.

    For multi-trace simulations, we can interleave the different parts of warmup: Synthesize an image from multiple images, interleave requests in dynamic warmup, and run a full simulation. A similar thing could be done for the front end, with branch predictors and BTBs. I emphasize that what I'm describing here reduces the dependency on relative timings, whereas the DPC4 methodology just tries to go for repeatability even if it's still timing-dependent.

    This requires a new trace format. I feel like I say this every 3-4 months.

    Considering marking instructions, I'm coming around on this. We used to have that flag in ChampSim, but I took it out because I insisted that a memory demand should just be a memory demand, and access patterns are access patterns. But, I think it does make sense to be a type, like you describe. Then, modules can make their own decisions about how to handle things.

  2. maccoymerrell commented on Feb 15, 2026

    @maccoymerrell
    ContributorAuthor

    In absence of a new trace format, perhaps we could do warmup via something close to the following:

    1. Strip virtual addresses from the full section of warmup instructions in the trace (defined by the user as done currently)
    2. Run these in-order and quickly through the memory model (this should be very fast, maybe less than 10 minutes for 2B instructions depending on the trace). We could also show a warning if the given warmup was insufficient to fill the caches. For shared caches and the like, we should interleave the requests coming from each cpu.
    3. Run the pipe and train the branch predictor, fill the btb, etc... -> this can start only a few million instructions before the warmup would end
    4. Simulation start.

    This wouldn't rely on flashing the cache, or modifying the trace format, which in some way might be bad but it does allow replacement policies and prefetchers to train during 1, along with building a valid virtual-physical map, etc... which would be problems for flashing the cache directly from a trace.

    If we agree on the approach to the second change, then I can make a pr to split packet LOAD types to LOAD_INSTR and LOAD_DATA. For legacy support, could we have those both alias into LOAD somehow? Maybe override the equals operator?

  3. alberto-ros commented on Feb 15, 2026

    @alberto-ros
    Collaborator

    Let me add something about warmup. Since cache latencies are neglected, and therefore the bandwidth hook in DPC4 shows always low utilization, prefetchers that use latency computations (e.g., Berti or I-POP) or bandwidth (e.g., Pythia) do not learn correctly during warmup. I would opt of no need to warmup (or having a real warmup), mostly if more than 100M instructions are executed for simulation. I think SimPoint papers mention that when running so many instructions warmup is not relevant.

  4. maccoymerrell commented on Feb 15, 2026

    @maccoymerrell
    ContributorAuthor

    I think this can be said to be true at the time of the simpoint papers, but modern memory systems (specifically LL caches) are large, to the point where 20M or more instructions may be needed to populate them fully and get replacement policies like SHiP or DRRIP trained (of course, this depends on the trace, I am sure lbm or mcf could fill them in 1M instructions). I would consider 20M of 100M statistically significant, such that warmup seems like a preferable choice over running 1B+ instructions to wash out initial performance overheads. Something could probably be said about ChampSim's simulation performance as well for this - anecdotally the cycle simulation time seems to have been ticking up since 2023, and running a multi-core simulation for more than 50M instructions should not be a multi-day endeavor.

    Regardless, ChampSim has the capability to do no warmup, so it seems that if a user wants to run without warmup then they will bear the burden of justifying it in whatever papers they publish and ChampSim should leave both options available to users.

    This is kind of tangential to what is being discussed, but cold-start/context-switch/phase-change overheads are important. Branch prediction research takes this fairly seriously, and any dynamic prefetching technique should consider this. What I am getting at is that if Berti or Pythia or I-POP cannot recover and retrain after warmup quickly, then that is not necessarily a fault in the warmup technique itself. For future DPCs, considering the comments made by Google and the like, these types of behaviors may become far more relevant and things like multithreading and scheduling should probably be added to ChampSim.

  5. ngober commented on Feb 16, 2026

    @ngober
    Collaborator

    In absence of a new trace format, perhaps we could do warmup via something close to the following:

    1. Strip virtual addresses from the full section of warmup instructions in the trace (defined by the user as done currently)
    
    2. Run these in-order and quickly through the memory model (this should be very fast, maybe less than 10 minutes for 2B instructions depending on the trace). We could also show a warning if the given warmup was insufficient to fill the caches. For shared caches and the like, we should interleave the requests coming from each cpu.
    
    3. Run the pipe and train the branch predictor, fill the btb, etc... -> this can start only a few million instructions before the warmup would end
    
    4. Simulation start.
    

    I like this idea as an intermediate step. The infrastructure can get built while the traces still get used. A note, though. I think the branch predictor should be warmed as well. It is a long-range predictor just like the LLC is. It could even be warmed in parallel with the caches!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions