---
title: Fortran软件使用KUPL接口-官方技术文章-鲲鹏社区
description: 关于Fortran软件如何使用KUPL接口介绍
keywords: Fortran,KUPL,软件使用,接口,官方技术文章,鲲鹏社区,软件如何使用,背景介绍
url: https://www.hikunpeng.com/developer/techArticles/20251223-2?envFlag=1
section: (其他)
---

# Fortran软件使用KUPL接口-官方技术文章-鲲鹏社区

URL: https://www.hikunpeng.com/developer/techArticles/20251223-2?envFlag=1
描述: 关于Fortran软件如何使用KUPL接口介绍
关键词: Fortran,KUPL,软件使用,接口,官方技术文章,鲲鹏社区,软件如何使用,背景介绍

官方技术文章 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles)

Fortran软件使用KUPL接口

Fortran软件使用KUPL接口

高性能计算HPC

发表于 2025/12/23

0

# Fortran软件如何使用KUPL接口

## 1 背景介绍

鲲鹏统一并行加速库（KUPL）是基于鲲鹏处理器深度优化的并行加速库，包括多线程编程，数据管理，矩阵编程三类基础与扩展功能，结合鲲鹏处理器硬件特性，提供优化的调度与同步算法、异步数据搬运等差异化能力，从高性能，高易用角度为鲲鹏平台应用加速提供助力。

详情链接：https://www.hikunpeng.com/developer/hpc/kupl [了解详情](https://www.hikunpeng.com/developer/hpc/kupl)

当前KUPL所有接口由C/C++、汇编语言实现，但在高性能计算领域，有许多软件是由Fortran语言编写的。

本文展示在Fortran软件中如何调用KUPL来进行优化。

## 2 基本流程

iso_c_binding 是 Fortran 2003 标准引入的一个内置模块，用于实现 Fortran 与 C 语言之间的互操作性。通过该模块，Fortran 程序可以安全、可移植地调用 C 函数，或被 C 程序调用。我们将使用该模块调用KUPL中的C/C++接口。

iso_c_binding 提供了一系列与 C 语言基本类型一一对应的 Fortran 类型种类（kind），例如：

| C类型 | Fortran对应 |
| --- | ---|
| int | integer(c_int) |
| double | real(c_double) |
| float | real(c_float) |
| char | character(c_char) |
| size_t | character(c_char) |
| void* | type(c_ptr) |

步骤一：声明C兼容的Fortran接口

在Fortran中使用 bind(C) 属性声明 C 兼容的接口，并通过 iso_c_binding 提供的类型传递参数。

请注意：C 默认按值传递，Fortran 默认按引用传递。

因此，声明参数时：

（1）如果 C 函数期望按值传参（如 int x），Fortran 声明的参数必须加 value 属性。如果 C 函数期望指针（如 int* x），Fortran 可直接声明。

（2）如果C接口接收的是结构体，在Fortran中同样需要使用 bind(C) 定义同样的结构体。

步骤二：在Fortran中调用声明的接口

如上一步所说，Fortran 默认按引用传递，一般情况下，Fortran 调用时可直接传变量（默认传地址）。

一个比较常见的特殊情况是，如果C 函数参数是 void* 或 type(c_ptr)，需要使用 c_loc 函数用于获取一个 Fortran 变量的 C 兼容指针（type(c_ptr)）。

步骤三：编译链接

将C接口编译成.o文件，如果Fortran声明的接口是独立文件，也需要编译出.mod和.o文件，Fortran可执行文件链接时需要加上这两个.o文件。

## 3 KUPL接口转换举例

### 3.1 kupl_parallel_for

将kupl_parallel_for封装一层C接口以更方便在软件中使用：

```
int kupl_parallel_for(kupl_parallel_for_desc_t *desc, kupl_pf_func_t func, void *args); // KUPL定义的接口

// 为方便使用封装一层
void c_kupl_parallel_for(int lower, int upper, void (*func)(kupl_nd_range_t *, void *, int, int), void *args)
{
    kupl_nd_range_t range;
    KUPL_1D_RANGE_INIT(range, lower, upper, 1);
    kupl_parallel_for_desc_t desc = {
        .range = &range,
        .concurrency = g_threads,
        .egroup = g_egroup,
        .policy = KUPL_LOOP_POLICY_STATIC
    };
    kupl_parallel_for(&desc, func, args);
}
```

Fortran接口的声明如下：

