|
|
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Usmanredwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы?Очевидно увеличится время получения значения из памяти Что-то для меня это вообще не очевидно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 12:52 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Usmanпропущено... Очевидно увеличится время получения значения из памятиЧто-то для меня это вообще не очевидно. http://ru.wikipedia.org/wiki/Кэш_процессора ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 13:04 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Usman, мы ж уже разобрались, что волатильная перменная один хрен будет читаться из памяти. Получается наоборот имеем излишние накладные расходы на запись в кеш, из которого никогда не будем читать эту переменную. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 13:07 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? 16254221 redwhite90волатильная перменная один хрен будет читаться из памятиС этим никто не спорит, другое дело, операция чтения/записи в volatile-переменную будет медленнее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 13:18 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Usmanredwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? 16254221 redwhite90волатильная перменная один хрен будет читаться из памятиС этим никто не спорит, другое дело, операция чтения/записи в volatile-переменную будет медленнее. Поясните! В одном случае пишется только в память, в другом в память и в кеш. и вы утверждаете, что писать в память и в кеш быстрее нежели чем просто в кеш. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 13:26 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90, volatile будет медленнее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 14:28 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
maytonredwhite90, volatile будет медленнее. согласен, но как это коррелируется с Usmanredwhite90Что поменялось бы если бы волатильная переменная не кешировалась бы? Очевидно увеличится время получения значения из памяти вообще не понимаю как это связано. UsmanС этим никто не спорит, другое дело, операция чтения/записи в volatile-переменную будет медленнее. медленне в каком случае ?как сейчас, когда пишется и в кеш и в память или когда пишется только в память? и кстати Blazkowicz , что подразумевается под памятью? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 15:28 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90и кстати Blazkowicz , что подразумевается под памятью? Современные процессоры, намного сложнее устроены. То что я тебе описал, это примерно на уровне Z80 и 8086. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 15:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90 , Вынужден констатировать, что все предоставленные вам ответы либо вообще некорректны, либо используют некорректную терминологию, а от того еще больше запутывают. Для понимания работы volatile (и JMM в целом) недостаточно знать Java. Надо понимать архитектуру компьютеру. Постараюсь вам все пояснить, пройдя "снизу вверх". I. Давайте начнем с того, что представим себе, что процессор общается с памятью напрямую. То есть нет никаких регистров, нет никаких кэшей, есть только ядро, память, и шина (суть "провода"), связывающие память и процессор. Когда процессору надо запросить какую-то информацию, он просто говорит памяти "дай мне данные по адресу 100". Просто? Просто. II. К сожалению, упомянутый выше подход не работает. Что такое код программы? Что записано в exe файле, в dll'ке или so'шнике? Это набор инструкций, которые процессор исполняет. В общем случае инструкции выполняются последовательно. Но иногда необходимо перепрыгнуть ряд инструкций, и уйти в другую область кода. Например, когда вы встретили if. Для этого у каждого процессора есть набор соответствующих инструкций (jmp, jne, и т.д..). Но для того, что бы осуществить прыжок, нужно знать адрес той инструкции, на которую надо прыгнуть. Отсюда мы приходим, что каждая инструкция должна иметь адрес, что бы можно было на нее "прыгнуть", так? Окей. а как задать адреса инструкциям? Как записать эти адреса в exe файл? Ну давайте просто последовательно их выдавать, начиная с нуля: 0, 1, 2, 3, ... А потом, когда мы запустим exe-шник, он просто загрузит эти инструкции в память по этим же адресам. То есть инструкция с адресом 100 будет в ячейке памяти 100, 101 в 101, и т.д.. Круто? Не очень, Ведь если вы сначала загрузили программу A, которая заняла адреса 0 ... 100, дошли до инструкции 50, а там вам сказали прыгнуть на 80. А в это время вы запустили программу B, которая перетерла эти инструкции своим кодом. В итоге вы из программы A прыгните на инструкцию 80 ... и начнете выполнять другую программу. Это не круто. Аналогично и с данными, которые нужны программе. Допустим, вы хотите записать по константному адресу какое-то значение, что бы другие участки программы могли ее считать. Вы говорите "запиши эту стрингу по адресу 100500". Потому стартует другая программа, которая ничего не знает о вашей, и просто перетирает ваши данные. Не круто. III. Что бы забороть эти проблемы вводят понятие виртуальных адресов. Когда вы стартуете процесс, ОС выделяет ему какую-то область памяти, к которой имеет доступ он и только он. Например, приложению A дали адреса 0 ... 99, приложению B 100 ... 199. Это круто. Но ведь в exe-шниках обеих программ записаны адреса, начиная с нуля! Как быть? А так, что процессор начинает работать с теми адресами, что записаны в исполняемом файле. Это виртуальные адреса. Но он каким-то образом понимает, что виртуальный адрес 10 для конкретного процесса, это адрес 110 в "реальной памяти" (физический адрес). Отсюда мы приходим к тому, что процессор не может работать с памятью напрямую. Ему как минимум нужен преобразователь адресов. Назовем это устройство "контроллер памяти". Он находится где-то между процессором и физической планкой памяти. И процессор вообще ничего не знает о памяти, установленной внутри вашей системы. Он знает только протокол общения с этим контроллером, и все. IV. Мы знаем, что адреса всегда проходят через этот контроллер. И каждый раз мы получаем виртуальный адрес, каким-то образом превращаем его в физический адрес, и отправляем запрос в память. Потом получаем ответ, делаем обратное преобразование, и отвечаем процессору. А можно ли как-то закэшировать эти пары? Ну, например, если я однажды узнал, что виртуальный адрес 100, а это реальный адрес 995, то я бы хотел запомнить где-то пару (100, 995), что бы потом быстрее делать эти преобразования. Это реально? Конечно реально! Для этого почти на каждом современном процессоре есть так называемый translation lookaside buffer (TLB), который хранит эти пары, ускоряя преобразования виртуаьлных адресов в физические и наоборот. Процессор ничего не знает про этот кэш, он просто спрашивает контроллер. V. Мы так же знаем, что данные так же всегда проходят через этот контроллер, так как процессор не может работать с памятью напрямую. Можем ли мы кэшировать данные так же, как мы кэшируем пары (виртуальный адрес, физический адрес)? Конечно можно! Давайте просто будем сохранять все прошедшие через нас данные куда-то, тем самым ускоряя доступ к ним? Это будет немного медленнее, чем прямая запись в память при первой записи/чтении, но даст нам огромный прирост при последующих доступах к этому же адресу. Мы приходим к первому важному выводу: процессор ничего не знает про кэш. Ни-че-го. Он не может сказать "дайте мне вот это из кэша, а вот это из физической планки". Он просто говорит контроллеру "дай мне такой-то адрес" или "запиши по такому-то адресу", а контроллер уже сам решает, как ему поступить. ВЫВОД 1: Процессор не отличает память и кэш, для него это единая комплексная система. VI. Когда у нас появляется больше, чем одно ядро, мы выделяем каждому ядру по своему кэшу. Но возникает вопрос: а что будет, если два ядра одновременно будут читать/писать по одному адресу? Будут проблемы. Например, в кэше одного процессора может оказаться одно значение, а в кэше другого другое. Или вот другая проблема - что, если в кэше нашего процессора нет значения адреса 100, но он есть в кэше другого процессра? Что нам делать - бежать в основную память, или запросить значение в другом кэше? Быстрее будет запросить у другого кэша. Поэтому, что бы скоординировать действия кэшей разных процессоров, нам надо придумать какой-то протокол их взаимодействия, надо придумать протокол когерентности кэшей . И он был придуман - MESI, и его многочисленные вариации. Когда один процессор записывает что-то по адресу A, то подсистема памяти проверяет кэши всех процессоров, что бы убедиться, что они сотрут (инвалидируют) у себя старое значение, и на следующем чтении смогут вычитать новое значение. Проблема в том, что протоколы когерентности привносят накладные расходы, которые хотелось бы минимизировать. И были придуманы две хитрости: 1) Когда мы делаем запись, то надо сначала инвалидировать значения в других кэшах, а потом уж записать свое значение. Окей, мы запускаем этот процесс ... но не ждем его завершения, а тут же сообщаем процессору "да, все ничтяк, записал", и идем дальше. И пока этот процесс не завершился, новое значение хранится в специальной структуре конкретного ядра - store buffer. Если процессору потребуется еще раз это значение, то мы выдадим ему значение из store buffer. А потом, чуть позже, когда другие кэши ответят, что успешно инвалидировали старое значение, мы уже по-настоящему перенесем это значение из store buffer в кэш. 2) Когда наш кэш просят инвалидировать значение, он может быть занят другими операциями, и ответит на запрос на инвалидацию задержкой. Но эта инвалидация в любом случае рано или поздно произойдет. Поэтому, когда нашему кэшу приходит запрос на инвалидацию, он кладет этот запрос в некую очередь, и сразу же отвечает "да, все ничтяк, инвалидировал", а на самом деле инвалидирует его позднее, когда ему будет это удобно сделать. Эта очередь называется invalidate queue. Эти две хитрости - store buffer и invalidate queue очень здорово ускоряют работу протокола когерентности. Но из-за того, что они по сути асинхронны, кэши разных процессоров могут временно разъезжаться. В итоге то они станут когерентными, но в моменте могут иметь разные значения. Поэтому два одновременных чтения одного и того же адреса на разных ядрах могут вернуть разный результат. Но что сделать, если я хочу, продолжить исполнение только тогда, когда мою запись гарантированно смогут увидеть все другие ядра? Для этого мне надо убедиться, что моя запись ушла из store buffer в кэш. А что сделать, если я хочу вычитать максимально актуальное значение текущей переменной? Для это я должен обработать все текущие invalidate запросы, и только потом попробовать вычитать это значение. Как попросить подсистему памяти сделать это? Для этого у процессоров существуют специальные инструкции (или модификаторы инструкций). Например, для x86 это префикс lock (и другие). А как попросить процессор выполнить эту инструкцию? Ну либо просто ее вызвать на ассемблере, либо же попросить об этом операционную систему, попросив ее вызвать так называемый барьер памяти, который синхронизирует определенным образом состояние кэша текущего процессора с кэшами других. VII Как именно происходит эта синхронизация? Если мне надо убедиться, что запись в кэш завершена, и другие процессору смогут ее увидеть, мне надо дождаться, пока моя запись не уйдет из store buffer в кэш. Но так как записи складываются в store buffer последовательно, к тому моменту, как моя запись уйдет в кэш, в него так же гарантированно уйдут и все предыдущие записи. А что с чтениями? Что бы убедиться, что следующее чтение вернет актуальное значение, мне надо обработать все запросы на инвалидацию из моей invalidate queue. Но это означает, что к моменту чтения актуального значения, я актуализирую не только саму переменную, но и все остальное, что было в моей invalidate queue. А что там могло быть? Как минимум - все то, что было инвалидировано до соответствующей записи из другого процессора. Поэтому, если одни процессор сделал: write A write B [дождаться сброса B] А другой сделал: [дождаться инвалидации всего, что сейчас есть в invalidate queue] read B ... то второй процессор, увидев обновленное B гарантированно увидит и обновленное A! Ничего не напоминает из JMM? Подводим промежуточные итоги: 1) Система кэш-память наразрывна, и процессор видит ее как одно целое. 2) Процессор на может читать/писать в обход кэша. 3) Протоколы когерентности кэшей допускают, что "резъезжание" данных между ядрами в моменте, но гарантирует, что все изменения будут рано или поздно видны всем. VIII Процессор так же любит реордерить инструкции для ускорения их выполнения. Упомянутые "барьеры памяти" предотвращают такие перестановки. IX Теперь перейдем к регистрам. Что это такое? Это небольшая память, находящаяся непосредственно на кристалле процессора. Она может здорово ускорять работу наших программ, так как доступ к данным в регистрах занимает буквально один такт. Для сравнения, доступ к кэшу первого уровня - это около 4 тактов, доступ к кэшу второго уровня - тактов 10-20, и т.д.. Но использовать регистры или нет - это дело разработчика. Теоретически можно работать вообще без регистров общего назначения. То есть оперировать только адресами памяти. И все будет работать. Но медленнее, чем хотелось бы. Поэтому рагистры активно используют. А кто их использует? Вы вот руками дергаете регистры? Нет. И я нет. А кто их использует? Их использует JVM. Она анализирует ваш код и стремиться сделать так, что бы минимизировать объем данных, прокачиваемых между подсистемой памяти и процессором. Для этого в JIT-компиляторе, который генерирует непосредственно машинный код, есть специальных модуль - Register Allocator. Именно он принимает решение как быть с данными - сохранять их в регистрах или нет. Например, увидев, что у вас рядом идут два чтения одной и той же переменной, register allocator может принять решение на первом чтении сохранить данные значение в регистре, и на втором чтении взять его оттуда, а не лезть в систему "память-кэш" снова. X Наконец, JIT может изменять логику вашего кода, что бы минимизировать работу с памятью. Например, если у вас есть цикл while (x == 0) sleep(100); Он может проверить x == 0 один раз, сохранить в регистре значение этого выражения (напр. false), а на следующих итерациях цикла не перечитывать x, а просто брать закэшированный результат. XI Что же мне надо сделать, что бы убедиться, что прочитанное сейчас значение является актуальным? 1) Надо обработать invalidate queue на ядре 2) Надо убедиться, что мое чтение не было переставлено в коде с последующими инструкциями компилятором 3) Надо убедиться, что я не подхвачу старое значение их регистров 4) Надо убедиться, что компилятор не сгенерировал хитровысушенный код, откуда это чтение будет просто напросто выпилено. Как это все сделать за раз? Ответ: volatile. Если мы отметим переменную volatile, то JVM: 1) Не будет сохранять ее в регистрах 2) Не будет оптимизировать код вокруг нее (не будет выпиливать ее чтения, не будет ее переставлять и т.д.) 3) Вокруг ее чтения/записи компилятор добавить специальных инструкций процессора, которые почистят store buffer / invalidate queue кэшей. Обычно это делают через вызов системных функций операционной системы, которая в свою очередь исполнит нужные инструкции процессора. Это и есть volatile, что называется, "на пальцах". Заметьте, volatile кэшируются в кэшах, так же, как и все другие переменные. Кэшировать надо все и всегда, так как читать из память очень дорого. Но для обеспечения правильной видимости, volatile: 1) Форсирует подсистему памяти синхронизировать состояние кэшей. 2) Запрещает JIT-у делать оптимизации на этой переменной. Поэтому, когда говорят, что "volatile медленный", имеют ввиду не то, что "такие переменные не кэшируются", и не то, что "идет сброс в основую память". Ни того, ни другого нет! Все кэшируется, а "сброс в память" лежит на совести подсистемы памяти, а не на volatile. Имеют ввиду то, что мы теряем время на барьерах, которые синхорнизируют кэши, и на оптимизациях, которые JIT мог бы применить, но не стал этого делать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2014, 22:14 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, спасибо, за подробный ответ и потраченное время. Думаю ешё не раз прочитаю этот текст. Судя по всему, разхожая фраза о том, что volatile не кешируется относится к тому, что volatile не кешируется в регистрах. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 13:23 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, Поэтому, когда говорят, что "volatile медленный", имеют ввиду не то, что "такие переменные не кэшируются", и не то, что "идет сброс в основую память". Ни того, ни другого нет! Все кэшируется, а "сброс в память" лежит на совести подсистемы памяти, а не на volatile. Имеют ввиду то, что мы теряем время на барьерах, которые синхорнизируют кэши, и на оптимизациях, которые JIT мог бы применить, но не стал этого делать. Большое вам спасибо за развернутый ответ. Это как раз то что я долго хотел сформулировать. Но в рамках действующего форума лучше не писать так много текста. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 14:40 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
DEVcoach, DEVcoachНазовем это устройство "контроллер памяти". Он находится где-то между процессором и физической планкой памяти. И процессор вообще ничего не знает о памяти, установленной внутри вашей системы. Он знает только протокол общения с этим контроллером, и все. В этом предложении под процессором понимаетс одно ядро или именно процессор ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 15:22 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90В этом предложении под процессором понимается одно ядро или именно процессор ?Ядро. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 15:49 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjv, я тут вооружился бумагой и ручкой и попытался всё это нарисовать) У меня что-то похожее получилсь: я не очень понимаю как контроллер памяти ядра один узнает о существовании переменной в кеше ядра 2. Какая сущность за это отвечает? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:00 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90, контроллер не знает ни о каких переменных. Он видит операции с памятью. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:24 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
maytonredwhite90, контроллер не знает ни о каких переменных. Он видит операции с памятью. что конкретно он видит? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:26 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90 , В целом вы все правильно нарисовали, за исключением связей между invalidate queue и store buffer - их нет. Между кешами есть шина данных. Когда кэш хочет, например, инвалидировать значение в других кэшах, он отправляет соответствующий запрос в шину, другие кэши его подхватывают, и выполняют инвалидацию. Это называется snooping . Аналогично и с чтением - если вы не находите данные у себя в кэше, вы посылаете запрос в шину. Кэши подхватывают этот запрос, проверяют, есть ли этот адрес у них. Если есть - они выдают его обратно в шину, а запрос в память отменяют. Это уже слишком низкоуровневые дебри. Если хотите в них въехать, то читайте документацию к конкретным процессорам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:35 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Нужно спуститься на несколько уровней ниже Java. Скачай любую книжку по Ассемблеру для Intel x86/x64 Есть класс команд (TRANSFER) осуществляющий операции с памятью. Например Код: plaintext 1. в случае когда dest или source являются адресом пишет или читает атомарную сущность из памяти в регистр или наоборот. Косвенно из сегмента кода, стека постоянно идёт вычитка и запись другими командами типа PUSH/POP/CALL. Вобщем чтива там - непочатый край. Разберись основательно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 17:45 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
cdtyjv redwhite90 , В целом вы все правильно нарисовали, за исключением связей между invalidate queue и store buffer - их нет. Между кешами есть шина данных. Когда кэш хочет, например, инвалидировать значение в других кэшах, он отправляет соответствующий запрос в шину, другие кэши его подхватывают, и выполняют инвалидацию. Это называется snooping . Аналогично и с чтением - если вы не находите данные у себя в кэше, вы посылаете запрос в шину. Кэши подхватывают этот запрос, проверяют, есть ли этот адрес у них. Если есть - они выдают его обратно в шину, а запрос в память отменяют. Это уже слишком низкоуровневые дебри. Если хотите в них въехать, то читайте документацию к конкретным процессорам. Я ниже вашего самого информационно ёмкого сообщения спускаться пока не готов) Но до этого уровня понять очень интересно. так и у меня на картинке связей между invalidate queue и store buffer нет. Эти стрелки значат, что одноврменно записываем в store buffer и в invalidate queue наши значения. Ещё обратную стрелку не нарисовал означающую, что когда значение исчезло из invalidate queue и обработалось кешем ядра, надо послать сигнал о том, что что кеш инвалидирован и соответственно из другого ядра из store buffer можно будет сделать flush этого значения в кеш. теперь по этому вопросу redwhite90я не очень понимаю как контроллер памяти ядра один узнает о существовании переменной в кеше ядра 2. Какая сущность за это отвечает? я так понимаю эта сущность это: авторМежду кешами есть шина данных эта самая "шина кешей" DEVcoach Когда кэш хочет, например, инвалидировать значение в других кэшах, он отправляет соответствующий запрос в шину, другие кэши его подхватывают, и выполняют инвалидацию. Это называется snooping. Извиняюсь за занудство, но тут мне кажется важны все детали. ну как минимум по моей картинке инициатором инвалидироваиня кеша выступает контроллер памяти. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 18:55 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Инвалидация кэша основана на том факте, что у логических схем есть три состояния - ноль, единица и "высокоимпедансное". В третьем состоянии схема не влияет на шину, но может читать сигналы, которые выставляют на ней другие участники. Процессор постоянно следит за (общей) шиной адреса и, если обнаруживает адрес, попадающий в его (процессора) кэш - выставляет флаг "строка кэша невалидна", если служебные сигналы показывают, что по адресу делается запись. Этот механизм работает, если кэш использует сквозную запись, т.к. при отложенной записи модификация строк в кэше процессора не сопровождается сигналами на (общих) шинах адреса/данных. Есть ньюансы "ядра одного кристала" и "ядра разных кристалов", но тут я подробностей не знаю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 19:28 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
redwhite90Извиняюсь за занудство, но тут мне кажется важны все детали. ну как минимум по моей картинке инициатором инвалидироваиня кеша выступает контроллер памяти.Не важны тут детали, пока вы не начнёте самостоятельно разрабатывать оптимизирующий компилятор или/и системные программы. В языке высокого уровня у вас есть набор примитивов, которыми можно пользоваться вообще не зная, что там происходит в памяти. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 19:31 |
|
||
|
Concurrency Vs multithreading
|
|||
|---|---|---|---|
|
#18+
Процессор (ядро процессора) - чёрный ящик, у которого "наружу" торчат две шины - адреса и данных. Эти шины - общие и существуют (аппаратно реализованные) механизмы арбитража, позволяющие корректно использовать эти шины в разных режимах передачи. "Хренотень внутри", которую вы нарисовали ... Можете забыть о ней. Никто, кроме самого изготовителя процессоров не знает в точности что и как устроено внутри чёрного ящика. И, что характерно, никому, кроме самого изготовителя этого и не надо знать - всем остальным достаточно "вполне стандартных" примитивов типа "барьер памяти" и "инвалидация кэша". И то и другое может быть гарантировано определёнными машинными командами и порядком их следования в коде. Да, в теории, знание конкретных детали позволит выжать "последний такт", но это сделает вас таким заложником этих деталей, что epic fail можно будет получить на любой мелочи. P.S. Прицепил вашу картинку файлом, т.к., например, у меня rghost блокирован как нерекомендованный сайт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2014, 20:04 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=38686943&tid=2126936]: |
0ms |
get settings: |
7ms |
get forum list: |
11ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
163ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
48ms |
get tp. blocked users: |
1ms |
| others: | 240ms |
| total: | 483ms |

| 0 / 0 |
