File: cpu_matmul_coo.cpp

package info (click to toggle)
onednn 3.9.1%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 79,124 kB
  • sloc: cpp: 850,217; ansic: 37,403; lisp: 16,757; python: 3,463; asm: 831; sh: 78; javascript: 66; makefile: 41
file content (108 lines) | stat: -rw-r--r-- 4,203 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*******************************************************************************
* Copyright 2024-2025 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

/// @example cpu_matmul_coo.cpp
/// > Annotated version: @ref cpu_matmul_coo_cpp
///
/// This C++ API example demonstrates how to create and execute a
/// [MatMul](@ref dev_guide_matmul) primitive that uses a source tensor
/// encoded with the COO sparse encoding.
///
/// @page cpu_matmul_coo_cpp MatMul Primitive Example
///
/// @include cpu_matmul_coo.cpp

#include <algorithm>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>

#include "dnnl.hpp"
#include "example_utils.hpp"

using namespace dnnl;

bool check_result(dnnl::memory dst_mem) {
    // clang-format off
    const std::vector<float> expected_result = {8.750000, 11.250000, 2.500000,
                                                6.000000,  2.250000, 3.750000,
                                               19.000000, 15.500000, 5.250000,
                                                4.000000,  7.000000, 3.000000};
    // clang-format on
    std::vector<float> dst_data(expected_result.size());
    read_from_dnnl_memory(dst_data.data(), dst_mem);
    return expected_result == dst_data;
}

void sparse_matmul() {
    dnnl::engine engine(engine::kind::cpu, 0);

    const memory::dim M = 4;
    const memory::dim N = 3;
    const memory::dim K = 6;

    // A sparse matrix represented in the COO format.
    std::vector<float> src_coo_values = {2.5f, 1.5f, 1.5f, 2.5f, 2.0f};
    std::vector<int32_t> src_coo_row_indices = {0, 1, 2, 2, 3};
    std::vector<int32_t> src_coo_col_indices = {0, 2, 0, 5, 1};

    // clang-format off
    std::vector<float> weights_data = {3.5f, 4.5f, 1.0f,
                                       2.0f, 3.5f, 1.5f,
                                       4.0f, 1.5f, 2.5f,
                                       3.5f, 5.5f, 4.5f,
                                       1.5f, 2.5f, 5.5f,
                                       5.5f, 3.5f, 1.5f};
    // clang-format on

    const int nnz = static_cast<int>(src_coo_values.size());

    // Create a memory descriptor for COO format by providing information
    // about number of non-zero entries and data types of metadata.
    const auto src_coo_md = memory::desc::coo(
            {M, K}, memory::data_type::f32, nnz, memory::data_type::s32);
    const auto wei_md = memory::desc(
            {K, N}, memory::data_type::f32, memory::format_tag::oi);
    const auto dst_md = memory::desc(
            {M, N}, memory::data_type::f32, memory::format_tag::nc);

    // This memory is created for the given values and metadata of COO format.
    memory src_coo_mem(src_coo_md, engine,
            {src_coo_values.data(), src_coo_row_indices.data(),
                    src_coo_col_indices.data()});
    memory wei_mem(wei_md, engine, weights_data.data());
    memory dst_mem(dst_md, engine);

    dnnl::stream stream(engine);

    auto sparse_matmul_pd
            = matmul::primitive_desc(engine, src_coo_md, wei_md, dst_md);
    auto sparse_matmul_prim = matmul(sparse_matmul_pd);

    std::unordered_map<int, memory> sparse_matmul_args;
    sparse_matmul_args.insert({DNNL_ARG_SRC, src_coo_mem});
    sparse_matmul_args.insert({DNNL_ARG_WEIGHTS, wei_mem});
    sparse_matmul_args.insert({DNNL_ARG_DST, dst_mem});

    sparse_matmul_prim.execute(stream, sparse_matmul_args);
    stream.wait();
    if (!check_result(dst_mem)) throw std::runtime_error("Unexpected output.");
}

int main(int argc, char **argv) {
    return handle_example_errors({engine::kind::cpu}, sparse_matmul);
}