Skip to content

Commit 1316f97

Browse files
authored
FPGA: Factor out the QRD function in a common include folder and create a QRI reference design (oneapi-src#847)
* Extended input matrix sizes support (from 4x4 to 512x512) and extending the testing of the results Signed-off-by: Yohann Uguen <[email protected]> * adjusting bit size of j loop index to work with sizes 8x8 to 32x32 Signed-off-by: Yohann Uguen <[email protected]> * Improve QRDecomposition function description Signed-off-by: Yohann Uguen <[email protected]> * Adding comment to the constexprs in the QRDecomposition function Signed-off-by: Yohann Uguen <[email protected]> * Improving comments of the main computation loop Signed-off-by: Yohann Uguen <[email protected]> * Improving comments for the control flow of the matrix writing Signed-off-by: Yohann Uguen <[email protected]> * Improve the comments of the loop that stores the computed values to the output buffer Signed-off-by: Yohann Uguen <[email protected]> * replacing deprecated fp-relaxed with ffp-reassociate Signed-off-by: Yohann Uguen <[email protected]> * Formatting Signed-off-by: Yohann Uguen <[email protected]> * Reverting the ffp-reassociate to fp-relaxed + Removing the use of ternary assignement to reach II 1 again Signed-off-by: Yohann Uguen <[email protected]> * Updating the unroller to support constexpr loop indexes Signed-off-by: Yohann Uguen <[email protected]> * Reduce the bit size of memory indexes and use of constexpr inside loops Signed-off-by: Yohann Uguen <[email protected]> * Remanings + reducing datapath width in load and store iteration selectors Signed-off-by: Yohann Uguen <[email protected]> * Making the input matrix use ac_complex instead of a series of values Signed-off-by: Yohann Uguen <[email protected]> * Use of ac_complex for the output matrices Signed-off-by: Yohann Uguen <[email protected]> * Templated the QRD function Signed-off-by: Yohann Uguen <[email protected]> * Added the option to control the matrix size using env variables + reworking the dummy iterations of the main computation loop Signed-off-by: Yohann Uguen <[email protected]> * Adding non-complex floating-point support Signed-off-by: Yohann Uguen <[email protected]> * Achieving II 1 for small sizes and non complex datatype Signed-off-by: Yohann Uguen <[email protected]> * Improving comments and formating Signed-off-by: Yohann Uguen <[email protected]> * Cleaning debug prints Signed-off-by: Yohann Uguen <[email protected]> * updating README Signed-off-by: Yohann Uguen <[email protected]> * restoring original stdout Signed-off-by: Yohann Uguen <[email protected]> * restoring rectangular matrix support Signed-off-by: Yohann Uguen <[email protected]> * fixing read index for rectangular matrices Signed-off-by: Yohann Uguen <[email protected]> * testing fmax increase Signed-off-by: Yohann Uguen <[email protected]> * changing a_compute memory representation Signed-off-by: Yohann Uguen <[email protected]> * Removing custom complexes Signed-off-by: Yohann Uguen <[email protected]> * removing debug information Signed-off-by: Yohann Uguen <[email protected]> * restored original memory structure for A_compute and moved to a systolic approach for loading/storing to DDR Signed-off-by: Yohann Uguen <[email protected]> * storing a matrices row wise for fmax test Signed-off-by: Yohann Uguen <[email protected]> * Adding registers to inputs of the dot product in an attemp to increase fmax Signed-off-by: Yohann Uguen <[email protected]> * fixing syntax error Signed-off-by: Yohann Uguen <[email protected]> * testing fmax and throughput of column wise memories Signed-off-by: Yohann Uguen <[email protected]> * non systolic mem read + column wise + col1 Signed-off-by: Yohann Uguen <[email protected]> * QR Inversion WIP Signed-off-by: Yohann Uguen <[email protected]> * Improving memory structure Signed-off-by: Yohann Uguen <[email protected]> * updating sample.json from qrd to qri Signed-off-by: Yohann Uguen <[email protected]> * Adding complex support to QRI Signed-off-by: Yohann Uguen <[email protected]> * improving memory structure and accesses Signed-off-by: Yohann Uguen <[email protected]> * simplifying communications between kernels Signed-off-by: Yohann Uguen <[email protected]> * changing memory attributes Signed-off-by: Yohann Uguen <[email protected]> * removed unused variables and duplicated memory kernels for reads multiple (and non-multiple) of DDR reads/writes Signed-off-by: Yohann Uguen <[email protected]> * updating cmake Signed-off-by: Yohann Uguen <[email protected]> * updating include names Signed-off-by: Yohann Uguen <[email protected]> * refactoring the QRD IP to use the streaming kernel headers Signed-off-by: Yohann Uguen <[email protected]> * updating CMake default values and removing debug statements Signed-off-by: Yohann Uguen <[email protected]> * cleaning demo file Signed-off-by: Yohann Uguen <[email protected]> * Removed using namespaces Signed-off-by: Yohann Uguen <[email protected]> * Fixing rectangular matrix support Signed-off-by: Yohann Uguen <[email protected]> * Increasing pipes depth and fixing the II issue on 4x4 Signed-off-by: Yohann Uguen <[email protected]> * adding support for chunk of matrices to be processed per iteration Signed-off-by: Yohann Uguen <[email protected]> * Comments to the MemoryTransfers file Signed-off-by: Yohann Uguen <[email protected]> * adding many comments Signed-off-by: Yohann Uguen <[email protected]> * commenting the qrd_demo file + removing the qrd.cpp file Signed-off-by: Yohann Uguen <[email protected]> * removing qri.cpp and updating cmake Signed-off-by: Yohann Uguen <[email protected]> * change the warmup matrix count to avoid assertion Signed-off-by: Yohann Uguen <[email protected]> * cleaning qri Signed-off-by: Yohann Uguen <[email protected]> * factorizing code between qrd and qri Signed-off-by: Yohann Uguen <[email protected]> * pipes with read/writes of single elements Signed-off-by: Yohann Uguen <[email protected]> * pipe transactions of the same size as DDR bursts Signed-off-by: Yohann Uguen <[email protected]> * supporting rectangular and non multiple of DDR burst size sizes of matrices Signed-off-by: Yohann Uguen <[email protected]> * Cleaning QRD Signed-off-by: Yohann Uguen <[email protected]> * Using small pipes Signed-off-by: Yohann Uguen <[email protected]> * QRI II1 S10 and Agilex Signed-off-by: Yohann Uguen <[email protected]> * changing default matrix number to run on HW Signed-off-by: Yohann Uguen <[email protected]> * QRD now uses USM and functors Signed-off-by: Yohann Uguen <[email protected]> * QRI now uses USM and functors Signed-off-by: Yohann Uguen <[email protected]> * fixing the USM pointers being passed as a 1-D array to the kernels making the compiler fail when generating the reports Signed-off-by: Yohann Uguen <[email protected]> * updating CMake to main and naming qrd and qri kernels Signed-off-by: Yohann Uguen <[email protected]> * updating cmake for windows Signed-off-by: Yohann Uguen <[email protected]> * updating MSVS files Signed-off-by: Yohann Uguen <[email protected]> * Fixing the MSVS config file to work with the include folder Signed-off-by: Yohann Uguen <[email protected]> * updating readmes and sample.json files to match main Signed-off-by: Yohann Uguen <[email protected]> * removing trailing whitespaces Signed-off-by: Yohann Uguen <[email protected]> * updating MSVS files Signed-off-by: Yohann Uguen <[email protected]> * setting compiler version to 2022 in MSVS config files Signed-off-by: Yohann Uguen <[email protected]> * running clang-format Signed-off-by: Yohann Uguen <[email protected]> * adding format security to cmake files Signed-off-by: Yohann Uguen <[email protected]> * adhering to the oneAPI code samples casing guidelines Signed-off-by: Yohann Uguen <[email protected]> * Porting PR oneapi-src#817 Signed-off-by: Yohann Uguen <[email protected]> * Removing block comments Signed-off-by: Yohann Uguen <[email protected]> * Using fp-model=precise rather than fno-fast-math Signed-off-by: Yohann Uguen <[email protected]> * increasing the number of private copies to see how it affects the throughput Signed-off-by: Yohann Uguen <[email protected]> * transfering R one element at the time and using private copies attributes Signed-off-by: Yohann Uguen <[email protected]> * addressing PR comments Signed-off-by: Yohann Uguen <[email protected]> * updating RAW latencies and cleaning up the qrd kernel Signed-off-by: Yohann Uguen <[email protected]> * removing reference to DDR in streaming_qrd/qri.hpp Signed-off-by: Yohann Uguen <[email protected]> * qrd 32 32 real throughput test Signed-off-by: Yohann Uguen <[email protected]> * vector transfer kernel rework Signed-off-by: Yohann Uguen <[email protected]> * memory transfers cleanup Signed-off-by: Yohann Uguen <[email protected]> * re-transfering R by bursts Signed-off-by: Yohann Uguen <[email protected]> * R single elem transfer, larger pipe Signed-off-by: Yohann Uguen <[email protected]> * qrd removing unneeded kernel waits Signed-off-by: Yohann Uguen <[email protected]> * Events double buffering Signed-off-by: Yohann Uguen <[email protected]> * QRD test throughput by copying a single matrix and repeat the decomposition many times Signed-off-by: Yohann Uguen <[email protected]> * R matrix from dual pumped to single pumped Signed-off-by: Yohann Uguen <[email protected]> * QRD computes 8 matrices Signed-off-by: Yohann Uguen <[email protected]> * QRI computes 8 matrices Signed-off-by: Yohann Uguen <[email protected]> * QRD 32x32 throughput test Signed-off-by: Yohann Uguen <[email protected]> * qrd default to 128x128 Signed-off-by: Yohann Uguen <[email protected]> * updating default number of matrices to run for the QRD and QRI Signed-off-by: Yohann Uguen <[email protected]> * QRI readme update Signed-off-by: Yohann Uguen <[email protected]> * updating qrd readme Signed-off-by: Yohann Uguen <[email protected]> * updating QRI readme with the correct kernel names Signed-off-by: Yohann Uguen <[email protected]> * removing memory_transfers from the common include directory Signed-off-by: Yohann Uguen <[email protected]> * cleanup and update of best seeds Signed-off-by: Yohann Uguen <[email protected]> * update include readme Signed-off-by: Yohann Uguen <[email protected]> * removing utils.hpp by using tuples and correcting readmes Signed-off-by: Yohann Uguen <[email protected]> * adding namespaces Signed-off-by: Yohann Uguen <[email protected]> * naming convention + upgrading cmake requirement for qri Signed-off-by: Yohann Uguen <[email protected]> * updating cmake for qri and changing QRI kernel name Signed-off-by: Yohann Uguen <[email protected]> * Adding actypes flag to link stage on windows Signed-off-by: Yohann Uguen <[email protected]> Co-authored-by: Yohann Uguen <[email protected]>
1 parent 5783661 commit 1316f97

26 files changed

+3828
-1048
lines changed

DirectProgramming/DPC++FPGA/ReferenceDesigns/qrd/README.md

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# QR Decomposition of Matrices
2-
This DPC++ reference design demonstrates high performance QR decomposition of complex matrices on FPGA.
2+
This DPC++ reference design demonstrates high performance QR decomposition of complex/real matrices on FPGA.
33

44
***Documentation***: The [DPC++ FPGA Code Samples Guide](https://software.intel.com/content/www/us/en/develop/articles/explore-dpcpp-through-intel-fpga-code-samples.html) helps you to navigate the samples and build your knowledge of DPC++ for FPGA. <br>
55
The [oneAPI DPC++ FPGA Optimization Guide](https://software.intel.com/content/www/us/en/develop/documentation/oneapi-fpga-optimization-guide) is the reference manual for targeting FPGAs through DPC++. <br>
@@ -21,13 +21,13 @@ Please refer to the performance disclaimer at the end of this README.
2121

2222
| Device | Throughput
2323
|:--- |:---
24-
| Intel® PAC with Intel Arria® 10 GX FPGA | 24.5k matrices/s for matrices of size 128 * 128
25-
| Intel® FPGA PAC D5005 (with Intel Stratix® 10 SX) | 7k matrices/s for matrices of size 256 * 256
24+
| Intel® PAC with Intel Arria® 10 GX FPGA | 24k matrices/s for complex matrices of size 128 * 128
25+
| Intel® FPGA PAC D5005 (with Intel Stratix® 10 SX) | 7k matrices/s for complex matrices of size 256 * 256
2626

2727

2828
## Purpose
2929

30-
This FPGA reference design demonstrates QR decomposition of matrices of complex numbers, a common operation employed in linear algebra. Matrix _A_ (input) is decomposed into a product of an orthogonal matrix _Q_ and an upper triangular matrix _R_.
30+
This FPGA reference design demonstrates QR decomposition of matrices of complex/real numbers, a common operation employed in linear algebra. Matrix _A_ (input) is decomposed into a product of an orthogonal matrix _Q_ and an upper triangular matrix _R_.
3131

3232
The algorithms employed by the reference design are the Gram-Schmidt QR decomposition algorithm and the thin QR factorization method. Background information on these algorithms can be found in Wikipedia's [QR decomposition](https://en.wikipedia.org/wiki/QR_decomposition) article. The original algorithm has been modified and optimized for performance on FPGAs in this implementation.
3333

@@ -36,14 +36,13 @@ QR decomposition is used extensively in signal processing applications such as b
3636

3737
### Matrix dimensions and FPGA resources
3838

39-
The QR decomposition algorithm factors a complex _m_×_n_ matrix, where _m__n_. The algorithm computes the vector dot product of two columns of the matrix. In our FPGA implementation, the dot product is computed in a loop over the column's _m_ elements. The loop is fully unrolled to maximize throughput. As a result, *m* complex multiplication operations are performed in parallel on the FPGA, followed by sequential additions to compute the dot product result.
39+
The QR decomposition algorithm factors a complex _m_ × _n_ matrix, where _m__n_. The algorithm computes the vector dot product of two columns of the matrix. In our FPGA implementation, the dot product is computed in a loop over the column's _m_ elements. The loop is fully unrolled to maximize throughput. As a result, *m* complex multiplication operations are performed in parallel on the FPGA, followed by sequential additions to compute the dot product result.
4040

4141
We use the compiler flag `-fp-relaxed`, which permits the compiler to reorder floating point additions (i.e. to assume that floating point addition is commutative). The compiler uses this freedom to reorder the additions so that the dot product arithmetic can be optimally implemented using the FPGA's specialized floating point DSP (Digital Signal Processing) hardware.
4242

43-
With this optimization, our FPGA implementation requires 4*m* DSPs to compute the complex floating point dot product. Thus, the matrix size is constrained by the total FPGA DSP resources available. Note that this upper bound is a consequence of this particular implementation.
44-
45-
By default, the design is parameterized to process 128 × 128 matrices when compiled targeting Intel® PAC with Intel Arria® 10 GX FPGA. It is parameterized to process 256 × 256 matrices when compiled targeting Intel® FPGA PAC D5005 (with Intel Stratix® 10 SX), a larger device.
43+
With this optimization, our FPGA implementation requires 4*_m_ DSPs to compute the complex floating point dot product or 2*m* DSPs for the real case. Thus, the matrix size is constrained by the total FPGA DSP resources available.
4644

45+
By default, the design is parameterized to process 128 × 128 matrices when compiled targeting Intel® PAC with Intel Arria® 10 GX FPGA. It is parameterized to process 256 × 256 matrices when compiled targeting Intel® FPGA PAC D5005 (with Intel Stratix® 10 SX), a larger device. However, the design can process matrices from 4 x 4 to 512 x 512.
4746

4847
## Key Implementation Details
4948
| Kernel | Description
@@ -57,7 +56,7 @@ To optimize the performance-critical loop in its algorithm, the design leverages
5756
* **Unrolling Loops** (loop_unroll)
5857

5958
The key optimization techniques used are as follows:
60-
1. Refactoring the algorithm to merge two dot products into one, reducing the total number of dot products needed to three from two. This helps us reduce the DSPs required for the implementation.
59+
1. Refactoring the original Gram-Schmidt algorithm to merge two dot products into one, reducing the total number of dot products needed to three from two. This helps us reduce the DSPs required for the implementation.
6160
2. Converting the nested loop into a single merged loop and applying Triangular Loop optimizations. This allows us to generate a design that is very well pipelined.
6261
3. Fully vectorizing the dot products using loop unrolling.
6362
4. Using the compiler flag -Xsfp-relaxed to re-order floating point operations and allowing the inference of a specialised dot-product DSP. This further reduces the number of DSP blocks needed by the implementation, the overall latency, and pipeline depth.
@@ -166,15 +165,17 @@ After learning how to use the extensions for Intel oneAPI Toolkits, return to th
166165
* An FPGA hardware target is not provided on Windows*.
167166
168167
*Note:* The Intel® PAC with Intel Arria® 10 GX FPGA and Intel® FPGA PAC D5005 (with Intel Stratix® 10 SX) do not yet support Windows*. Compiling to FPGA hardware on Windows* requires a third-party or custom Board Support Package (BSP) with Windows* support.<br>
169-
*Note:* If you encounter any issues with long paths when compiling under Windows*, you may have to create your ‘build’ directory in a shorter path, for example c:\samples\build. You can then run cmake from that directory, and provide cmake with the full path to your sample directory.
168+
169+
*Note:* If you encounter any issues with long paths when compiling under Windows*, you may have to create your ‘build’ directory in a shorter path, for example c:\samples\build. You can then run cmake from that directory, and provide cmake with the full path to your sample directory.
170+
170171
171172
### In Third-Party Integrated Development Environments (IDEs)
172173
173174
You can compile and run this Reference Design in the Eclipse* IDE (in Linux*) and the Visual Studio* IDE (in Windows*). For instructions, refer to the following link: [Intel® oneAPI DPC++ FPGA Workflows on Third-Party IDEs](https://software.intel.com/en-us/articles/intel-oneapi-dpcpp-fpga-workflow-on-ide)
174175
175176
## Running the Reference Design
176177
You can apply QR decomposition to a number of matrices, as shown below. This step performs the following:
177-
* Generates the number of random matrices specified as the command line argument (defaults to 1).
178+
* Generates the number of random matrices specified as the command line argument (defaults to 128).
178179
* Computes QR decomposition on all matrices.
179180
* Evaluates performance.
180181
NOTE: The design is optimized to perform best when run on a large number of matrices, where the total number of matrices is a power of 2.
@@ -190,39 +191,55 @@ NOTE: The design is optimized to perform best when run on a large number of matr
190191
qrd.fpga_emu.exe (Windows)
191192
```
192193
193-
2. Run the sample on the FPGA device. It is recommended to pass in an optional argument (as shown) when invoking the sample on hardware. Otherwise, the performance will not be representative.
194+
2. Run the sample on the FPGA device. It is recommended to pass in an optional argument (as shown) when invoking the sample on hardware. Otherwise, the performance will not be representative of the design's throughput. Indeed, the throughput is measured as the total kernel execution time divided by the number of matrices decomposed. However, the transfer of the matrices from the host/device to the device/host also takes some time. This memory transfer is performed by chunks of matrices in parallel to the compute kernel. The first/last chunk of matrices transferred will therefore occur with the computation kernel doing nothing. Thus, the higher the number of matrices to be decomposed, the more accurate the throughput result will be.
194195
```
195-
./qrd.fpga 40960 (Linux)
196+
./qrd.fpga (Linux)
196197
```
197198
### Application Parameters
198199
199200
| Argument | Description
200201
--- |---
201-
| `<num>` | Optional argument that specifies the number of matrices to decompose. Its default value is `1`.
202+
| `<num>` | Optional argument that specifies the number of times to repeat the decomposition of 8 matrices. Its default value is `16` for the emulation flow and '819200' for the FPGA flow.
202203
203204
### Example of Output
204205
205-
Example output when running on Intel® PAC with Intel Arria® 10 GX FPGA for 32768 matrices (each consisting of 128*128 complex numbers):
206+
Example output when running on Intel® PAC with Intel Arria® 10 GX FPGA for 8 matrices 819200 times (each matrix consisting of 128*128 complex numbers):
206207
207208
```
208209
Device name: pac_a10 : Intel PAC Platform (pac_f000000)
209-
Generating 32768 random matrices
210-
Running QR decomposition of 32768 matrices repeatedly
211-
Total duration: 42.3408 s
212-
Throughput: 24.7652k matrices/s
213-
Verifying results on matrix 0 16384 32767
210+
Generating 8 random complex matrices of size 128x128
211+
Running QR decomposition of 8 matrices 819200 times
212+
Total duration: 268.733 s
213+
Throughput: 24.387k matrices/s
214+
Verifying results on matrix 0
215+
1
216+
2
217+
3
218+
4
219+
5
220+
6
221+
7
222+
214223
PASSED
215224
```
216225
217-
Example output when running on Intel® FPGA PAC D5005 (with Intel Stratix® 10 SX) for 40960 matrices (each consisting of 256*256 complex numbers):
226+
Example output when running on Intel® FPGA PAC D5005 (with Intel Stratix® 10 SX) for the decomposition of 8 matrices 409600 times (each matrix consisting of 256*256 complex numbers):
218227
219228
```
220229
Device name: pac_s10 : Intel PAC Platform (pac_f100000)
221-
Generating 4096 random matrices
222-
Running QR decomposition of 4096 matrices repeatedly
223-
Total duration: 17.3197 s
224-
Throughput: 7.36231k matrices/s
225-
Verifying results on matrix 0 20480 40959
230+
Generating 8 random complex matrices of size 256x256
231+
Running QR decomposition of 8 matrices 819200 times
232+
Total duration: 888.077 s
233+
Throughput: 7.37954k matrices/s
234+
Verifying results on matrix 0
235+
1
236+
2
237+
3
238+
4
239+
5
240+
6
241+
7
242+
226243
PASSED
227244
```
228245
@@ -240,12 +257,10 @@ PASSED
240257
`-DROWS_COMPONENT` | Specifies the number of rows of the matrix
241258
`-DCOLS_COMPONENT` | Specifies the number of columns of the matrix
242259
`-DFIXED_ITERATIONS` | Used to set the ivdep safelen attribute for the performance critical triangular loop
260+
`-DCOMPLEX` | Used to select between the complex and real QR decomposition (complex is the default)
243261
244262
NOTE: The values for `seed`, `FIXED_ITERATIONS`, `ROWS_COMPONENT`, `COLS_COMPONENT` are set according to the board being targeted.
245263
246-
### Host Limitations
247-
The QRD demo host is not optimized for a very large number of matrices. Running the QRD executable with number of matrices that occupy more memory than what is physically available on the host machine will result in system performance degradation due to virtual memory thrashing by the operating system.
248-
249264
### Performance disclaimers
250265
251266
Tests document performance of components on a particular test, in specific systems. Differences in hardware, software, or configuration will affect actual performance. Consult other sources of information to evaluate performance as you consider your purchase. For more complete information about performance and benchmark results, visit [www.intel.com/benchmarks](www.intel.com/benchmarks).
@@ -259,5 +274,3 @@ The performance was measured by Intel on July 29, 2020.
259274
Intel and the Intel logo are trademarks of Intel Corporation or its subsidiaries in the U.S. and/or other countries.
260275
261276
(C) Intel Corporation.
262-
263-
Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
1-
2-
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 15
4-
VisualStudioVersion = 15.0.28307.705
5-
MinimumVisualStudioVersion = 10.0.40219.1
6-
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qrd", "qrd.vcxproj", "{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}"
7-
EndProject
8-
Global
9-
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10-
Debug|x64 = Debug|x64
11-
Release|x64 = Release|x64
12-
EndGlobalSection
13-
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14-
{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}.Debug|x64.ActiveCfg = Debug|x64
15-
{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}.Debug|x64.Build.0 = Debug|x64
16-
{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}.Release|x64.ActiveCfg = Release|x64
17-
{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}.Release|x64.Build.0 = Release|x64
18-
EndGlobalSection
19-
GlobalSection(SolutionProperties) = preSolution
20-
HideSolutionNode = FALSE
21-
EndGlobalSection
22-
GlobalSection(ExtensibilityGlobals) = postSolution
23-
SolutionGuid = {97D1BD74-AAAB-4835-8F00-37A58B70871A}
24-
EndGlobalSection
25-
EndGlobal
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio 15
3+
VisualStudioVersion = 15.0.28307.705
4+
MinimumVisualStudioVersion = 10.0.40219.1
5+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qrd", "qrd.vcxproj", "{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}"
6+
EndProject
7+
Global
8+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9+
Debug|x64 = Debug|x64
10+
Release|x64 = Release|x64
11+
EndGlobalSection
12+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
13+
{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}.Debug|x64.ActiveCfg = Debug|x64
14+
{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}.Debug|x64.Build.0 = Debug|x64
15+
{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}.Release|x64.ActiveCfg = Release|x64
16+
{ACDE6B7A-6F9A-428E-B040-CEDC5B1E2C79}.Release|x64.Build.0 = Release|x64
17+
EndGlobalSection
18+
GlobalSection(SolutionProperties) = preSolution
19+
HideSolutionNode = FALSE
20+
EndGlobalSection
21+
GlobalSection(ExtensibilityGlobals) = postSolution
22+
SolutionGuid = {97D1BD74-AAAB-4835-8F00-37A58B70871A}
23+
EndGlobalSection
24+
EndGlobal

0 commit comments

Comments
 (0)