Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

why the result is different add thread by loop

I am the novice of multithreading, and I want to try to use the 2048*2048 height map texture to generate a set of vertices.

void HeightMap::CalculateVertices(Vector3 vertex_scale, Vector2 texture_scale, int start, int end, GLubyte* data) {
    for (unsigned int z = start; z < end; ++z) {
        for (unsigned int x = 0; x < width; ++x) {
            unsigned int offset = z * height + x;
            vertices[offset] = Vector3(x, data[offset], z) * vertex_scale;
            textureCoords[offset] = Vector2(x, z) * texture_scale;
        }
    }
}

The problem is when I try to add thread to vector, if I add them one by one:

    threads.push_back(std::thread([&]
        {CalculateVertices(vertex_scale, texture_scale, 0, dataSize, data); }));
    threads.push_back(std::thread([&]
        {CalculateVertices(vertex_scale, texture_scale, dataSize, dataSize * 2, data); }));
    threads.push_back(std::thread([&]
        {CalculateVertices(vertex_scale, texture_scale, dataSize * 2, dataSize * 3, data); }));
    threads.push_back(std::thread([&]
        {CalculateVertices(vertex_scale, texture_scale, dataSize * 3, dataSize * 4, data); }));

Then everything run properly.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

But if I use loop to add thread:

    for (int i = 0; i < 4; ++i) {
        threads.push_back(std::thread([&]
            {CalculateVertices(vertex_scale, texture_scale, dataSize * i, dataSize * (i + 1), data); }));
    }

, the error occured, it shows the parameter "end" in the function "CalculateVertices" is 2560. Logically, the range should not exceed 2048.

Then I try to do some change, I just calculate the "start" and "end" not in the parameter list:

    for (int i = 0; i < 4; ++i) {
        int start = dataSize * i;
        int end = dataSize * (i + 1);
        threads.push_back(std::thread([&]
            {CalculateVertices(vertex_scale, texture_scale, dataSize * i, dataSize * (i + 1), data); }));
    }

, now the out of range problem is fixed, but the result still wrong, it seems only generate half of the vertices.

I am not familiar to multithreading, and this is my first attempt to use multithreading, I want to know the reason of the problem. According to my experience, I just change one-by-one code to loop, the logic should not be different.

>Solution :

The secret is your lazy auto-capture-by reference:

std::thread([&]{ /*...*/ })

This is almost always a bad idea. In this case, you are capturing i by reference, which means when the thread invokes the lambda, i might not even exist and will certainly not have the correct value.

At the very least, capture i by value. In fact, you can probably capture all this stuff by value in this case.

std::thread([=]{ /*...*/ })
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading