1. 程式人生 > >非同步記憶體、直接複製及流處理複製對比

非同步記憶體、直接複製及流處理複製對比

#include<iostream>

#include<cuda.h>
#include<cuda_runtime.h>


using namespace std;


template<const int n>
__device__ void saxpy_unrolled(
float *out,
const float *px,
const float *py,
size_t N,
float alpha
)
{
float x[n],y[n];
size_t i;
for(i=n*blockIdx.x*blockDim.x+threadIdx.x;
i<N+n*blockDim.x*gridDim.x;
i+=n*blockDim.x*gridDim.x)
{
for(int j=0;j<n;j++)
{
size_t index=i+j*blockDim.x;
if(index<N)
{
x[j]=px[index];
y[j]=py[index];
}

}
for(int j=0;j<n;j++)
{
size_t index=i+j*blockDim.x;
if(index<N) out[index]=alpha*x[j]+y[j];
}
}
}


__global__ void saxpyGPU(float *out,const float *px,const float *py,
size_t N,float alpha)
{
saxpy_unrolled<4>(out,px,py,N,alpha);
}




int main(void)
{
const size_t N=52428800;
float *dptrX,*hptrX,*dptrY,*hptrY,*dptrOut,*hptrOut;
float alpha=0.5;


//申明空間
hptrX=new float[N];
hptrY=new float[N];
hptrOut=new float[N];
cudaMalloc((void**)&dptrX,N*sizeof(float));
cudaMalloc((void**)&dptrY,N*sizeof(float));
cudaMalloc((void**)&dptrOut,N*sizeof(float));


//簡單賦值
for(size_t i=0;i<N;i++)
{
hptrX[i]=5.6;
hptrY[i]=6.5;
}


//設定執行緒
int nBlocks=2048,nThreads=256;


//宣告事件
cudaEvent_t start_sync,HtoD_sync,kernel_sync,DtoH_sync,stop_sync,
start_Async,HtoD_Async,kernel_Async,DtoH_Async,stop_Async;


//宣告耗時
float mcpy_HtoD_sync,kernelTime_sync,mcpy_DtoH_sync,total_sync,
mcpy_HtoD_Async,kernelTime_Async,mcpy_DtoH_Async,total_Async;


//建立事件
cudaEventCreate(&start_sync);
cudaEventCreate(&HtoD_sync);
cudaEventCreate(&kernel_sync);
cudaEventCreate(&DtoH_sync);
cudaEventCreate(&stop_sync);
cudaEventCreate(&start_Async);
cudaEventCreate(&HtoD_Async);
cudaEventCreate(&kernel_Async);
cudaEventCreate(&DtoH_Async);
cudaEventCreate(&stop_Async);


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//同步核心計時
cudaEventRecord(start_sync,0);
cudaMemcpy(dptrX,hptrX,N*sizeof(float),cudaMemcpyHostToDevice);
cudaMemcpy(dptrY,hptrY,N*sizeof(float),cudaMemcpyHostToDevice);
cudaEventRecord(HtoD_sync,0);
saxpyGPU<<<nBlocks,nThreads>>>(dptrOut,dptrX,dptrY,N,alpha);
cudaEventRecord(kernel_sync,0);
cudaMemcpy(hptrOut,dptrOut,N*sizeof(float),cudaMemcpyDeviceToHost);
cudaEventRecord(DtoH_sync,0);
cudaEventRecord(stop_sync,0);
cudaDeviceSynchronize();


//統計同步核心耗時
cudaEventElapsedTime(&mcpy_HtoD_sync,start_sync,HtoD_sync);
cudaEventElapsedTime(&kernelTime_sync,HtoD_sync,kernel_sync);
cudaEventElapsedTime(&mcpy_DtoH_sync,kernel_sync,DtoH_sync);
cudaEventElapsedTime(&total_sync,start_sync,stop_sync);


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//非同步核心計時
cudaEventRecord(start_Async,0);
cudaMemcpyAsync(dptrX,hptrX,N*sizeof(float),cudaMemcpyHostToDevice,NULL);
cudaMemcpyAsync(dptrY,hptrY,N*sizeof(float),cudaMemcpyHostToDevice,NULL);
cudaEventRecord(HtoD_Async,0);
saxpyGPU<<<nBlocks,nThreads>>>(dptrOut,dptrX,dptrY,N,alpha);
cudaEventRecord(kernel_Async,0);
cudaMemcpyAsync(hptrOut,dptrOut,N*sizeof(float),cudaMemcpyDeviceToHost,NULL);
cudaEventRecord(DtoH_Async,0);
cudaEventRecord(stop_Async,0);
cudaDeviceSynchronize();


//統計非同步核心耗時
cudaEventElapsedTime(&mcpy_HtoD_Async,start_Async,HtoD_Async);
cudaEventElapsedTime(&kernelTime_Async,HtoD_Async,kernel_Async);
cudaEventElapsedTime(&mcpy_DtoH_Async,kernel_Async,DtoH_Async);
cudaEventElapsedTime(&total_Async,start_Async,stop_Async);






//流的事件及事件的宣告
cudaEvent_t stream_start,stream_stop;
float total_stream;


//流的個數
const int nStream=10;
cudaStream_t streams[nStream];
size_t streamStep=N/10;
for(int i=0;i<nStream;i++)
cudaStreamCreate(&streams[i]);




//事件的建立
cudaEventCreate(&stream_start);
cudaEventCreate(&stream_stop);


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//事件的記錄
cudaEventRecord(stream_start,0);
for(int iStream=0;iStream<nStream;iStream++)
{
cudaMemcpyAsync(dptrX+iStream*streamStep,
hptrX+iStream*streamStep,
streamStep*sizeof(float),
cudaMemcpyHostToDevice,
streams[iStream]);
cudaMemcpyAsync(dptrY+iStream*streamStep,
hptrY+iStream*streamStep,
streamStep*sizeof(float),
cudaMemcpyHostToDevice,
streams[iStream]);
}


for(int iStream=0;iStream<nStream;iStream++)
{
saxpyGPU<<<nBlocks,nThreads,0,streams[iStream]>>>(
dptrOut+iStream*streamStep,
dptrX+iStream*streamStep,
dptrY+iStream*streamStep,
streamStep,
alpha);
}


for(int iStream=0;iStream<nStream;iStream++)
{
cudaMemcpyAsync(dptrOut+iStream*streamStep,
hptrOut+iStream*streamStep,
streamStep*sizeof(float),
cudaMemcpyHostToDevice,
streams[iStream]);
}


cudaEventRecord(stream_stop,0);
cudaDeviceSynchronize();

//計算流處理資料傳輸所耗時間
cudaEventElapsedTime(&total_stream,stream_start,stream_stop);




//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//用鎖頁記憶體來傳輸
float *host_alloc_X,*host_alloc_Y,*host_alloc_Out;
cudaEvent_t host_alloc_start,host_alloc_HtoD,host_alloc_DtoH,
host_alloc_kernel,host_alloc_stop;
float host_alloc_time_HtoD,host_alloc_time_Kernel,
host_alloc_time_DtoH,host_alloc_time_Total;
cudaHostAlloc((void**)&host_alloc_X,N*sizeof(float),cudaHostAllocDefault);
cudaHostAlloc((void**)&host_alloc_Y,N*sizeof(float),cudaHostAllocDefault);
cudaHostAlloc((void**)&host_alloc_Out,N*sizeof(float),cudaHostAllocDefault);
for(size_t i=0;i<N;i++)
{
host_alloc_X[i]=5.6;
host_alloc_Y[i]=6.5;
}
cudaEventCreate(&host_alloc_start);
cudaEventCreate(&host_alloc_HtoD);
cudaEventCreate(&host_alloc_DtoH);
cudaEventCreate(&host_alloc_kernel);
cudaEventCreate(&host_alloc_stop);
cudaEventRecord(host_alloc_start,0);
cudaMemcpyAsync(dptrX,host_alloc_X,N*sizeof(float),cudaMemcpyHostToDevice,NULL);
cudaMemcpyAsync(dptrY,host_alloc_Y,N*sizeof(float),cudaMemcpyHostToDevice,NULL);
cudaEventRecord(host_alloc_HtoD,0);
saxpyGPU<<<nBlocks,nThreads>>>(dptrOut,dptrX,dptrY,N,alpha);
cudaEventRecord(host_alloc_kernel,0);
cudaMemcpyAsync(hptrOut,dptrOut,N*sizeof(float),cudaMemcpyDeviceToHost,NULL);
cudaEventRecord(host_alloc_DtoH,0);
cudaEventRecord(host_alloc_stop,0);


cudaDeviceSynchronize();


cudaEventElapsedTime(&host_alloc_time_HtoD,host_alloc_start,host_alloc_HtoD);
cudaEventElapsedTime(&host_alloc_time_Kernel,host_alloc_HtoD,host_alloc_kernel);
cudaEventElapsedTime(&host_alloc_time_DtoH,host_alloc_kernel,host_alloc_DtoH);
cudaEventElapsedTime(&host_alloc_time_Total,host_alloc_start,host_alloc_stop);
cudaFreeHost(host_alloc_X);
cudaFreeHost(host_alloc_Y);
cudaFreeHost(host_alloc_Out);



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//使用零拷貝來實現
cudaEvent_t zero_start,zero_stop;
float zero_time;
float *hostX,*hostY,*hostOut,*zeroX,*zeroY,*zeroOut;
cudaHostAlloc((void**)&hostX,N*sizeof(float),cudaHostAllocWriteCombined|
cudaHostAllocMapped);
cudaHostAlloc((void**)&hostY,N*sizeof(float),cudaHostAllocWriteCombined|
cudaHostAllocMapped);
cudaHostAlloc((void**)&hostOut,N*sizeof(float),cudaHostAllocWriteCombined|
cudaHostAllocMapped);

//**************************************************************************
//這裡需要先釋放了上面的對映鎖頁記憶體,否則不能夠賦值************************
for(size_t i=0;i<N;i++)
{
hostX[i]=5.6;
hostY[i]=6.5;
//hostOut[i]=0.5;//可以不用先賦值,只需傳個指標到GPU
}
//**************************************************************************
cudaEventCreate(&zero_start);
cudaEventCreate(&zero_stop);
cudaEventRecord(zero_start,0);
cudaHostGetDevicePointer(&zeroX,hostX,0);
cudaHostGetDevicePointer(&zeroY,hostY,0);
cudaHostGetDevicePointer(&zeroOut,hostOut,0);
saxpyGPU<<<nBlocks,nThreads>>>(zeroOut,zeroX,zeroY,N,alpha);
cudaEventRecord(zero_stop,0);

cudaThreadSynchronize();
cudaEventElapsedTime(&zero_time,zero_start,zero_stop);
cudaFreeHost(hostX);
cudaFreeHost(hostY);
cudaFreeHost(hostOut);

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//使用unified memory來測試
cudaEvent_t unified_start,unified_copy,unified_kernel,unified_stop;
float unified_time_HtoD,unified_time_kernel,unified_time_DtoH,unified_time_total;
float *unifiedX,*unifiedY,*unifiedOut;
cudaMallocManaged(&unifiedX,N*sizeof(float));
cudaMallocManaged(&unifiedY,N*sizeof(float));
cudaMallocManaged(&unifiedOut,N*sizeof(float));
cudaEventCreate(&unified_start);
cudaEventCreate(&unified_copy);
cudaEventCreate(&unified_kernel);
cudaEventCreate(&unified_stop);
cudaEventRecord(unified_start,0);

for(size_t i=0;i<N;i++)
{
unifiedX[i]=hptrX[i];
unifiedY[i]=hptrY[i];
unifiedOut[i]=hptrOut[i];
}

cudaEventRecord(unified_copy,0);

saxpyGPU<<<nBlocks,nThreads>>>(unifiedOut,unifiedX,unifiedY,N,alpha);
cudaDeviceSynchronize();//一定要用這個核心函式同步語句才可以
cudaEventRecord(unified_kernel,0);
for(size_t i=0;i<N;i++)
{
hptrOut[i]=unifiedOut[i];
}
cudaEventRecord(unified_stop,0);
cudaDeviceSynchronize();
cudaEventElapsedTime(&unified_time_HtoD,unified_start,unified_copy);
cudaEventElapsedTime(&unified_time_kernel,unified_copy,unified_kernel);
cudaEventElapsedTime(&unified_time_DtoH,unified_kernel,unified_stop);
cudaEventElapsedTime(&unified_time_total,unified_start,unified_stop);

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//顯示同步核心耗時
cout<<"cudaMemcpy processing..."<<endl;
cout<<"Memcpy(host->device):"<<mcpy_HtoD_sync<<"ms"<<endl;
cout<<"Kernel processing:"<<kernelTime_sync<<"ms"<<endl;
cout<<"Memcpy(device->host):"<<mcpy_DtoH_sync<<"ms"<<endl;
cout<<"Total time:"<<total_sync<<"ms"<<endl;


//顯示非同步核心耗時
cout<<endl<<"cudaMemcpyAsync processing..."<<endl;
cout<<"Memcpy(host->device):"<<mcpy_HtoD_Async<<"ms"<<endl;
cout<<"Kernel processing:"<<kernelTime_Async<<"ms"<<endl;
cout<<"Memcpy(device->host):"<<mcpy_DtoH_Async<<"ms"<<endl;
cout<<"Total time:"<<total_Async<<"ms"<<endl;


//顯示流處理所耗時
cout<<endl<<"Stream processing..."<<endl;
cout<<"Total time:"<<total_stream<<"ms"<<endl;


//顯示對映鎖頁記憶體耗時
cout<<endl<<"cudaHostAlloc processing..."<<endl;
cout<<"Memcpy(host->device):"<<host_alloc_time_HtoD<<"ms"<<endl;
cout<<"Kernel processing:"<<host_alloc_time_Kernel<<"ms"<<endl;
cout<<"Memcpy(device->host):"<<host_alloc_time_DtoH<<"ms"<<endl;
cout<<"Total time:"<<host_alloc_time_Total<<"ms"<<endl;


//顯示零拷貝耗時
cout<<endl<<"zeroCopy processing..."<<endl;
cout<<"Total time:"<<zero_time<<endl;


//顯示unified memory耗時
cout<<endl<<"unified memory processing..."<<endl;
cout<<"Memcpy(host->device):"<<unified_time_HtoD<<"ms"<<endl;
cout<<"Kernel processing:"<<unified_time_kernel<<"ms"<<endl;
cout<<"Memcpy(device->host):"<<unified_time_DtoH<<"ms"<<endl;
cout<<"Total time:"<<unified_time_total<<"ms"<<endl;

return 0;
}




