【超算/先进计算学习】日报2

今日已完成任务列表


4-2、编辑器Vim、编译器GCC、工程构建工具Make

遇到的问题及解决方案


对练习代码进行编译时使用如下指令:

gcc -o main main.cpp

将会报错:

xxx:xxx: undefined reference to `operator new[](unsigned int)'…

解决方案:
因为写的是 C++ 程序😅

g++ -o main main.cpp

任务完成详细笔记


编辑器Vim

程序开发步骤

程序开发:将人类想要计算执行的工作按照计算机所支持的方式流程化、格式化、系统化的,使用编译器支持的开发语言组织成文,并由编译器翻译成机器码供计算机执行
C/C++ 程序开发一般包含以下步骤:

  • 明确任务需求或目标
  • 算法设计
  • 编码源文件(通过编辑器 Vim 编写)
  • 编译二进制文件(通过编译器 GCC 完成)
  • 运行二进制文件(通过任务管理系统 slurm 运行计算任务)
  • 调试程序(debug)

文件编辑器 Vim 快速入门

  • 命令行式编辑器:Vim(通过终端对文件进行查看、编写和保存)
vim [filename]

在这里插入图片描述

  • Vim 编辑环境下的三种常用模式
    • 普通模式(冒号 ’ :')

移动
方向键
:1 快速跳转到文件第1行
:$ 快速跳转到文件最后一行

退出
w (保存)、q (退出)、! (强制)
:wq 保存文件并退出 Vim
:q! 强制退出,不保存修改

替换
s,:[addr]s/源字符串/目的字符串/[option]
全局替换:
%s/源字符串/目的字符串/g
2,10s/源字符串/目的字符串/g

例如:在使用vim编辑文件 cal_pi.cpp 时 ,若要把第 20 至 30 行代码中的 val_pi 字符串,一次性全部替换成 pi_value ,需键入命令 :20,30s/val_pi/pi_value/g

    • 插入模式(i)

只有在插入模式下,才可以做文字输入,i 进入插入模式,按 [ESC] 回到普通模式

    • 可视模式(v)

选定文段进行操作等,v 或 ctrl + v 进入,方向键选择,按 [ESC] 退出

复制
y 复制光标所选定文段

粘贴
p 在光标所在行处粘贴

删除、裁切
x 删除光标所选文段

任务练习

使用 Vim 编辑器,编写C语言程序 saxpy
程序saxpy实现了单精度浮点型数据的向量加法运算,其具体公式如下:
y[n]=y[n]+a*x[n]
其中,n为向量长度,x、y为向量数组,a为标量系数,x、y、a均为单精度浮点型float

各变量的初始值如下:
n为102400
a为3.14
x中各元素初始为0.0~6.0间的浮点型随机数
y初始取值为y[n]=12.0-x[n]

程序文件组织如下:
kernel_axpy.h
负责向量加法接口函数的声明如下:
void saxpy(const int a,const float * const x, float *y)
其中,a、x为输入,y即为输入、也为输出

void saxpy(const int a,const float * const x, float *y);

kernel_axpy.cpp
负责向量加法接口函数saxpy()的定义实现

#include "kernel_axpy.h"
using namespace std;

void saxpy(const int a,const float * const x, float *y)
{
    for (int i=0; i<102400; ++i)
    {
        y[i] += a*x[i];
    }
}

main.cpp
负责初始化向量
调用向量加法接口saxpy()
使用计时函数clock()统计saxpy()的运行时间,并打印到屏幕
打印结果y的前20个元素数值到文件y_value.txt

#include <iostream>
#include <stdlib.h>
#include <ctime>
#include <fstream>
#include "kernel_axpy.h"
using namespace std;

const int n = 102400;
const float a = 3.14;

int main()
{
    float *x = new float[n];
    float *y = new float[n];
    srand((unsigned)time(NULL));
    for (int i=0; i<n; ++i)
    {
        x[i] = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/6));
        y[i] = 12 - x[i];
    }
    clock_t startTime, endTime;
    startTime = clock();
    saxpy(a, x, y);
    endTime = clock();
    cout<<(double)(endTime - startTime) / CLOCKS_PER_SEC<<endl;
    ofstream out("y_value.txt");
    for (int i=0; i<20; ++i)
    {
        out<<y[i]<<endl;
    }
    out.close();
    return 0;
}

生成指定范围的浮点类型随机数: link
clock() 的使用: link

编译器 GCC

程序编译流程

编译过程:预处理、编译、链接

  • 预处理:处理 .c 文件的 #define,#include 等预处理指令
  • 编译:把高级语言 (.c) 翻译成汇编指令 (.s),再翻译成机器码 (.o)
  • 链接:将所有目标文件 (.o) 和第三方库文件,链接成二进制文件 (.exe)

编译器 gcc 的简易使用

源文件与编译器:
在这里插入图片描述
gcc命令的建议编译规则:

gcc -o [binaryfile] [sourcefile1] [sourefile2]…
例如:
编译处可执行文件:gcc -o HelloWorld main.c
执行:./HelloWorld

gcc 编译链接命令规则及常用编译选项

  • 编译与链接
    示例:需要编译 main.c、kernel.c 成 exe,其使用了 /home/opt/ 路径下的第三方库 math,其中 opt 目录下包含:/include/mymath.h、/lib/mymath.so

    • 1、分步进行编译和链接
      编译 (将源文件逐个编译成目标文件)

gcc -o [obj_file] -c [src_file] -I [include_path]
最后一个是字母 i 的大写不是 l
例如:
gcc -c main.c -o main.o
gcc -c kernel.c -o kernel.o -I /home/opt/include

链接 (将所有目标文件,以及第三方库,链接成二进制文件)

gcc -o [bin] [all_obj_files] -L [library_path] -l [library_file_name]
最后一个是小写字母 l
例如:
gcc -o exe main.o kernel.o -L /home/opt/lib -l mymath

    • 2、直接编译出二进制文件

gcc -o [bin] [all_src_files] -I [include_path] -L [library_path] -l [library_file_name]
前面那个 -l 是大写的 i,后面那个 -l 是小写的 L
例如:
gcc -o exe main.c kernel.c -I /home/opt/include -L /home/opt/lib -l mymath

  • 编译选项
    gcc [-option] -o [bin] [src_file]
    常用的option编译选项:

优化等级选项:
-O0,-O1,-O2,-O3 由编译器自动进行代码性能优化,等级越大,程序运行速度越快
警告选项:
-Wall 显示所有警告
调试选项:
-g 通常结合 -O0 优化等级编译,后期可使用 gdb 工具对二进制文件进行调试。会降低程序计算速度
性能分析选项:
-pg 后期可用于 gprof 工具对二进制文件进行性能分析。会降低程序计算速度
宏定义选项
-D 对应着程序代码中的宏定义。如 -DUSE_MPI

工程构建工具 Make

make 命令与makefile文件的规则和逻辑

  • Make 与 Makefile
    GNU Make 是最基本的项目构建工具,Make 通过 Makefile 文件,获取如何构建执行文件信息,并按照 Makefile 里面设定的规则,根据源文件的依赖关系,调用编译器自动执行编译
  • Makefile 的逻辑与规则
    在这里插入图片描述
  • Makefile 组成结构:目标、目标的前置条件 (依赖)、规则,还包括变量以及内置函数
  • 一个目标 (最终的执行文件),会依赖一些文件 (如源文件、目标文件、库文件等),所依赖的文件也可以作为新的目标 (子目标) 放在后面,建立其对应的规则
  • 执行 make 指令时,make首先执行的是 Makefile 里面的第一个目标,检查第一个目标的前置条件,然后寻找 “前置条件” 的前置条件,以此类推
  • 执行某个特定的目标,不遵循默认从第一个目标开始,则输入:
    make [targetName]

makefile 文件编写案例

  • 编写 makefile
    以为 hello.cpp 编写 makefile 为例
BIN=hello                     "="定义变量BIN: 要生成的二进制文件名称为"hello"
SRC=hello.cpp                 
all:$(BIN)                    all为make默认执行目标, 这个目标所依赖文件: 二进制文件BIN  
$(BIN):$(SRC)                 二进制文件BIN依赖于源码文件SRC 
	g++ -o $(BIN) $(SRC)      建立SRC到BIN的规则
clean:                        clean 目标不依赖任何其他, 执行时将执行文件删除命令
	rm -rf $(BIN) $(OBJ)
  • 使用 makefile
  • 安装可执行文件:make
  • 清除:make clean

填空练习

现有一个程序,包含main.cpp、kernel.cpp源文件,并使用了/home/opt/路径下的第三方库mymath,其中opt路径下包含头文件./include/mymath.h和库文件./lib/libmymath.so。需要在与源文件同级目录下编写makefile文件来安装该程序,来编译出二进制文件exe

BIN=exe
OBJ=main.o kernel.o
CXX=g++
CXXFLAGS=-O2
LDFLAGS=$(CXXFLAGS)
INC=-I/home/opt/include
LIB=-L/home/opt/lib -lmymath
ALL:$(BIN)
	$(BIN):$(OBJ)
	$(CXX) $(LDFLAGS) -o $@ $^ $(LIB)
%.o:%.cpp
	$(CXX) $(CXXFLAGS) -o $@ -c $< $(INC)
.PHONY:clean
clean:
	rm -rf $(OBJ) $(BIN)

对自己的表现是否满意


今天的内容比较硬核,虽然之前或多或少了解过,但再次接触依然比较陌生。虽然把课程和任务过了一遍,但应该只是接触了这部分的皮毛,之后再遇到问题时还是要多查、多悟

简述下次计划


作业管理系统slurm、调试器GDB、高性能算法等

其他反馈


课程终端好卡…

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼树C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值