Java Vector внутренние продукты
У меня есть массив m-мерных векторов (хранится как простые массивы) v1, v2 ... vn.
Мне приходится многократно вычислять внутренние произведения между двумя векторами, которые я выбираю из этих векторов.
Один из способов сделать это - простой цикл for для всех его компонентов.
double sum=0;
for(int i=0; i<m; i++)
sum+=v1[i]*v2[i];
Это практически единственная операция по линейной алгебре, которую я намереваюсь выполнить над своими данными.
Будет ли эффективнее импортировать библиотеку linalg, такую как JAMA или la4j, хранить все как матрицы и вычислять внутренние продукты? (это даже не большие умножения матриц, а только внутренние произведения между одномерными векторами)
Как la4j(и т. Д.) Реализует точечный продукт? Разве он не будет перебирать каждый индекс и умножать каждую пару компонентов?
3 ответа
la4j
является открытым исходным кодом, посмотрите на код. С использованием AbstractVector
Внутренний продукт менее эффективен, чем ваш собственный код, поскольку он создает дополнительные объекты операций, здесь OoPlaceInnerProduct.
Однако: в большинстве случаев я все же предпочел бы использовать существующий, хорошо протестированный пакет векторной математики, чем реализовывать свой собственный. (Кнут: "Мы должны забыть о малой эффективности, скажем, в 97% случаев: преждевременная оптимизация - корень всего зла".)
Обратите внимание, что многопоточность тоже не помогает. Даже высокоэффективный LAPACK
Пакет использует тот же код, что и ваш.
Что касается библиотеки la4j: в новой версии 0.5.0 используются облегченные разреженные итерации, поэтому вам не нужно беспокоиться о переборе нулевых значений в разреженных векторах. Вот пример API
Vector a = new BasicVector(...); // dense
Vector b = new CompressedVector(...); // sparse
double dot = a.innerProduct(b);
Вы можете объединить любую возможную пару: разреженно-разреженный, разреженно-разреженный, плотно-плотный, плотно-разреженный. Библиотека la4j всегда будет использовать наиболее эффективный алгоритм в зависимости от ваших данных.
Если вы хотите вычислить все внутренние продукты, я рекомендую это: в матрице A храните ваши векторы в строках, а в B - в столбцах. Тогда в A*B вы будете иметь положение (i,j) внутреннего произведения v_i и v_j.
Хитрость в том, что нормальное матричное умножение занимает n^3 времени, но некоторые умные алгоритмы имеют более эффективные методы, но только для ~ 30 и более векторов.