![](/img/trans.png)
[英]matrix multiplication in swift using Accelerate framework 32 bit vs 64 bit
[英]Matrix multiplication and inverse problems with accelerate framework
我试图在Objective-C中乘以两个矩阵。 我已经将加速框架导入了我在Xcode中的项目,一切都编译得很好。 我在我的计算器上进行了矩阵乘法并得到了正确的值,但是,在运行代码时,我没有。 这就是我定义矩阵的方式..
float matrixA [3][3] = {{-.045, -.141, -.079}, {-.012, -.079, .0578}, {.112, -.011, -.0830}};
float matrixB [3][1] = {{40}, {-61}, {98}};
然后我在加速框架中使用了mmul函数。
vDSP_mmul(&matrixA[3][3], 1, &matrixB[3][1], 1, &results[3][1], 1, 3, 1, 3);
通过执行以下操作创建了数组结果。
float results[3][1];
我只是把它放在一个空项目的viewDidLoad方法中,所以我可以NSLog结果。 所以当我将matrixA乘以matrixB时,我得到以下结果..(-1,10,-3)。 但是,NSLog中的结果显示(-0.045,0.000,0.000)。 这是不正确的,我不明白为什么。 我的理解是这个函数会将两个矩阵相乘。 但我不确定它在做什么。 我可能输错了东西,并希望有人可以帮助我。
侧注:matrixA实际上是另一个矩阵的逆。 但是,我在加速框架中找不到任何反向的东西。 我确实找到了一个叫做的函数
sgetrf_
有了LAPACK但是没有真正得到它。 如果有人有任何帮助,建议或一些教程可以遵循我会很感激,已经在这三天了,现在在互联网上寻找东西!
让我们通过三种不同的方式在OS X或iOS上进行这种计算(包括逆向)。
首先,让我们做你或多或少尝试做的事情:我们将使用Accelerate框架中的LAPACK和BLAS进行计算。 请注意,我使用BLAS函数cblas_sgemv
而不是vDSP_mmul
来执行矩阵向量乘法。 我这样做有三个原因。 首先,它在使用LAPACK的代码中更具惯用性。 其次,LAPACK确实希望以列主要顺序存储矩阵,BLAS支持这些矩阵,但vDSP不支持。 最后, vDSP_mmul
实际上只是BLAS矩阵乘法例程的包装器,因此我们可以删除中间人。 这将在OS X上恢复到10.2并且iOS可以恢复到4.0 - 即在您今天可以合理期望遇到的任何目标上。
#include <Accelerate/Accelerate.h>
#include <stdio.h>
#include <string.h>
void using_blas_and_lapack(void) {
printf("Using BLAS and LAPACK:\n");
// Note: you'll want to store A in *column-major* order to use it with
// LAPACK (even though it's not strictly necessary for this simple example,
// if you try to do something more complex you'll need it).
float A[3][3] = {{-4,-3,-5}, {6,-7, 9}, {8,-2,-1}};
float x[3] = { -1, 10, -3};
// Compute b = Ax using cblas_sgemv.
float b[3];
cblas_sgemv(CblasColMajor, CblasNoTrans, 3, 3, 1.f, &A[0][0], 3, x, 1, 0.f, b, 1);
printf("b := A x = [ %g, %g, %g ]\n", b[0], b[1], b[2]);
// You probably don't actually want to compute A^-1; instead you simply
// want to solve the equation Ay = b for y (like y = A\b in matlab). To
// do this with LAPACK, you typically use the routines sgetrf and sgetrs.
// sgetrf will overwrite its input matrix with the LU factorization, so
// we'll make a copy first in case you need to use A again.
float factored[3][3];
memcpy(factored, A, sizeof factored);
// Now that we have our copy, go ahead and factor it using sgetrf.
__CLPK_integer n = 3;
__CLPK_integer info = 0;
__CLPK_integer ipiv[3];
sgetrf_(&n, &n, &factored[0][0], &n, ipiv, &info);
if (info != 0) { printf("Something went wrong factoring A\n"); return; }
// Finally, use the factored matrix to solve y = A\b via sgetrs. Just
// like sgetrf overwrites the matrix with its factored form, sgetrs
// overwrites the input vector with the solution, so we'll make a copy
// before calling the function.
float y[3];
memcpy(y, b, sizeof y);
__CLPK_integer nrhs = 1;
sgetrs_("No transpose", &n, &nrhs, &factored[0][0], &n, ipiv, y, &n, &info);
printf("y := A\\b = [ %g, %g, %g ]\n\n", y[0], y[1], y[2]);
}
接下来,让我们使用LinearAlgebra.h进行计算,这是iOS 8.0和OS X 10.10中Accelerate Framework的一个新功能。 它抽象了几乎所有这些计算所需的簿记,但它只提供了LAPACK和BLAS中可用的全部功能的一小部分。 请注意,虽然有一些样板需要将原始数组转换为la_objects和从la_objects转换,但是一旦我们得到它们,实际的计算就非常简单了。
#include <Accelerate/Accelerate.h>
#include <stdio.h>
void using_la(void) {
printf("Using LA:\n");
// LA accepts row-major as well as column-major data, but requires a short
// two-step dance to get our data in.
float Adata[3][3] = {{-4, 6, 8}, {-3,-7,-2}, {-5, 9,-1}};
float xdata[3] = { -1, 10, -3};
la_object_t A = la_matrix_from_float_buffer(&Adata[0][0], 3, 3, 3, LA_NO_HINT, LA_DEFAULT_ATTRIBUTES);
la_object_t x = la_vector_from_float_buffer(xdata, 3, 1, LA_DEFAULT_ATTRIBUTES);
// Once our data is stored as LA objects, it's easy to do the computation:
la_object_t b = la_matrix_product(A, x);
la_object_t y = la_solve(A, b);
// And finally we need to get our data back out:
float bdata[3];
if (la_vector_to_float_buffer(bdata, 1, b) != LA_SUCCESS) {
printf("Something went wrong computing b.\n");
return;
} else printf("b := A x = [ %g, %g, %g ]\n", bdata[0], bdata[1], bdata[2]);
float ydata[3];
if (la_vector_to_float_buffer(ydata, 1, y) != LA_SUCCESS) {
printf("Something went wrong computing y.\n");
return;
} else printf("y := A\\b = [ %g, %g, %g ]\n\n", ydata[0], ydata[1], ydata[2]);
}
最后,还有一种方法。 如果你的矩阵实际上只是3x3,这就是我将使用的方法,因为前面任一方法所涉及的开销都会影响实际的计算。 但是,这仅适用于尺寸为4x4或更小的矩阵。 在iOS 8.0和OS X 10.10中还有另一个新的标题,专门针对小矩阵和矢量数学,这使得这非常简单和有效:
#include <simd/simd.h>
#include <stdio.h>
void using_simd(void) {
printf("Using <simd/simd.h>:\n");
matrix_float3x3 A = matrix_from_rows((vector_float3){-4, 6, 8},
(vector_float3){-3, -7, -2},
(vector_float3){-5, 9, -1});
vector_float3 x = { -1, 10, -3 };
vector_float3 b = matrix_multiply(A, x);
printf("b := A x = [ %g, %g, %g ]\n", b[0], b[1], b[2]);
vector_float3 y = matrix_multiply(matrix_invert(A),b);
printf("y := A^-1 b = [ %g, %g, %g ]\n\n", y[0], y[1], y[2]);
}
最后,让我们仔细检查这些都会得到相同的结果(直到小的舍入差异):
scanon$ xcrun -sdk macosx clang matrix.m -framework Accelerate && ./a.out
Using BLAS and LAPACK:
b := A x = [ 40, -61, 98 ]
y := A\b = [ -0.999999, 10, -3 ]
Using LA:
b := A x = [ 40, -61, 98 ]
y := A\b = [ -1, 10, -3 ]
Using <simd/simd.h>:
b := A x = [ 40, -61, 98 ]
y := A^-1 b = [ -1, 10, -3 ]
在矩阵结束后 ,您将指针传递给内存。
修复看起来像这样(未经测试的代码):
vDSP_mmul(&matrixA[0][0], 1, &matrixB[0][0], 1, &results[0][0], 1, 3, 1, 3);
将数组传递给C中的函数实际上会将指针传递给数组的第一个元素,在这种情况下,这似乎是您需要做的事情。 你在矩阵中的最后一个数组元素之后直接传递指向一块内存的指针,这意味着你会得到无意义的结果或崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.