简介

将在Fortran程序中初始化的矩阵数组传递给C程序,由C程序启动DCU,每个线程根据自己的线程ID号定位到矩阵的对应行上,将该行每个元素的值加上该线程ID号。

特别注意与错误定位

(1)Fortran数组为列优先存储,两层循环初始化数组时注意外层循环变量在矩阵索引的第二维度上。否则可能出现内存读写错误。

(2)传递到C程序的参数皆为指针,即在C中要以指针类型接收数据。

(3)C数组为行优先存储,在传递之后从软件层来看矩阵自动进行了转置,然而在内存中的存储位置并没有发生任何改变,因此只需将矩阵的行列号交换即可获得转置后的矩阵。

(4)参与混编的C函数必须是小写(Fortran不区分大小写但C区分),函数名后加‘_’(下划线),函数名前用extern “C”声明。否则编译时找不到该混编函数。

(5)调用DCU需要指定编译指令,编译指令与所在环境息息相关。编译指令与编译程序时所在的环境与运行程序时所在的环境需统一。

(6)目前DCU核函数内不支持C++库(以后可能会支持),也不支持malloc动态内存分配。DCU所需要的内存需要在主机端使用hipMalloc等提前开辟,再将显存指针传入DCU中。否则报DCU显存页不存在或不可用错误。

Fortran源代码

文件名:fMain.F90

program mainimplicit none! 进行混合编译的c函数名(computefordcu)必须是小写,原因是Fortran语言不区分大小写,而混合编译时对其是区分大小写的external :: computefordcu! 测试矩阵,对矩阵进行每一列的元素加上该列号的操作,Fortran存储为列优先real*8, allocatable, dimension(:,:) :: matrix! 测试矩阵的行数,列数integer :: row, col! 测试结果real*8, allocatable, dimension(:) :: relvectorinteger :: i, jrow = 10col = 8! 为测试矩阵分配内存allocate(matrix(row, col))! 为测试结果分配内存allocate(relvector(col))! 初始化测试矩阵,Fortran数组索引从1开始,同时计算测试结果即每列元素之和do i = 1, colrelvector(i) = 0do j = 1, row! 列优先初始化,颠倒顺序极易出错matrix(j, i) = jrelvector(i) = relvector(i) + matrix(j, i)end do! 打印测试结果print *, "Sum of matrix column(", i, ")elements :", relvector(i)end do! C数组的存储为行优先,因此传入的矩阵会自动转置,所以在此颠倒行列数call computefordcu(matrix, col, row)! 打印、验证结果do i = 1, colrelvector(i) = 0do j = 1, rowrelvector(i) = relvector(i) + matrix(j, i)end do! 打印测试结果print *, "Sum of matrix column(", i, ")elements :", relvector(i)end do
end program

C源代码

文件名:cMain.cpp

