Orange AIpro Color triangle帧率测试

news2024/11/17 21:41:12
 

OpenGL概述

OpenGL ES是KHRNOS Group推出的嵌入式加速3D图像标准,它是嵌入式平台上的专业图形程序接口,它是OpenGL的一个子集,旨在提供高效、轻量级的图形渲染功能。现推出的最新版本是OpenGL ES 3.2。OpenGL和OpenCV OpenCL不同,OpenCV主要用于计算机视觉和图像处理。它提供了一系列算法和函数,用于图像处理、对象检测、机器学习,而OpenGL专注于图形渲染,帮助开发者绘制复杂的2D和3D图形,主要应用于视频游戏、虚拟现实,OpenCL则是一个并行计算框架,主要用于编写并行程序。

 

本文目的

我们这里在Orange AIpro上写了一个color triangle程序,color triangle程序在图形学的地位类似于编程语言学习的Hello World了,可以说人尽皆知了。这边文章介绍了在Orang AIpro上开发运行OpenGL color triangle 并查看帧率

本文使用的窗口管理用SDL2开发,SDL2是一个非常底层的跨平台的多媒体库,主要用于开发2D游戏和多媒体应用程序。提供能了图形、音频、输入输出设备、窗口管理等,功能非常丰富。

 

开发环境

安装部署OpenGL开发环境

sudo apt install libgles2-mesa libgles2-mesa-dev -y
sudo apt install libsdl2-2.0-0 libsdl2-dev
 

源码

项目文件结构

项目主要开发语言是c语言,vertex shader 和 fragmeng shader用glsl语言编写,项目的代码在main.cpp中,utils.cpp和utils.cpp中存放了一个工具函数,从文件中读取shader源码编译,编译工具用cmake,compile.sh中存放着重编译运行的shell命令。

├── CMakeLists.txt
├── colortriangle
│   └── utils.hpp
├── compile.sh
├── shader
│   ├── colortriangle.frag
│   └── colortriangle.vert
└── src
    ├── main.cpp
    └── utils.cpp
 

窗口循环

主要代码都存放在main.cpp中,对应的文件路径是./src/main.cpp

main.cpp代码如下

#define GL_GLEXT_PROTOTYPES
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <GLES3/gl32.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
#include <chrono>
#include <sys/time.h>

#include "../colortriangle/utils.hpp"

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

uint32_t gWinWidth = 800;
uint32_t gWinHeight = 600;

struct Vertex
{
    glm::vec3 position;
    glm::vec4 color;
};

struct alignas(16) MVP
{
    glm::mat4 model;
    glm::mat4 view;
    glm::mat4 project;
};

MVP mvp = {};

std::vector<Vertex> basevertex = {
    {{200, 200, 0}, {1, 0, 0, 1}},
    {{600, 200, 0}, {0, 1, 0, 1}},
    {{600, 400, 0}, {0, 0, 1, 1}},
    {{200, 200, 0}, {0, 1, 0, 1}},
    {{200, 400, 0}, {0, 0, 1, 1}},
    {{600, 400, 0}, {1, 1, 1, 1}}};

std::vector<Vertex> vertex = {
    {{-10, -10, 0}, {1, 0, 0, 1}},
    {{10, -10, 0}, {0, 1, 0, 1}},
    {{10, 10, 0}, {0, 0, 1, 1}},
    {{-10, -10, 0}, {1, 0, 0, 1}},
    {{-10, 10, 0}, {0, 1, 0, 1}},
    {{10, 10, 0}, {0, 0, 1, 1}}};

GLuint indics[] = {0, 1, 2, 0, 4, 5};

void UpdateUniformBuffer();

