Skip to content

Commit 316d1b0

Browse files
committed
successfully implemented e2e tests
1 parent 83e22b5 commit 316d1b0

12 files changed

+354
-20
lines changed

CMakeLists.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ set(CMAKE_CXX_FLAGS "-O3 -march=native -Wall -Wno-narrowing -fPIC")
1616

1717
add_subdirectory(include)
1818
add_subdirectory(src)
19-
add_subdirectory(examples)
2019

2120
#### binsparse reference implementation configuration
2221

@@ -67,3 +66,8 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${taco_SOURCE_DIR}/include)
6766

6867
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_BINARY_DIR}/include)
6968
target_link_libraries(${PROJECT_NAME} PUBLIC binsparse-rc taco)
69+
70+
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
71+
add_subdirectory(examples)
72+
add_subdirectory(test)
73+
endif()

dev.sh

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env sh
2+
3+
CONTAINER='bsp-to-taco'
4+
IMAGE='docker.io/junikimm717/nvim2025:finch'
5+
DIR="$(realpath "$(dirname "$0")")"
6+
7+
case "$1" in
8+
pull|p)
9+
podman pull "$IMAGE"
10+
(podman container ls | grep "$CONTAINER" > /dev/null 2>&1) && podman container rm -fv "$CONTAINER"
11+
;;
12+
clear|c)
13+
(podman container ls -a | grep "$CONTAINER" > /dev/null 2>&1)\
14+
&& {
15+
podman container kill "$CONTAINER" > /dev/null 2>&1;
16+
podman container rm "$CONTAINER"
17+
}
18+
;;
19+
*)
20+
set +x
21+
if ! (podman container ls -a | grep "$CONTAINER" > /dev/null 2>&1); then
22+
podman run\
23+
-dt\
24+
--name "$CONTAINER"\
25+
--group-add keep-groups\
26+
-v "$DIR:/workspace"\
27+
--privileged\
28+
--rm\
29+
"$IMAGE"
30+
fi || exit 1
31+
podman exec\
32+
-e ENV=/root/.profile\
33+
-it "$CONTAINER" /bin/bash
34+
;;
35+
esac

examples/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ endfunction()
99

1010
add_example(taco_experiments)
1111
add_example(parse_taco)
12+
add_example(tensor_test)

examples/parse_taco.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ int main(int argc, char** argv) {
2525
for (int j = 0; j < index.getModeIndex(i).numIndexArrays(); j++) {
2626
auto array = index.getModeIndex(i).getIndexArray(j);
2727
for (int k = 0; k < array.getSize(); k++) {
28-
cout << array.get(k).get().int64Value << " ";
28+
cout << array.get(k).get().int32Value << " ";
2929
}
3030
cout << "\n";
3131
}
@@ -50,6 +50,5 @@ int main(int argc, char** argv) {
5050
for (int i = 0; i < vals.getSize(); i++) std::cout << vals.get(i).get().float64Value << " ";
5151
cout << "\n";
5252
auto format = tensor.getStorage().getFormat();
53-
//bsp_destroy_tensor_t(bsp);
5453
return 0;
5554
}

examples/taco_experiments.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ int main() {
2626

2727
Format fmt({Compressed({ModeFormat::ORDERED, ModeFormat::NOT_UNIQUE}),
2828
Singleton({ModeFormat::ORDERED, ModeFormat::NOT_UNIQUE})});
29-
Tensor<double> A({5, 5}, fmt);
29+
Tensor<double> A({4, 2}, fmt);
3030

3131
// TODO: generate with finch, use experimental parse_taco.cpp and check the
3232
// tensor below is the same.
3333

3434
// Insert non-zero values with explicit coordinates
35-
A.insert({0, 0}, 3.5);
36-
A.insert({1, 2}, 4.2);
37-
A.insert({1, 1}, 1.1);
38-
A.insert({2, 3}, 1.4);
35+
A.insert({0, 1}, 1.0);
36+
A.insert({1, 0}, 1.0);
37+
A.insert({3, 0}, 3.0);
38+
A.insert({3, 1}, 4.0);
3939

4040
A.pack();
4141

@@ -60,8 +60,8 @@ int main() {
6060

6161
cout << "===================\n";
6262
cout << "Extract some values: \n";
63-
for (int k = 0; k < 5; k++) {
64-
for (int i = 0; i < 5; i++) {
63+
for (int k = 0; k < 4; k++) {
64+
for (int i = 0; i < 2; i++) {
6565
cout << A(k, i) << " ";
6666
}
6767
cout << "\n\n";

examples/tensor_test.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <binsparse/tensor.h>
2+
#include <binsparse/read_tensor.h>
3+
#include <binsparse/write_tensor.h>
4+
#include "bsp_to_taco.hpp"
5+
#include "taco/tensor.h"
6+
#include "taco_to_bsp.hpp"
7+
8+
using namespace std;
9+
10+
int main(int argc, char** argv) {
11+
if (argc < 3) {
12+
fprintf(stderr, "usage: ./tensor_test [file_name.h5] [output_file_name.h5]\n");
13+
return 1;
14+
}
15+
char* file_name = argv[1];
16+
bsp_tensor_t tensor = bsp_read_tensor(argv[1], NULL);
17+
taco::TensorBase taco = makeTacoTensor(tensor);
18+
tensor = makeBspTensor(taco);
19+
{
20+
bsp_level_t* curLevel = tensor.level;
21+
while(true) {
22+
bool breakvar = false;
23+
switch(curLevel->kind) {
24+
case BSP_TENSOR_DENSE: {
25+
cout << "dense layer!" << endl;
26+
bsp_dense_t* data = (bsp_dense_t*) curLevel->data;
27+
curLevel = data->child;
28+
break;
29+
}
30+
case BSP_TENSOR_SPARSE: {
31+
cout << "sparse layer!" << endl;
32+
bsp_sparse_t* data = (bsp_sparse_t*) curLevel->data;
33+
curLevel = data->child;
34+
break;
35+
}
36+
case BSP_TENSOR_ELEMENT: {
37+
breakvar = true;
38+
break;
39+
}
40+
}
41+
if (breakvar) break;
42+
}
43+
}
44+
bsp_write_tensor(argv[2], tensor, NULL, NULL, 9);
45+
bsp_destroy_tensor_t(tensor);
46+
return 0;
47+
}

include/taco_to_bsp.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "taco/tensor.h"
2+
#include <binsparse/tensor.h>
3+
#include <binsparse/read_tensor.h>
4+
#include <taco.h>
5+
6+
bsp_tensor_t makeBspTensor(taco::TensorBase tacoTensor);

src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44

55
target_sources(bsp-to-taco PRIVATE
66
src/bsp_to_taco.cpp
7+
src/taco_to_bsp.cpp
78
)

src/bsp_to_taco.cpp

+16-10
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
#include "taco/storage/storage.h"
99
#include "taco/tensor.h"
1010
#include "taco/type.h"
11-
#include <algorithm>
12-
1311

1412
static std::vector<int> getDimensions(bsp_tensor_t& tensor) {
1513
std::vector<int> dims(tensor.rank);
@@ -49,15 +47,15 @@ static inline taco::Datatype getTacoDataType(bsp_array_t& array) {
4947
case BSP_COMPLEX_FLOAT64:
5048
return taco::Complex128;
5149
default:
52-
taco_ierror;
50+
taco_uerror << "Unsupported type supplied to taco converter";
5351
return taco::Float64;
5452
}
5553
}
5654

5755
static taco::Array bspToTacoArray(bsp_array_t& array) {
5856
taco::Datatype dataType = getTacoDataType(array);
5957
bsp_type_t type = array.type;
60-
taco::Array res = taco::makeArray(getTacoDataType(array), array.size);
58+
taco::Array res = taco::makeArray(dataType, array.size);
6159
// eventually, get rid of memcpy?
6260
memcpy(res.getData(), array.data, array.size * dataType.getNumBytes());
6361
return res;
@@ -91,9 +89,7 @@ static taco::Format createTacoFormat(bsp_tensor_t& tensor) {
9189
std::vector<int> modeOrdering(tensor.rank);
9290
for (int i = 0; i < tensor.rank; i++) {
9391
modeOrdering[i] = tensor.transpose[i];
94-
std::cout << tensor.transpose[i] << " ";
9592
}
96-
std::cout << " size: " << modeTypes.size() << "\n";
9793
return taco::Format(modeTypes, modeOrdering);
9894
}
9995
return taco::Format(modeTypes);
@@ -110,22 +106,28 @@ static taco::Index createTacoIndex(bsp_tensor_t& tensor, taco::Format& format) {
110106
level = ((bsp_dense_t*) level->data)->child;
111107
break;
112108
}
113-
// eventually, this should probably not be UserOwns.
114109
case BSP_TENSOR_SPARSE: {
115110
bsp_sparse_t* data = (bsp_sparse_t*) level->data;
111+
if (data->pointers_to != NULL && data->pointers_to->type != BSP_INT32) {
112+
taco_uerror << "pointers_to just be an int32 type to interface "
113+
<< "properly with taco!";
114+
}
116115
modeIndices.push_back(taco::ModeIndex({
117116
data->pointers_to != NULL
118117
? taco::Array(getTacoDataType(*data->pointers_to),
119118
data->pointers_to->data, data->pointers_to->size,
120119
taco::Array::Free)
121120
: taco::makeArray({
122-
(int64_t) 0,
123-
(int64_t) data->indices[0].size,
121+
(int) 0,
122+
(int) data->indices[0].size,
124123
}),
125124
taco::Array(getTacoDataType(data->indices[0]), data->indices[0].data,
126125
data->indices[0].size, taco::Array::Free),
127126
}));
128127
for (int i = 1; i < data->rank; i++) {
128+
if (data->indices[i].type != BSP_INT32)
129+
taco_terror << "indices just be an int32 type to interface properly "
130+
<< "with taco!";
129131
modeIndices.push_back(taco::ModeIndex({
130132
taco::makeArray(getTacoDataType(data->indices[i]), 0),
131133
taco::Array(getTacoDataType(data->indices[i]),
@@ -143,6 +145,10 @@ static taco::Index createTacoIndex(bsp_tensor_t& tensor, taco::Format& format) {
143145
return taco::Index(format, modeIndices);
144146
}
145147

148+
/*
149+
Creates a taco object from a bsp tensor.
150+
Note that this function **consumes** the bsp tensor object!
151+
*/
146152
taco::TensorBase makeTacoTensor(bsp_tensor_t& tensor) {
147153
bsp_level_t* level = tensor.level;
148154

@@ -151,7 +157,7 @@ taco::TensorBase makeTacoTensor(bsp_tensor_t& tensor) {
151157
taco::Index tacoIndex = createTacoIndex(tensor, tacoFormat);
152158
taco::TensorBase tacoTensor(getTacoDataType(values), getDimensions(tensor),
153159
tacoFormat);
154-
//tacoTensor.setNeedsPack(false);
160+
// tacoTensor.setNeedsPack(false);
155161
auto storage = tacoTensor.getStorage();
156162
storage.setIndex(tacoIndex);
157163
storage.setValues(bspToTacoArray(values));

src/taco_to_bsp.cpp

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#include "binsparse/types.h"
2+
#include "taco/format.h"
3+
#include <binsparse/tensor.h>
4+
#include <binsparse/write_tensor.h>
5+
#include <taco.h>
6+
7+
static inline bsp_type_t getTacoDataType(taco::Datatype type) {
8+
if (type == taco::UInt8)
9+
return BSP_UINT8;
10+
else if (type == taco::UInt16)
11+
return BSP_UINT16;
12+
else if (type == taco::UInt32)
13+
return BSP_UINT32;
14+
else if (type == taco::UInt64)
15+
return BSP_UINT64;
16+
else if (type == taco::Int8)
17+
return BSP_INT8;
18+
else if (type == taco::Int16)
19+
return BSP_INT16;
20+
else if (type == taco::Int32)
21+
return BSP_INT32;
22+
else if (type == taco::Int64)
23+
return BSP_INT64;
24+
else if (type == taco::Float32)
25+
return BSP_FLOAT32;
26+
else if (type == taco::Float64)
27+
return BSP_FLOAT64;
28+
else if (type == taco::Int8)
29+
return BSP_BINT8;
30+
else if (type == taco::Complex64)
31+
return BSP_COMPLEX_FLOAT32;
32+
else if (type == taco::Complex128)
33+
return BSP_COMPLEX_FLOAT64;
34+
else {
35+
taco_uerror << "Unsupported type supplied to taco converter";
36+
return BSP_INVALID_TYPE;
37+
}
38+
}
39+
40+
static bsp_array_t makeBspIndexArray(taco::Array arr) {
41+
taco_uassert(arr.getType() == taco::Int32);
42+
bsp_array_t res = bsp_construct_array_t(arr.getSize(), BSP_INT32);
43+
memcpy(res.data, arr.getData(), taco::Int32.getNumBytes() * arr.getSize());
44+
return res;
45+
}
46+
47+
bsp_tensor_t makeBspTensor(taco::TensorBase tacoTensor) {
48+
bsp_tensor_t res = bsp_construct_default_tensor_t();
49+
auto storage = tacoTensor.getStorage();
50+
auto index = storage.getIndex();
51+
52+
// copy over the transposes.
53+
auto modeOrdering = storage.getFormat().getModeOrdering();
54+
res.transpose = (size_t*) malloc(sizeof(size_t) * modeOrdering.size());
55+
for (int i = 0; i < modeOrdering.size(); i++) {
56+
res.transpose[i] = (size_t) modeOrdering[i];
57+
}
58+
59+
// copy over the dimensions.
60+
auto dims = storage.getDimensions();
61+
res.rank = dims.size();
62+
res.dims = (size_t*) malloc(sizeof(size_t) * dims.size());
63+
for (int i = 0; i < dims.size(); i++) {
64+
res.dims[i] = dims[i];
65+
}
66+
67+
std::vector<taco::ModeFormat> formats = storage.getFormat().getModeFormats();
68+
69+
int dimsPtr = 0;
70+
res.level = (bsp_level_t*) malloc(sizeof(bsp_level_t));
71+
bsp_level_t* curLevel = res.level;
72+
73+
while (dimsPtr < dims.size()) {
74+
taco::ModeFormat format = formats[dimsPtr];
75+
76+
if (format.getName() == taco::Sparse.getName()) {
77+
int boundary = dimsPtr + 1;
78+
while (boundary < dims.size() &&
79+
typeid(formats[boundary]) != typeid(taco::Singleton)) {
80+
boundary++;
81+
}
82+
curLevel->kind = BSP_TENSOR_SPARSE;
83+
84+
bsp_sparse_t* data = (bsp_sparse_t*) malloc(sizeof(bsp_sparse_t));
85+
curLevel->data = data;
86+
87+
data->pointers_to = NULL;
88+
if (dimsPtr != 0) {
89+
data->pointers_to = (bsp_array_t*) malloc(sizeof(bsp_array_t));
90+
*data->pointers_to =
91+
makeBspIndexArray(index.getModeIndex(dimsPtr).getIndexArray(0));
92+
}
93+
94+
data->rank = boundary - dimsPtr;
95+
data->indices = (bsp_array_t*) malloc(sizeof(bsp_array_t) * data->rank);
96+
for (int indicesIdx = 0; indicesIdx < data->rank; indicesIdx++) {
97+
data->indices[indicesIdx] = makeBspIndexArray(
98+
index.getModeIndex(dimsPtr + indicesIdx).getIndexArray(1));
99+
}
100+
101+
data->child = (bsp_level_t*) malloc(sizeof(bsp_level_t));
102+
curLevel = data->child;
103+
104+
dimsPtr = boundary;
105+
} else if (format.getName() == taco::Dense.getName()) {
106+
curLevel->kind = BSP_TENSOR_DENSE;
107+
bsp_dense_t* data = (bsp_dense_t*) malloc(sizeof(bsp_dense_t));
108+
curLevel->data = data;
109+
110+
data->rank = 1;
111+
data->child = (bsp_level_t*) malloc(sizeof(bsp_level_t));
112+
curLevel = data->child;
113+
114+
dimsPtr++;
115+
} else {
116+
taco_uerror << "This should be impossible; neither dense nor sparse";
117+
}
118+
}
119+
120+
// code to deal with copying over the actual data.
121+
{
122+
curLevel->kind = BSP_TENSOR_ELEMENT;
123+
taco::Array values = storage.getValues();
124+
res.nnz = values.getSize();
125+
bsp_element_t* data = (bsp_element_t*) malloc(sizeof(bsp_element_t));
126+
127+
bsp_array_t valuesArray =
128+
bsp_construct_array_t(res.nnz, getTacoDataType(values.getType()));
129+
memcpy(valuesArray.data, values.getData(),
130+
values.getType().getNumBytes() * values.getSize());
131+
132+
bsp_array_t* arr = (bsp_array_t*) malloc(sizeof(bsp_array_t));
133+
*arr = valuesArray;
134+
135+
curLevel->data = arr;
136+
}
137+
return res;
138+
}

0 commit comments

Comments
 (0)