```
module kupl_mod
  use iso_c_binding
  implicit none

  interface
    subroutine f_kupl_parallel_for(lower, upper, func, args) bind(c, name="c_kupl_parallel_for")
      import :: c_funptr, c_ptr, c_int
      integer(c_int), value :: lower
      integer(c_int), value :: upper
      type(c_funptr), value :: func
      type(c_ptr), value :: args
    end subroutine f_kupl_parallel_for
  end interface
end module kupl_mod
```

Fortran调用：

```
type(cell_loop_stru), target :: args ! args要用到c_loc，需要target属性
type(c_funptr) :: func ! parallel接口需要回调函数，声明为c_funptr

func = c_funloc(cell_loop) ! cell_loop是KUPL定义的回调函数，需要c_funloc转换

call f_kupl_parallel_for(1, n, func, c_loc(args)) ! 直接传变量，args因为是void*，需要c_loc
```

### 3.2 共享内存通信函数

KUPL提供了共享内存底层通信接口，以及基于这些接口的集合通信函数实现，常与MPI协作使用。

C接口：

```
int kupl_shm_comm_create(int size, int rank, int pid, kupl_shm_oob_cb_h oob_cbs, void *group, kupl_shm_comm_h *comm);

int kupl_shm_win_alloc(size_t size, kupl_shm_comm_h comm, void **baseptr, kupl_shm_win_h *win);

void c_kupl_shm_comm_create(int *shm_comm, int rank, kupl_shm_comm_h *kupl_comm)
{
    MPI_Comm comm = MPI_Comm_f2c(*shm_comm); // MPI提供通信域的转换接口

    int size;
    MPI_Comm_size(comm, &size);
    // ...一些赋值...

    kupl_shm_comm_create(size, rank, pid, oob_cbs_h, (void *)comm, kupl_comm);
}
```

Fortran接口：

```
! 接口用到了结构体需要定义
type, bind(c) :: kupl_shm_comm_h
  type(c_ptr) :: ptr
end type kupl_shm_comm_h

type, bind(c) :: kupl_shm_win_h
  type(c_ptr) :: ptr
end type

subroutine f_kupl_shm_comm_create(comm, rank, kupl_comm) bind(c, name="c_kupl_shm_comm_create")
  import :: c_int, kupl_shm_comm_h
  integer(c_int) :: comm
  integer(c_int), value :: rank
  type(kupl_shm_comm_h), intent(out) :: kupl_comm
end subroutine

function f_kupl_shm_win_alloc(buf_size, kupl_comm, baseptr, win) bind(c, name="kupl_shm_win_alloc") ! function定义需要返回值的接口
  import :: c_size_t, c_ptr, kupl_shm_comm_h, kupl_shm_win_h, c_int
  integer(c_size_t), value :: buf_size
  type(kupl_shm_comm_h), value :: kupl_comm
  type(c_ptr), intent(out) :: baseptr
  type(kupl_shm_win_h), intent(out) :: win
  integer(c_int) :: err ! 最后一个参数是函数返回值
end function
```

Fortran调用：

```
type(kupl_shm_comm_h) :: kupl_comm
call f_kupl_shm_comm_create(mpi_comp_comm, mpi_comp_rank, kupl_comm)

type(c_ptr) :: local_buffer
type(kupl_shm_win_h) :: kupl_win
real(8), pointer :: mpi_send_buf(:)
err = f_kupl_shm_win_alloc(buf_size, kupl_comm, local_buffer, kupl_win)
CALL c_f_pointer(local_buffer, mpi_send_buf, [send_count]) ! local_buffer是出参，Fortran需要c_f_pointer转为Fortran指针
```

## 4 注意事项

1、C 函数需要的入参是值，Fortran 的参数传递方式一定要加 value，否则会读错内存。

2、传给C接口的字符串必须以 \0 结尾：

```
msg = 'Hello' // c_null_char ! 必须补 \0
```

3、在 Fortran 中定义的二维（及以上）数组传递给 C 函数时，在内存中的排布方式（存储顺序）是列优先，而 C 语言默认使用行优先。因此将Fortran的数组传给C前，需要先将Fortran的数组按照行优先的逻辑重新排列再传入。

4、C 数组下标从 0 开始，Fortran 从 1 开始。在内存中传递的只是地址，与下标无关，但如果涉及到索引计算等操作时，需注意下标代表的含义。

本页内容
