c - 如何构建Catboost C评估库API?

标签 c go segmentation-fault incomplete-type catboost

我必须在某些编程语言(Golang 和 Python)中使用 Catboost 模型。最好的选择(为了性能和兼容性)是使用评估库,它可以是 C 或 C++ API。我关注了official documentation编译C API,但它有很多问题需要解决才能工作。

这些是我们在尝试用 C 语言创建评估库时遇到的问题:

1.

error: variable has incomplete type 'ModelCalcerHandle' (aka 'void')
    ModelCalcerHandle modelHandle;
  • c_wrapper.c:16:13: warning: incompatible pointer types passing 'float (*)[3]' to parameter of type 'const float **' [-Wincompatible-pointer-types]
                &floatFeatures, 3,
                ^~~~~~~~~~~~~~
    /Users/eli/workspace/test_c_api/catboost/catboost/libs/model_interface/c_api.h:151:19: note: passing argument to parameter 'floatFeatures' here
        const float** floatFeatures, size_t floatFeaturesSize,
                      ^
    c_wrapper.c:17:13: warning: incompatible pointer types passing 'char *(*)[4]' to parameter of type 'const char ***' [-Wincompatible-pointer-types]
                &catFeatures, 4,
                ^~~~~~~~~~~~
    /Users/eli/workspace/test_c_api/catboost/catboost/libs/model_interface/c_api.h:152:19: note: passing argument to parameter 'catFeatures' here
        const char*** catFeatures, size_t catFeaturesSize,
                      ^
    c_wrapper.c:18:13: warning: incompatible pointer types passing 'double (*)[1]' to parameter of type 'double *' [-Wincompatible-pointer-types]
                &result, 1
                ^~~~~~~
    /Users/eli/workspace/test_c_api/catboost/catboost/libs/model_interface/c_api.h:153:13: note: passing argument to parameter 'result' here
        double* result, size_t resultSize);
    

    解决方案:

    1. 我们通过将 modelHandle 变量重新定义为以下方式解决了问题 #1:
    ModelCalcerHandle *modelHandle = ModelCalcerCreate();
    

    进行此更改后,可以编译 C 程序,但我们收到了一个新错误:

    [1]    6489 segmentation fault  ./program
    
  • 段错误与问题 #2 中列出的警告有关。我们必须重新定义变量来解决它:
  • float floatFeaturesRaw[100];
    const float *floatFeatures = floatFeaturesRaw;
    const char *catFeaturesRaw[2] = {"1", "2"};
    const char **catFeatures = catFeaturesRaw;
    double resultRaw[1];
    double *result = resultRaw;
    

    if (!CalcModelPredictionSingle(
            modelHandle,
            &floatFeatures, 3,
            &catFeatures, 4,
            result, 1)) //We remove `&`
    {
       printf("CalcModelPrediction error message: %s\n", GetErrorString());
    }
    

    我将在评论中添加完整的解决方案,从代码修复到如何编译 C 代码。

    最佳答案

    这是完整的解决方案:

    1. 克隆 catboost 存储库:

    git 克隆 https://github.com/catboost/catboost.git

  • 从 CatBoost 存储库的本地副本中打开 catboost 目录。

  • 构建评估库(我选择了共享库,但您可以选择您需要的库)。就我而言,我必须更改 --target-platform 参数,我使用的是 Mac M1 和 macOS Ventura 13.1,clang 版本是 14.0.0:

  • ./ya make -r catboost/libs/model_interface --target-platform CLANG14-DARWIN-ARM64
    
  • 创建 C 文件。修复了 C 示例代码:
  • #include <stdio.h>
    #include <c_api.h>
    
    int main()
    {
        float floatFeaturesRaw[3] = {0, 89, 1};
        const float *floatFeatures = floatFeaturesRaw;
        const char *catFeaturesRaw[4] = {"Others", "443_HTTPS", "6", "24"};
        const char **catFeatures = catFeaturesRaw;
        double resultRaw[4];
        double *result = resultRaw;
    
        ModelCalcerHandle *modelHandle = ModelCalcerCreate();
        if (!LoadFullModelFromFile(modelHandle, "catboost_model"))
        {
            printf("LoadFullModelFromFile error message: %s\n", GetErrorString());
        }
        SetPredictionType(modelHandle, 3);
        if (!CalcModelPredictionSingle(
                modelHandle,
                floatFeatures, 3,
                catFeatures, 4,
                result, 4))
        {
            printf("CalcModelPrediction error message: %s\n", GetErrorString());
        }
        printf("%f\n", result[0]);
        printf("%f\n", result[1]);
        printf("%f\n", result[2]);
        printf("%f\n", result[3]);
        ModelCalcerDelete(modelHandle);
    }
    

    考虑:

    • 我已将 SetPredictionType 设置为 APT_PROBABILITY
    • 我们的模型预测多个类别,因此结果[4]
    • 我们一次只需要预测一条记录,因此我们使用 CalcModelPredictionSingle 方法。
  • 编译 C 代码:
  • gcc -v -o program.out c_code.c -l catboostmodel -I /path/to/catboost/repo/catboost/catboost/libs/model_interface/ -L /path/to/catboost/repo/catboost/catboost/libs/model_interface/
    

    重要提示:确保未显示任何警告或错误消息。

  • 现在您可以运行它:
  • 重要提示:确保 catboost 模型文件与 program.out 位于同一路径。

    ./program.out
    

    关于c - 如何构建Catboost C评估库API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74962479/

    相关文章:

    c - 如何使用 zlib 在 C 中压缩并在 golang 中解压缩

    c - 初始化结构段错误

    在 C 中创建广义舍入函数

    c - 如何在DOS提示符下运行C程序

    arrays - 我如何在go中找到数组的大小

    regex - 捕获两个大括号之间的所有数据

    c - 两次调用 mmap 时出现 SIGSEGV

    c - 在 C 中使用 memcpy 时出现段错误

    c - 使用 MS Visual Studio 与 GCC 的不同结果

    c - Mac OS 上的混合静态和动态链接