#include <iostream>
#include <stdio.h>
#include <hip/hip_runtime.h>using namespace std;// 测试标志
#define TESTON true
// 错误码
#define MATRIX_SIZE_ERROR        0x100001  // 矩阵规模错误
#define MATRIX_POINTER_NULL      0x100002  // 矩阵空指针
#define DCUMEM_ALLOC_ERROR       0x100003  // 内存分配错误/* DCU核函数,对矩阵的每一行元素加上其行号* pfMatrix: 需要处理的矩阵首地址* row: 矩阵的行数* col: 矩阵的列数* */
__global__ void MatrixProcess(double *pfMatrix, int row, int col)
{// 测试if (TESTON){// DCU编程不支持C++库printf("DCU Program Started! \n");}// 错误检查if (row < 1 || col < 1){printf("ERROR OCCURRE! ERROR CODE : %x", MATRIX_SIZE_ERROR);return;}if (pfMatrix == NULL){printf("ERROR OCCURRE! ERROR CODE : %x", MATRIX_POINTER_NULL);return;}int tid;double *pfMatRow;tid = blockDim.x * blockIdx.x + threadIdx.x;// 依据该线程ID找到该线程需要处理的数据的首地址pfMatRow = (double*)((char*)pfMatrix + col * tid * sizeof(double));for (int i = 0; i < col; i++){pfMatRow[i] = pfMatRow[i] + tid;}return;
}/* Fortran调用C的入口函数,进行混编的c函数名需要加'_'(下划线),传入函数的参数均为指针* matrix: 矩阵首地址* row: 矩阵的行数* col: 矩阵的列数* */
extern "C" void computefordcu_(double *matrix, int *row, int *col)
{// 测试if (TESTON){cout << "C Program Started!" << endl;}// 错误检查if (*row < 1 || *col < 1){printf("ERROR OCCURRE! ERROR CODE : %x", MATRIX_SIZE_ERROR);return;}int iErr, iSize;// DCU显存指针double *pfDevMatrix;// 统计时间float fTimeElapsed;// 任务流hipStream_t hipStream;// 记录时间hipEvent_t start, stop;//设置当前设备hipSetDevice(0);// 创建事件hipEventCreate(&start);hipEventCreate(&stop);// 创建任务流hipStreamCreate(&hipStream);// 为待处理矩阵指针分配DCU显存iSize = (*row) * (*col) * sizeof(double);hipMalloc((void**)&pfDevMatrix, iSize);if (pfDevMatrix == nullptr){printf("ERROR OCCURRE! ERROR CODE : %x", DCUMEM_ALLOC_ERROR);return;}hipEventRecord(start, hipStream);// 内存数据拷贝到显存hipMemcpyAsync(pfDevMatrix, matrix, iSize, hipMemcpyHostToDevice, hipStream);// 启动核函数,每个线程处理矩阵的一行数据hipLaunchKernelGGL(MatrixProcess, dim3(1), dim3(*row), 0, hipStream, pfDevMatrix, *row, *col);// 显存数据拷贝回内存hipMemcpyAsync(matrix, pfDevMatrix, iSize, hipMemcpyDeviceToHost, hipStream);hipEventRecord(stop, hipStream);// 同步hipEventSynchronize(stop);hipEventElapsedTime(&fTimeElapsed, start, stop);cout << "DCU TIME : " << fTimeElapsed << " ms" << endl;//清除设备显存hipFree(pfDevMatrix);//清除事件hipEventDestroy(start);hipEventDestroy(stop);//清除流hipStreamDestroy(hipStream);return;
}

MakeFile文件

文件名:makefile

HIP_INSTALL_PATH = /public/software/compiler/rocm/rocm-4.0.1# 编译器
CC = hipcc
FC = gfortran# 链接器
LD = gfortran# 编译C程序的指令
CFLAGS = --offload-arch=gfx906
# 编译Fortran程序的指令
FFLAGS =# 链接指令
LIBS = -lstdc++ -lamdhip64 -lhsa-runtime64 -lamd_comgr -lhsakmt -L$(HIP_INSTALL_PATH)/lib64/ -L$(HIP_INSTALL_PATH)/hip/lib -L$(HIP_INSTALL_PATH)/lib/ -L$(HIP_INSTALL_PATH)/hipfort/lib/# Fortran源文件
FFILES = fMain.F90# C/HIP源文件
CFILES = cMain.cpp# 中间文件
OBJECTS = fMain.o cMain.o# 目标文件
TARGET = main.outall:$(FC) $(FFLAGS) -c $(FFILES)$(CC) $(CFLAGS) -c $(CFILES)$(LD) $(LIBS) $(OBJECTS) -o $(TARGET)clean:rm -f *.o $(TARGET)

申请DCU节点

salloc -p kshdnormal -N 1 --gres=dcu:1

切换运行环境及编译环境

module switch compiler/rocm/4.0.1

编译及运行程序

make

