Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: "CI"

on:
push:
branches:
- main

pull_request:

jobs:
build:
runs-on: 'ubuntu-latest'
strategy:
matrix:
include:
- id: gcc-12
cc: gcc-12
cxx: g++-12
- id: clang
cc: clang
cxx: clang++
name: Build (${{ matrix.cc }})
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
steps:
- uses: actions/checkout@v4
- name: CMake
run: |
sudo apt-get update
sudo apt-get install libhdf5-dev gcc-12 g++-12 clang
cmake -B build
- name: Build
run: VERBOSE=true make -C build -j `nproc`
- name: Archive Build
run: tar -czf build.tar.gz build
- uses: actions/upload-artifact@v4
with:
name: compliance-build-${{ matrix.id }}
path: build.tar.gz
retention-days: 1

test:
name: Test (${{ matrix.cc }})
needs: build
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
matrix:
include:
- id: gcc-12
cc: gcc-12
- id: clang
cc: clang
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: compliance-build-${{ matrix.id }}
- name: Restore Build
run: tar -xzf build.tar.gz
- name: Install Runtime Dependencies
run: |
sudo apt-get update
sudo apt-get install libhdf5-dev
- uses: prefix-dev/setup-pixi@v0.10.0
with:
run-install: false
cache: false
- name: CMake Tests
run: ctest --test-dir build --output-on-failure
- name: Compliance Tests
env:
BINSPARSE_BUILD_DIR: ${{ github.workspace }}/build
run: ./test/compliance/run-binsparse-tests.sh -q
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
scripts
venv
build
build-*
._*
tensor_test_files
12 changes: 6 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
include(FetchContent)

cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.20)
project(bsp-to-taco)

add_library(bsp-to-taco SHARED)

cmake_policy(SET CMP0079 NEW)

set(CMAKE_C_STANDARD 11)

#set(CMAKE_CXX_STANDARD 20)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
target_compile_features(bsp-to-taco PUBLIC cxx_std_11)

#set(CMAKE_C_FLAGS "-O3 -march=native")
set(CMAKE_CXX_FLAGS "-O3 -march=native -Wall -Wno-narrowing -fPIC")
Expand All @@ -21,8 +21,8 @@ add_subdirectory(src)

FetchContent_Declare(
binsparse
GIT_REPOSITORY https://github.com/junikimm717/binsparse-reference-c
GIT_TAG main
GIT_REPOSITORY https://github.com/Binsparse/binsparse-reference-c
GIT_TAG 13e56902c6f729822730297a5d13bbdbc62e619b
)
FetchContent_MakeAvailable(binsparse)
target_include_directories(bsp-to-taco PUBLIC ${binsparse_SOURCE_DIR}/include)
Expand Down Expand Up @@ -65,7 +65,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${taco_SOURCE_DIR}/include)
#### Project Configuration

target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_BINARY_DIR}/include)
target_link_libraries(${PROJECT_NAME} PUBLIC binsparse-rc taco)
target_link_libraries(${PROJECT_NAME} PUBLIC binsparse taco)

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
add_subdirectory(examples)
Expand Down
5 changes: 3 additions & 2 deletions include/bsp_taco/bsp_to_taco.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#include <binsparse/tensor.h>
#include <binsparse/read_tensor.h>
#include <binsparse/tensor.h>
#include <taco.h>

#pragma once

namespace bsp_taco {
taco::TensorBase makeTacoTensor(bsp_tensor_t& tensor);
taco::TensorBase makeTacoTensor(bsp_tensor_t& tensor,
const bsp_array_t* fill = nullptr);

taco::TensorBase readBinSparse(std::string filename);
}
1 change: 0 additions & 1 deletion include/bsp_taco/taco_to_bsp.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include "taco/tensor.h"
#include <binsparse/tensor.h>
#include <binsparse/write_tensor.h>
#include <taco.h>
Expand Down
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
# SPDX-License-Identifier: BSD-3-Clause

target_sources(bsp-to-taco PRIVATE
src/bsp_to_taco.cpp
src/taco_to_bsp.cpp
bsp_to_taco.cpp
taco_to_bsp.cpp
)
135 changes: 109 additions & 26 deletions src/bsp_to_taco.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#include <bsp_taco/bsp_to_taco.hpp>

#include <complex>
#include <cstring>
#include <cstdint>

