Я делаю проект для класса, который фокусируется на хранении огромной матрицы с в основном нулевыми значениями в памяти и выполнении над ней математических вычислений.Моей первой мыслью было использовать HashMap
для хранения матричных элементов и хранить только те элементы, которые не равны нулю, чтобы избежать использования огромного количества памяти.
Я хотел создать ключ для HashMap
, который бы представлял номер строки и столбца элемента таким образом, чтобы при доступе к этой записи на карте я мог повторно извлечь оба ценности. Я не знаю Java так же хорошо, как C # - в C # я бы сделал структуру struct
с членами Row
и Column
, но в Java я быстро понял, что есть нет типов пользовательских значений. С приближением крайнего срока я сделал беспроигрышную ставку и сделал ключ ключом
длинным. Я сохранил данные строки (32-битное int) в первых 32 битах и данные столбца в последних 32, используя очень простой сдвиг бит. [РЕДАКТИРОВАТЬ: я также хотел бы отметить, что моя HashMap инициализируется с определенным начальным размером, который точно представляет количество значений, которые я храню в нем, которое никогда не превышается.]
[Дополнительное примечание: я хочу снова получить возможность извлекать данные строки / столбца, чтобы значительно повысить эффективность умножения матриц, с O (n ^ 2)
до O (n)
и меньший n
для загрузки]
. После реализации этой структуры я заметил, что для чтения матрицы 23426 x 23426 из текстового файла в при этом заданы только ненулевые элементы, но вычисление собственных значений, которые мы должны предоставить, занимает всего 2 секунды! После выборочного комментирования методов я пришел к выводу, что большая часть этого 7-секундного промежутка времени уходит на сохранение моих значений в HashMap
.
public void Set(double value, int row, int column) {
//assemble the long key, placing row and column in adjacent sets of bits
long key = (long)row << SIZE_BIT_MAX; //(SIZE_BIT_MAX is 32)
key += column;
elements.put(key, value);
}
Это код для установки значения. Если я воспользуюсь этим методом:
public void Set(double value, int row, int column) {
//create a distinct but smaller key (around 32 bits max)
long key = (long)(row * matrixSize) + column;
elements.put(key, value);
}
Чтение займет всего 2 секунды. Обе эти версии ключа различны для каждого элемента, оба имеют длинный тип, и фактический код для создания любого из них минимален по сложности. Это elements.put (key, value)
, который определяет разницу между 7 секундами и 2.
У меня вопрос, почему? Разница, которую я вижу между этими ключевыми версиями, заключается в том, что первая имеет биты, установленные на 1 повсюду и чаще, в то время как вторая имеет все самые высокие 32 бита, установленные на 0. Я преследую отвлекающий маневр, или это довольно резкое различие в производительности результат чего-то внутреннего в методе HashMap.put
?