<commit_before>/*******************************************************
 * Copyright (c) 2020, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <common/Logger.hpp>
#include <common/err_common.hpp>
#include <common/util.hpp>
#include <cudnnModule.hpp>
#include <device_manager.hpp>
#include <utility.hpp>

#include <array>
#include <string>
#include <tuple>

using common::Version;
using std::make_tuple;
using std::string;

namespace cuda {

// clang-format off
// Latest version from each minor releases are enlisted below
constexpr std::array<common::Version, 10> cudnnVersions = {
    make_tuple(7, 6,  5),
    make_tuple(7, 5,  1),
    make_tuple(7, 4,  2),
    make_tuple(7, 3,  1),
    make_tuple(7, 2,  1),
    make_tuple(7, 1,  4),
    make_tuple(7, 0,  5),
    make_tuple(6, 0, 21),
    make_tuple(5, 1, 10),
    make_tuple(4, 0,  7)
};
// clang-format on

spdlog::logger* cudnnModule::getLogger() const noexcept {
    return module.getLogger();
}

auto cudnnVersionComponents(size_t version) {
    size_t major = version / 1000;
    size_t minor = (version - (major * 1000)) / 100;
    size_t patch = (version - (major * 1000) - (minor * 100));
    return make_tuple(major, minor, patch);
}

cudnnModule::cudnnModule()
    : module({"cudnn"}, {"", "64_7", "64_8", "64_6", "64_5", "64_4"}, {""},
             cudnnVersions.size(), cudnnVersions.data()) {
    if (!module.isLoaded()) {
        AF_TRACE(
            "WARNING: Unable to load cuDNN: {}"
            "\ncuDNN failed to load. Try installing cuDNN or check if cuDNN is "
            "in the search path. On Linux, you can set the LD_DEBUG=libs "
            "environment variable to debug loading issues. Falling back to "
            "matmul based implementation",
            module.getErrorMessage());

        return;
    }

    MODULE_FUNCTION_INIT(cudnnGetVersion);

    int rtmajor, rtminor;
    size_t cudnn_version          = this->cudnnGetVersion();
    size_t cudnn_rtversion        = 0;
    std::tie(major, minor, patch) = cudnnVersionComponents(cudnn_version);

    if (cudnn_version >= 6000) {
        MODULE_FUNCTION_INIT(cudnnGetCudartVersion);
        cudnn_rtversion = this->cudnnGetCudartVersion();
    } else {
        AF_TRACE(
            "Warning: This version of cuDNN({}.{}) does not support "
            "cudnnGetCudartVersion. No runtime checks performed.",
            major, minor);
    }

    std::tie(rtmajor, rtminor, std::ignore) =
        cudnnVersionComponents(cudnn_rtversion);

    AF_TRACE("cuDNN Version: {}.{}.{} cuDNN CUDA Runtime: {}.{}", major, minor,
             patch, rtmajor, rtminor);

    // Check to see if the version of cuDNN ArrayFire was compiled against
    // is compatible with the version loaded at runtime
    if (CUDNN_VERSION <= 6000 && cudnn_version > CUDNN_VERSION) {
        string error_msg = fmt::format(
            "ArrayFire was compiled with an older version of cuDNN({}.{}) that "
            "does not support the version that was loaded at runtime({}.{}).",
            CUDNN_MAJOR, CUDNN_MINOR, major, minor);
        AF_ERROR(error_msg, AF_ERR_NOT_SUPPORTED);
    }

    int afcuda_runtime = 0;
    cudaRuntimeGetVersion(&afcuda_runtime);
    if (afcuda_runtime != static_cast<int>(cudnn_version)) {
        getLogger()->warn(
            "WARNING: ArrayFire CUDA Runtime({}) and cuDNN CUDA "
            "Runtime({}.{}) do not match. For maximum compatibility, make sure "
            "the two versions match.(Ignoring check)",
            // NOTE: the int version formats from CUDA and cuDNN are different
            // so we are using int_version_to_string for the ArrayFire CUDA
            // runtime
            int_version_to_string(afcuda_runtime), rtmajor, rtminor);
    }

    MODULE_FUNCTION_INIT(cudnnConvolutionBackwardData);
    MODULE_FUNCTION_INIT(cudnnConvolutionBackwardFilter);
    MODULE_FUNCTION_INIT(cudnnConvolutionForward);
    MODULE_FUNCTION_INIT(cudnnCreate);
    MODULE_FUNCTION_INIT(cudnnCreateConvolutionDescriptor);
    MODULE_FUNCTION_INIT(cudnnCreateFilterDescriptor);<commit_msg>Fix cuDNN runtime version checks and warnings<commit_after>/*******************************************************
 * Copyright (c) 2020, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <common/Logger.hpp>
#include <common/err_common.hpp>
#include <common/util.hpp>
#include <cudnnModule.hpp>
#include <device_manager.hpp>
#include <utility.hpp>

#include <array>
#include <string>
#include <tuple>

using common::Version;
using std::make_tuple;
using std::string;

namespace cuda {

// clang-format off
// Latest version from each minor releases are enlisted below
constexpr std::array<common::Version, 10> cudnnVersions = {
    make_tuple(7, 6,  5),
    make_tuple(7, 5,  1),
    make_tuple(7, 4,  2),
    make_tuple(7, 3,  1),
    make_tuple(7, 2,  1),
    make_tuple(7, 1,  4),
    make_tuple(7, 0,  5),
    make_tuple(6, 0, 21),
    make_tuple(5, 1, 10),
    make_tuple(4, 0,  7)
};
// clang-format on

spdlog::logger* cudnnModule::getLogger() const noexcept {
    return module.getLogger();
}

auto cudnnVersionComponents(size_t version) {
    size_t major = version / 1000;
    size_t minor = (version - (major * 1000)) / 100;
    size_t patch = (version - (major * 1000) - (minor * 100));
    return make_tuple(major, minor, patch);
}

auto cudaRuntimeVersionComponents(size_t version) {
    auto major = version / 1000;
    auto minor = (version - (major * 1000)) / 10;
    return make_tuple(major, minor);
}

cudnnModule::cudnnModule()
    : module({"cudnn"}, {"", "64_7", "64_8", "64_6", "64_5", "64_4"}, {""},
             cudnnVersions.size(), cudnnVersions.data()) {
    if (!module.isLoaded()) {
        AF_TRACE(
            "WARNING: Unable to load cuDNN: {}"
            "\ncuDNN failed to load. Try installing cuDNN or check if cuDNN is "
            "in the search path. On Linux, you can set the LD_DEBUG=libs "
            "environment variable to debug loading issues. Falling back to "
            "matmul based implementation",
            module.getErrorMessage());

        return;
    }

    MODULE_FUNCTION_INIT(cudnnGetVersion);

    int rtmajor, rtminor;
    size_t cudnn_version          = this->cudnnGetVersion();
    size_t cudnn_rtversion        = 0;
    std::tie(major, minor, patch) = cudnnVersionComponents(cudnn_version);

    if (cudnn_version >= 6000) {
        MODULE_FUNCTION_INIT(cudnnGetCudartVersion);
        cudnn_rtversion = this->cudnnGetCudartVersion();
    } else {
        AF_TRACE(
            "Warning: This version of cuDNN({}.{}) does not support "
            "cudnnGetCudartVersion. No runtime checks performed.",
            major, minor);
    }

    std::tie(rtmajor, rtminor) = cudaRuntimeVersionComponents(cudnn_rtversion);

    AF_TRACE("cuDNN Version: {}.{}.{} cuDNN CUDA Runtime: {}.{}", major, minor,
             patch, rtmajor, rtminor);

    // Check to see if the version of cuDNN ArrayFire was compiled against
    // is compatible with the version loaded at runtime
    if (CUDNN_VERSION <= 6000 && cudnn_version > CUDNN_VERSION) {
        string error_msg = fmt::format(
            "ArrayFire was compiled with an older version of cuDNN({}.{}) that "
            "does not support the version that was loaded at runtime({}.{}).",
            CUDNN_MAJOR, CUDNN_MINOR, major, minor);
        AF_ERROR(error_msg, AF_ERR_NOT_SUPPORTED);
    }

    int afcuda_runtime = 0;
    cudaRuntimeGetVersion(&afcuda_runtime);
    if (afcuda_runtime != static_cast<int>(cudnn_rtversion)) {
        getLogger()->warn(
            "WARNING: ArrayFire CUDA Runtime({}) and cuDNN CUDA "
            "Runtime({}) do not match. For maximum compatibility, make sure "
            "the two versions match.(Ignoring check)",
            // NOTE: the int version formats from CUDA and cuDNN are different
            // so we are using int_version_to_string for the ArrayFire CUDA
            // runtime
            int_version_to_string(afcuda_runtime),
            int_version_to_string(cudnn_rtversion));
    }

    MODULE_FUNCTION_INIT(cudnnConvolutionBackwardData);
    MODULE_FUNCTION_INIT(cudnnConvolutionBackwardFilter);
    MODULE_FUNCTION_INIT(cudnnConvolutionForward);
    MODULE_FUNCTION_INIT(cudnnCreate);
    MODULE_FUNCTION_INIT(cudnnCreateConvolutionDescriptor);
    MODULE_FUNCTION_INIT(cudnnCreateFilterDescriptor);
{'fraction_non_alphanumeric': 0.1375812150917588, 'fraction_numerical': 0.020061552490596147, 'mean_word_length': 3.182078169685415, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7369559', 'n_tokens_mistral': 2898, 'n_tokens_neox': 2722, 'n_words': 711}