Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimizations method weighted #23

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
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
16 changes: 8 additions & 8 deletions src/mir/method/MethodWeighted.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
#include "mir/util/Trace.h"
#include "mir/util/Types.h"

#pragma omp declare reduction(vec_merge_sorted : std::vector<size_t> : \
omp_out.insert(omp_out.end(), omp_in.begin(), omp_in.end()); \
std::inplace_merge(omp_out.begin(), omp_out.begin() + omp_out.size() - omp_in.size(), omp_out.end())) \
initializer(omp_priv = decltype(omp_orig)())

namespace mir::method {

Expand Down Expand Up @@ -429,14 +433,10 @@ void MethodWeighted::execute(context::Context& ctx, const repres::Representation
ASSERT(W.cols() == npts_inp);

std::vector<size_t> forceMissing; // reserving size unnecessary (not the general case)
{
auto begin = W.begin(0);
auto end(begin);
for (size_t r = 0; r < W.rows(); r++) {
if (begin == (end = W.end(r))) {
forceMissing.push_back(r);
}
begin = end;
#pragma omp parallel for reduction(vec_merge_sorted:forceMissing)
for (size_t r = 0; r < W.rows(); ++r) {
if (W.outer()[r] == W.outer()[r + 1]) {
forceMissing.push_back(r);
}
}
Comment on lines 435 to 441
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part corresponds to Section 3. If I am not mistaken, this calculation could be performed during matrix creation, as the original empty rows in the weight matrix are part of the geometry. A vector containing the indices of these empty rows could be stored as a private member and cached. This approach could save significant time, especially with larger matrices, where traversing all rows is costly. For example, in the base case profiling with eORCA12, each MIR API call takes approximately 40 ms.


Expand Down
43 changes: 19 additions & 24 deletions src/mir/method/nonlinear/MissingIfHeaviestMissing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,36 +32,34 @@ bool MissingIfHeaviestMissing::treatment(DenseMatrix& /*A*/, WeightMatrix& W, De
const MIRValuesVector& values, const double& missingValue) const {

// correct matrix weigths for the missing values
ASSERT(W.cols() == values.size());

ASSERT(W.cols() == values.size());
auto* outer = W.outer();
auto* inner = W.inner();
auto* data = const_cast<WeightMatrix::Scalar*>(W.data());
bool modif = false;

WeightMatrix::Size i = 0;
WeightMatrix::iterator it(W);
#pragma omp parallel for reduction(||:modif)
for (WeightMatrix::Size r = 0; r < W.rows(); ++r) {
const WeightMatrix::iterator end = W.end(r);
WeightMatrix::Size row_start = outer[r];
WeightMatrix::Size row_end = outer[r + 1]; // Marks the end of this row

// count missing values, accumulate weights (disregarding missing values) and find maximum weight in row
size_t i_missing = i;
// Initialize variables for tracking missing values and weights in the row
size_t i_missing = row_start;
size_t N_missing = 0;
size_t N_entries = 0;
size_t N_entries = row_end - row_start;
double sum = 0.;
double heaviest = -1.;
bool heaviest_is_missing = false;

WeightMatrix::iterator kt(it);
WeightMatrix::Size k = i;
for (; it != end; ++it, ++i, ++N_entries) {

const bool miss = values[it.col()] == missingValue;
for (WeightMatrix::Size i = row_start; i < row_end; ++i) {
const bool miss = values[inner[i]] == missingValue;

if (miss) {
++N_missing;
i_missing = i;
}
else {
sum += *it;
} else {
sum += data[i];
}

if (heaviest < data[i]) {
Expand All @@ -70,21 +68,18 @@ bool MissingIfHeaviestMissing::treatment(DenseMatrix& /*A*/, WeightMatrix& W, De
}
}

// weights redistribution: zero-weight all missing values, linear re-weighting for the others;
// if all values are missing, or the closest value is missing, force missing value
if (N_missing > 0) {
if (N_missing == N_entries || heaviest_is_missing || eckit::types::is_approximately_equal(sum, 0.)) {

for (WeightMatrix::Size j = k; j < k + N_entries; ++j) {
data[j] = j == i_missing ? 1. : 0.;
for (WeightMatrix::Size i = row_start; i < row_end; ++i) {
data[i] = (i == i_missing) ? 1. : 0.;
}
}
else {
} else {

const double factor = 1. / sum;
for (WeightMatrix::Size j = k; j < k + N_entries; ++j, ++kt) {
const bool miss = values[kt.col()] == missingValue;
data[j] = miss ? 0. : (factor * data[j]);
for (WeightMatrix::Size i = row_start; i < row_end; ++i) {
const bool miss = values[inner[i]] == missingValue;
data[i] = miss ? 0. : (factor * data[i]);
}
}
modif = true;
Expand Down