Orange AIpro Color triangle帧率测试

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 600uint32_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 450layout(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.mzph.cn/bicheng/18691.shtml

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

相关文章

实操专区-第15周-课堂练习专区-漏斗图与金字塔图

实操专区-第15周-课堂练习专区-漏斗图 下载安装ECharts&#xff0c;完成如下样式图形。 代码和截图上传 基本要求&#xff1a;下图3选1&#xff0c;完成代码和截图 完成 3.1.3.16 漏斗图中的任务点 基本要求&#xff1a;2个选一个完成&#xff0c;多做1个加2分。 请用班级学号姓…

银行对公贷款软件业务流程详解

对公贷款业务是指商业银行向企事业单位提供资金支持&#xff0c;用于资本扩充、生产经营、项目建设等方面的融资。其目的在于支持企事业单位的发展&#xff0c;推动经济增长。通过提供资金支持&#xff0c;企事业单位可以获得必要的资金来扩大生产规模、提高生产能力、研发新产…

第8周 分布式事务与数据一致性主流解决方案落地

第8周 分布式事务与数据一致性主流解决方案落地 1. 最终一致性原理与解析2. 微服务的解耦3. 本地消息存储4. 自定义事务管理器5. 本地消息删除********************************************************************************** 本周拓展数据的一致性落地&#xff0c;采用弱…

【Java EE】网络原理——HTTP请求

目录 1.认识URL 2.认识“方法&#xff08;method&#xff09;” 2.1GET方法 2.1.1使用Fiddler观察GET请求 2.1.2 GET请求的特点 2.2 POST方法 2.2.1 使用FIddler观察POST方法 2.2.2 POST请求的特点 3.认识请求“报头”&#xff08;header&#xff09; 3.1 Host 3.2 C…

Spring MVC 工作流程源码分析

前言&#xff1a; 我们知道 Spring MVC 的核心是前端控制器 DispatcherServlet&#xff0c;客户端所有的请求都会交给 DispatcherServlet 来处理&#xff0c;本篇我我们来分析 Spring MVC 处理客户端请求的流程&#xff0c;也就是工作流程。 Sping MVC 只是储备传送门&#x…

Java整合EasyExcel实战——3(上下列相同合并单元格策略)

参考&#xff1a;https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06 准备条件 依赖 <dependency><groupId>com.alibaba</gr…

邻接矩阵广度优先遍历

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

新人学习笔记之(数组1)

一、数组的概念 1.数组&#xff08;Array&#xff09;可以把一组相关的数据一起存放&#xff0c;并提供方便的访问&#xff08;获取&#xff09;方式 2.数组是指一组数据的集合&#xff0c;其中的每个数据被称作元素&#xff0c;在数组中可以存放任意类型的元素&#xff0c;数组…

数据结构——二叉树的基本应用

在此之前我们已经初步了解了二叉树&#xff0c;在介绍堆的基本应用时&#xff0c;我们已经具体介绍了完全二叉树的基本应用&#xff0c;本章我们介绍二叉树的基本应用&#xff0c;这个不止指的是完全二叉树&#xff0c;而是指泛型的二叉树。 二叉树的基本应用&#xff0c;由于…

代码随想录算法训练营第54天|● 392.判断子序列 ● 115.不同的子序列

392. 判断子序列 这个微软面试的时候考过 双指针就行 编辑距离入门题&#xff1a; 思路是一样的 相同字符1 否则从前面顺下来 class Solution:def isSubsequence(self, s: str, t: str) -> bool:dp[[0]*(len(t)1) for _ in range(len(s)1)]for i in range(1,len(s)1):f…

aspose-*的使用

文章目录 aspose-*一、依赖--maven二、需求1、word------>pdf2、doc------>docx2、xls------>xlsx aspose-* 一、依赖–maven 备注&#xff1a;第三方的jar包可以从资源中下载&#xff0c;有上传的 <!--aspose依赖--><dependency><groupId>aspose…

刷代码随想录有感(81):贪心算法——分发饼干

题干&#xff1a; class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.begin(), s.end());int index s.size() - 1;int res 0;for(int i g.size() - 1; i > 0; i--){if(index >…

GitLab项目中添加用户,并设置其角色权限等

注意&#xff1a;创建用户(new user)&#xff0c;创建完用户然后再项目邀请用户&#xff0c;选择创建过的用户 一、以管理员身份登录GitLab的WebUI并创建用户 1>.使用管理员登录GitLab 使用管理员(root)用户登录成功后&#xff0c;点击如下图所示的小扳手&#xff0c;点击…

java 反射的用法

下面是一个简单的Java反射示例&#xff0c;演示了如何使用反射机制获取类的信息并调用其方法&#xff1a; import java.lang.reflect.Method;class MyClass {private String name;public void setName(String name) {this.name name;}public String getName() {return name;}…

C++数据结构之:链List

摘要&#xff1a; it人员无论是使用哪种高级语言开发东东&#xff0c;想要更高效有层次的开发程序的话都躲不开三件套&#xff1a;数据结构&#xff0c;算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合&#xff0c;即带“结构”的数据元素的集合&am…

在HTML和CSS当中运用显示隐藏

1.显示与隐藏 盒子显示:display:block;盒子隐藏: display:none:隐藏该元素并且该元素所占的空间也不存在了。 visibility:hidden:隐藏该元素但是该元素所占的内存空间还存在&#xff0c;即“隐身效果”。 2.圆角边框 在CSS2中添加圆角&#xff0c;我们不得不使用背景图像&am…

学习笔记——数据通信基础——数据通信网络(网络工程师)

网络工程师 网络工程&#xff0c;就是围绕着网络进行的一系列的活动&#xff0c;包括∶网络规划、设计、实施、调试、排错等。网络工程设计的知识领域很宽广&#xff0c;其中路由和交换是计算机网络的基本。 网络工程师∶是在网络工程领域&#xff0c;掌握专业的网络技术&…

散户如何参与期权交易?

期权就是股票&#xff0c;唯一区别标的物上证指数&#xff0c;会看大盘吧&#xff0c;期权交易两个方向认购做多&#xff0c;认沽做空&#xff0c;双向t0交易没了&#xff0c;期权交易跟期货一样&#xff0c;对的&#xff0c;玩的也是合约&#xff0c;唯一区别没有保证金不会爆…

军工行业运维解决方案

一、引言 随着军工行业的快速发展&#xff0c;信息化建设已成为提高作战效能、保障信息安全的重要支撑。然而&#xff0c;军工行业面临着多战区、跨区域、多阵地、多数据中心的复杂运维挑战。为了满足这些挑战&#xff0c;我们提出了一套基于美信时代的军工行业运维解决方案&am…

127.0.0.1 和 localhost 以及 0.0.0.0 区别

之前用 nginx 的时候&#xff0c;发现用这几个 IP&#xff0c;都能正常访问到 nginx 的欢迎网页。一度认为这几个 IP 都是一样的。 但本质上还是有些区别的。 首先 localhost 就不叫 IP&#xff0c;它是一个域名&#xff0c;就跟 "baidu.com",是一个形式的东西&…