int main(int argc, char *argv[])
{
    bool isquit = false;
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    SDL_Window *window = SDL_CreateWindow("color_triangle",
                                          SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                          WINDOW_WIDTH, WINDOW_HEIGHT,
                                          SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);

    SDL_GLContext context = SDL_GL_CreateContext(window);

    GLuint vs, fs, program;

    vs = glCreateShader(GL_VERTEX_SHADER);
    fs = glCreateShader(GL_FRAGMENT_SHADER);

    std::string vertexShader = readfile("./shader/colortriangle.vert");
    int length = vertexShader.length();
    const GLchar *ptr = vertexShader.c_str();
    glShaderSource(vs, 1, (const GLchar **)&ptr, nullptr);
    glCompileShader(vs);

    GLint status;
    glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE)
    {
        throw std::runtime_error("vertex shader compilation failed");
        return 1;
    }

    std::string fragmentShader = readfile("./shader/colortriangle.frag");
    length = fragmentShader.length();
    ptr = fragmentShader.c_str();
    glShaderSource(fs, 1, (const GLchar **)&ptr, nullptr);
    glCompileShader(fs);

    glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE)
    {
        throw std::runtime_error("fragment shader compilation failed");
        return 1;
    }

    program = glCreateProgram();
    UpdateUniformBuffer();
    glAttachShader(program, vs);
    glAttachShader(program, fs);

    glBindAttribLocation(program, 0, "position");
    glBindAttribLocation(program, 1, "color");
    glLinkProgram(program);

    glUseProgram(program);

    glEnable(GL_DEPTH_TEST);
    glClearColor(0, 0.0, 0.0, 0.0);
    glViewport(0, 0, gWinWidth, gWinHeight);

    GLuint vao, vbo, ebo, uboBlock;

    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);
    glGenBuffers(1, &ebo);

    glGenBuffers(1, &uboBlock);
    glBindBuffer(GL_UNIFORM_BUFFER, uboBlock);
    glBufferData(GL_UNIFORM_BUFFER, sizeof(MVP), NULL, GL_STATIC_DRAW);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
    const auto vpIndex = glGetUniformBlockIndex(program, "ubo");
    glUniformBlockBinding(program, vpIndex, 0);   
    glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBlock);

    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(sizeof(vertex[0].position)));

    glBufferData(GL_ARRAY_BUFFER, vertex.size() * sizeof(Vertex), vertex.data(), GL_DYNAMIC_DRAW);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indics), indics, GL_STATIC_DRAW);

    SDL_Event event;
    struct timeval t1, t2;
    struct timezone tz;
    float deltatime;
    float totaltime = 0.0f;
    uint32_t frames = 0;
    gettimeofday(&t1, &tz);
    while (!isquit)
    {
        gettimeofday(&t2, &tz);
        deltatime = (float)(t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6);
        t1 = t2;
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
                isquit = true;
            if (event.type == SDL_WINDOWEVENT)
            {
                if (event.window.event == SDL_WINDOWEVENT_RESIZED)
                {
                    for (size_t i = 0; i < vertex.size(); i++)
                    {
                        SDL_GetWindowSize(window, (int *)&gWinWidth, (int *)&gWinHeight);
                        vertex[i].position.x = gWinWidth / WINDOW_WIDTH * basevertex[i].position.x;
                        vertex[i].position.y = gWinHeight / WINDOW_HEIGHT * basevertex[i].position.y;
                    }
                }
            }
        }
        UpdateUniformBuffer();
        glBindBuffer(GL_UNIFORM_BUFFER, uboBlock);
        glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), &mvp.model);
        glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), &mvp.view);
        glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * 2, sizeof(glm::mat4), &mvp.project);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);

        glViewport(0, 0, gWinWidth, gWinHeight);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glBindVertexArray(vao);
        glDrawElements(GL_TRIANGLES, sizeof(indics), GL_UNSIGNED_INT, 0);
        SDL_GL_SwapWindow(window);
        totaltime += deltatime;
        frames++;
        if (totaltime > 2.0f)
        {
            SDL_Log("%4d frames rendered in %1.4f seconds -> FPS=[%3.4f]\n", frames, totaltime, frames / totaltime);
            totaltime = 0.0f;
            frames = 0;
        }
    }
    SDL_GL_DeleteContext(context);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

void UpdateUniformBuffer()
{
    static auto startTime = std::chrono::high_resolution_clock::now();
    auto currentTime = std::chrono::high_resolution_clock::now();
    float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();

    mvp.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
    mvp.view = glm::lookAt(glm::vec3(40.0f, 40.0f, 40.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
    mvp.project = glm::perspective(glm::radians(45.0f), (float)gWinWidth / (float)gWinHeight, 0.1f, 100.0f);
    // mvp.model[1][1] *= -2;
    // mvp.view[1][1] *= 2;
    mvp.project[1][1] *= 1;
}
 
SDL WindowsLoop

在main.cpp的main函数中窗口的循环如下:

while (!isquit)
    {
        gettimeofday(&t2, &tz);
        deltatime = (float)(t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6);
        t1 = t2;
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
                isquit = true;
            if (event.type == SDL_WINDOWEVENT)
            {
                if (event.window.event == SDL_WINDOWEVENT_RESIZED)
                {
                    for (size_t i = 0; i < vertex.size(); i++)
                    {
                        SDL_GetWindowSize(window, (int *)&gWinWidth, (int *)&gWinHeight);
                        vertex[i].position.x = gWinWidth / WINDOW_WIDTH * basevertex[i].position.x;
                        vertex[i].position.y = gWinHeight / WINDOW_HEIGHT * basevertex[i].position.y;
                    }
                }
            }
        }
        UpdateUniformBuffer();
        glBindBuffer(GL_UNIFORM_BUFFER, uboBlock);
        glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), &mvp.model);
        glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), &mvp.view);
        glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * 2, sizeof(glm::mat4), &mvp.project);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);

        glViewport(0, 0, gWinWidth, gWinHeight);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glBindVertexArray(vao);
        glDrawElements(GL_TRIANGLES, sizeof(indics), GL_UNSIGNED_INT, 0);
        SDL_GL_SwapWindow(window);
        totaltime += deltatime;
        frames++;
        if (totaltime > 2.0f)
        {
            SDL_Log("%4d frames rendered in %1.4f seconds -> FPS=[%3.4f]\n", frames, totaltime, frames / totaltime);
            totaltime = 0.0f;
            frames = 0;
        }
    }
 

