Skip to content

Commit 2217b41

Browse files
authored
Merge pull request #148 from ecmwf/feature/eckit-sparsematrix-allocators
Feature/eckit sparsematrix allocators reorganization, new in-place allocator
2 parents 800531f + 77fc1ac commit 2217b41

File tree

11 files changed

+451
-67
lines changed

11 files changed

+451
-67
lines changed

src/eckit/linalg/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ list( APPEND eckit_la_srcs
1818
Triplet.h
1919
Vector.cc
2020
Vector.h
21+
allocator/BufferAllocator.cc
22+
allocator/BufferAllocator.h
23+
allocator/NonOwningAllocator.cc
24+
allocator/NonOwningAllocator.h
25+
allocator/StandardAllocator.cc
26+
allocator/StandardAllocator.h
27+
allocator/StandardContainerAllocator.cc
28+
allocator/StandardContainerAllocator.h
2129
dense/LinearAlgebraGeneric.cc
2230
dense/LinearAlgebraGeneric.h
2331
sparse/LinearAlgebraGeneric.cc

src/eckit/linalg/SparseMatrix.cc

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
#include "eckit/exception/Exceptions.h"
2424
#include "eckit/io/AutoCloser.h"
2525
#include "eckit/io/MemoryHandle.h"
26-
#include "eckit/log/Bytes.h"
26+
#include "eckit/linalg/allocator/BufferAllocator.h"
27+
#include "eckit/linalg/allocator/StandardAllocator.h"
2728
#include "eckit/log/Log.h"
2829
#include "eckit/memory/MemoryBuffer.h"
2930
#include "eckit/serialisation/FileStream.h"
@@ -37,64 +38,6 @@ static_assert(sizeof(Index) == sizeof(SparseMatrix::UIndex), "sizeof(sizeof(Inde
3738
static constexpr bool littleEndian = eckit_LITTLE_ENDIAN != 0;
3839

3940

40-
//----------------------------------------------------------------------------------------------------------------------
41-
42-
namespace detail {
43-
44-
class StandardAllocator : public SparseMatrix::Allocator {
45-
public:
46-
StandardAllocator() : membuff_(0) {}
47-
48-
SparseMatrix::Layout allocate(SparseMatrix::Shape& shape) override {
49-
if (shape.allocSize() > membuff_.size()) {
50-
membuff_.resize(shape.allocSize());
51-
}
52-
53-
SparseMatrix::Layout p;
54-
55-
char* addr = membuff_;
56-
57-
p.data_ = reinterpret_cast<Scalar*>(addr);
58-
p.outer_ = reinterpret_cast<SparseMatrix::UIndex*>(addr + shape.sizeofData());
59-
p.inner_ = reinterpret_cast<Index*>(addr + shape.sizeofData() + shape.sizeofOuter());
60-
61-
return p;
62-
}
63-
64-
void deallocate(SparseMatrix::Layout p, SparseMatrix::Shape) override {}
65-
bool inSharedMemory() const override { return false; }
66-
void print(std::ostream& out) const override {
67-
out << "StandardAllocator[" << Bytes{static_cast<double>(membuff_.size())} << "]";
68-
}
69-
70-
MemoryBuffer membuff_;
71-
};
72-
73-
74-
class BufferAllocator : public SparseMatrix::Allocator {
75-
public:
76-
BufferAllocator(const MemoryBuffer& buffer) : buffer_(buffer, buffer.size()) {}
77-
78-
SparseMatrix::Layout allocate(SparseMatrix::Shape& shape) override {
79-
SparseMatrix::Layout layout;
80-
81-
SparseMatrix::load(buffer_.data(), buffer_.size(), layout, shape);
82-
83-
return layout;
84-
}
85-
86-
void deallocate(SparseMatrix::Layout, SparseMatrix::Shape) override {}
87-
bool inSharedMemory() const override { return false; }
88-
void print(std::ostream& out) const override {
89-
out << "BufferAllocator[" << Bytes{static_cast<double>(buffer_.size())} << "]";
90-
}
91-
92-
MemoryBuffer buffer_;
93-
};
94-
95-
96-
} // namespace detail
97-
9841
//----------------------------------------------------------------------------------------------------------------------
9942

10043
void SparseMatrix::Shape::print(std::ostream& os) const {
@@ -105,19 +48,19 @@ void SparseMatrix::Shape::print(std::ostream& os) const {
10548
}
10649

10750

108-
SparseMatrix::SparseMatrix(Allocator* alloc) : owner_(alloc != nullptr ? alloc : new detail::StandardAllocator) {
51+
SparseMatrix::SparseMatrix(Allocator* alloc) : owner_(alloc != nullptr ? alloc : new allocator::StandardAllocator) {
10952
spm_ = owner_->allocate(shape_);
11053
}
11154

11255

11356
SparseMatrix::SparseMatrix(Size rows, Size cols, Allocator* alloc) :
114-
owner_(alloc != nullptr ? alloc : new detail::StandardAllocator) {
57+
owner_(alloc != nullptr ? alloc : new allocator::StandardAllocator) {
11558
reserve(rows, cols, 1);
11659
}
11760

11861

11962
SparseMatrix::SparseMatrix(Size rows, Size cols, const std::vector<Triplet>& triplets) :
120-
owner_(new detail::StandardAllocator) {
63+
owner_(new allocator::StandardAllocator) {
12164

12265
// Count number of non-zeros, allocate memory 1 triplet per non-zero
12366
Size nnz = std::count_if(triplets.begin(), triplets.end(), [](const auto& tri) { return tri.nonZero(); });
@@ -163,17 +106,17 @@ SparseMatrix::SparseMatrix(Size rows, Size cols, const std::vector<Triplet>& tri
163106
}
164107

165108

166-
SparseMatrix::SparseMatrix(Stream& s) : owner_(new detail::StandardAllocator) {
109+
SparseMatrix::SparseMatrix(Stream& s) : owner_(new allocator::StandardAllocator) {
167110
decode(s);
168111
}
169112

170113

171-
SparseMatrix::SparseMatrix(const MemoryBuffer& buffer) : owner_(new detail::BufferAllocator(buffer)) {
114+
SparseMatrix::SparseMatrix(const MemoryBuffer& buffer) : owner_(new allocator::BufferAllocator(buffer)) {
172115
spm_ = owner_->allocate(shape_);
173116
}
174117

175118

176-
SparseMatrix::SparseMatrix(const SparseMatrix& other) : owner_(new detail::StandardAllocator) {
119+
SparseMatrix::SparseMatrix(const SparseMatrix& other) : owner_(new allocator::StandardAllocator) {
177120
if (!other.empty()) { // in case we copy an other that was constructed empty
178121

179122
reserve(other.rows(), other.cols(), other.nonZeros());
@@ -539,7 +482,7 @@ void SparseMatrix::decode(Stream& s) {
539482

540483
reset();
541484

542-
owner_ = std::make_unique<detail::StandardAllocator>();
485+
owner_ = std::make_unique<allocator::StandardAllocator>();
543486

544487
reserve(rows, cols, nnz);
545488

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* (C) Copyright 1996- ECMWF.
3+
*
4+
* This software is licensed under the terms of the Apache Licence Version 2.0
5+
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6+
* In applying this licence, ECMWF does not waive the privileges and immunities
7+
* granted to it by virtue of its status as an intergovernmental organisation
8+
* nor does it submit to any jurisdiction.
9+
*/
10+
11+
12+
#include "eckit/linalg/allocator/BufferAllocator.h"
13+
14+
#include <ostream>
15+
16+
#include "eckit/log/Bytes.h"
17+
18+
19+
namespace eckit::linalg::allocator {
20+
21+
22+
BufferAllocator::BufferAllocator(const MemoryBuffer& buffer) : buffer_(buffer, buffer.size()) {}
23+
24+
25+
SparseMatrix::Layout BufferAllocator::allocate(SparseMatrix::Shape& shape) {
26+
SparseMatrix::Layout layout;
27+
SparseMatrix::load(buffer_.data(), buffer_.size(), layout, shape);
28+
return layout;
29+
}
30+
31+
32+
void BufferAllocator::deallocate(SparseMatrix::Layout, SparseMatrix::Shape) {}
33+
34+
35+
bool BufferAllocator::inSharedMemory() const {
36+
return false;
37+
}
38+
39+
40+
void BufferAllocator::print(std::ostream& out) const {
41+
out << "BufferAllocator[" << Bytes{static_cast<double>(buffer_.size())} << "]";
42+
}
43+
44+
45+
} // namespace eckit::linalg::allocator
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* (C) Copyright 1996- ECMWF.
3+
*
4+
* This software is licensed under the terms of the Apache Licence Version 2.0
5+
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6+
* In applying this licence, ECMWF does not waive the privileges and immunities
7+
* granted to it by virtue of its status as an intergovernmental organisation
8+
* nor does it submit to any jurisdiction.
9+
*/
10+
11+
12+
#pragma once
13+
14+
#include "eckit/linalg/SparseMatrix.h"
15+
16+
#include "eckit/memory/MemoryBuffer.h"
17+
18+
19+
namespace eckit::linalg::allocator {
20+
21+
22+
class BufferAllocator : public SparseMatrix::Allocator {
23+
public:
24+
BufferAllocator(const MemoryBuffer&);
25+
26+
SparseMatrix::Layout allocate(SparseMatrix::Shape&) override;
27+
28+
void deallocate(SparseMatrix::Layout, SparseMatrix::Shape) override;
29+
bool inSharedMemory() const override;
30+
void print(std::ostream&) const override;
31+
32+
MemoryBuffer buffer_;
33+
};
34+
35+
36+
} // namespace eckit::linalg::allocator
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* (C) Copyright 2024- ECMWF.
3+
*
4+
* This software is licensed under the terms of the Apache Licence Version 2.0
5+
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6+
* In applying this licence, ECMWF does not waive the privileges and immunities
7+
* granted to it by virtue of its status as an intergovernmental organisation
8+
* nor does it submit to any jurisdiction.
9+
*/
10+
11+
12+
#include "eckit/linalg/allocator/NonOwningAllocator.h"
13+
14+
#include <ostream>
15+
16+
#include "eckit/exception/Exceptions.h"
17+
18+
19+
namespace eckit::linalg::allocator {
20+
21+
22+
NonOwningAllocator::NonOwningAllocator(Size Nr, Size Nc, Size nnz, Index* ia, Index* ja, Scalar* a) :
23+
Nr_(Nr), Nc_(Nc), nnz_(nnz), ia_(ia), ja_(ja), a_(a) {
24+
ASSERT(ia_ != nullptr);
25+
ASSERT(ja_ != nullptr);
26+
ASSERT(a_ != nullptr);
27+
}
28+
29+
30+
SparseMatrix::Layout NonOwningAllocator::NonOwningAllocator::allocate(SparseMatrix::Shape& shape) {
31+
shape.size_ = nnz_;
32+
shape.rows_ = Nr_;
33+
shape.cols_ = Nc_;
34+
35+
SparseMatrix::Layout layout;
36+
layout.outer_ = reinterpret_cast<decltype(SparseMatrix::Layout::outer_)>(ia_);
37+
layout.inner_ = ja_;
38+
layout.data_ = a_;
39+
40+
return layout;
41+
}
42+
43+
44+
void NonOwningAllocator::deallocate(SparseMatrix::Layout, SparseMatrix::Shape) {}
45+
46+
47+
bool NonOwningAllocator::inSharedMemory() const {
48+
return false;
49+
}
50+
51+
52+
void NonOwningAllocator::print(std::ostream& out) const {
53+
out << "NonOwningAllocator[Nr=" << Nr_ << ",Nc=" << Nc_ << ",nnz=" << nnz_ << "]";
54+
}
55+
56+
57+
} // namespace eckit::linalg::allocator
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* (C) Copyright 2024- ECMWF.
3+
*
4+
* This software is licensed under the terms of the Apache Licence Version 2.0
5+
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6+
* In applying this licence, ECMWF does not waive the privileges and immunities
7+
* granted to it by virtue of its status as an intergovernmental organisation
8+
* nor does it submit to any jurisdiction.
9+
*/
10+
11+
12+
#pragma once
13+
14+
#include "eckit/linalg/SparseMatrix.h"
15+
16+
17+
namespace eckit::linalg::allocator {
18+
19+
20+
/**
21+
* @brief In-place allocator for sparse matrices, directly mapping supporting arrays including from another
22+
* SparseMatrix. It is able to provide a "view".
23+
*/
24+
class NonOwningAllocator : public SparseMatrix::Allocator {
25+
public:
26+
NonOwningAllocator(Size Nr, Size Nc, Size nnz, Index* ia, Index* ja, Scalar* a);
27+
28+
SparseMatrix::Layout allocate(SparseMatrix::Shape&) override;
29+
30+
void deallocate(SparseMatrix::Layout, SparseMatrix::Shape) override;
31+
bool inSharedMemory() const override;
32+
void print(std::ostream&) const override;
33+
34+
private:
35+
const Size Nr_;
36+
const Size Nc_;
37+
const Size nnz_;
38+
Index* ia_; // NOTE: not owned
39+
Index* ja_; // NOTE: not owned
40+
Scalar* a_; // NOTE: not owned
41+
};
42+
43+
44+
} // namespace eckit::linalg::allocator
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
/*
3+
* (C) Copyright 1996- ECMWF.
4+
*
5+
* This software is licensed under the terms of the Apache Licence Version 2.0
6+
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
7+
* In applying this licence, ECMWF does not waive the privileges and immunities
8+
* granted to it by virtue of its status as an intergovernmental organisation
9+
* nor does it submit to any jurisdiction.
10+
*/
11+
12+
13+
#include "eckit/linalg/allocator/StandardAllocator.h"
14+
15+
#include <ostream>
16+
17+
#include "eckit/log/Bytes.h"
18+
19+
20+
namespace eckit::linalg::allocator {
21+
22+
23+
StandardAllocator::StandardAllocator() : buffer_(0) {}
24+
25+
26+
SparseMatrix::Layout StandardAllocator::allocate(SparseMatrix::Shape& shape) {
27+
if (shape.allocSize() > buffer_.size()) {
28+
buffer_.resize(shape.allocSize());
29+
}
30+
31+
SparseMatrix::Layout layout;
32+
33+
char* addr = buffer_;
34+
35+
layout.data_ = reinterpret_cast<Scalar*>(addr);
36+
layout.outer_ = reinterpret_cast<SparseMatrix::UIndex*>(addr + shape.sizeofData());
37+
layout.inner_ = reinterpret_cast<Index*>(addr + shape.sizeofData() + shape.sizeofOuter());
38+
39+
return layout;
40+
}
41+
42+
43+
void StandardAllocator::deallocate(SparseMatrix::Layout p, SparseMatrix::Shape) {}
44+
45+
46+
bool StandardAllocator::inSharedMemory() const {
47+
return false;
48+
}
49+
50+
51+
void StandardAllocator::print(std::ostream& out) const {
52+
out << "StandardAllocator[" << Bytes{static_cast<double>(buffer_.size())} << "]";
53+
}
54+
55+
56+
} // namespace eckit::linalg::allocator

0 commit comments

Comments
 (0)