Intel® 高层次综合编译器专业版Pro版: 参考手册

ID 683349
日期 12/04/2023
Public
文档目录

4.3.1. pipe类别及其用途

pipe类别暴露了将数据写入管道和从管道读取数据的静态方法。读取和写入可以是阻塞,也可以是非阻塞的,具体形式取决于过载解析。

pipe API相当于以下类声明:
template <class name,
          class dataT,
          size_t min_capacity = 0>
class pipe {
public:
  // Blocking
  static dataT read();
  static void write(dataT data);
  // Non-blocking
  static dataT read(bool &success);
  static void write(dataT data, bool &success);
}
其中的模板参数定义如下:
表 12.   pipe API模板参数
参数 描述
name 为管道创建唯一标识符的类型。

通常是定义用户类别,位于用户命名空间(namespace)中。转发类型声明就已足够,无需定义类型。

dataT 管道内包含的数据包的数据类型。

该数据类型是成功的管道read()操作期间读取的数据类型,或者成功的管道write()操作期间被写入的数据类型。

该类型必须具有标准布局并且易于复制。

min_capacity 管道必须能够存储并且不被读出的最小字数(以dataT为单位)。

出于性能考虑,编译器可能会创建容量更大的管道。

使用管道的实例

以下代码实例显示了可以在源代码库中使用或者在组件或任务函数中使用的头文件。
#include "HLS/hls.h"

template<unsigned ID, class T, unsigned pipe_capacity> class TaskSystem {
private:
  template<unsigned SystemID> class InputPipeID {};
  template<unsigned SystemID> class TaskPipeID {};
  template<unsigned SystemID> class OutputPipeID {};

public:
  using input_pipe  = ihc::pipe<class InputPipeID<ID>, T, pipe_capacity>;
  using output_pipe = ihc::pipe<class OutputPipeID<ID>, T, pipe_capacity>;
  using task_pipe   = ihc::pipe<class TaskPipeID<ID>, T, pipe_capacity>;

  static void first_task(unsigned N) {
    T data;
    for(unsigned i=0; i<N; ++i) {
      data = input_pipe::read();
      task_pipe::write(data);
    }
  }

  static void second_task(unsigned N) {
    T data;
    for(unsigned i=0; i<N; ++i) {
      data = task_pipe::read();
      output_pipe::write(data);
    }
  }
};

通过该头文件,可以从单独的任务函数调用first_tasksecond_task来实现并发。

假设文件中有一个名为task_system.h的头文件,您可以创建一个任务组件系统,如以下实例所示:
#include "HLS/hls.h"
#include <iostream>

#include “task_system.h”

unsigned constexpr ID = 42; // can be any unique value
unsigned constexpr CAPACITY = 100;
using MySystem = TaskSystem<ID, int, CAPACITY>;

int main() {
  ihc::launch<MySystem::first_task>(CAPACITY);
  ihc::launch<MySystem::second_task>(CAPACITY);

  for(int i = 0; i < CAPACITY; ++i) {
    std::cout << "input: " << i << "\n";
    MySystem::input_pipe::write(i);
  }

  for(int i = 0; i < CAPACITY; ++i) {
    int data = MySystem::output_pipe::read();
    std::cout << "output: " << data << "\n";
  }

  return 0;
}

管道数组(Array)实例

以下代码实例使用模板实现管道数组,并包含写入此类数组的函数。

#include "HLS/hls.h"

// PipeArray

template <class ArrayID, typename T, unsigned pipeCapacity, unsigned arraySize>
class PipeArray {
private:
  template <unsigned idx> struct StructIndex;
  template <unsigned idx> struct VerifyIndex {
    static_assert(idx < arraySize, "Index out of bounds");
    using VerifiedPipe = ihc::pipe<StructIndex<idx>, T, pipeCapacity>;
  };

public:
  template <unsigned idx>
  using pipe_at = typename VerifyIndex<idx>::VerifiedPipe;
  static void write_to_pipes(T *values);
};

// Write Unroller

template <class ArrayID, typename T, unsigned pipeCapacity, unsigned arraySize,
          unsigned idx>
struct WriteUnroller {
  using my_array = PipeArray<ArrayID, T, pipeCapacity, arraySize>;
  static void write_to_pipes_impl(T *values) {
    my_array::template pipe_at<idx>::write(values[idx]);
    WriteUnroller<ArrayID, T, pipeCapacity, arraySize,
                  idx + 1>::write_to_pipes_impl(values);
  }
};

template <class ArrayID, typename T, unsigned pipeCapacity, unsigned arraySize>
struct WriteUnroller<ArrayID, T, pipeCapacity, arraySize, arraySize> {
  static void write_to_pipes_impl(T *values) {}
};

// Write function

template <class ArrayID, typename T, unsigned pipeCapacity, unsigned arraySize>
void PipeArray<ArrayID, T, pipeCapacity, arraySize>::write_to_pipes(T *values) {
  WriteUnroller<ArrayID, T, pipeCapacity, arraySize, 0>::write_to_pipes_impl(
      values);
}

函数PipeArray::write_to_pipes从要被写入的值中选取一个数组,并调用WriteUnroller::write_to_pipes_impl,该操作使用递归式模板方式写入数组中的每个管道。从管道数组中读取时也是类似的实现方式。