Is it safe to prefetch a potentially invalid address?

The documentation for prefetch_read_data does not specify whether it is safe to pass a pointer that is potentially out of bounds. It would be convenient if this is allowed, as it allows eg. a loop to prefetch data for a future iteration, without having to take care of whether there is in fact a next iteration.

Does anyone know if there are any common architectures where prefetching an invalid address could cause a fault?

I found some info on Stack Overflow but this is limited to x86-64.

1 Like

The docs say:

Prefetches have no effect on the behavior of the program

So it is safe.

5 Likes

Semi-relatedly, the docs for the prefetch_read_data mention a locality parameter, and how it is used as a locality specifier, but it doesn't mention whether that is the source or target of the prefetch.
A clarification on that in those docs would be useful and welcome.

I'm not to sure what can be clarified there, though. Modern CPUs have prefetch instructions. These come in different form and, sometimes, have a locality argument. Which, in most extreme cases goes from 0 to NTA. And treatment of that argument is not just architecture-specific, but CPU-specific (note how even architecture-specific documentation talks about T0, T1, T2, and NTA hints without precisely specifying what they mean… you need CPU-specific documentation to get precise info… and often sign an NDA before you'll get it).

Do you want to add 100+ pages research paper to the documentation or what?

If you have link to such paper then it would be interesting for someone, I assume, but documentation already includes all easily accessible publicly-available documentation.

It's not really meaningful to talk about the "source" and "target" of a prefetch when you're looking at a locality parameter; the underlying CPU instructions are defined as doing a fetch from memory into closer-to-core structures, so the source is always memory, and the target is always some data structure specified by the locality parameter.

I would, however, agree that if Rust adds a stable counterpart to the unstable intrinsic (just as std::intrinsics::powf32 has f32::powf as the stable counterpart), it should be a lot better documented - it should, at the very least, be an enum for locality, not an integer, and the enum should have clear meaning.

But that conflicts with the level to which processor vendors currently document prefetch instructions publicly. For example. locality level 0 is defined by Intel as NTA, which in turn is defined as "prefetch data into non-temporal cache structure and into a location close to the processor, minimizing cache pollution"), where there's no clear meaning given (but, for example, there exists a processor on which the equivalent of an NTA prefetch is defined as filling the TLB for that address so that a non-temporal access of that address does not wait for virtual to physical address translation).

Further, processor vendors have historically treated some locality hints as identical - for example, locality 1 and 2 were the same on some CPUs (but not others), and the impact of prefetching with the wrong locality hint has varied between CPUs - some CPUs will abandon the prefetch when it's clear that the result will be instantly discarded, while others will let it complete (with associated memory traffic and other costs) and then evict the prefetch result from cache.

3 Likes

Thanks. I was hoping that "no effect" included "no effect even if the input is an invalid pointer", but wasn't completely sure.

1 Like