相關推薦

非同步記憶體直接複製處理複製對比

#include<iostream> #include<cuda.h> #include<cuda_runtime.h> using namespace std; template<const int n> __device_

【Java筆記】IO中檔案複製異常處理

import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Main

Android中記憶體內部儲存外部儲存的區別

我們在做專案的過程中,經常有新來的同學問我們手機是什麼配置的? 我們經常說3+32GB 或者3+64GB。這些數字又都是指的什麼?現在總結如下: 對於Android來說,我們把儲存主要分為三個部分:記憶體、內部儲存以及外部儲存。我們可以跟PC想比較來認識這三個部分。 (1

Linux下搭建實現HttpRunnerManager的非同步執行定時任務任務監控

前言 在之前搭建的HttpRunnerManager介面測試平臺,我們還有一些功能沒有實現,比如非同步執行、定時任務、任務監控等,要完成非同步執行,需要搭建 RabbitMQ 等環境,今天我們就來實現這些功能。 需要在Linux上提前準備的環境(下面是本人搭建時的環境): 1,HttpRunnerManag

處理框架對比

分散式流處理是對無邊界資料集進行連續不斷的處理、聚合和分析的過程,與MapReduce一樣是一種通用計算框架,期望延遲在毫秒或者秒級別。這類系統一般採用有向無環圖(DAG)。DAG是任務鏈的圖形化表示,用它來描述流處理作業的拓撲。在選擇不同的流處理系統時,通常會關注以下幾點: 執行時和程式設

DijkstraBellman-FordSpfa演算法思想對比

Dijkstra dijkstra演算法本質上算是貪心的思想,每次在剩餘節點中找到離起點最近的節點放到佇列中,並用來更新剩下的節點的距離,再將它標記上表示已經找到到它的最短路徑,以後不用更新它了。這樣做的原因是到一個節點的最短路徑必然會經過比它離起點更近的節點

處理bat實現建立複製刪除檔案資料夾

1 建bat檔案自動執行復制,刪除命令。  例1:以下是複製cd.dll檔案至windows\system32的bat檔案內容:          copy cd.dll %windir%\system32     例2:下面一行是解除安裝windows\system32

MySQL主備複製原理實現異常處理

複製概述 MySQL支援三種複製方式:基於行(Row)的複製、基於語句(Statement)的複製和混合型別(Mixed)的複製。 基於語句的複製早在3.23版本中就存在,而基於行的複製方式在5.1版本中才被加進來。這兩種方式都是通過在主庫上記錄二進位制日誌

Java虛擬機器自動記憶體管理機制物件建立記憶體分配

  1、物件是如何建立: 步驟:    (1)、虛擬機器遇到new <類名>的指令---->根據new的引數是否在常量池中定位一個類的符號引用    (2)、檢測該符號引用代表的類是否已經被載入、解析、和初始化。(如果沒有則

裝置IO之一(mmap直接IO以及非同步IO)

現在,在linux中經常可以看到在使用者空間編寫的驅動程式,比如X伺服器,一些廠商的私有驅動等等,這就意味著使用者空間取得了對硬體的訪問能力,這通常是通過mmap將裝置記憶體對映到了使用者程序空間,從而使得使用者可以通過讀寫這些記憶體來獲取對硬體的訪問能力。 核心一般會對I/O操作進行緩衝以獲取

ThreadLocal原理使用場景存在記憶體洩漏的原因

什麼是執行緒封閉 當多執行緒訪問共享變數時,往往需要加鎖來保證共享變數的執行緒安全(資料同步)。一種避免使用加鎖方式就是不共享資料,而是讓執行緒獨享資料。由於資料本身就是執行緒私有的,這樣,如果僅在單執行緒內訪問資料就不需要同步,這種避免共享資料的技術稱為執行緒封閉。在Java語言中,提供了一些

**萬能的“一鍵複製到剪貼簿”,支援IE火狐谷歌移動版瀏覽器**

說到點選按鈕“複製到剪貼簿",大家都可能用過,但是之前的實現方不是隻支援某些瀏覽器,就是要在網頁內嵌swf(Flash)檔案。 這兩種方法:第一種不能很好的相容多數瀏覽器,第二種方式下開發人員可能會擔心Flash的安全性問題。 現在出現了一種新的實現方式:clipboard

關於linux複製刪除移動檔案資料夾

新建:         新建資料夾使用:mkdir命令,mkdir是“make directory”的縮寫詞。         mkdir是一個用來在linux系統下建立目錄的命令,此命令屬於內建命令。

flume高階配置——資料複製分流負載均衡故障轉移

一、在前面幾篇文章中介紹過幾種常見的flume pipeline 場景。我們在回顧一下,主要有一下幾種: 1、多個 agent 順序連線: 可以將多個Agent順序連線起來,將最初的資料來源經過收集,儲存到最終的儲存系統中。這是最簡單的情況,一般情況下,應該控制這種順

℃江的觀後感 -- Java 虛擬機器的方法區直接記憶體和執行時常量池

方法區 我們知道方法區,當然是和方法有關,Java虛擬機器的作用就兩個,儲存、運算。其實我們叫其方法區,說明和儲存東西有關,但是存什麼呢?這塊儲存的是虛擬機器載入的類資訊,常亮,靜態變數和有個就是即使編譯後的程式碼等資料。方法區一般在hotspot被稱為永久代

程序執行緒共享記憶體學習筆記

程序:計算機上每個執行的活動,執行一個可執行程式是一個程序,開啟一個軟體是一個程序,開啟一個終端是一個程序等等。 多程序:為了充分利用計算機資源產生了多程序的執行方式。通俗來講就是在同一時間做多個事情,從而可以充分利用計算機資源還可以提高程式的執行效率。在建立一個新的子程序後,子程序會會獲得計算機分配的資源

javaSE (三十三)其他(序列記憶體輸出隨機訪問物件操作資料輸入輸出列印標準輸入輸出properties)

1、序列流(SequenceInputStream ): 序列流主要的作用就是整合位元組輸入流,將很多的進口整合成一個 這裡著重講一下多於兩個輸入流的整合: 步驟: 建立三個輸入流 建立vector集合存入這些輸入流 將這些輸入流變成列舉型別 Vector.e

寫程式碼實現棧溢位堆溢位永久代溢位直接記憶體溢位

棧溢位(StackOverflowError) 堆溢位(OutOfMemoryError:Java heap space) 永久代溢位(OutOfMemoryError: PermGen space) 直接記憶體溢位 一、堆溢位 建立物件時如果沒有可以分配的堆記憶體,

小視訊APP開發中關於儲存廣告位官方通知的一些短視訊原始碼處理

短視訊作為時下粉絲經濟中最匯聚流量的內容傳播方式,吸引著一大批資本家的投資熱情,短視訊系統開發正處在移動網際網路的風口之中。面對短視訊行業的發展機遇短視訊系統也在不斷更新,下面就為大家介紹一下小視訊APP開發中的儲存方式、廣告位及官方通知的一些程式碼。 一、小視訊APP開發的儲存形式方式 以

學習筆記 --- JVM 堆溢位棧溢位永久代溢位直接記憶體溢位

棧溢位(StackOverflowError)           ---    遞迴引起  棧空間不足      ---   執行緒請求的棧