Modern scientific computing focuses on developing applications using GPUs because of the rapid growth in computing power, and drop in the price of massively parallel accelerators. The abundant data parallelism available in many-core GPUs has been a key interest to improve accuracy in scientific and engineering simulation. Modern GPUs use multiple streaming multiprocessors (SMs) with potentially thousands of cores, fast context switching, and high memory bandwidth to tolerate ever-increasing latencies to main memory by overlapping long-latency loads in stalled threads with useful computation in other threads. The Compute Unified Device Architecture (CUDA) is a simple C-like interface proposed for programming NVIDIA GPUs. However, porting applications to CUDA remains a challenge to average programmers. CUDA places on the programmer the burden of packaging GPU code in separate functions, of explicitly managing data transfer between the host and GPU memories, and of manually optimizing the utilization of the GPU memory. Hence, the pre-condition in efficient utilization of the GPU resources is a comprehensive understanding of the underlying architecture, and the 3 exertion of complex kernel optimizations.