На самом деле, люди, которые пишут Java, не имеют ничего общего с процессором. В лучшем случае это как -то связано с тем, как запустить процессор и как установить количество потоков, которые мы упоминали ранее. Однако этот алгоритм является просто ссылкой. Многие различные сценарии требуют практических средств для его решения. Более того, после запуска процессора мы также рассмотрим, как сделать процессор не таким полным. Ха -ха, люди, вот и все. Ха -ха, хорошо, эта статья о других вещах. Может быть, вы почти не пишете код на Java. Обратите внимание на процессор, потому что удовлетворение бизнеса - первая важная вещь. Если вы хотите достичь уровня структуры и предоставить структуру со многими общими кэшами данных, в середине должно быть много проблем с заявлением данных. Конечно, Java предоставляет много классов параллельных пакетов, и вы можете использовать их, но как это делается внутри, вы должны понимать детали, чтобы использовать их лучше, иначе лучше не использовать его. Эта статья может не объяснить это содержимое как фокус, потому что, как и заглавная вечеринка: мы хотим поговорить о процессоре, ха -ха.
То же самое говорится, кажется, что Java не имеет ничего общего с процессором, так что давайте поговорим о том, что происходит сейчас;
1. При столкновении с общим элементом наша первая идея состоит в том, чтобы обеспечить постоянные операции чтения через летучую, то есть абсолютную видимость. Так называемая видимость означает, что каждый раз, когда вы хотите использовать эти данные, ЦП не будет использовать какое-либо содержание кэша и будет получать данные из памяти. Этот процесс по -прежнему действителен для нескольких процессоров, что означает, что процессор и память в настоящее время синхронизируются. ЦП издаст инструкцию по сбору, похожая на Lock Addl 0, как шина, +0, но ничего не будет делать по отношению к чему -либо. Однако после завершения инструкции последующие операции больше не будут влиять на доступ других потоков этого элемента, что является абсолютной видимостью, которую он может достичь, но не может реализовать последовательные операции. То есть то, что волатило не может достичь, так это согласованность таких операций, как i ++ (параллелизм в нескольких потоках), потому что операции I ++ разлагаются на:
int tmp = i; tmp = tmp + 1; i = tmp;
Эти три шага завершены. С этого момента вы также можете понять, почему i ++ может сначала делать другие вещи, а затем добавить 1 к себе, потому что ему присваивается значение другой переменной.
2. Если мы хотим использовать многопоточную согласованность параллелизма, нам нужно использовать механизм блокировки. В настоящее время такие вещи, как атомный*, могут соответствовать этим требованиям. Многие небезопасные методы класса предоставляются внутри. Постоянно сравнивая данные абсолютной видимости, мы можем убедиться, что полученные данные обновлены; Далее мы будем продолжать говорить о других вопросах процессора.
3. Так как мы упомянули об этом сегодня, мы кратко поговорим о задержке. Вообще говоря, текущий процессор имеет трехуровневый кэш, а задержки различны в разных возрастах, поэтому конкретное число может быть примерно справедливым. Сегодняшние процессоры, как правило, имеют задержку 1-2NS, кэш второго уровня, как правило, составляет от нескольких нс до десяти нс, а кэш третьего уровня, как правило, составляет от 30 нс до 50 нс, и доступ к памяти, как правило, достигает 70NS или даже больше (компьютер развивается очень быстро, и это значение предназначено только для данных на некоторых ЦП, для эталона диапазона); Хотя эта задержка очень мала, все на уровне наносекунды, вы обнаружите, что, когда ваша программа будет разделена на операции с инструкциями, будет много взаимодействий ЦП. Если задержка каждого взаимодействия настолько велика, производительность системы изменится в настоящее время;
4. Вернитесь к упомянутому прямо сейчас. Каждый раз, когда он получает данные из памяти, он отказывается от кеша. Конечно, если он становится медленнее в некоторых операциях с одной отдельной трубой, он станет медленнее. Иногда мы должны это сделать. Даже операции чтения и записи требуют последовательности, и даже весь блок данных синхронизирован. Мы можем в определенной степени уменьшить гранулярность замка, но у нас вообще не может быть замков. Даже сам уровень процессора будет иметь ограничения на уровень обучения.
5. Атомные операции на уровне процессора обычно называются барьерами с барьерами чтения, записи барьеры и т. Д. Они обычно запускаются в одну точку. Когда несколько инструкций программы отправляются в процессор, некоторые инструкции не могут быть выполнены в порядке программы, а некоторые должны быть выполнены в порядке программы, если они могут гарантировать, что они будут последовательными в окончательном порядке программы. С точки зрения сортировки, JIT изменится во время выполнения, а уровень инструкции процессора также изменится. Основная причина состоит в том, чтобы оптимизировать инструкции по выполнению выполнения, чтобы программа работала быстрее.
6. Уровень процессора будет управлять линейкой кэша в памяти. Так называемая линия кеша будет постоянно считывать кусок памяти, которая обычно связана с моделью процессора и архитектурой. В настоящее время многие процессоры, как правило, будут читать непрерывную память каждый раз, а ранние будут иметь 32BITE, так что это будет быстрее при переселении некоторых массивов (это очень медленно на основе обхода столбца), но это не совсем правильно. Следующее сравнит некоторые противоположные ситуации.
7. Если процессор изменяет данные, мы должны поговорить о состоянии ЦП, изменяющего данные. Если все данные считываются, их можно прочитать параллельно несколькими потоками в нескольких процессорах. При написании операций на блоках данных это отличается. Блоки данных будут иметь эксклюзивные, модифицированные, недействительные и другие состояния, и данные естественным образом не будут проходить после модификации. Когда несколько потоков изменяют один и тот же блок данных в нескольких процессорах, возникнет копия данных шины (QPI) между процессорами. Конечно, если мы изменем его на одни и те же данные, у нас нет выбора, но когда мы возвращаемся к линии кэша в точке 6, проблема более хлопотна. Если данные находятся на одном и том же массиве, а элементы в массиве будут кэшированы в процессоре одновременно, QPI многопоточных отчетов будет очень частым. Иногда эта проблема возникает, даже если объекты, собранные на массиве, собираются, например:
Класс inputInteger {private int value; public inputInteger (int i) {this.value = i;}} inputInteger [] integers = new InputInteger [size]; for (int i = 0; i <size; i ++) {integers [i] = new Inputeger (i);} В настоящее время вы можете видеть, что все в целых числах является объектами, и есть только ссылки на объекты на массиве, но расположение объектов теоретически независимо и не будет храниться непрерывно. Однако, когда Java выделяет память объекта, ее часто постоянно выделяют в области Эдема. Когда в цикле FOR, если никаких других потоков не доступно, эти объекты будут храниться вместе. Даже если они GC в старую область, это, скорее всего, будет собрано вместе. Следовательно, способ изменить весь массив, полагаясь на простые объекты для решения линии кэша, кажется ненадежным, потому что это 4 байта. Если в режиме 64, этот размер составляет 24 байта (4bytes заполнен), а сжатие указателя составляет 16 байт; То есть процессор может каждый раз соответствовать 3-4 объектам. Как сделать кеш ЦП, но он не влияет на QPI системы. Не думайте о том, чтобы завершить его, разделяя объекты, потому что процесс копирования памяти процесса GC, вероятно, будет скопирован вместе. Лучший способ - заполнить его. Хотя это немного отходы памяти, это самый надежный метод, который должен заполнить объект до 64 байтов. Если сжатие указателя не включено, есть 24 байта, а в настоящее время есть 40 байтов. Вам нужно только добавить 5 длины в объект.
класс inputinteger {public int value; private long a1, a2, a3, a4, a5;} Ха -ха, этот метод очень деревенский, но он работает очень хорошо. Иногда, когда JVM составлен, он обнаруживает, что эти параметры не были сделаны, поэтому он убит непосредственно для вас. Оптимизация недействительна. Метод плюс метод состоит в том, чтобы просто управлять этими 5 параметрами в теле метода (использовал их все), но этот метод никогда не будет называть его.
8. На уровне процессора иногда может быть невозможно сделать первое, что нужно сделать. Это король. В операции Atomicintegerfieldupdater, если вы позвоните Getanteset (True) в одном потоке, вы обнаружите, что он работает довольно быстро, и он начинает замедляться под многоядерным процессором. Почему это ясно сказано выше? Поскольку GetandSet модифицируется и сравнивается, а затем сначала измените его, QPI будет очень высоким, поэтому в настоящее время лучше сначала выполнить операции, а затем изменить его; И это также хороший способ получить это один раз. Если его нельзя получить, сдайте и позвольте другим потокам делать другие вещи;
9. Иногда, чтобы решить проблему некоторого процессора, занятого и не занятого, будет много алгоритмов для решения. Например, NUMA является одним из решений. Однако, независимо от того, какая архитектура более полезна в определенных сценариях, она может быть не эффективной для всех сценариев. Существует механизм блокировки очередей для завершения управления состоянием ЦП, но это также имеет проблему линии кэша, поскольку состояние часто изменяется, а ядра различных приложений также будут создавать некоторые алгоритмы для того, чтобы сделать для сотрудничества с ЦП, так что ЦП может использоваться более эффективно, например, доступы CLH.
Есть много подробностей об этом, таких как суперпозиция обычных петлей переменных, летучих типов и атомных* серий, которые совершенно разные; Многомерные петли массивов, зацикленные в обратном порядке в разных широтах, и есть много деталей, и я понимаю, почему есть вдохновение в реальном процессе оптимизации; Детали замков слишком тонкие и головокружительные, а на нижнем уровне системы всегда есть некоторые легкие атомные операции. Независимо от того, кто говорит, что его код не требует блокировки, лучшие могут быть такими же простыми, как процессор может выполнять только одну инструкцию в каждый момент. Многоядерные процессоры также будут иметь общую область для управления некоторым контентом на уровне шины, включая уровень чтения, уровень записи, уровень памяти и т. Д. В различных сценариях гранулярность блокировки уменьшается как можно больше. Производительность системы самоочевидна, и это нормальный результат.