# Analyzing GPU Performance in Virtualized Environments: A Case Study
## 5 Use Cases
### GVT-g Scheduling  
In this case study, we use our framework to examine the internal mechanics of the GVT-g scheduler, as its operations may impact the performance of GPU virtualization solutions. Specifically, GVT-g uses a kernel thread named _gvt_service_thr_ and multiple additional threads, which are referred to as _workloads thread X_, where \"X\" represents a specific engine supported by the pGPU, such as render or video command streamers. The _gvt_service_thr_ is responsible for managing vGPU scheduling and context switching, and the _workloads thread X_ threads are initiated when a vGPU is activated. These threads concurrently monitor the waiting queue, facilitating the transfer of GPU requests to the host GPU driver, as depicted in Figure 5.  
Figure 5: Time-graph view illustrating the wait times of GPU requests in GVT-g and host driver queues, as well as their respective execution times. It also shows how the scheduler defers the execution of vGPU1 requests to the next period when its allocated time slice is exhausted. \begin{table}
\begin{tabular}{l l l l} \hline \hline
**Host Machine** & \multicolumn{3}{l}{**Virtual Machine**} \\ \hline CPU & Intel Core i7-7500U @2.70 GHz & vCPU & 2 \\ GPU & HD Graphics 620 & vGPU Mem. & Low: 64 MB/High: 384 MB \\ RAM & 16 GB & RAM & 4 GB \\ OS & Ubuntu 16.04 (Kernel 4.14.15) & OS & Ubuntu 16.04 (Kernel 4.15) \\ Qemu & v2.11.1 & & \\ LTTng & v2.10.8 & & \\ \hline \hline \end{tabular}
\end{table} 
Table 3: Experimental configurations of the hardware and software. Our initial experiment involved two GPU-accelerated virtual machines (VM1 and VM2) sharing a single pGPU via GVT-g, with each VM hosting a similarly configured vGPU and equal resource allocation weights. These weights, assigned by GVT-g at instantiation, determine each vGPU's share of pGPU resources. We executed a series of benchmarks from the Rodinia GPU benchmark suite [43] on VM1. We repeated these benchmarks after completely shutting down VM2. Figure 6 presents histograms comparing the benchmarks' execution times in both scenarios. Notably, the benchmarks executed slower when VM2 was idle than when it was shut down, with significant time discrepancies in the Gaussian, Lud, and Heartwall benchmarks. This study considered a VM idle if it did not engage in significant GPU workloads. To investigate the performance difference, we analyzed the execution of the Gaussian benchmark on VM1 using our framework. Figure 7 illustrates the benchmark's execution duration and GPU utilization. Initially, the benchmark lasted 59 s with an average GPU utilization of about 45%. In contrast, after shutting down VM2, the benchmark was completed in 27 s with a GPU utilization near 80%. This comparison highlights the performance impact of VM2's concurrent operation, despite it being inactive. Further examination of the GVT-g scheduler's operations revealed its reliance on time multiplexing for fair pGPU resource distribution among vGPUs. The scheduler, which was operated via the _gvt_service_thr_ thread, simultaneously managed all of the GPU engines to minimize scheduling complexity and avoid synchronization bottlenecks. It assigned time slices to vGPUs based on their weights, deducting the aggregate execution time of a vGPU's requests from its time slice (see the formula below). If a vGPU depletes its time slice within a certain interval (100 ms), the scheduler suspends its operations, recalibrating time slices every ten intervals (one second) and ignoring past debts or credits. **Example 1**. : _Let us consider two vGPUs sharing the host GPU's resources, and each is assigned an identical weight. In this scenario, the GVT-g scheduler assigns each vGPU a 50 ms time slice per period. If one vGPU is removed, the remaining one receives the entire 100 ms time slice per period, fully utilizing the available resources._  
The GVT-g scheduler follows a round-robin policy, cycling every 1 millisecond to inspect vGPU queues for new requests.