static std::vector<int> getDimensions(bsp_tensor_t& tensor) {
std::vector<int> dims(tensor.rank);
for (int i = 0; i < tensor.rank; i++) {
Expand Down Expand Up @@ -45,20 +49,63 @@ static inline taco::Datatype getTacoDataType(bsp_array_t& array) {

static taco::Array bspToTacoArray(bsp_array_t& array) {
taco::Datatype dataType = getTacoDataType(array);
bsp_type_t type = array.type;
taco::Array res = taco::makeArray(dataType, array.size);
// eventually, get rid of memcpy?
memcpy(res.getData(), array.data, array.size * dataType.getNumBytes());
return res;
}

static taco::Array bspIndexArrayToTacoInt32Array(bsp_array_t& array) {
taco::Array res = taco::makeArray(taco::Int32, array.size);
auto* out = static_cast<int32_t*>(res.getData());
for (size_t i = 0; i < array.size; ++i) {
size_t value = 0;
switch (array.type) {
case BSP_UINT8:
value = static_cast<uint8_t*>(array.data)[i];
break;
case BSP_UINT16:
value = static_cast<uint16_t*>(array.data)[i];
break;
case BSP_UINT32:
value = static_cast<uint32_t*>(array.data)[i];
break;
case BSP_UINT64:
value = static_cast<uint64_t*>(array.data)[i];
break;
case BSP_INT8:
case BSP_BINT8:
value = static_cast<int8_t*>(array.data)[i];
break;
case BSP_INT16:
value = static_cast<int16_t*>(array.data)[i];
break;
case BSP_INT32:
value = static_cast<int32_t*>(array.data)[i];
break;
case BSP_INT64:
value = static_cast<int64_t*>(array.data)[i];
break;
default:
taco_uerror << "Unsupported Binsparse coordinate type";
}
taco_uassert(value <= static_cast<size_t>(INT32_MAX))
<< "Binsparse coordinate is too large for TACO int32 storage";
out[i] = static_cast<int32_t>(value);
}
return res;
}

static taco::Format createTacoFormat(bsp_tensor_t& tensor) {
bsp_level_t* level = tensor.level;
std::vector<taco::ModeFormatPack> modeTypes;
while (level->kind != BSP_TENSOR_ELEMENT) {
switch (level->kind) {
case BSP_TENSOR_DENSE: {
modeTypes.push_back(taco::Dense());
bsp_dense_t* data = (bsp_dense_t*) level->data;
for (int i = 0; i < data->rank; i++) {
modeTypes.push_back(taco::Dense());
}
level = ((bsp_dense_t*) level->data)->child;
break;
}
Expand Down Expand Up @@ -86,68 +133,105 @@ static taco::Format createTacoFormat(bsp_tensor_t& tensor) {
return taco::Format(modeTypes);
}

static size_t storedDimension(bsp_tensor_t& tensor, int depth) {
size_t logical = tensor.transpose != NULL ? tensor.transpose[depth] : depth;
taco_uassert(logical < (size_t) tensor.rank)
<< "Binsparse transpose is not a permutation";
return tensor.dims[logical];
}

static taco::Index createTacoIndex(bsp_tensor_t& tensor, taco::Format& format) {
bsp_level_t* level = tensor.level;
size_t* dims = tensor.dims;
std::vector<taco::ModeIndex> modeIndices;
int depth = 0;
while (level->kind != BSP_TENSOR_ELEMENT) {
switch (level->kind) {
case BSP_TENSOR_DENSE: {
modeIndices.push_back(taco::ModeIndex({taco::makeArray({(int) *dims})}));
bsp_dense_t* data = (bsp_dense_t*) level->data;
for (int i = 0; i < data->rank; i++) {
size_t dimension = storedDimension(tensor, depth + i);
taco_uassert(dimension <= static_cast<size_t>(INT32_MAX))
<< "Binsparse dimension is too large for TACO int32 storage";
modeIndices.push_back(
taco::ModeIndex({taco::makeArray({(int) dimension})}));
}
depth += data->rank;
level = ((bsp_dense_t*) level->data)->child;
break;
}
case BSP_TENSOR_SPARSE: {
bsp_sparse_t* data = (bsp_sparse_t*) level->data;
if (data->pointers_to != NULL && data->pointers_to->type != BSP_INT32) {
taco_uerror << "pointers_to just be an int32 type to interface "
<< "properly with taco!";
}
modeIndices.push_back(taco::ModeIndex({
data->pointers_to != NULL
? taco::Array(getTacoDataType(*data->pointers_to),
data->pointers_to->data, data->pointers_to->size,
taco::Array::Free)
? bspIndexArrayToTacoInt32Array(*data->pointers_to)
: taco::makeArray({
(int) 0,
(int) data->indices[0].size,
}),
taco::Array(getTacoDataType(data->indices[0]), data->indices[0].data,
data->indices[0].size, taco::Array::Free),
bspIndexArrayToTacoInt32Array(data->indices[0]),
}));
for (int i = 1; i < data->rank; i++) {
if (data->indices[i].type != BSP_INT32)
taco_terror << "indices just be an int32 type to interface properly "
<< "with taco!";
modeIndices.push_back(taco::ModeIndex({
taco::makeArray(getTacoDataType(data->indices[i]), 0),
taco::Array(getTacoDataType(data->indices[i]),
data->indices[i].data, data->indices[i].size,
taco::Array::Free),
taco::makeArray(taco::Int32, 0),
bspIndexArrayToTacoInt32Array(data->indices[i]),
}));
}
depth += data->rank;
level = ((bsp_sparse_t*) level->data)->child;
break;
}
default:;
}
dims++;
}
return taco::Index(format, modeIndices);
}

template <typename T>
static taco::Literal scalarLiteral(const bsp_array_t& array) {
T value;
memcpy(&value, array.data, sizeof(value));
return taco::Literal(value);
}

static taco::Literal getFillLiteral(const bsp_array_t& fill) {
switch (fill.type) {
case BSP_UINT8: return scalarLiteral<uint8_t>(fill);
case BSP_UINT16: return scalarLiteral<uint16_t>(fill);
case BSP_UINT32: return scalarLiteral<uint32_t>(fill);
case BSP_UINT64: return scalarLiteral<uint64_t>(fill);
case BSP_INT8:
case BSP_BINT8: return scalarLiteral<int8_t>(fill);
case BSP_INT16: return scalarLiteral<int16_t>(fill);
case BSP_INT32: return scalarLiteral<int32_t>(fill);
case BSP_INT64: return scalarLiteral<int64_t>(fill);
case BSP_FLOAT32: return scalarLiteral<float>(fill);
case BSP_FLOAT64: return scalarLiteral<double>(fill);
case BSP_COMPLEX_FLOAT32:
return scalarLiteral<std::complex<float>>(fill);
case BSP_COMPLEX_FLOAT64:
return scalarLiteral<std::complex<double>>(fill);
default:
taco_uerror << "Unsupported fill type supplied to taco converter";
return taco::Literal();
}
}

/*
Creates a taco object from a bsp tensor.
Note that this function **consumes** the bsp tensor object!
*/
taco::TensorBase bsp_taco::makeTacoTensor(bsp_tensor_t& tensor) {
bsp_level_t* level = tensor.level;
taco::TensorBase bsp_taco::makeTacoTensor(bsp_tensor_t& tensor,
const bsp_array_t* fill) {
if (tensor.is_iso)
taco_uerror << "TACO does not support iso-valued tensor storage";

bsp_array_t values = bsp_get_tensor_values(tensor);
taco::Format tacoFormat = createTacoFormat(tensor);
taco::Index tacoIndex = createTacoIndex(tensor, tacoFormat);
taco::Literal tacoFill =
fill == nullptr ? taco::Literal() : getFillLiteral(*fill);
taco::TensorBase tacoTensor(getTacoDataType(values), getDimensions(tensor),
tacoFormat);
tacoFormat, tacoFill);
// tacoTensor.setNeedsPack(false);
auto storage = tacoTensor.getStorage();
storage.setIndex(tacoIndex);
Expand All @@ -158,6 +242,5 @@ taco::TensorBase bsp_taco::makeTacoTensor(bsp_tensor_t& tensor) {

taco::TensorBase bsp_taco::readBinSparse(std::string filename) {
bsp_tensor_t tensor = bsp_read_tensor(filename.data(), NULL);
taco::TensorBase taco = bsp_taco::makeTacoTensor(tensor);
return taco;
return bsp_taco::makeTacoTensor(tensor);
}
Loading
Loading