DEV Community

Pencilcaseman for LibRapid

Posted on

Make std::vector 5x Faster with LibRapid

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

LibRapid GitHub Repository

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

We could use LibRapid's Array class!

LibRapid Implementation

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
Enter fullscreen mode Exit fullscreen mode

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 for instructions on setting up LibRapid

#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;
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)