Vengineerの妄想

人生を妄想しています。

Tenstorrent : TT-Metalium (その3)

はじめに

Tenstorrent : TT-Metaliumのその3.今回は、カーネルプログラムのData Moverコアの例を見てみます。

ホスト側のプログラム

前回のホスト側のプログラムとほぼ同じです。カーネルプログラムの紐づけと、SetRuntimeArgs API の数が違うだけです。

#include "tt_metal/host_api.hpp"
#include "tt_metal/impl/device/device.hpp"

using namespace tt;
using namespace tt::tt_metal;

int main(int argc, char **argv) {

    // Initialize Program and Device

    constexpr CoreCoord core = {0, 0};
    int device_id = 0;
    Device *device = CreateDevice(device_id);
    CommandQueue& cq = device->command_queue();
    Program program = CreateProgram();

    // Configure and Create Void DataMovement Kernels

    KernelHandle void_dataflow_kernel_noc0_id = CreateKernel(
        program,
        "tt_metal/programming_examples/hello_world_datamovement_kernel/kernels/dataflow/void_dataflow_kernel.cpp",
        core,
        DataMovementConfig{.processor = DataMovementProcessor::RISCV_0, .noc = NOC::RISCV_0_default});

    KernelHandle void_dataflow_kernel_noc1_id = CreateKernel(
        program,
        "tt_metal/programming_examples/hello_world_datamovement_kernel/kernels/dataflow/void_dataflow_kernel.cpp",
        core,
        DataMovementConfig{.processor = DataMovementProcessor::RISCV_1, .noc = NOC::RISCV_1_default});

    // Configure Program and Start Program Execution on Device

    SetRuntimeArgs(program, void_dataflow_kernel_noc0_id, core, {});
    SetRuntimeArgs(program, void_dataflow_kernel_noc1_id, core, {});
    EnqueueProgram(cq, program, false);
    printf("Hello, Core {0, 0} on Device 0, I am sending you some data. Standby awaiting communication.\n");

    // Wait Until Program Finishes, Print "Hello World!", and Close Device

    Finish(cq);
    printf("Thank you, Core {0, 0} on Device 0, for the completed task.\n");
    CloseDevice(device);

    return 0;

}

カーネルプログラムの紐づけは、2つあります。一つ目は、下記の部分です。カーネルプログラムのソースコードは、"tt_metal/programming_examples/hello_world_datamovement_kernel/kernels/dataflow/void_dataflow_kernel.cpp"です。このカーネルプログラムは、Data Movement コア の RISCV_0 が実行します。

    KernelHandle void_dataflow_kernel_noc0_id = CreateKernel(
        program,
        "tt_metal/programming_examples/hello_world_datamovement_kernel/kernels/dataflow/void_dataflow_kernel.cpp",
        core,
        DataMovementConfig{.processor = DataMovementProcessor::RISCV_0, .noc = NOC::RISCV_0_default});

もう一つのカーネルプログラムの紐づけは、下記の部分です。カーネルプログラムのソースコードは、"tt_metal/programming_examples/hello_world_datamovement_kernel/kernels/dataflow/void_dataflow_kernel.cpp"で、同じです。このカーネルプログラムは、Data Movement コア の RISCV_1 が実行します。

    KernelHandle void_dataflow_kernel_noc1_id = CreateKernel(
        program,
        "tt_metal/programming_examples/hello_world_datamovement_kernel/kernels/dataflow/void_dataflow_kernel.cpp",
        core,
        DataMovementConfig{.processor = DataMovementProcessor::RISCV_1, .noc = NOC::RISCV_1_default});

SetRuntimeArgs API はそれぞれのカーネルプログラムに対応しています。

    SetRuntimeArgs(program, void_dataflow_kernel_noc0_id, core, {});
    SetRuntimeArgs(program, void_dataflow_kernel_noc1_id, core, {});

カーネルプログラム

カーネルプログラムは、下記にあります。

Data Movement コアの場合は、void kernel_main の中に書きます (Compute コアの時は、void MAIN でした)。カーネルプログラムでは、DPRINT_DATA0 / DPRINT_DATA1 にてメッセージを表示しています。 0

#include "debug/dprint.h"  // required in all kernels using DPRINT
#include "dataflow_api.h"

void kernel_main() {

        // Nothing to move. Print respond message.
        // Make sure to export TT_METAL_DPRINT_CORES=0,0 before runtime.

        DPRINT_DATA0(DPRINT << "Hello, Master, I am running a void data movement kernel on NOC 0." << ENDL());
        DPRINT_DATA1(DPRINT << "Hello, Master, I am running a void data movement kernel on NOC 1." << ENDL());

}

おわりに

今回は、Data Movement コアのサンプルプログラムについて、見ていました。

次回は、2つの整数の加算をするサンプルプログラムを見てみます。