megenginelite-sys 1.8.2

A safe megenginelite wrapper in Rust
Documentation
/**
 * \file dnn/src/naive/dropout/opr_impl.cpp
 * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
 *
 * Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 */
#include "src/naive/dropout/opr_impl.h"
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include "src/common/utils.h"
#include "src/naive/handle.h"

using namespace megdnn;
using namespace naive;
using namespace std;
namespace {

using Param = megdnn::Dropout::Param;

dt_float32 get_random_number(uint64_t x) {
    union {
        uint32_t i;
        dt_float32 f;
    } u;
    u.i = (0x7F << 23) | (x >> 41);
    return 2 - u.f;
}

template <typename T>
void forward(
        T* inp, T* oup, void* raw_reserved, size_t len, Xoroshiro128plus& rng,
        float drop_prob) {
    uint8_t* reserved = reinterpret_cast<uint8_t*>(raw_reserved);
    float scale = 1.0f / (1.0f - drop_prob);
    for (size_t i = 0; i < len; ++i) {
        float rn = get_random_number(rng());
        reserved[i] = rn < drop_prob ? 0 : 1;
        oup[i] = static_cast<T>(reserved[i] ? static_cast<float>(inp[i]) * scale : 0.f);
    }
}

template <typename T>
void backward(T* doup, T* dinp, void* raw_reserved, size_t len, float drop_prob) {
    uint8_t* reserved = reinterpret_cast<uint8_t*>(raw_reserved);
    float scale = 1.0f / (1.0f - drop_prob);
    for (size_t i = 0; i < len; ++i) {
        dinp[i] =
                static_cast<T>(reserved[i] ? static_cast<float>(doup[i]) * scale : 0.f);
    }
}

}  // namespace

namespace megdnn {
namespace naive {

size_t DropoutForwardImpl::get_mask_size_in_bytes(const TensorLayout& inp) {
    return inp.total_nr_elems();
}

void DropoutForwardImpl::exec(
        _megdnn_tensor_in inp, _megdnn_tensor_out oup, _megdnn_tensor_out mask,
        _megdnn_workspace workspace) {
    check_exec(inp.layout, oup.layout, mask.layout, workspace.size);
    size_t length = inp.layout.total_nr_elems();
    uint64_t seed = param().seed;

    m_rng.ensure_seed(seed);

#define cb(DType)                                                          \
    if (inp.layout.dtype == DType()) {                                     \
        using T = typename DTypeTrait<DType>::ctype;                       \
        MEGDNN_DISPATCH_CPU_KERN_OPR(forward<T>(                           \
                inp.ptr<T>(), oup.ptr<T>(), mask.raw_ptr(), length, m_rng, \
                param().drop_prob));                                       \
        return;                                                            \
    }
    MEGDNN_FOREACH_COMPUTING_DTYPE_FLOAT(cb)
#undef cb
    megdnn_throw("bad dtype");
}

void DropoutBackwardImpl::exec(
        _megdnn_tensor_in doup, _megdnn_tensor_in mask, _megdnn_tensor_out dinp,
        _megdnn_workspace workspace) {
    check_exec(doup.layout, mask.layout, dinp.layout, workspace.size);
    size_t length = doup.layout.total_nr_elems();

#define cb(DType)                                                     \
    if (doup.layout.dtype == DType()) {                               \
        using T = typename DTypeTrait<DType>::ctype;                  \
        MEGDNN_DISPATCH_CPU_KERN_OPR(backward<T>(                     \
                doup.ptr<T>(), dinp.ptr<T>(), mask.raw_ptr(), length, \
                param().drop_prob));                                  \
        return;                                                       \
    }
    MEGDNN_FOREACH_COMPUTING_DTYPE_FLOAT(cb)
#undef cb
    megdnn_throw("bad dtype");
}

}  // namespace naive
}  // namespace megdnn
// vim: syntax=cpp.doxygen