曙光超算Fortran混编C并启动DCU计算相关推荐

  1. python fortran混编 ctypes_关于python调用fortran编译的dll的问题

    [Fortran] 纯文本查看 复制代码Module proc Use, Intrinsic :: ISO_C_BINDING Implicit None ! 将常量.模型参数定义为一个结构体(全局变 ...

  2. python fortran混编 ctypes_Python调用C/Fortran混合的动态链接库--上篇

    内容描述: 在32位或64位的windows或GNU/Linux系统下利用Python的ctypes和numpy模块调用C/Fortran混合编程的有限元数值计算程序 操作系统及编译环境: 32bit ...

  3. Linux下C++和Fortran的混编

    事情的起因是我需要计算多组分燃烧问题中的粘性项,实现起来非常麻烦.并且CHEMKIN中有现成的代码,但问题在于我的程序为.cpp的MPI并行代码.将Fortran代码翻译成C++代码再用也可,但是仅仅 ...

  4. 百度App Objective-C/Swift 组件化混编之路(一)

    作者丨郭金.陈佳 来源丨百度App技术 一. 背景 1.1 Swift 发展历史 2010 年 7 月,克里斯(Chris Lattner)开始设计 Swift.完成基础架构后,克里斯带领开发小组陆续 ...

  5. C++和Objective-C混编(官方文档翻译)

    苹果的Objective-C编译器允许用户在同一个源文件里自由地混合使用C++和Objective-C,混编后的语言叫Objective-C++.有了它,你就可以在Objective-C应用程序中使用 ...

  6. iphone开发之C++和Objective-C混编

    C++和Objective-C混编(官方文档翻译) 原文网址: http://developer.apple.com/iphone/library/documentation/Cocoa/Concep ...

  7. Objective-C和C++混编的要点

    原帖地址   http://www.cocoachina.com/bbs/read.php?tid-9111-fpage-3.html Using C++ With Objective-C     苹 ...

  8. keil c语言pdf,Keil软件“C语言”与“汇编”混编 —— 相关知识整理.pdf

    Keil软件"C语言"与"汇编"混编 -- 相关知识整理.pdf Keil 软件软件C 语言语言与与汇编汇编混编混编 相关知识整理相关知识整理 用 Keil 在 ...

  9. 解决了java+matlab混编+web(jsp)调用Matlab,网页中显示Figure,详细实例

    例子简介 网上java+matlab混编的挺多,大多数实例也都能实现出来,但是将matlab生成出来Figure显示在jsp页面中并配合WebFigure实现的例子却很少,所以我将自己的尝试结果详细的 ...

最新文章

  1. 基于区块链交易技术开发的证券
  2. 神龙架构没那么难理解—图解世界领先的阿里云神龙架构(二)神龙出世
  3. Windows任务管理 连接用户登录信息 通用类[C#版]
  4. Chrome浏览器如何安装与使用PDFViewer扩展程序
  5. [ZT]MSN Messenger的口令获取源代码, MSNMessenger的口令是经过DPAPI加密后保存在注册表中...
  6. 【Elasticsearch】数据预加载
  7. 专栏:谈谈我对当下大数据整顿的理解与风控建议
  8. NUC1131 Triangle【DP】
  9. django orm 操作表
  10. 门店销售系统开发实例
  11. 液晶显示器测试软件6,屏幕坏点检测工具(Datum pixel repair)
  12. Redis的雪崩,击穿,穿透详解
  13. java json 解析字符串_java-解析JSON字符串的最简单方法
  14. 解读MT7620A上的DTS文件
  15. js提示“未结束的字符串常量”
  16. 12306 抢票系列之只要搞定RAIL_DEVICEID的来源,从此抢票不再掉线(上)
  17. 怎么用Q-Q图验证数据集的分布
  18. 高通平台开发系列讲解(USB篇)USB端口的说明及切换方法
  19. 计算机操作电脑试题评分标准,2014计算机一级上机试题(1—5套)评分标准.docx
  20. 初识python评课稿_pythonrange函数

热门文章

  1. pytest—setup和teardown简单用法
  2. 用户疑问解答:我是做电子烟行业的,看到同行也在用粉丝圈,有人了解吗?
  3. 中国物业服务行业发展可行性及未来战略分析报告2021-2027年版
  4. 解决“移动硬盘出现文件被占用”的问题
  5. 前端websocket使用心得-------二进制数据传输
  6. PLSQL/Oracle解决中文乱码问题
  7. 时钟传感器—DS3231
  8. 【React Native】请求设备权限
  9. 97条架构师必须掌握的知识
  10. 绕过CSP之Dangling markup技术