C语言性能优化:从基础到高级的全面指南

news2025/2/7 9:58:25
引言

C 语言以其高效、灵活和功能强大而著称,被广泛应用于系统编程、嵌入式开发、游戏开发等领域。然而,要写出高性能的 C 语言代码,需要对 C 语言的特性和底层硬件有深入的了解。本文将详细介绍 C 语言性能优化的背后技术,并通过具体的代码示例来展示如何实现性能优化。本文分为多个部分,从基本概念和技巧到高级性能优化技术,全面覆盖 C 语言性能优化的各个方面。
在这里插入图片描述

1. 基本概念和技巧
1.1 数据对齐

数据对齐是指数据的内存地址与数据大小的整数倍对齐。大多数现代计算机系统都要求数据对齐,因为对齐的数据访问速度更快。在 C 语言中,可以通过 #pragma pack 指令来设置数据对齐的方式。

#include <stdio.h>
#pragma pack(1) // 设置数据对齐为1字节
struct Example {
    char a;
    int b;
    char c;
};
#pragma pack() // 恢复默认数据对齐方式

int main() {
    struct Example ex;
    printf("Size of struct: %zu\n", sizeof(ex)); // 输出结构体大小
    return 0;
}

在上面的代码中,通过设置 #pragma pack(1),将数据对齐方式设置为 1 字节。这样,结构体 Example 中的数据将按照 1 字节对齐,而不是默认的 4 字节对齐。这会导致结构体的大小变小,但可能会降低访问速度。因此,在实际开发中,需要根据具体情况来选择合适的数据对齐方式。

1.2 循环展开

循环展开是一种通过增加每次迭代中执行的操作数来减少循环次数的技术。这可以减少循环的开销,提高代码的执行速度。

#include <stdio.h>

void loop_unrolling(int *arr, int n, int value) {
    int i;
    for (i = 0; i < n; i += 2) {
        arr[i] = value;
        arr[i + 1] = value;
    }
}

int main() {
    int arr[10];
    loop_unrolling(arr, 10, 5);
    for (int i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

在上面的代码中,通过将每次迭代中的操作数从 1 增加到 2,将循环次数减少了一半。这样可以减少循环的开销,提高代码的执行速度。但需要注意的是,循环展开会增加代码的大小,因此需要根据具体情况来选择是否使用循环展开。

1.3 函数内联

函数内联是一种通过将函数调用展开为函数体来减少函数调用开销的技术。在 C 语言中,可以通过 inline 关键字来声明内联函数。

#include <stdio.h>

inline int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(3, 4);
    printf("Result: %d\n", result);
    return 0;
}

在上面的代码中,通过将 add 函数声明为内联函数,编译器会将函数调用展开为函数体,从而减少函数调用的开销。但需要注意的是,内联函数会增加代码的大小,因此需要根据具体情况来选择是否使用内联函数。

2. 编译器优化
2.1 编译器选项

编译器提供了多种优化选项,这些选项可以影响编译过程,从而生成更高效的机器代码。以下是一些常用的编译器优化选项。

  • -O0:无优化(默认选项),用于调试。
  • -O1:一级优化,主要包括去除冗余代码、常量折叠等,不会进行复杂的优化。
  • -O2:二级优化,除了包含一级优化的所有内容外,还包括循环展开、指令重排等。
  • -O3:三级优化,在二级优化的基础上,增加更多的优化措施,如自动向量化。
  • -Ofast:允许编译器进行一些可能违反语言标准的优化,通常能提供更高的性能。
  • -march=native:启用针对本机 CPU 架构的优化,使得生成的代码能够更好地利用特定硬件的特性。
gcc -O0 -o compute_O0 compute.c # 无优化版本
gcc -O1 -o compute_O1 compute.c # 一级优化版本
gcc -O2 -o compute_O2 compute.c # 二级优化版本
gcc -O3 -o compute_O3 compute.c # 三级优化版本
gcc -Ofast -o compute_Ofast compute.c # 可能违反标准的优化版本
gcc -march=native -o compute_native compute.c # 针对本地架构优化版本

通过比较不同优化级别的执行时间,可以选择最适合当前程序的优化选项。

2.2 编译器内置函数

现代编译器通常提供一些内置函数,这些函数可以替代标准库函数或手动编写的代码,以提供更好的性能。

  • __builtin_expect:用于分支预测优化。
  • __builtin_prefetch:用于数据预取,以减少缓存未命中的次数。
#include <stdio.h>

// 假设我们有一个检查错误码的函数
int error_check(int error_code) {
    if (error_code == 0) {
        // 正常情况
    } else {
        // 错误处理
    }
}

// 使用 __builtin_expect 优化
int error_check_optimized(int error_code) {
    if (__builtin_expect(error_code, 0)) {
        // 错误处理
    } else {
        // 正常情况
    }
}

int main() {
    int result = error_check_optimized(0);
    return 0;
}

在这个例子中,我们假设 error_code 很可能为 0,那么这个分支就不太可能被执行。通过使用 __builtin_expect,可以优化分支预测,提高性能。

3. 高级性能优化技术
3.1 缓存优化

现代计算机体系结构中,缓存是提高数据访问速度的关键组件。理解缓存的工作原理对于优化程序性能至关重要。缓存优化主要包括两个方面:缓存行利用和减少缓存失效。

3.1.1 缓存行利用

缓存是由缓存行组成的,通常是 64 字节。当数据被加载到缓存中时,它会填充整个缓存行。因此,连续的数据访问(如数组访问)可以充分利用缓存行,提高数据访问的局部性。

#include <stdio.h>

void cache_line_utilization(int *arr, int n) {
    for (int i = 0; i < n; i++) {
        arr[i] = i;
    }
}

int main() {
    int n = 1024;
    int arr[n];
    cache_line_utilization(arr, n);
    // ...后续使用 arr 的代码...
    return 0;
}

在上面的代码中,cache_line_utilization 函数通过连续访问数组 arr 来充分利用缓存行,从而提高性能。

3.1.2 减少缓存失效

缓存失效是指缓存中的数据不再有效,需要从主存中重新加载。减少缓存失效可以提高程序性能。

#include <stdio.h>

void reduce_cache_misses(int *arr, int n) {
    for (int i = 0; i < n; i += 64) { // 64 是假设的缓存行大小
        for (int j = 0; j < 64 && i + j < n; j++) {
            arr[i + j] = i + j;
        }
    }
}

int main() {
    int n = 1024;
    int arr[n];
    reduce_cache_misses(arr, n);
    // ...后续使用 arr 的代码...
    return 0;
}

在上面的代码中,reduce_cache_misses 函数通过减少跨缓存行的跳跃来减少缓存失效,从而提高性能。

3.2 指令级优化

指令级优化涉及到编译器和处理器的指令集架构。通过理解和利用这些底层细节,可以编写出更高效的代码。

3.2.1 循环展开和向量化

现代处理器通常支持 SIMD(单指令多数据)指令,允许同时对多个数据执行相同的操作。通过循环展开和向量化,可以利用这些指令来提高性能。

#include <stdio.h>
#include <emmintrin.h> // SSE 指令集

void vectorization(int *arr, int n, int value) {
    for (int i = 0; i < n; i += 4) {
        __m128i vec = _mm_set1_epi32(value); // 创建一个包含 value 的向量
        _mm_storeu_si128((__m128i *)&arr[i], vec); // 将向量存储到 arr 中
    }
}

int main() {
    int n = 1024;
    int arr[n];
    vectorization(arr, n, 5);
    // ...后续使用 arr 的代码...
    return 0;
}

在上面的代码中,我们使用了 SSE 指令集来实现向量化。这种方法可以显著提高性能,尤其是在处理大型数据集时。

3.2.2 分支预测优化

现代处理器使用分支预测来猜测程序的控制流,以提高指令流水线的效率。优化分支可以提高性能。

#include <stdio.h>

int main() {
    int arr[1024];
    for (int i = 0; i < 1024; i++) {
        arr[i] = i % 2 == 0 ? i : -i;
    }
    // ...后续使用 arr 的代码...
    return 0;
}

在这个例子中,我们通过条件表达式来优化分支,减少不必要的分支预测错误。

4. 内存管理优化
4.1 静态分配与动态分配

静态分配和动态分配各有优缺点。静态分配在编译时确定内存大小,适用于大小固定的数组。动态分配在运行时确定内存大小,适用于大小不确定的数组。

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 静态分配数组
    int arr[100];

    // 动态分配数组
    int *dynArr = malloc(100 * sizeof(int));
    if (dynArr == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }

    // 使用 dynArr 进行操作
    for (int i = 0; i < 100; i++) {
        dynArr[i] = i;
    }

    // 释放内存
    free(dynArr);
    return 0;
}

在上面的代码中,我们展示了静态分配和动态分配的区别,并演示了如何动态分配和释放内存。

