電子商務(wù)seo是指什么意思seo是哪個英文的簡寫
前言
本文是對jupyterlab中oneAPI_Essentials/03_Unified_Shared_Memory文檔的學(xué)習(xí)記錄,主要包含對統(tǒng)一共享內(nèi)存的講解
USM概述
USM (Unified Shared Memory)是SYCL中基于指針的內(nèi)存管理。對于使用malloc或new來分配數(shù)據(jù)的C和C++程序員來說應(yīng)該很熟悉。當(dāng)將現(xiàn)有的C/ C++代碼移植到SYCL時,USM簡化了程序員的開發(fā)
使用USM,開發(fā)人員可以在主機和設(shè)備代碼中引用相同的內(nèi)存對象
Types of USM
統(tǒng)一共享內(nèi)存為管理內(nèi)存提供了顯式和隱式模型
USM初始化:下面的初始化顯示了使用malloc_shared共享分配的示例,“q”隊列參數(shù)提供了有關(guān)內(nèi)存可訪問的設(shè)備的信息
下面是在host上分配內(nèi)存的方法:
釋放USM
數(shù)據(jù)隱式移動
下面的SYCL代碼顯示了使用malloc_shared的USM的實現(xiàn),其中數(shù)據(jù)在主機和設(shè)備之間隱式地移動??梢杂米钌俚拇a快速獲得功能,開發(fā)人員不必擔(dān)心在主機和設(shè)備之間移動內(nèi)存
#include <sycl/sycl.hpp>
using namespace sycl;static const int N = 16;int main() {queue q;std::cout << "Device : " << q.get_device().get_info<info::device::name>() << "\n";//# USM allocation using malloc_sharedint *data = malloc_shared<int>(N, q);//# Initialize data arrayfor (int i = 0; i < N; i++) data[i] = i;//# Modify data array on deviceq.parallel_for(range<1>(N), [=](id<1> i) { data[i] *= 2; }).wait();//# print outputfor (int i = 0; i < N; i++) std::cout << data[i] << "\n";free(data, q);return 0;
}
運行結(jié)果
數(shù)據(jù)顯示移動
下面的SYCL代碼顯示了使用malloc_device的USM實現(xiàn),其中主機和設(shè)備之間的數(shù)據(jù)移動應(yīng)該由開發(fā)人員使用memcpy顯式地完成
#include <sycl/sycl.hpp>
using namespace sycl;static const int N = 16;int main() {queue q;std::cout << "Device : " << q.get_device().get_info<info::device::name>() << "\n";//# initialize data on hostint *data = static_cast<int *>(malloc(N * sizeof(int)));for (int i = 0; i < N; i++) data[i] = i;//# Explicit USM allocation using malloc_deviceint *data_device = malloc_device<int>(N, q);//# copy mem from host to deviceq.memcpy(data_device, data, sizeof(int) * N).wait();//# update device memoryq.parallel_for(range<1>(N), [=](id<1> i) { data_device[i] *= 2; }).wait();//# copy mem from device to hostq.memcpy(data, data_device, sizeof(int) * N).wait();//# print outputfor (int i = 0; i < N; i++) std::cout << data[i] << "\n";free(data_device, q);free(data);return 0;
}
運行結(jié)果
代碼解釋
本代碼讓數(shù)據(jù)在主機區(qū)和設(shè)備區(qū)顯示移動,提高了開發(fā)人員對數(shù)據(jù)的可控性
首先本代碼使用malloc在主機分配內(nèi)存,然后給這些內(nèi)存賦值,然后使用malloc_device在設(shè)備區(qū)分配內(nèi)存,然后把主機區(qū)的內(nèi)存拷貝到設(shè)備區(qū)的這些內(nèi)存中,然后在設(shè)備區(qū)加速處理這些數(shù)據(jù)之后再拷貝到主機區(qū)的原內(nèi)存中,最后使用cout輸出
USM的優(yōu)勢
SYCL*緩沖區(qū)功能強大且優(yōu)雅,但是,在c++程序中用緩沖區(qū)替換所有指針和數(shù)組可能會給程序員帶來負擔(dān),因此在這種情況下可以考慮使用USM
1.當(dāng)把c++代碼移植到sycl時,想要盡可能更改少的代碼
2.當(dāng)需要控制數(shù)據(jù)移動時,使用顯式USM分配
3.在移植代碼時使用共享分配可以快速獲得功能
Data dependency in USM
程序員可以顯式地使用wait對象,也可以使用命令組中的depends_on方法來指定在任務(wù)開始之前必須完成的事件列表
在下面的示例中,兩個內(nèi)核任務(wù)正在更新相同的數(shù)據(jù)數(shù)組,這兩個內(nèi)核可以同時執(zhí)行,并且可能導(dǎo)致錯誤的結(jié)果
Different options to manage data dependency when using USM:
wait()
在內(nèi)核任務(wù)上使用q.wait()來等待下一個依賴的任務(wù)可以開始,但是它會阻塞主機上的執(zhí)行
in_order queue property
為隊列使用in_order?隊列屬性,這將序列化所有內(nèi)核任務(wù)。注意,即使隊列沒有數(shù)據(jù)依賴關(guān)系,執(zhí)行也不會重疊
depends_on
在命令組中使用h.depends_on(e)方法來指定任務(wù)開始之前必須完成的事件
簡化版
Code Example: USM and Data dependency
這個例子主要演示了上面三種方法的使用
初始代碼
想要修改上面代碼,只需下面三種方法三選一
使用wait
使用in_order queue property
使用depends_on
運行結(jié)果
Lab Exercise: Unified Shared Memory
實驗要求
下面是我已經(jīng)補全的代碼和運行結(jié)果
#include <sycl/sycl.hpp>
#include <cmath>
using namespace sycl;
static const int N = 1024;
int main() {queue q;std::cout << "Device : " << q.get_device().get_info<info::device::name>() << "\n";//intialize 2 arrays on hostint *data1 = static_cast<int *>(malloc(N * sizeof(int)));int *data2 = static_cast<int *>(malloc(N * sizeof(int)));for (int i = 0; i < N; i++) {data1[i] = 25;data2[i] = 49;}//# STEP 1 : Create USM device allocation for data1 and data2//# YOUR CODE GOES HEREint *data_device1 = malloc_device<int>(N, q);int *data_device2 = malloc_device<int>(N, q);//# STEP 2 : Copy data1 and data2 to USM device allocation//# YOUR CODE GOES HERE q.memcpy(data_device1, data1, sizeof(int) * N).wait();q.memcpy(data_device2, data2, sizeof(int) * N).wait();//# STEP 3 : Write kernel code to update data1 on device with sqrt of valueq.parallel_for(N, [=](auto i) { //# YOUR CODE GOES HERE data_device1[i] = (int)std::sqrt(float(data_device1[i]));}).wait();//# STEP 3 : Write kernel code to update data2 on device with sqrt of valueq.parallel_for(N, [=](auto i) { //# YOUR CODE GOES HERE data_device2[i] = (int)std::sqrt(float(data_device2[i]));}).wait();//# STEP 5 : Write kernel code to add data2 on device to data1q.parallel_for(N, [=](auto i) { //# YOUR CODE GOES HERE data_device1[i] += data_device2[i];}).wait();//# STEP 6 : Copy data1 on device to host//# YOUR CODE GOES HERE q.memcpy(data1, data_device1, sizeof(int) * N).wait();//# verify resultsint fail = 0;for (int i = 0; i < N; i++) if(data1[i] != 12) {fail = 1; break;}if(fail == 1) std::cout << " FAIL"; else std::cout << " PASS";std::cout << "\n";//# STEP 7 : Free USM device allocations//# YOUR CODE GOES HEREfree(data_device1, q);free(data_device2, q);free(data1);free(data2);//# STEP 8 : Add event based kernel dependency for the Steps 2 - 6return 0;
}
?運行結(jié)果
注:
?
這里可能轉(zhuǎn)成double或者什么也不轉(zhuǎn)都會報錯,我電腦對這一塊好像僅支持單精度,只能轉(zhuǎn)成float才能運行,具體原理也不理解