Skip to content

Commit

Permalink
temp commit for vectorization_1 solution
Browse files Browse the repository at this point in the history
  • Loading branch information
mapochamp committed Jan 31, 2025
1 parent 5070644 commit f1c10e3
Showing 1 changed file with 74 additions and 40 deletions.
114 changes: 74 additions & 40 deletions labs/core_bound/vectorization_1/solution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,53 @@
#include <cassert>
#include <type_traits>

// Introduce a vector of scores.
using simd_score_t = std::array<int16_t, sequence_count_v>;
using simd_sequence_t = std::array<simd_score_t, sequence_size_v>;

// Transpose a collection of sequences to a sequence of simd vectors
simd_sequence_t transpose(std::vector<sequence_t> const &sequences)
{
assert(sequences.size() == sequence_count_v);

simd_sequence_t simd_sequence{};

for(size_t i=0; i< simd_sequence.size(); ++i)
for(size_t j = 0; j < sequences.size(); ++j)
{
{
simd_sequence[i][j] = sequences[j][i]; // can be done in place
}
}

return simd_sequence;
}

// The alignment algorithm which computes the alignment of the given sequence
// pairs.
result_t compute_alignment(std::vector<sequence_t> const &sequences1,
std::vector<sequence_t> const &sequences2) {
result_t result{};

for (size_t sequence_idx = 0; sequence_idx < sequences1.size();
++sequence_idx) {
using score_t = int16_t;
using column_t = std::array<score_t, sequence_size_v + 1>;

sequence_t const &sequence1 = sequences1[sequence_idx];
sequence_t const &sequence2 = sequences2[sequence_idx];
// transpose the sequences.
auto trSeq1 = transpose(sequences1);
auto trSeq2 = transpose(sequences2);

using score_t = simd_score_t;
using column_t = std::array<score_t, sequence_size_v + 1>;

/*
* Initialise score values.
*/
score_t gap_open{-11};
score_t gap_extension{-1};
score_t match{6};
score_t mismatch{-4};
score_t gap_open{};
gap_open.fill(-11);
score_t gap_extension{};
gap_extension.fill(-1);
score_t match{};
match.fill(6);
score_t mismatch{};
mismatch.fill(-4);

/*
* Setup the matrix.
Expand All @@ -42,47 +68,55 @@ result_t compute_alignment(std::vector<sequence_t> const &sequences1,
last_vertical_gap = gap_open;

for (size_t i = 1; i < score_column.size(); ++i) {
score_column[i] = last_vertical_gap;
horizontal_gap_column[i] = last_vertical_gap + gap_open;
last_vertical_gap += gap_extension;
for(size_t k = 0; k < sequence_count_v; ++k)
{
score_column[i][k] = last_vertical_gap[k];
horizontal_gap_column[i][k] = last_vertical_gap[k] + gap_open[k];
last_vertical_gap[k] += gap_extension[k];
}
}

/*
* Compute the main recursion to fill the matrix.
*/
for (unsigned col = 1; col <= sequence2.size(); ++col) {
for (unsigned col = 1; col <= trSeq2.size(); ++col) {
score_t last_diagonal_score =
score_column[0]; // Cache last diagonal score to compute this cell.
score_column[0] = horizontal_gap_column[0];
last_vertical_gap = horizontal_gap_column[0] + gap_open;
horizontal_gap_column[0] += gap_extension;

for (unsigned row = 1; row <= sequence1.size(); ++row) {
// Compute next score from diagonal direction with match/mismatch.
score_t best_cell_score =
last_diagonal_score +
(sequence1[row - 1] == sequence2[col - 1] ? match : mismatch);
// Determine best score from diagonal, vertical, or horizontal
// direction.
best_cell_score = std::max(best_cell_score, last_vertical_gap);
best_cell_score = std::max(best_cell_score, horizontal_gap_column[row]);
// Cache next diagonal value and store optimum in score_column.
last_diagonal_score = score_column[row];
score_column[row] = best_cell_score;
// Compute the next values for vertical and horizontal gap.
best_cell_score += gap_open;
last_vertical_gap += gap_extension;
horizontal_gap_column[row] += gap_extension;
// Store optimum between gap open and gap extension.
last_vertical_gap = std::max(last_vertical_gap, best_cell_score);
horizontal_gap_column[row] =
std::max(horizontal_gap_column[row], best_cell_score);
for(size_t k = 0; k < sequence_count_v; ++k)
{
score_column[0][k] = horizontal_gap_column[0][k];
last_vertical_gap[k] = horizontal_gap_column[0][k] + gap_open[k];
horizontal_gap_column[0][k] += gap_extension[k];
}

for (unsigned row = 1; row <= trSeq1.size(); ++row) {
// Compute next score from diagonal direction with match/mismatch.
score_t best_cell_score = last_diagonal_score;
for(size_t k = 0; k < sequence_count_v; ++k)
best_cell_score[k] += (trSeq1[row - 1][k] == trSeq2[col - 1][k] ? match[k] : mismatch[k]);
// Determine best score from diagonal, vertical, or horizontal
// direction.
for(size_t k = 0; k < sequence_count_v; ++k) {
best_cell_score[k] = std::max(best_cell_score[k], last_vertical_gap[k]);
best_cell_score[k] = std::max(best_cell_score[k], horizontal_gap_column[row][k]);
// Cache next diagonal value and store optimum in score_column.
last_diagonal_score[k] = score_column[row][k];
score_column[row][k] = best_cell_score[k];
// Compute the next values for vertical and horizontal gap.
best_cell_score[k] += gap_open[k];
last_vertical_gap[k] += gap_extension[k];
horizontal_gap_column[row][k] += gap_extension[k];
// Store optimum between gap open and gap extension.
last_vertical_gap[k] = std::max(last_vertical_gap[k], best_cell_score[k]);
horizontal_gap_column[row][k] =
std::max(horizontal_gap_column[row][k], best_cell_score[k]);
}
}
}

// Report the best score.
result[sequence_idx] = score_column.back();
}
for(size_t k = 0; k < sequence_count_v; ++k)
result[k] = score_column.back()[k];

return result;
}

0 comments on commit f1c10e3

Please sign in to comment.