Make std::vector 5x Faster with LibRapid
Tags: cpp, librapid, optimisation, opensource
Published: 2023-02-11 21:50:54

###### (We're currently looking for a cloud instance sponsorship. If you'd like to support LibRapid in this way, please contact us!)

<b/>

#### [LibRapid GitHub Repository](https://github.com/LibRapid/librapid)

<b/>

LibRapid provides a cohesive ecosystem of classes, functions and tools to accelerate developement and improve the performance of your code.

For example, take the STL code below. It's very clunky and verbose, and isn't very nice to read or work with. How could this be simplified by using LibRapid?


![Standard Library Implementation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t8xl8067w7ij3u94a43v.png)


**We could use LibRapid's Array class!**


![LibRapid Implementation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbu0igrs2qdpsyonjbxj.png)


As you can see, the code is much clearer and more concise, and even formats the output nicely. Additionally, it's ***FAST***.

Running the same code (approximately 15,000 times) with much larger matrices (1000 x 1000) gives the following times:

```
STL      : 1.589ms
LibRapid : 284.405µs
Speedup  : 558.71%

- MSVC 19.33
- Default settings
- LibRapid Optimise Small Arrays: OFF
- Ryzen 9 3950x
- Windows 10 Pro
```

Swapping from `std::vector` to LibRapid for Array-based calculations has resulted in shorter, simpler code, a cleaner output and a speedup of over 500% over the standard library implementation!

# Code

Here is the code for the benchmarks. Feel free to copy-paste it and play around with it :)

Check out the [LibRapid GitHub Page](https://github.com/LibRapid/librapid) for instructions on setting up LibRapid

```cpp
#include <librapid>
namespace lrc = librapid;

int main() {
	{
		// LibRapid Benchmark
		int64_t elements = 1000;
		lrc::Array<double> aa(lrc::Shape({elements, elements}));
		lrc::Array<double> bb(lrc::Shape({elements, elements}));
		lrc::Array<double> cc(lrc::Shape({elements, elements}));
		lrc::Array<double> res(lrc::Shape({elements, elements}));

		double benchTime = 5;
		int64_t iters	 = 0;

		double start = lrc::now();
		while (lrc::now() - start < benchTime) {
			res = aa * bb - cc;
			++iters;
		}
		double end = lrc::now();
		fmt::print("Elapsed: {} over {} iterations\n", lrc::formatTime(end - start), iters);
		fmt::print("Average: {}\n", lrc::formatTime((end - start) / (double)iters));
	}

	{
		// STL Benchmark

		int64_t elements = 1000;
		std::vector<std::vector<double>> aa(elements, std::vector<double>(elements, 3));
		std::vector<std::vector<double>> bb(elements, std::vector<double>(elements, 3));
		std::vector<std::vector<double>> cc(elements, std::vector<double>(elements, 3));
		std::vector<std::vector<double>> res(elements, std::vector<double>(elements, 3));

		double benchTime = 5;
		int64_t iters	 = 0;

		double start = lrc::now();
		while (lrc::now() - start < benchTime) {
			for (int64_t i = 0; i < elements; ++i) {
				for (int64_t j = 0; j < elements; ++j) {
					res[i][j] = aa[i][j] * bb[i][j] - cc[i][j];
				}
			}
			++iters;
		}
		double end = lrc::now();

		fmt::print("Elapsed: {}\n", lrc::formatTime(end - start));
		fmt::print("Average: {}\n", lrc::formatTime((end - start) / (double)iters));
	}

	return 0;
}
```