Adding new unroll example (#1187)

[ROCm/clr commit: 3cb87cdc46]
Bu işleme şunda yer alıyor:
Jatin Chaudhary
2019-07-03 14:21:19 +05:30
işlemeyi yapan: Maneesh Gupta
ebeveyn 8b74b0e2b2
işleme db5f404b5c
2 değiştirilmiş dosya ile 64 ekleme ve 68 silme
+5 -7
Dosyayı Görüntüle
@@ -16,17 +16,15 @@ Programmers familiar with CUDA, OpenCL will be able to quickly learn and start c
## Simple Matrix Transpose ## Simple Matrix Transpose
For this tutorial we will be using MatrixTranspose with shfl operation i.e., our 4_shfl tutorial since it is the only examples where we used loops inside the kernel. For this tutorial we will be using an example which sums up the row of a 2D matrix and writes it in a 1D array.
In this tutorial, we'll use `#pragma unroll`. In the same sourcecode, we used for MatrixTranspose. We'll add it just before the for loop as following: In this tutorial, we'll use `#pragma unroll`. In the same sourcecode, we used for gpuMatrixRowSum. We'll add it just before the for loop as following:
``` ```
#pragma unroll #pragma unroll
for(int i=0;i<width;i++) for (int i = 0; i < width; i++) {
{ output[index] += input[index * width + i]
for(int j=0;j<width;j++) }
out[i*width + j] = __shfl(val,j*width + i);
}
``` ```
Specifying the optional parameter, #pragma unroll value, directs the unroller to unroll the loop value times. Be careful while using it. Specifying the optional parameter, #pragma unroll value, directs the unroller to unroll the loop value times. Be careful while using it.
+59 -61
Dosyayı Görüntüle
@@ -25,100 +25,98 @@ THE SOFTWARE.
// hip header file // hip header file
#include "hip/hip_runtime.h" #include "hip/hip_runtime.h"
#define LENGTH 4
#define WIDTH 4 #define SIZE (LENGTH * LENGTH)
#define NUM (WIDTH * WIDTH) #define THREADS_PER_BLOCK 1
#define BLOCKS_PER_GRID LENGTH
#define THREADS_PER_BLOCK_X 4 // CPU function - basically scan each row and save the output in array
#define THREADS_PER_BLOCK_Y 4 void matrixRowSum(int* input, int* output, int width) {
#define THREADS_PER_BLOCK_Z 1
// Device (Kernel) function, it must be void
__global__ void matrixTranspose(float* out, float* in, const int width) {
int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x;
float val = in[x];
#pragma unroll
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
for (int j = 0; j < width; j++) out[i * width + j] = __shfl(val, j * width + i); for (int j = 0; j < width; j++) {
} output[i] += input[i * width + j];
}
// CPU implementation of matrix transpose
void matrixTransposeCPUReference(float* output, float* input, const unsigned int width) {
for (unsigned int j = 0; j < width; j++) {
for (unsigned int i = 0; i < width; i++) {
output[i * width + j] = input[j * width + i];
} }
} }
} }
int main() { // Device (kernel) function
float* Matrix; __global__ void gpuMatrixRowSum(int* input, int* output, int width) {
float* TransposeMatrix; int index = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x;
float* cpuTransposeMatrix; #pragma unroll
for (int i = 0; i < width; i++) {
output[index] += input[index * width + i];
}
}
float* gpuMatrix; int main() {
float* gpuTransposeMatrix; int* Matrix;
int* sumMatrix;
int* cpuSumMatrix;
int* gpuMatrix;
int* gpuSumMatrix;
hipDeviceProp_t devProp; hipDeviceProp_t devProp;
hipGetDeviceProperties(&devProp, 0); hipGetDeviceProperties(&devProp, 0);
std::cout << "Device name " << devProp.name << std::endl; std::cout << "Device name " << devProp.name << std::endl;
int i; Matrix = (int*)malloc(sizeof(int) * SIZE);
int errors; sumMatrix = (int*)malloc(sizeof(int) * LENGTH);
cpuSumMatrix = (int*)malloc(sizeof(int) * LENGTH);
Matrix = (float*)malloc(NUM * sizeof(float)); for (int i = 0; i < SIZE; i++) {
TransposeMatrix = (float*)malloc(NUM * sizeof(float)); Matrix[i] = i * 2;
cpuTransposeMatrix = (float*)malloc(NUM * sizeof(float));
// initialize the input data
for (i = 0; i < NUM; i++) {
Matrix[i] = (float)i * 10.0f;
} }
// allocate the memory on the device side for (int i = 0; i < LENGTH; i++) {
hipMalloc((void**)&gpuMatrix, NUM * sizeof(float)); cpuSumMatrix[i] = 0;
hipMalloc((void**)&gpuTransposeMatrix, NUM * sizeof(float)); }
// Memory transfer from host to device // Allocated Device Memory
hipMemcpy(gpuMatrix, Matrix, NUM * sizeof(float), hipMemcpyHostToDevice); hipMalloc((void**)&gpuMatrix, SIZE * sizeof(int));
hipMalloc((void**)&gpuSumMatrix, LENGTH * sizeof(int));
// Lauching kernel from host // Memory Copy to Device
hipLaunchKernelGGL(matrixTranspose, dim3(1), dim3(THREADS_PER_BLOCK_X * THREADS_PER_BLOCK_Y), 0, 0, hipMemcpy(gpuMatrix, Matrix, SIZE * sizeof(int), hipMemcpyHostToDevice);
gpuTransposeMatrix, gpuMatrix, WIDTH); hipMemcpy(gpuSumMatrix, cpuSumMatrix, LENGTH * sizeof(float), hipMemcpyHostToDevice);
// Memory transfer from device to host // Launch device kernels
hipMemcpy(TransposeMatrix, gpuTransposeMatrix, NUM * sizeof(float), hipMemcpyDeviceToHost); hipLaunchKernelGGL(gpuMatrixRowSum, dim3(BLOCKS_PER_GRID), dim3(THREADS_PER_BLOCK), 0, 0,
gpuMatrix, gpuSumMatrix, LENGTH);
// Memory copy back to device
hipMemcpy(sumMatrix, gpuSumMatrix, LENGTH * sizeof(int), hipMemcpyDeviceToHost);
// Cpu implementation
matrixRowSum(Matrix, cpuSumMatrix, LENGTH);
// CPU MatrixTranspose computation
matrixTransposeCPUReference(cpuTransposeMatrix, Matrix, WIDTH);
// verify the results // verify the results
errors = 0; int errors = 0;
double eps = 1.0E-6; for (int i = 0; i < LENGTH; i++) {
for (i = 0; i < NUM; i++) { if (sumMatrix[i] != cpuSumMatrix[i]) {
if (std::abs(TransposeMatrix[i] - cpuTransposeMatrix[i]) > eps) { printf("%d - cpu: %d gpu: %d\n", i, sumMatrix[i], cpuSumMatrix[i]);
printf("%d cpu: %f gpu %f\n", i, cpuTransposeMatrix[i], TransposeMatrix[i]);
errors++; errors++;
} }
} }
if (errors != 0) {
printf("FAILED: %d errors\n", errors); if (errors == 0) {
printf("PASSED\n");
} else { } else {
printf("PASSED!\n"); printf("FAILED with %d errors\n", errors);
} }
// free the resources on device side // GPU Free
hipFree(gpuMatrix); hipFree(gpuMatrix);
hipFree(gpuTransposeMatrix); hipFree(gpuSumMatrix);
// free the resources on host side // CPU Free
free(Matrix); free(Matrix);
free(TransposeMatrix); free(sumMatrix);
free(cpuTransposeMatrix); free(cpuSumMatrix);
return errors; return errors;
} }