4.2 内存对齐

适当对齐数据结构可以提高内存访问速度。减少缓存未命中,提高性能。

#include <stdio.h>
#include <stdalign.h>

struct Example {
    int a;
    char b;
    double c;
} __attribute__((aligned(8)));

int main() {
    struct Example ex;
    printf("Size of struct: %zu\n", sizeof(ex)); // 输出结构体大小
    return 0;
}

在上面的代码中,通过指定 __attribute__((aligned(8))),我们确保结构体的每个实例在内存中从 8 的倍数地址开始,这有助于提高内存访问的效率,尤其是在 64 位处理器上。

4.3 避免内存泄漏

合理管理动态分配的内存,避免内存泄漏。对于长期运行的程序尤为重要。

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = malloc(100 * sizeof(int));
    if (ptr == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }

    // 使用 ptr 进行操作
    for (int i = 0; i < 100; i++) {
        ptr[i] = i;
    }

    // 释放内存
    free(ptr);
    return 0;
}

在上面的代码中,我们展示了如何动态分配内存并在使用完毕后释放内存,避免内存泄漏。

5. 算法和数据结构优化
5.1 选择合适的算法和数据结构

选择合适的算法和数据结构可以显著提高程序的效率。例如,对于需要频繁插入和删除操作的数据,使用链表比使用数组更高效。

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node *next;
} Node;

void insert(Node **head, int value) {
    Node *new_node = (Node *)malloc(sizeof(Node));
    new_node->data = value;
    new_node->next = *head;
    *head = new_node;
}

int main() {
    Node *head = NULL;
    insert(&head, 1);
    insert(&head, 2);
    // ...后续操作...
    return 0;
}

在上面的代码中,我们使用链表来实现插入和删除操作,相比于数组,链表的插入和删除操作更高效。

5.2 查表优化

查表是一种常见的优化技术,特别是在需要频繁进行相同计算的情况下。通过预先计算并将结果存储在表中,可以避免在运行时重复计算。

#include <stdio.h>

static long factorial_table[] = {1, 1, 2, 6, 24, 120, 720 /* etc */ };

long factorial(int i) {
    return factorial_table[i];
}

int main() {
    int i = 5;
    printf("Factorial of %d is %ld\n", i, factorial(i));
    return 0;
}

在上面的代码中,我们预先计算了阶乘值并存储在 factorial_table 数组中,通过查表来获取阶乘值,避免了在运行时重复计算。

5.3 使用位操作

位操作可以直接操作数据的最小单元——位,常用于优化数据结构和实现加密算法。

#include <stdio.h>

int main() {
    unsigned char flags = 0;
    flags |= (1 << 2);  // 设置第3位
    flags &= ~(1 << 2); // 清除第3位
    printf("Flags: %02X\n", flags);
    return 0;
}

在上面的代码中,我们使用位操作来设置和清除特定的位,这种方式比使用布尔变量更高效。

6. 并行计算和多线程优化
6.1 使用多线程

多线程可以充分利用多核处理器的计算能力,提高程序的执行效率。C 语言中可以使用 POSIX 线程库(pthread)来实现多线程。

#include <stdio.h>
#include <pthread.h>

void *thread_function(void *arg) {
    int *data = (int *)arg;
    for (int i = 0; i < 1000000; i++) {
        (*data)++;
    }
    return NULL;
}

int main() {
    pthread_t threads[4];
    int data[4] = {0};

    for (int i = 0; i < 4; i++) {
        pthread_create(&threads[i], NULL, thread_function, &data[i]);
    }

    for (int i = 0; i < 4; i++) {
        pthread_join(threads[i], NULL);
    }

    for (int i = 0; i < 4; i++) {
        printf("Thread %d result: %d\n", i, data[i]);
    }

    return 0;
}

在上面的代码中,我们创建了 4 个线程,每个线程独立地对一个整数进行累加操作。通过多线程,可以显著提高计算效率。

6.2 使用 OpenMP

OpenMP 是一种并行编程模型,可以简化多线程编程。通过在代码中添加简单的指令,可以轻松实现并行计算。

#include <omp.h>
#include <stdio.h>

int main() {
    int sum = 0;

    #pragma omp parallel for reduction(+:sum)
    for (int i = 0; i < 1000000; i++) {
        sum += i;
    }

    printf("Sum: %d\n", sum);
    return 0;
}

