Operation speed on different types

Viewed 71

I have quite stupid class task: measure which types works faster in C++. Firstly I thought "it`s obvious, that the fastest type is the type that corresponds to processor word-size, so it will be int64_t on my AMD Ryzen 7 2700x) and, of course, double and float will be much slower than ints. I wrote simple program, but can`t explain its output to myself... Probably, I`m missing something. (compiled in x64 release msvc142).

#include <vector>
#include <chrono>
#include <array>

template <typename T>
T** newMatr1(size_t n)
{
    T** res = new T * [n];
    for (size_t i = 0; i < n; i++)
    {
        res[i] = new T[n];
    }
    return res;
}
template <typename T>
void delMatr1(T** matr, size_t n)
{
    for (size_t i = 0; i < n; i++)
    {
        delete[] matr[i];
    }
    delete matr;
}
template <typename T>
void initMatr(T** matr, size_t n)
{
    for (size_t i = 0; i < n; i++)
    {
        for (size_t j = 0; j < n; j++)
        {
            matr[i][j] = rand();
        }   
    }   
}

template <typename T>
void multiplyMatr(T** matr1, T** matr2, size_t n)
{
    T** res = newMatr1<T>(n);
    for (size_t i = 0; i < n; ++i)
    {
        for (size_t j = 0; j < n; ++j)
        {
            for (size_t k = 0; k < n; ++k)
            {
                res[i][j] += matr1[i][k] * matr2[k][j];
            }
        }
    }
    delMatr1(res, n);
}

template <typename T>
std::vector<std::vector<T>> initVec(size_t n)
{
    std::vector<std::vector<T>> matr(n, std::vector<T>(n));
    for (size_t i = 0; i < n; i++)
    {
        for (size_t j = 0; j < n; j++)
        {
            matr[i][j] = rand();
        }
    }
    return matr;
}

template <typename T>
void multiplyVect(const std::vector<std::vector<T>>& matr1, const std::vector<std::vector<T>>& matr2, size_t n)
{
    std::vector<std::vector<T>> res(n, std::vector<T>(n));
    for (size_t i = 0; i < n; ++i)
    {
        for (size_t j = 0; j < n; ++j)
        {
            for (size_t k = 0; k < n; ++k)
            {
                res[i][j] += matr1[i][k] * matr2[k][j];
            }
        }
    }   

}

template <typename Func, typename T>
std::chrono::high_resolution_clock::duration getMinTime(Func function, const T& matr1, const T& matr2,  int n, int count)
{
    auto min = std::chrono::high_resolution_clock::duration::max();
    
    for (size_t i = 0; i < count; ++i)
    {
        auto start = std::chrono::high_resolution_clock::now();
        function(matr1, matr2, n);
        auto end = std::chrono::high_resolution_clock::now();
        auto diff = end - start;
        if(diff < min)
            min = diff;
    }
    return min;
}

template <typename T>
void getTime()
{
    std::vector<size_t> sizes{ 512 };// , 1024, 2048
    for (int i = 0; i < sizes.size(); ++i)
    {
        std::cout << sizes[i] << ":\n";
        std::cout << "std::vector: ";
        std::vector<std::vector<T>> vec1 = initVec<T>(sizes[i]);
        std::vector<std::vector<T>> vec2 = initVec<T>(sizes[i]);
        std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(getMinTime(multiplyVect<T>, vec1, vec2, sizes[i], 10)).count() << "ms";
        std::cout << " arr(raw ptr): ";
        T** matr1 = newMatr1<T>(sizes[i]);
        T** matr2 = newMatr1<T>(sizes[i]);
        initMatr(matr1, sizes[i]);
        initMatr(matr2, sizes[i]);
        std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(getMinTime(multiplyMatr<T>, matr1, matr2, sizes[i], 10)).count() << "ms\n";
        delMatr1(matr1, sizes[i]);
        delMatr1(matr2, sizes[i]);
    }
}

int main()
{
    std::vector<size_t> sizes{ 512, 1024 }; //, 2048
    std::cout << "int8_t\n";
    getTime<int8_t>();
    std::cout << "int16_t\n";
    getTime<int16_t>();
    std::cout << "int32\n";
    getTime<int>();
    std::cout << "int64_t\n";
    getTime<int64_t>();
    std::cout << "float\n";
    getTime<float>();
    std::cout << "double\n";
    getTime<double>();
    system("pause");
} 

the output I got:

int8_t
512:
std::vector: 233ms arr(raw ptr): 228ms
int16_t
512:
std::vector: 233ms arr(raw ptr): 230ms
int32
512:
std::vector: 237ms arr(raw ptr): 235ms
int64_t
512:
std::vector: 250ms arr(raw ptr): 236ms
float
512:
std::vector: 104ms arr(raw ptr): 104ms
double
512:
std::vector: 106ms arr(raw ptr): 106ms

what is wrong? Why floats and doubles are much faster that ints? And why double not slower than float?
Flags:
/permissive- /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"x64\Release\vc142.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /FC /Fa"x64\Release" /EHsc /nologo /Fo"x64\Release" /Ot /Fp"x64\Release\tmp.pch" /diagnostics:column

0 Answers
Related