2010-07-14 4 views
9

На таких процессорах, как x86, которые обеспечивают согласованность кеша, как это полезно с практической точки зрения? Я понимаю, что идея состоит в том, чтобы сделать обновление памяти на одном ядре сразу же видимым на всех остальных ядрах. Это полезное свойство. Однако нельзя полагаться на него слишком сильно, если не писать на ассемблере, потому что компилятор может хранить назначения переменных в регистрах и никогда не записывать их в память. Это означает, что все еще нужно предпринимать явные шаги, чтобы убедиться, что материал, созданный в других потоках, виден в текущем потоке. Таким образом, с практической точки зрения, достигнута ли когерентность кеширования?Какой смысл когерентности кеша?

ответ

6

Представьте, что вы делаете это:

lock(); //some synchronization primitive e.g. a semaphore/mutex 
globalint = somevalue; 
unlock(); 

Если бы не было когерентность кэша, что в прошлом unlock() бы гарантировать, что globalint теперь видны повсюду, с кэш-coherance все, что вам нужно сделать, это написать его память и пусть аппаратное обеспечение делает магию. Программное решение могло бы сохранить то, какая память существует, в которой кеши, на каких ядрах, и каким-то образом убедиться, что они синхронно синхронно.

Вы получите выигрышную награду, если сможете найти программное обеспечение, которое отслеживает все фрагменты памяти, которые существуют в кэшах, которые должны синхронизироваться, что более эффективно, чем текущее аппаратное решение.

1

Когерентность кеша становится чрезвычайно важной, когда вы имеете дело с несколькими потоками и получаете доступ к одной и той же переменной из нескольких потоков. В этом конкретном случае у вас есть, чтобы гарантировать, что все процессоры/ядра видят одно и то же значение, если они одновременно обращаются к переменной, иначе у вас будет чудесно недетерминированное поведение.

9

Короткий рассказ о том, что когерентная система, не относящаяся к кешу, чрезвычайно сложна для программирования, особенно если вы хотите сохранить эффективность, что также является основной причиной, по которой большинство систем NUMA сегодня являются кеш-когерентными.

Если тайники несовместимы, «явные шаги» должны были бы обеспечить согласованность. Явные действия, как правило, такие вещи, как критические разделы/мьютексы (например, volatile в C/C++ достаточно редко). Это довольно сложно, если не невозможно, для таких сервисов, как мьютексы, отслеживать только память, которая имеет изменения и должна быть обновлена ​​во всех кэшах - это, вероятно, должно было бы обновить всю память, а это значит, что она может даже отслеживать в каких ядрах есть какие части этой памяти в своих кэшах.

Предполагается, что аппаратное обеспечение может выполнять гораздо лучшую и эффективную работу по отслеживанию адресов/диапазонов памяти, которые были изменены, и держать их в синхронизации.

И представьте себе процесс, выполняющийся на ядре 1, и выгружается. Когда он снова будет назначен, он будет назначен на ядро ​​2.

Это было бы довольно фатально, если бы кеши не были хороши, так как в противном случае могут быть остатки данных процесса в кеше ядра 1, что не существуют в кеше 2-го уровня. Хотя для систем, работающих таким образом, ОС необходимо будет обеспечить согласованность кеша, поскольку потоки запланированы, что, вероятно, будет «обновлять всю память в кэшах между всеми ядрами» или, возможно, может отслеживать грязные страницы с помощь MMU и только синхронизировать страницы памяти, которые были изменены - опять же, аппаратное обеспечение, скорее всего, позволит кешам связываться более тонко и эффективно.

+0

Процесс миграции между ядрами не является очень частым, поэтому затраты на очистку кэша записи для любого ядра, которое теряет процесс, или очистка кэша чтения для любого ядра, которое его получает, действительно не должно быть слишком большим проблема. Большая проблема заключается в том, что если процесс # 1 работает на ядрах A и B, а процесс №2 работает на C и D, ядра C и D не должны инвестировать какие-либо ресурсы, наблюдающие обращения к памяти, сделанные от имени процесса № 1 по ядрам A и B, поскольку эти области памяти действительно не должны представлять интереса. – supercat

0

Это не требуется для блокировки. Код блокировки будет включать очистку кеша, если это необходимо. В основном необходимо убедиться, что одновременные обновления различными процессорами для разных переменных в одной строке кэша не теряются.

6

Есть некоторые нюансы, не покрываемые замечательными ответами других авторов.

Прежде всего, учтите, что процессор не имеет памяти побайтовым, а с линиями кеша. Линия может иметь 64 байта. Теперь, если я выделяю 2-байтовую часть памяти в местоположении P, а другой CPU выделяет 8-байтовую часть памяти в местоположении P + 8, и оба P и P + 8 живут в одной и той же строке кэша, наблюдайте, что без когерентности кэша два ЦП не могут одновременно обновлять P и P + 8 без скрещивания друг друга! Поскольку каждый процессор выполняет чтение-изменение-запись в строке кэша, они могут выписать копию строки, которая не включает изменения другого ЦП! Последний автор выиграет, и одна из ваших модификаций в памяти «исчезнет»!

Другая вещь, которую следует учитывать, - это различие между согласованностью и согласованностью. Поскольку даже процессоры с процессором x86 используют буферы хранилища, нет гарантий, которые вы могли бы ожидать, что уже завершенные инструкции изменили память таким образом, что другие процессоры могут видеть эти изменения, даже если компилятор решил записать значение обратно (возможно, из-за volatile?). Вместо этого моды могут сидеть в буферах хранилища. Практически все процессоры в целом используют кеш-когерентность, но очень немногие процессоры имеют модель согласованности, столь же прощающую, как и x86. Проверьте, например, http://www.cs.nmsu.edu/~pfeiffer/classes/573/notes/consistency.html для получения дополнительной информации по этой теме.

Надеюсь, что это помогает, и BTW, я работаю в Corensic, компании, которая строит отладчик параллелизма, который вы можете проверить. Это помогает собирать куски, когда предположения о параллельности, согласованности и последовательности оказываются необоснованными :)

+1

доступ запрещен к ссылке. Ошибка 403. ( – Ayrat

0

Когерентность кэша реализована на аппаратных средствах, поскольку программисту не нужно беспокоиться о том, чтобы все потоки отображали самое последнее значение памяти при работе в многоядерных/многопроцессорных средах. Когерентность кэша дает абстракцию, что все ядра/процессоры работают в одном унифицированном кеше, хотя у каждого ядра/процессора есть свой собственный кеш.

Он также гарантирует, что устаревший многопоточный код работает так же, как на новых моделях процессоров/многопроцессорных системах, без внесения каких-либо изменений кода для обеспечения согласованности данных.