在上面的代码中,我们使用 OpenMP 的 #pragma omp parallel for 指令将循环并行化,并使用 reduction 子句来处理累加操作。通过这种方式,可以显著提高计算效率。

7. 性能分析和调试
7.1 使用性能分析工具

为了有效地进行性能优化,需要使用一系列的性能分析工具来识别和诊断性能瓶颈。以下是一些常用的性能分析工具及其使用场景。

  • gprof:一个功能强大的性能分析工具,可以显示程序运行的 CPU 时间分布,帮助开发者找到优化的热点。
  • Valgrind:一个编程工具,主要用于内存调试、内存泄漏检测和性能分析。其性能分析工具 Callgrind 可以生成详细的调用图和性能数据。
  • perf:Linux 内核提供的一个性能分析工具,可以用来分析程序的性能问题,特别是 CPU 缓存使用、分支预测等方面。
# 使用 gprof
gcc -pg -o my_program my_program.c
./my_program
gprof my_program > profile.txt

# 使用 Valgrind
valgrind --tool=callgrind ./my_program

# 使用 perf
perf record -g ./my_program
perf report
7.2 性能优化原则

在进行性能优化时,应遵循以下原则:

  • 先测量,后优化:不要基于猜测进行优化,而是要通过测量来确定性能瓶颈。
  • 关注主要矛盾:优化那些对性能影响最大的部分,遵循 80/20 法则。
  • 逐步迭代:性能优化是一个迭代过程,需要逐步调整和验证。
  • 保持代码可读性:在优化性能的同时,尽量保持代码的清晰和可维护性。
8. 实际应用案例
8.1 用户输入验证

在实际开发中,用户输入验证是一个常见的应用场景。通过 scanf 函数可以方便地读取用户的输入并进行验证。

#include <stdio.h>
#include <stdlib.h>

int main() {
    int age;
    printf("请输入您的年龄:");
    if (scanf("%d", &age) != 1 || age <= 0) {
        printf("无效的年龄输入!\n");
        return 1;
    }
    printf("您的年龄:%d\n", age);
    return 0;
}
8.2 文件读取

scanf 函数可以结合文件输入流读取文件中的数据。

#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("文件打开失败");
        return 1;
    }

    int a, b;
    if (fscanf(file, "%d %d", &a, &b) != 2) {
        printf("文件读取错误!\n");
        fclose(file);
        return 1;
    }

    printf("文件中的数据:a = %d, b = %d\n", a, b);
    fclose(file);
    return 0;
}
8.3 数据解析

scanf 函数可以用于解析复杂的输入数据格式。

#include <stdio.h>

int main() {
    char name[50];
    int age;
    float salary;
    printf("请输入员工信息(姓名 年龄 薪水):");
    if (scanf("%49s%d%f", name, &age, &salary) != 3) {
        printf("输入格式错误!\n");
        return 1;
    }
    printf("员工信息:姓名:%s,年龄:%d,薪水:%.2f\n", name, age, salary);
    return 0;
}
9. 总结

C 语言因其高效、灵活和功能强大而广受欢迎。通过理解底层优化、编译器优化、内存管理和高级编程技巧,程序员可以编写出性能卓越的 C 程序。本文提供了详细的优化策略和代码案例,希望对读者深入理解 C 语言性能优化有所帮助。在实际应用中,性能优化是一个复杂的过程,需要根据具体的应用场景和目标平台进行细致的分析和调整。

参考文献

