Visual C++ parallel_for + vectors access violation

4

I am trying to convert a process that loops through a ~12,000x12,000 cell matrix (around 125 times) to use parallel processing (via parallel_for). The code I am using is below. You can see where the for loop is commented out.

When I run this code with the for loop, there are no problems. When I run it (in debug) using parallel_for, it crashes at random points with "Unhandled exception at 0x00f3d4ae in FratarProcess.exe 0xC0000005: Access violation writing location 0x0000000.

Note: accessMatrix is declared as vector <vector <unsigned short> > accessMatrix; and is filled prior to this point.

void dumpMatrix(unsigned short m)
{

int complete=0, start=2532, todo=accessMatrix.size()-start;

    vector <string> sqlStrings;

    Concurrency::parallel_for(start, (int)accessMatrix.size(),[&complete,&todo,&m,&sqlStrings](int i)
    //for(int i=start;i<accessMatrix.size();i++)
    {
        printf("Processing i=%i... completed %i/%i\n",i,complete,todo);
        for(unsigned short j=1;j<accessMatrix[i].size();j++)
        {
            if(accessMatrix[i][j]>0)
            {
                stringstream strSQL;
                strSQL << "INSERT INTO debug.dbf (I,J,M,V) VALUES(" << i << "," << j << "," << m << "," << accessMatrix[i][j] << ")";
                sqlStrings.push_back(strSQL.str());
            }
        }
        complete++;
    });
...
}

Can someone get me pointed in the right direction so I can get this process using all 8 cores of my machine instead of one? Note that I am somewhat of a novice at C++. I am using Visual C++ Express.

c++
visual-c++
vector
parallel-for
asked on Stack Overflow Aug 3, 2011 by Andrew Rohne • edited May 28, 2016 by Ajay

3 Answers

3

You've used no synchronization protection for sqlStrings. It is not safe to mutate the container, print to output, or even increment a shared variable from multiple threads concurrently without using synchronization.

answered on Stack Overflow Aug 4, 2011 by Puppy
3

This will also solve the problem:

Declare a combinable object:

Concurrency::combinable<vector <string>> sqlStringsCombinable;

And in the loop:

sqlStringsCombinable.local().push_back(strSQL.str());

After the loop, combine them:

sqlStringsCombinable.combine_each([&sqlStrings](const std::vector<CString>& vec)
    {
        std::copy(vec.cbegin(), vec.cend(), back_inserter(sqlStrings));
    });

And this will speed up parallel_for as opposed to manually synchronizing the loop.

answered on Stack Overflow Aug 7, 2011 by Ajay
1

You can also use the Concurrent_Vector class.

  1. Add #include<concurrent_vector.h>.
  2. then add using namespace concurrency;.
  3. Then you can initialize the vector like so concurrent_vector<pair<int,int>> xy_coords;.

The usage of this vector is just like {std::vector} class.

answered on Stack Overflow Jun 21, 2019 by Faizan Cassim

User contributions licensed under CC BY-SA 3.0