Коротко говоря, системы, не связанные с кэшем, чрезвычайно трудно программировать, особенно если вы хотите поддерживать эффективность, что также является основной причиной того, что даже большинство систем NUMA сегодня являются когерентными.
Если кеши не являются связными, то «явные шаги» должны были бы обеспечить согласованность - явные шаги обычно бывают такими, как критические секции / мьютексы (например, volatile в C / C ++ достаточно редко). Для таких сервисов, как мьютексы, довольно сложно, если не невозможно, отслеживать только память, которая имеет изменения и должна быть обновлена во всех кэшах, - вероятно, ей придется обновить всю память, а это если бы она могла даже отслеживать какие ядра имеют какие части этой памяти в своих кешах.
Предположительно, аппаратное обеспечение может выполнять гораздо лучшую и эффективную работу по отслеживанию адресов / диапазонов памяти, которые были изменены, и поддерживает их синхронизацию.
И представьте себе процесс, работающий на ядре 1 и прерванный. Когда он снова запланирован, он будет назначен на ядре 2.
Это было бы довольно фатально, если бы кэши не были выбраны, так как в противном случае могли бы быть остатки данных процесса в кэше ядра 1, которого нет в кэше ядра 2. Хотя для систем, работающих таким образом, ОС должна обеспечивать согласованность кэша при планировании потоков - что, вероятно, будет операцией «обновить всю память в кэшах между всеми ядрами», или, возможно, она может отслеживать грязные страницы с помощью с помощью MMU и синхронизировать только те страницы памяти, которые были изменены - опять же, аппаратное обеспечение, скорее всего, сохранит целостность кэшей более тонко и эффективно.