Multiple RHSs on solvers in Fortran. ~2x speed up on matlab implementation for a single RHS. for multiple RHS there are still some problems.

Someone with some knowledge of how fortran works should look at this code.

Added a setup.py script that complies things. f2py should work on most computers, because it is included in the numpy distribution.
This commit is contained in:
Rowan Cockett
2013-11-12 10:36:20 -08:00
parent ea5dc21517
commit d3f38047e4
7 changed files with 95 additions and 409 deletions
+32 -10
View File
@@ -1,14 +1,22 @@
import numpy as np
import scipy.sparse as sparse
import scipy.sparse.linalg as linalg
from SimPEG.utils import mkvc
DEFAULTS = {'direct':'scipy', 'forward':'fortran', 'backward':'fortran', 'diagonal':'python'}
try:
import TriSolve
except Exception, e:
import os
# Note: this may not work from SublimeText, if that is the case, just run the command in your shell.
os.system('f2py -c TriSolve.f -m TriSolve')
import TriSolve
try:
import os
# Note: this may not work from SublimeText, if that is the case, just run the command in your shell.
os.system('f2py -c TriSolve.f -m TriSolve')
import TriSolve
except Exception, e:
print 'Warning: Python backend is being used for solver. Run setup.py from the command line.'
DEFAULTS['forward'] = 'python'
DEFAULTS['backward'] = 'python'
class Solver(object):
"""
@@ -76,7 +84,7 @@ class Solver(object):
del self.dsolve
self.dsolve = None
def solveDirect(self, b, factorize=False, backend='scipy'):
def solveDirect(self, b, factorize=False, backend=None):
"""
Use solve instead of this interface.
@@ -85,6 +93,8 @@ class Solver(object):
:rtype: numpy.ndarray
:return: x
"""
if backend is None: backend = DEFAULTS['scipy']
assert np.shape(self.A)[1] == np.shape(b)[0], 'Dimension mismatch'
if factorize and self.dsolve is None:
@@ -111,7 +121,7 @@ class Solver(object):
def solveIter(self, b, M=None, iterSolver='CG'):
pass
def solveBackward(self, b, backend='python'):
def solveBackward(self, b, backend=None):
"""
Use solve instead of this interface.
@@ -121,6 +131,7 @@ class Solver(object):
:rtype: numpy.ndarray
:return: x
"""
if backend is None: backend = DEFAULTS['backward']
if type(self.A) is not sparse.csr.csr_matrix:
from scipy.sparse import csr_matrix
self.A = csr_matrix(self.A)
@@ -128,7 +139,11 @@ class Solver(object):
rowptr = self.A.indptr
colind = self.A.indices
if backend == 'fortran':
x = TriSolve.backward(vals, rowptr, colind, b, self.A.data.size, b.size)
if len(b.shape) == 1 or b.shape[1] == 1:
x = TriSolve.backward(vals, rowptr, colind, b, self.A.data.size, b.size, 1)
x = mkvc(x)
else:
x = TriSolve.backward(vals, rowptr, colind, b, self.A.data.size, b.shape[0], b.shape[1])
elif backend == 'python':
x = np.empty_like(b) # empty() is faster than zeros().
for i in reversed(xrange(self.A.shape[0])):
@@ -138,7 +153,7 @@ class Solver(object):
x[i] = (b[i] - np.dot(ith_row[1:], x_vals[1:])) / ith_row[0]
return x
def solveForward(self, b, backend='python'):
def solveForward(self, b, backend=None):
"""
Use solve instead of this interface.
@@ -148,6 +163,7 @@ class Solver(object):
:rtype: numpy.ndarray
:return: x
"""
if backend is None: backend = DEFAULTS['forward']
if type(self.A) is not sparse.csr.csr_matrix:
from scipy.sparse import csr_matrix
self.A = csr_matrix(self.A)
@@ -155,7 +171,11 @@ class Solver(object):
rowptr = self.A.indptr
colind = self.A.indices
if backend == 'fortran':
x = TriSolve.forward(vals, rowptr, colind, b, self.A.data.size, b.size)
if len(b.shape) == 1 or b.shape[1] == 1:
x = TriSolve.forward(vals, rowptr, colind, b, self.A.data.size, b.size, 1)
x = mkvc(x)
else:
x = TriSolve.forward(vals, rowptr, colind, b, self.A.data.size, b.shape[0], b.shape[1])
elif backend == 'python':
x = np.empty_like(b) # empty() is faster than zeros().
for i in xrange(self.A.shape[0]):
@@ -165,7 +185,7 @@ class Solver(object):
x[i] = (b[i] - np.dot(ith_row[:-1], x_vals[:-1])) / ith_row[-1]
return x
def solveDiagonal(self, b, backend='python'):
def solveDiagonal(self, b, backend=None):
"""
Use solve instead of this interface.
@@ -175,6 +195,8 @@ class Solver(object):
:rtype: numpy.ndarray
:return: x
"""
if backend is None: backend = DEFAULTS['diagonal']
diagA = self.A.diagonal()
if len(b.shape) == 1 or b.shape[1] == 1:
# Just one RHS
+26 -16
View File
@@ -1,54 +1,64 @@
c File TriSolve.f
subroutine forward(al, ial, jal, b, nv, n, x)
subroutine forward(al, ial, jal, b, nv, n, nRHS, x)
double precision al(nv)
integer ial(n+1)
integer jal(nv)
double precision b(n)
double precision x(n)
double precision b(n,nRHS)
double precision x(n,nRHS)
integer nv
integer n
integer nRHS
integer rhs
cf2py intent(in) :: al
cf2py intent(in) :: ial
cf2py intent(in) :: jal
cf2py intent(in) :: b
cf2py intent(in) :: nv
cf2py intent(in) :: n
cf2py intent(in) :: nRHS
cf2py intent(out) :: x
real ( kind = 8 ) t
do k = 1, n
t = b(k)
do j = ial(k)+1, ial(k+1)
t = t - al(j) * x(jal(j)+1)
do rhs = 1, nRHS
do k = 1, n
t = b(k,rhs)
do j = ial(k)+1, ial(k+1)
t = t - al(j) * x(jal(j)+1,rhs)
end do
x(k,rhs) = t/al(ial(k+1))
end do
x(k) = t/al(ial(k+1))
end do
end subroutine forward
subroutine backward(au,iau, jau, b, nv, n, x)
subroutine backward(au,iau, jau, b, nv, n, nRHS, x)
double precision au(nv)
integer iau(n+1)
integer jau(nv)
double precision b(n)
double precision x(n)
double precision b(n,nRHS)
double precision x(n,nRHS)
integer nv
integer n
integer nRHS
integer rhs
cf2py intent(in) :: au
cf2py intent(in) :: iau
cf2py intent(in) :: jau
cf2py intent(in) :: b
cf2py intent(in) :: nv
cf2py intent(in) :: n
cf2py intent(in) :: nRHS
cf2py intent(out) :: x
real ( kind = 8 ) t
do k = n, 1, -1
t = b(k)
do j = iau(k)+1, iau(k+1)
t = t - au(j) * x(jau(j)+1)
do rhs = 1, nRHS
do k = n, 1, -1
t = b(k,rhs)
do j = iau(k)+1, iau(k+1)
t = t - au(j) * x(jau(j)+1,rhs)
end do
x(k,rhs) = t/au(iau(k)+1)
end do
x(k) = t/au(iau(k)+1)
end do
end subroutine backward
+2 -2
View File
@@ -3,9 +3,9 @@ import sputils
import lomutils
import interputils
import ModelBuilder
import Solver
from Solver import Solver
from matutils import getSubArray, mkvc, ndgrid, ind2sub, sub2ind
from sputils import spzeros, kron3, speye, sdiag
from lomutils import volTetra, faceInfo, inv2X2BlockDiagonal, inv3X3BlockDiagonal, indexCube, exampleLomGird
from interputils import interpmat
import Solver
from Solver import Solver