C кодирование методов для производительности или размера кода - вне того, что делает компилятор

Если Вам не нужна ленивая загрузка, тогда просто пробуют

public class Singleton {
    private final static Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() { return Singleton.INSTANCE; }

    protected Object clone() {
        throw new CloneNotSupportedException();
    }
}

, Если Вы хотите ленивую загрузку, и Вы хотите, чтобы Ваша Singleton была ориентирована на многопотоковое исполнение, попробовала шаблон перепроверки

public class Singleton {
        private static Singleton instance = null;

        private Singleton() {}

        public static Singleton getInstance() { 
              if(null == instance) {
                  synchronized(Singleton.class) {
                      if(null == instance) {
                          instance = new Singleton();
                      }
                  }
               }
               return instance;
        }

        protected Object clone() {
            throw new CloneNotSupportedException();
        }
}

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

5
задан Community 23 May 2017 в 12:12
поделиться

6 ответов

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

Это относится ко всем языкам программирования, но если вы программируете на C, производительность, вероятно, для вас критична, поэтому это особенно актуально.

6
ответ дан 18 December 2019 в 09:52
поделиться

«Всегда» знать временную и пространственную сложность ваших алгоритмов. Компилятор никогда не сможет выполнить эту работу так же хорошо, как вы. :)

5
ответ дан 18 December 2019 в 09:52
поделиться

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

Выбор правильных структур данных для вашей конкретной задачи. может значительно повысить производительность (я видел случаи, когда переход от Kd-дерева к BVH делал бы это в этом конкретном случае).

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

Компиляторы по-прежнему не делают ваш код автоматически многопоточным, и использование openmp, по моему опыту, не очень помогает. (Вы действительно должны понимать openmp, чтобы значительно повысить производительность). Итак, в настоящее время вы сами занимаетесь многопоточностью.

3
ответ дан 18 December 2019 в 09:52
поделиться

To add to what Martin says above about cache-friendliness:

  • reordering your structures such that fields which are commonly accessed together are in the same cache line can help (for instance by loading just one cache line rather than two.) You are essentially increasing the density of useful data in your data cache by doing this. There is a linux tool which can help you in doing this: dwarves 1. http://www.linuxinsight.com/files/ols2007/melo-reprint.pdf

  • you can use a similar strategy for increasing density of your code. In gcc you can mark hot and cold branches using likely/unlikely tags. That enables gcc to keep the cold branches separately which helps in increasing the icache density.

And now for something completely different:

  • for fields that might be accessed (read and written) across CPUs, the opposite strategy makes sense. The trouble is that for coherence purposes only one CPU can be allowed to write to the same address (in reality the same cacheline.) This can lead to a condition called cache-line ping pong. This is pretty bad and could be worse if that cache-line contains other unrelated data. Here, padding this contended data to a cache-line length makes sense.

Note: these clearly are micro-optimizations, to be done only at later stages when you are trying to wring the last bits of performance from your code.

2
ответ дан 18 December 2019 в 09:52
поделиться

Предварительные вычисления там, где это возможно ... (извините, но это не всегда возможно ... Я выполнил обширные предварительные вычисления на моем шахматном движке.) Сохраните эти результаты в памяти, не забывая о кеше .. чем больше Чем меньше размер данных предварительного вычисления в памяти, тем меньше вероятность попадания в кэш. Поскольку большинство новейшего оборудования является многоядерным, вы можете создать свое приложение, ориентированное на него.

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

1
ответ дан 18 December 2019 в 09:52
поделиться

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

0
ответ дан 18 December 2019 в 09:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: