Skip to content

Commit 6298b39

Browse files
committed
2 parents e335c47 + ec14cb6 commit 6298b39

File tree

6 files changed

+127
-30
lines changed

6 files changed

+127
-30
lines changed

numpy/ufuncs.py

+33-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from scipy.sparse import random, csr_matrix
33
import sparse
44
import pytest
5-
from util import TensorCollectionFROSTT, PydataTensorShifter
5+
from util import TensorCollectionFROSTT, PydataTensorShifter, TensorCollectionSuiteSparse, ScipyTensorShifter, PydataMatrixMarketTensorLoader, ScipyMatrixMarketTensorLoader
66

77
# TODO (rohany): Ask hameer about this. pydata/sparse isn't happy when
88
# given this ufunc to evaluate.
@@ -90,12 +90,40 @@ def bench():
9090
# Run benchmarks against the FROSTT collection.
9191
FROSTTTensors = TensorCollectionFROSTT()
9292
@pytest.mark.parametrize("tensor", FROSTTTensors.getTensors(), ids=FROSTTTensors.getTensorNames())
93-
def bench_pydata_frostt_ufunc_sparse(tacoBench, tensor):
94-
frTensor = tensor.load()
93+
@pytest.mark.parametrize("ufunc", [numpy.logical_xor, numpy.ldexp, numpy.right_shift])
94+
def bench_pydata_frostt_ufunc_sparse(tacoBench, tensor, ufunc):
95+
frTensor = tensor.load().astype('int64')
9596
shifter = PydataTensorShifter()
9697
other = shifter.shiftLastMode(frTensor).astype('int64')
9798
def bench():
98-
# TODO (rohany): Expand this test beyond ldexp.
99-
c = numpy.ldexp(frTensor, other)
99+
c = ufunc(frTensor, other)
100+
return c
101+
tacoBench(bench)
102+
103+
# Run benchmarks against the SuiteSparse collection.
104+
SuiteSparseTensors = TensorCollectionSuiteSparse()
105+
@pytest.mark.parametrize("tensor", SuiteSparseTensors.getTensors(), ids=SuiteSparseTensors.getTensorNames())
106+
@pytest.mark.parametrize("ufunc", [numpy.logical_xor, numpy.ldexp, numpy.right_shift])
107+
def bench_pydata_suitesparse_ufunc_sparse(tacoBench, tensor, ufunc):
108+
ssTensor = tensor.load(PydataMatrixMarketTensorLoader()).astype('int64')
109+
shifter = PydataTensorShifter()
110+
other = shifter.shiftLastMode(ssTensor).astype('int64')
111+
def bench():
112+
c = ufunc(ssTensor, other)
113+
return c
114+
tacoBench(bench)
115+
116+
# TODO (rohany): scipy doesn't support these, I forgot. If that's the case,
117+
# do we really need to compare against suitesparse?
118+
@pytest.mark.skip(reason="scipy doesn't support this actually")
119+
@pytest.mark.parametrize("tensor", SuiteSparseTensors.getTensors(), ids=SuiteSparseTensors.getTensorNames())
120+
@pytest.mark.parametrize("ufunc", [numpy.logical_xor, numpy.ldexp, numpy.right_shift])
121+
@pytest.mark.parametrize("format", ["csr", "csc"])
122+
def bench_scipy_suitesparse_ufunc_sparse(tacoBench, tensor, ufunc, format):
123+
ssTensor = tensor.load(ScipyMatrixMarketTensorLoader(format)).astype('int64')
124+
shifter = ScipyTensorShifter(format)
125+
other = shifter.shiftLastMode(ssTensor).astype('int64')
126+
def bench():
127+
c = ufunc(ssTensor, other)
100128
return c
101129
tacoBench(bench)

numpy/util.py

+50-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import scipy.sparse
2+
import scipy.io
23
import sparse
34
import os
45
import glob
@@ -167,7 +168,9 @@ def shiftLastMode(self, tensor):
167168
for i in range(len(data)):
168169
for j in range(len(tensor.shape)):
169170
resultCoords[j][i] = coords[j][i]
170-
resultValues[i] = data[i]
171+
# resultValues[i] = data[i]
172+
# TODO (rohany): Temporarily use a constant as the value.
173+
resultValues[i] = 2
171174
resultCoords[-1][i] = (resultCoords[-1][i] + 1) % tensor.shape[-1]
172175
return sparse.COO(resultCoords, resultValues, tensor.shape)
173176

@@ -183,10 +186,55 @@ def shiftLastMode(self, tensor):
183186
for coord, val in dok.items():
184187
newCoord = list(coord[:])
185188
newCoord[-1] = (newCoord[-1] + 1) % tensor.shape[-1]
186-
result[tuple(newCoord)] = val
189+
# result[tuple(newCoord)] = val
190+
# TODO (rohany): Temporarily use a constant as the value.
191+
result[tuple(newCoord)] = 2
187192
if self.format == "csr":
188193
return scipy.sparse.csr_matrix(result)
189194
elif self.format == "csc":
190195
return scipy.sparse.csc_matrix(result)
191196
else:
192197
assert(False)
198+
199+
class ScipyMatrixMarketTensorLoader:
200+
def __init__(self, format):
201+
self.format = format
202+
203+
def load(self, path):
204+
coo = scipy.io.mmread(path)
205+
if self.format == "csr":
206+
return scipy.sparse.csr_matrix(coo)
207+
elif self.format == "csc":
208+
return scipy.sparse.csc_matrix(coo)
209+
else:
210+
assert(False)
211+
212+
class PydataMatrixMarketTensorLoader:
213+
def __init__(self):
214+
pass
215+
216+
def load(self, path):
217+
coo = scipy.io.mmread(path)
218+
return sparse.COO.from_scipy_sparse(coo)
219+
220+
class SuiteSparseTensor:
221+
def __init__(self, path):
222+
self.path = path
223+
224+
def __str__(self):
225+
f = os.path.split(self.path)[1]
226+
return f.replace(".mtx", "")
227+
228+
def load(self, loader):
229+
return loader.load(self.path)
230+
231+
class TensorCollectionSuiteSparse:
232+
def __init__(self):
233+
data = os.path.join(TENSOR_PATH, "suitesparse")
234+
sstensors= glob.glob(os.path.join(data, "*.mtx"))
235+
self.tensors = [SuiteSparseTensor(t) for t in sstensors]
236+
237+
def getTensors(self):
238+
return self.tensors
239+
def getTensorNames(self):
240+
return [str(tensor) for tensor in self.getTensors()]

taco/bench.h

+20-4
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,33 @@
4141
std::string getTacoTensorPath();
4242
taco::TensorBase loadRandomTensor(std::string name, std::vector<int> dims, float sparsity, taco::Format format);
4343

44-
template<typename T>
45-
taco::Tensor<T> shiftLastMode(std::string name, taco::Tensor<T> original) {
44+
template<typename T, typename T2>
45+
taco::Tensor<T> shiftLastMode(std::string name, taco::Tensor<T2> original) {
4646
taco::Tensor<T> result(name, original.getDimensions(), original.getFormat());
4747
std::vector<int> coords(original.getOrder());
48-
for (auto& value : taco::iterate<T>(original)) {
48+
for (auto& value : taco::iterate<T2>(original)) {
4949
for (int i = 0; i < original.getOrder(); i++) {
5050
coords[i] = value.first[i];
5151
}
5252
int lastMode = original.getOrder() - 1;
5353
coords[lastMode] = (coords[lastMode] + 1) % original.getDimension(lastMode);
54-
result.insert(coords, value.second);
54+
// TODO (rohany): Temporarily use a constant value here.
55+
result.insert(coords, T(2));
56+
}
57+
result.pack();
58+
return result;
59+
}
60+
61+
template<typename T>
62+
taco::Tensor<T> readIntoType(std::string name, std::string path, taco::ModeFormat format) {
63+
auto tensor = taco::read(path, format);
64+
taco::Tensor<T> result(name, tensor.getDimensions(), tensor.getFormat());
65+
std::vector<int> coords(tensor.getOrder());
66+
for (auto& value : taco::iterate<double>(tensor)) {
67+
for (int i = 0; i < tensor.getOrder(); i++) {
68+
coords[i] = value.first[i];
69+
}
70+
result.insert(coords, T(value.second));
5571
}
5672
result.pack();
5773
return result;

taco/ufuncs.cpp

+16-18
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ static void applyBenchSizes(benchmark::internal::Benchmark* b) {
151151
TACO_BENCH_ARGS(bench_ufunc_sparse, xor_0.01, 0.01, "xor")->Apply(applyBenchSizes);
152152
TACO_BENCH_ARGS(bench_ufunc_sparse, rightShift_0.01, 0.01, ">>")->Apply(applyBenchSizes);
153153

154-
static void bench_frostt_ufunc(benchmark::State& state, std::string tnsPath) {
154+
static void bench_frostt_ufunc(benchmark::State& state, std::string tnsPath, Func op) {
155155
auto path = getTacoTensorPath();
156156
auto frosttTensorPath = path;
157157
if (frosttTensorPath[frosttTensorPath.size() - 1] != '/') {
@@ -161,50 +161,48 @@ static void bench_frostt_ufunc(benchmark::State& state, std::string tnsPath) {
161161
frosttTensorPath += tnsPath;
162162

163163
// TODO (rohany): What format do we want to do here?
164-
auto frosttTensor = read(frosttTensorPath, Sparse);
165-
Tensor<double> other = shiftLastMode<double>("other", frosttTensor);
166-
167-
// TODO (rohany): Parametrize by the ufunc as well.
168-
// TODO (rohany): Certain ufuncs need for operands to be of a certain type.
169-
// ldexp for example requires the right hand side to be an integer (for python
170-
// at least). Not sure how we'll handle that for this.
171-
Func ldExp("2^", Ldexp(), leftIncAlgebra());
164+
auto frosttTensor = readIntoType<int64_t>("frostt", frosttTensorPath, Sparse);
165+
Tensor<int64_t> other = shiftLastMode<int64_t, int64_t>("other", frosttTensor);
172166

173167
for (auto _ : state) {
174168
state.PauseTiming();
175-
Tensor<double> result("result", frosttTensor.getDimensions(), frosttTensor.getFormat());
169+
Tensor<int64_t> result("result", frosttTensor.getDimensions(), frosttTensor.getFormat());
170+
result.setAssembleWhileCompute(true);
176171
switch (frosttTensor.getOrder()) {
177172
case 4: {
178173
IndexVar i, j, k, l;
179-
result(i, j, k, l) = ldExp(frosttTensor(i, j, k, l), other(i, j, k, l));
174+
result(i, j, k, l) = op(frosttTensor(i, j, k, l), other(i, j, k, l));
180175
break;
181176
}
182177
case 5: {
183178
IndexVar i, j, k, l, m;
184-
result(i, j, k, l, m) = ldExp(frosttTensor(i, j, k, l, m), other(i, j, k, l, m));
179+
result(i, j, k, l, m) = op(frosttTensor(i, j, k, l, m), other(i, j, k, l, m));
185180
break;
186181
}
187182
default:
188183
state.SkipWithError("invalid tensor dimension");
189184
return;
190185
}
191186
result.compile();
192-
result.assemble();
193187
state.ResumeTiming();
194188

195189
result.compute();
196190
}
197191
}
198192

199-
// TODO (rohany): We can define another macro to "nest" defining benchmarks
200-
// for each of the ufuncs that we want to operate on.
193+
Func ldExp("ldexp", Ldexp(), leftIncAlgebra());
194+
Func rightShift("rightShift", RightShift(), leftIncAlgebra());
195+
Func xorOp("xor", GeneralAdd(), xorAlgebra());
196+
201197
#define FOREACH_FROSTT_TENSOR(__func__) \
202198
__func__(nips, "nips.tns") \
203199
__func__(uber_pickups, "uber-pickups.tns") \
204-
__func__(chicaco_crime, "chicago-crime.tns") \
200+
__func__(chicago_crime, "chicago-crime.tns") \
205201
__func__(lbnl_network, "lbnl-network.tns")
206202

207203
#define DECLARE_FROSTT_UFUNC_BENCH(name, path) \
208-
TACO_BENCH_ARGS(bench_frostt_ufunc, name, path);
204+
TACO_BENCH_ARGS(bench_frostt_ufunc, name/xor, path, xorOp); \
205+
TACO_BENCH_ARGS(bench_frostt_ufunc, name/ldExp, path, ldExp); \
206+
TACO_BENCH_ARGS(bench_frostt_ufunc, name/rightShift, path, rightShift); \
209207

210-
FOREACH_FROSTT_TENSOR(DECLARE_FROSTT_UFUNC_BENCH)
208+
FOREACH_FROSTT_TENSOR(DECLARE_FROSTT_UFUNC_BENCH)

unpack_suitesparse.sh

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
cd data/suitesparse/
4+
5+
for f in *.tar.gz; do
6+
tar -xvf "$f" --strip=1
7+
done

0 commit comments

Comments
 (0)