这部分代码绘制了两个三角形并在窗口循环中创建一个定时器,每两秒计算帧率并输出帧率,这里我们用的手机录制视频,解释一下为什么用手机录制,如果用的录屏软件或者远程vnc远程工具录制都会导致掉帧严重,所以这里采用手机对着显示屏录制

 

创建的为800*600的窗口,帧率稳定在250帧左右

 

 
Vertex Shader Fragment Shader

vertex Shader代码如下,对应的文件路径是./shader/colortriangle.vert

#version 450

layout(std140, binding = 0) uniform UBO {
    mat4 model;
    mat4 view;
    mat4 project;
}ubo;

layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
layout(location = 0) out vec4 v_color;

void main() {
    v_color = color;
    gl_Position = ubo.project * ubo.view * ubo.model * vec4(position, 1.0);
}
 

fragment Shader代码如下,对应的文件路径是./shader/colortriangle.frag

#version 450 
layout(location = 0) in vec4 v_color;
layout(location = 0) out vec4 o_color;

void main() 
{
    o_color = v_color;
}
 

其中通过model view projectation矩阵来控制两个三角形旋转和观察角度

这部分代码如下

void UpdateUniformBuffer()
{
    static auto startTime = std::chrono::high_resolution_clock::now();
    auto currentTime = std::chrono::high_resolution_clock::now();
    float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();

    mvp.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
    mvp.view = glm::lookAt(glm::vec3(40.0f, 40.0f, 40.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
    mvp.project = glm::perspective(glm::radians(45.0f), (float)gWinWidth / (float)gWinHeight, 0.1f, 100.0f);
    // mvp.model[1][1] *= -2;
    // mvp.view[1][1] *= 2;
    mvp.project[1][1] *= 1;
}
 

首先定义计算程序经过的时间段,用于更新模型矩阵,动态更新,实现动画效果。

其中glm::rotate()用来旋转矩阵

观察矩阵用来设置相机位置观察点以及上向量

投影矩阵用来定义投影视场角宽高比和远近裁剪面,在代码中我定义的两个直角等腰三角形

位置如下:

struct Vertex
{
    glm::vec3 position;
    glm::vec4 color;
};

std::vector<Vertex> vertex = {
    {{-10, -10, 0}, {1, 0, 0, 1}},
    {{10, -10, 0}, {0, 1, 0, 1}},
    {{10, 10, 0}, {0, 0, 1, 1}},
    {{-10, -10, 0}, {1, 0, 0, 1}},
    {{-10, 10, 0}, {0, 1, 0, 1}},
    {{10, 10, 0}, {0, 0, 1, 1}}};

 

将位置信息颜色信息传入vertex shader,模型、观察、投影矩阵通过uniformbufferobject传入vertexshader

 

 

 
读取shader文件代码

这部分代码在utils.cpp中,从文件中读取shader代码,并调用glCompileShader编译,源码对应路径是./src/utils.cpp,头文件是./colortriangle/utils.hpp

utils.cpp如下:

#include "../colortriangle/utils.hpp"

std::string readfile(const std::string &filepath)
{
    std::ifstream file(filepath);
    if (!file.is_open())
    {
        throw std::runtime_error("read shader failed");
    }

    std::stringstream sstr;
    sstr << file.rdbuf();
    std::string ret = sstr.str();
    return ret;
}
 

utils.hpp如下:

#pragma once

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

std::string readfile(const std::string &filepath);

 

 
编译命令

项目根目录CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(colortriangle VERSION 1.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
find_package(OpenGL REQUIRED)
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
include_directories(${OPENGL_INCLUDE_DIRS})
file(GLOB SOURCES "./src/*.cpp")
add_executable(colortriangle ${SOURCES})
target_link_libraries(colortriangle ${OPENGL_LIBRARIES} ${SDL2_LIBRARIES})
 
编译脚本:

在根目录执行./compile.sh即可重编译

根目录compile.sh如下:

#!/bin/bash
rm -rf build
mkdir build 
cd build 
cmake ..
make -j$(nproc)
cd ..
./build/colortriangle
 

测试在800*600的窗口帧率大概在250帧左右

 

缩小窗口后帧率可以达到2500帧

 

全屏屏后帧率稳定在60多帧,我这里全屏后无法看到color triangle了,需要切应用

 

 

程序运行动图

这是用向日葵工具远程,然后再windows主机上用录制工具录制,看以看到帧率还没有60帧

 

由于手机录制的2分钟视频文件过大,只能存放于百度网盘,附上网盘链接:

链接:https://pan.baidu.com/s/1jbxyl0npx8GE6xP5aS6avQ?pwd=3w8q

提取码:3w8q

 

 

 

 

 

 

 

 

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

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

相关文章

HTTP协议的基本了解

一、HTTP-概述 HTTP&#xff1a;Hyper Text Transfer Protocol(超文本传输协议)&#xff0c;规定了浏览器与服务器之间数据传输的规则。 http是互联网上应用最为广泛的一种网络协议 。http协议要求&#xff1a;浏览器在向服务器发送请求数据时&#xff0c;或是服务器在向浏览器…

计算机网络7——网络安全1 概述与加密

文章目录 一、网络安全问题概述1、计算机网络面临的安全性威胁2、安全的计算机网络3、数据加密模型 二、两类密码体制1、对称密钥密码体制2、公钥密码体制 随着计算机网络的发展&#xff0c;网络中的安全问题也日趋严重。当网络的用户来自社会各个阶层与部门时&#xff0c;大量…

区间相交-435. 无重叠区间,56. 合并区间

题目连接及描述 435. 无重叠区间 - 力扣&#xff08;LeetCode&#xff09; 56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 题目分析 二维数组&#xff0c;数组中每个元素为大小为2的一维数组&#xff0c;求移除区间的最小数量&#xff0c;使剩余区间互不重叠。今天写…

Python-3.12.0文档解读-内置函数pow()详细说明+记忆策略+常用场景+巧妙用法+综合技巧

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 详细说明 功能描述 参数 返回值 使用规则 示例代码 基本使用 模运算 变动记录…

Windows 下载安装Apache

一、官网下载 1、打开Apache官网http://httpd.apache.org&#xff0c;点击Download。 2、选择Windows版本&#xff0c;点击链接。 3、选择对应版本选择下载。 二、安装、设置 1、将下载好的解压。 2、依次打开Apache24-conf-httpd.conf,用记事本打开 1)、修改路径 2)、修改…

C# TcpClient

TcpClient 自己封装的话&#xff0c;还是比较麻烦的&#xff0c;可以基于线程&#xff0c;也可以基于异步写&#xff0c;最好的办法是网上找个插件&#xff0c;我发现一个插件还是非常好用的&#xff1a;STTech.BytesIO.Tcp 下面是这个插件作者的帖子&#xff0c;有兴趣的可以…

【深度学习实战—9】:基于MediaPipe的人脸关键点检测

✨博客主页&#xff1a;王乐予&#x1f388; ✨年轻人要&#xff1a;Living for the moment&#xff08;活在当下&#xff09;&#xff01;&#x1f4aa; &#x1f3c6;推荐专栏&#xff1a;【图像处理】【千锤百炼Python】【深度学习】【排序算法】 目录 &#x1f63a;一、Med…

IDEA中各种Maven相关问题(文件飘红、下载依赖和启动报错)

错误情况 包名、类名显示红色、红色波浪线&#xff0c;大量依赖提示不存在&#xff08;程序包xxx不存在&#xff09; 工程无法启动 一、前提条件 1、使用英文原版IDEA 汉化版的可能有各种奇怪的问题。建议用IDEA英文版&#xff0c;卸载重装。 2、下载maven&#xff0c;配置环…

PFC+LLC 概述

总电路图 方案为&#xff1a;PFC&#xff08;NCP1654D&#xff09;LLC&#xff08;NCPB97B&#xff09;同步整流 输入为220V&#xff08;正负20%&#xff09;输出48V&#xff0c;600W电源 组成 1.输入 零线&#xff0c;火线&#xff0c;大地线&#xff0c;有防雷电路&#…

后量子加密算法的数学原理

后量子加密算法是一类专为抵御量子计算机攻击而设计的加密算法。随着量子计算技术的迅速发展&#xff0c;传统的加密算法如RSA和椭圆曲线密码学在量子计算机面前变得脆弱&#xff0c;因此&#xff0c;开发能够在量子计算时代保持安全性的加密算法变得尤为重要。下面将详细介绍后…

使用小猪APP分发打造高效的App封装工具

你是否曾经因为App封装和分发的复杂性而头疼不已&#xff1f;在这个移动应用迅速发展的时代&#xff0c;开发人员不仅需要专注于应用的功能和用户体验&#xff0c;还必须面对繁琐的封装和分发过程。幸运的是&#xff0c;小猪APP分发www.appzhu.cn正好为我们提供了一个简便而高效…

STM32_HAL_使用FPEC实现闪存的读写

STM32的FLASH结构 主存储器&#xff08;Main Memory&#xff09;&#xff1a;这是STM32中最大的存储区域&#xff0c;用于存储用户的程序代码、常量数据以及程序运行时不变的数据。STM32的主存储器通常被组织为多个扇区&#xff08;sector&#xff09;&#xff0c;每个扇区的大…

构建高效稳定的运维服务体系:技术架构解析与最佳实践

在当今数字化时代&#xff0c;运维服务对于企业的稳定运行和业务发展至关重要。本文将深入探讨运维服务的技术架构&#xff0c;介绍如何构建高效稳定的运维服务体系&#xff0c;并分享最佳实践。 ### 1. 概述 运维服务的技术架构是支撑整个运维体系的核心&#xff0c;它涵盖了…

邻接矩阵广度优先遍历

关于图的遍历实际上就两种 广度优先和深度优先&#xff0c;一般关于图的遍历都是基于邻接矩阵的&#xff0c;考试这些&#xff0c;用的也是邻接矩阵。 本篇文章先介绍广度优先遍历的原理&#xff0c;和代码实现 什么是图的广度优先遍历&#xff1f; 这其实和二叉树的层序遍…

基于魔搭开源推理引擎 DashInfer实现CPU服务器大模型推理--理论篇

前言 在人工智能技术飞速发展的今天&#xff0c;如何高效地在CPU上运行大规模的预训练语言模型&#xff08;LLM&#xff09;成为了加速生成式AI应用广泛落地的核心问题。阿里巴巴达摩院模型开源社区ModelScope近期推出了一款名为DashInfer的推理引擎&#xff0c;旨在解决这一挑…

Ingress controller:Kubernetes 的瑞士军刀

原文作者&#xff1a;Brian Ehlert of F5 原文链接&#xff1a;Ingress controller&#xff1a;Kubernetes 的瑞士军刀 转载来源&#xff1a;NGINX 中文官网 NGINX 唯一中文官方社区 &#xff0c;尽在 nginx.org.cn 许多人认为 Ingress controller&#xff08;Ingress 控制器&…

CCF20211201——序列查询

CCF20211201——序列查询 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; #define Max 10000000 int a[Max]{0},b[Max]{0}; int main() {int n,m;int sum0,x0,flag0;cin>>n>>m;for(int i1;i<n;i){cin>>a[i];}for(int i0,x0;i&l…

闪电加载:Hexo博客性能优化全攻略

巴索罗缪大熊 前言 这些年积累了很多前端性能优化的知识点和思路&#xff0c;日常工作很少涉及技术层极限优化&#xff0c;近期终于一点点把博客独立搭建并部署了&#xff0c;对之前的一些技术点进行了深度探索&#xff0c;最终结果也达到了预期效果&#xff0c;由于水平有限&…

【安装笔记-20240528-Linux-在 Vultr 云服务器上安装 OpenWRT】

安装笔记-系列文章目录 安装笔记-20240528-Linux-在 Vultr 云服务器上安装测试 OpenWRT 文章目录 安装笔记-系列文章目录安装笔记-20240528-Linux-在 Vultr 云服务器上安装测试 OpenWRT 前言一、软件介绍名称&#xff1a;OpenWRT主页官方介绍 二、安装步骤测试版本&#xff1a…

【html+css(大作业)】二级菜单导航栏

目录 实现效果 代码及其解释 html部分 CSS部分 hello&#xff0c;hello好久不见&#xff01; 今天我们来写二级导航栏&#xff0c;所谓二级导航栏&#xff0c;简单来说就是鼠标放上去就有菜单拉出&#xff1a; 实现效果 代码及其解释 html部分 <!DOCTYPE html> &l…