[1] C语言代码优化11种实用方法 - 知乎
[2] C语言程序性能优化:十大策略及代码案例解析
[3] C语言代码优化艺术:深入细节,提升效率与性能的实践指南
[4] 高性能计算|C语言常见优化策略 - 知乎
[5] C语言性能优化 - 裸睡的猪 - 博客园
[6] 超全 | 只有高手才知道的C语言高效编程与代码优化方法(一 …
[7] C语言性能优化 - CSDN博客
[8] C语言代码优化方法详解 - CSDN博客
[9] 优化C/C++代码性能的27条建议——<Tips for Optimizing C …
[10] 18|极致优化(上):如何实现高性能的 C 程序?
[11] C语言代码性能优化:提升程序效率的10大技巧 - CSDN文库
[12] C语言性能深度剖析:从底层优化到高级技巧及实战案例分析
[13] C语言性能优化参考手册 - CSDN博客
[14] C语言程序性能优化:十大策略及代码案例解析
[15] 性能优化技巧:C语言程序的高效实现 - CSDN文库
[16] C语言代码优化实战指南与案例分析 - CSDN文库
[17] [大师C语言 (第十篇)]C语言性能优化的技术详解_c语言性能 …
[18] 如何在C语言中优化代码性能 - PingCode
[19] 高性能计算|C语言常见优化策略 - 知乎
[20] 19|极致优化(下):如何实现高性能的 C 程序?-深入C语言 …
[21] 【C 言专栏】优化 C 语言程序性能的策略 - 阿里云开发者社区
[22] c语言如何提高性能 | PingCode智库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2267366.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言-数据结构-查找

目录 一,查找的概念 二,线性查找 1,顺序查找 2,折半查找 3,分块查找 三,树表的查找 1,二叉排序树 (1)查找方式: (2)、二叉排序树的插入和生成 (3)、二叉排序树的删除 2,平衡二叉树 (1)、什么是平衡二叉树 (2)、平衡二叉树的插入调整 &#xff08;1&#xff09;L…

[江科大编程技巧] 第1期 定时器实现非阻塞式程序 按键控制LED闪烁模式——笔记

提前声明——我只是写的详细其实非常简单&#xff0c;不要看着多就放弃学习&#xff01; 阻塞&#xff1a;执行某段程序时&#xff0c;CPU因为需要等待延时或者等待某个信号而被迫处于暂停状态一段时间&#xff0c;程序执行时间较长或者时间不定 非阻塞&#xff1a;执行某段程…

如何理解:产品线经营管理的战略、组织、业务、项目、流程、绩效之间的逻辑关系?-中小企实战运营和营销工作室博客

如何理解&#xff1a;产品线经营管理的战略、组织、业务、项目、流程、绩效之间的逻辑关系&#xff1f;-中小企实战运营和营销工作室博客 产品线经营管理中&#xff0c;战略、组织、业务、项目、流程、绩效之间存在着紧密的逻辑关系&#xff0c;它们相互影响、相互作用&#xf…

【CSS in Depth 2 精译_096】16.4:CSS 中的三维变换 + 16.5:本章小结

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 16.2.1 放大图标&am…

Oracle 11G还有新BUG?ORACLE 表空间迷案!

前段时间遇到一个奇葩的问题&#xff0c;在开了SR和oracle support追踪两周以后才算是有了不算完美的结果&#xff0c;在这里整理出来给大家分享。 1.问题描述 12/13我司某基地MES全厂停线&#xff0c;系统卡死不可用&#xff0c;通知到我排查&#xff0c;查看alert log看到是…

三只脚的电感是什么东西?

最近在做加湿器&#xff0c;把水雾化的陶瓷片需要有专门的驱动电路。 我参考了某宝卖家的驱动板以及网上的开源项目&#xff0c;发现了驱动电路的核心就是一个三脚电感。 在此之前我都没注意过这玩意&#xff0c;三脚电感不也还是电感嘛&#xff1f; 今天我们就来看看三脚电…

pyQT + OpenCV相关练习

一、设计思路 1、思路分析与设计 本段代码是一个使用 PyQt6 和 OpenCV 创建的图像处理应用程序。其主要功能是通过一个图形界面让用户对图片进行基本的图像处理操作&#xff0c;如灰度化、翻转、旋转、亮度与对比度调整&#xff0c;以及一些滤镜效果&#xff08;模糊、锐化、边…

【Git_bugs】remote error GH013 Repository rule violations found for.md

背景 1 在一个分支上的提交顺序如下&#xff1a;-> 代表新的提交 在提交 E 中&#xff0c;文件包含了 GitHub 生成的 token提交 F 是一次普通的提交&#xff0c;不包含 token A -> ... -> E -> F (敏感信息在 E 中)附&#xff1a;给提交起名是为了方便说明问题。…

Day1 微服务 单体架构、微服务架构、微服务拆分、服务远程调用、服务注册和发现Nacos、OpenFeign

目录 1.导入单体架构项目 1.1 安装mysql 1.2 后端 1.3 前端 2.微服务 2.1 单体架构 2.2 微服务 2.3 SpringCloud 3.微服务拆分 3.1 服务拆分原则 3.1.1 什么时候拆 3.1.2 怎么拆 3.2 拆分购物车、商品服务 3.2.1 商品服务 3.2.2 购物车服务 3.3 服务调用 3.3.1 RestTemplate 3.…

安卓执法仪Android接入国标GB28181平台实现实时监控、对讲、报警、定位等管理方案

最近协助不少企业完成了4G无线设备国标接入的需求&#xff0c;尤其是国产芯片的接入&#xff0c;国标发展了十年的时间&#xff0c;目前协议从完成度、性能、AI等各个方面&#xff0c;都已经非常完美地满足各种各样的场景需求&#xff0c;尤其是GB28181-2022的推出&#xff0c;…

SpringMVC学习(二)——RESTful API、拦截器、异常处理、数据类型转换

一、RESTful (一)RESTful概述 RESTful是一种软件架构风格&#xff0c;用于设计网络应用程序。REST是“Representational State Transfer”的缩写&#xff0c;中文意思是“表现层状态转移”。它基于客户端-服务器模型和无状态操作&#xff0c;以及使用HTTP请求来处理数据。RES…

国内独立开发者案例及免费送独立开发蓝图书

独立开发者在国内越来越受到关注&#xff0c;他们追求的是一种自由且自给自足的工作状态。 送这个&#xff1a; 少楠light&#xff08;Flomo、小报童、如果相机&#xff09;&#xff1a;他们是独立开发者的典范&#xff0c;不仅开发了多款产品&#xff0c;还坚信“剩者为王”…

【JavaEE进阶】@RequestMapping注解

目录 &#x1f4d5;前言 &#x1f334;项目准备 &#x1f332;建立连接 &#x1f6a9;RequestMapping注解 &#x1f6a9;RequestMapping 注解介绍 &#x1f384;RequestMapping是GET还是POST请求&#xff1f; &#x1f6a9;通过Fiddler查看 &#x1f6a9;Postman查看 …

一文详解MacOS+CLion——构建libtorch机器学习开发环境

对于希望在本地环境中进行深度学习开发的开发者来说&#xff0c;配置合适的工具链是至关重要的一步。本文旨在帮助您在 macOS 操作系统上&#xff0c;利用 CLion IDE 和 PyTorch 的 C依赖库——libtorch&#xff0c;快速搭建起一个高效的开发环境。这里我们将一步步地讲解如何下…

Bert中文文本分类

这是一个经典的文本分类问题&#xff0c;使用google的预训练模型BERT中文版bert-base-chinese来做中文文本分类。可以先在Huggingface上下载预训练模型备用。https://huggingface.co/google-bert/bert-base-chinese/tree/main 我使用的训练环境是 pip install torch2.0.0; pi…

shardingsphere分库分表项目实践5-自己用java写一个sql解析器+完整项目源码

前1节我们介绍了 shardingsphere 分表分库的sql解析与重写&#xff1a; shardingsphere分库分表项目实践4-sql解析&重写-CSDN博客 那么shardingsphere sql 解析底层究竟是怎么实现的呢&#xff0c;其实它直接用了著名的开源软件 antlr . antlr 介绍&#xff1a; ANTLR&a…

10分钟掌握项目管理核心工具:WBS、甘特图、关键路径法全解析

一、引言 在项目管理的广阔天地里&#xff0c;犹如一场精心编排的交响乐演奏&#xff0c;每个乐器、每个音符都需精准配合才能奏响美妙乐章。而 WBS&#xff08;工作分解结构&#xff09;、甘特图、关键路径法无疑是这场交响乐中的关键乐章&#xff0c;它们从不同维度为项目管…

【LLM】OpenAI 的DAY12汇总和o3介绍

note o3 体现出的编程和数学能力&#xff0c;不仅达到了 AGI 的门槛&#xff0c;甚至摸到了 ASI&#xff08;超级人工智能&#xff09;的边。 Day 1&#xff1a;o1完全版&#xff0c;开场即巅峰 12天发布会的开场即是“炸场级”更新——o1完全版。相比此前的预览版本&#x…

使用Kubernetes部署MySQL+WordPress

目录 前提条件 部署MySQL和WordPress 编写yaml文件 应用yaml文件 存在问题及解决方案 创建PV(持久化卷) 创建一个PVC(持久化卷声明) 部署添加PVC 查看PV对应的主机存储 删除资源 查看资源 删除deployment和service 查看主机数据 删除PVC和PV 删除主机数据 前提条…

RabbitMQ中的异步Confirm模式:提升消息可靠性的利器

在现代分布式系统中&#xff0c;消息队列&#xff08;Message Queue&#xff09;扮演着至关重要的角色&#xff0c;它能够解耦系统组件、提高系统的可扩展性和可靠性。RabbitMQ作为一款广泛使用的消息队列中间件&#xff0c;提供了多种机制来确保消息的可靠传递。其中&#xff…