Skip to content

wrapping a vendor dscal #328

@amklinv-nnl

Description

@amklinv-nnl

@georgemalerbo is interested in automatically generating BLAS wrappers for us. Thanks George!

Before we do that, @mhoemmen could you please provide feedback on the following dscal wrapper?

// Compiled with g++-16 -std=c++23 dscal_example.cpp -lblas
#include<cassert>
#include <vector>
#include <mdspan>
#include <iostream>

using namespace std;

// Should come from CMake or a config header
using blas_index_t = int; // BLAS typically uses int for sizes and indices

extern "C" {
    // We need to account for the Fortran name mangling, which often appends an underscore to the function name
    // The mangling should be automatically detected
    void dscal_(blas_index_t* n, double* a, double* x, blas_index_t* incx);
}

// Which accessors does it make sense to support?
template<class SizeType,
         ::std::size_t ext0,
         class Layout,
         class Accessor>
// scal requires strided data, so we can enforce this at compile time
// What is the difference between is_always_strided and is_strided? Should we support both?
requires ( mdspan<double, extents<SizeType, ext0>, Layout, Accessor>::is_always_strided() )
void scale(double a, mdspan<double, extents<SizeType, ext0>, Layout, Accessor> x) {
    blas_index_t n = x.extent(0);
    // This should be checked before calling the function
    // Like, in a "does it make sense to call BLAS?" function
    assert(n <= std::numeric_limits<blas_index_t>::max() && "Size of x exceeds maximum value for blas_index_t");

    // Assuming contiguous data, this will be 1 for a standard vector
    // This code will still work for non-contiguous data, but the performance may be worse due to cache misses
    blas_index_t incx = x.stride(0);
    dscal_(&n, &a, x.data_handle(), &incx);
}

int main() {
    vector<double> x_data = {1.0, 2.0, 3.0};
    auto x = mdspan(x_data.data(), x_data.size());

    double a = 2.0;
    scale(a, x);

    for(int i = 0; i < x.extent(0); ++i) {
        cout << x[i] << " ";
    }
    cout << endl;

    return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions