簡體   English   中英

sycl/dpc++ 使用全局指針訪問全局變量

[英]sycl/dpc++ accessing global variable using global pointer

我正在嘗試從 sycl kernel 內部訪問一個全局變量。 使用此模式及其 output 的代碼如下。

#include<CL/sycl.hpp>
using namespace sycl;
int g_var = 22;
int * const g_ptr = &g_var;
int main() {
    queue q{host_selector{}};
    g_var = 27;
    std::cout<<"global var changed : " <<g_var<<" "<<*g_ptr<<"\n";
    q.submit( [=] (handler &h) {
        stream os(1024, 128, h);
        h.single_task([=] () {
            os<<"global var : "<<*g_ptr<<"\n";
        });
    }).wait();
    return 0;
}

其output如下。

$$ dpcpp test.cpp; ./a.out
global var changed : 27 27
global var : 22

即使將 g_var 更改為 27,它也會在 kernel 內部以 22 的初始值打印。 這是預期的行為嗎?

通常 lambdas 不會創建全局變量的副本。 dpc++ 編譯器是在設備內部創建全局變量的副本還是在編譯期間傳播常量值以便在運行時不訪問全局 memory?

SYCL 通過“主機”和“設備”來划分執行和數據。 “主機”上的數據正常存在於 CPU 上,需要傳輸到“設備”(通常是 GPU)才能訪問以在 SYCL kernel 中使用。

SYCL 使用緩沖區和訪問器或“統一共享內存”來傳輸和提供對“設備”端代碼(即在 GPU 上運行的代碼)的數據的訪問。 因此,您的指針永遠不會發送到設備,因此永遠不會被修改。

所以不要使用int * const g_ptr = &g_var; 您應該使用緩沖區或 USM。 SYCL Academy中有一些關於緩沖區和 USM 的課程。

例如使用緩沖區和訪問器:

int a = 18, b = 24, r = 0;

  auto defaultQueue = sycl::queue{};

  {
    auto bufA = sycl::buffer{&a, sycl::range{1}};
    auto bufB = sycl::buffer{&b, sycl::range{1}};
    auto bufR = sycl::buffer{&r, sycl::range{1}};

    defaultQueue
        .submit([&](sycl::handler &cgh) {
          auto accA = sycl::accessor{bufA, cgh, sycl::read_only};
          auto accB = sycl::accessor{bufB, cgh, sycl::read_only};
          auto accR = sycl::accessor{bufR, cgh, sycl::write_only};

          cgh.single_task<scalar_add>([=] { accR[0] = accA[0] + accB[0]; });
        })
        .wait();
  }

並使用 USM:

 auto usmQueue = sycl::queue{usm_selector{}, asyncHandler};

 usmQueue.memcpy(devicePtrA, a, sizeof(float) * dataSize).wait();
 usmQueue.memcpy(devicePtrB, b, sizeof(float) * dataSize).wait();

 usmQueue
     .parallel_for<vector_add>(sycl::range{dataSize},
                                  [=](sycl::id<1> idx) {
                                    auto globalId = idx[0];
                                    devicePtrR[globalId] =
                                        devicePtrA[globalId] +
                                        devicePtrB[globalId];
                                  })
     .wait();

 usmQueue.memcpy(r, devicePtrR, sizeof(float) * dataSize).wait();

 sycl::free(devicePtrA, usmQueue);
 sycl::free(devicePtrB, usmQueue);
 sycl::free(devicePtrR, usmQueue);

 usmQueue.throw_asynchronous();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM