多线程返回用于存储信息的未处理异常

蛋糕

我将尽力解释我的问题。我有一个必须处理的多线程框架。这是一个路径跟踪渲染器。当我尝试存储线程提供的某些信息时,它给了我错误。为了避免发布所有代码,我将逐步解释我的意思:

我的TileTracer类是线程

class TileTracer : public Thread{
...
}

而且我有一定数量的线程:

#define MAXTHREADS      32
TileTracer* worker[MAXTHREADS];

在下面的初始化代码中设置了工作线程的数量,其中还启动了线程:

void Renderer::Init(){
    accumulator = (vec3*)MALLOC64(sizeof(vec3)* SCRWIDTH * SCRHEIGHT);
    memset(accumulator, 0, SCRWIDTH * SCRHEIGHT * sizeof(vec3));
    SYSTEM_INFO systeminfo;
    GetSystemInfo(&systeminfo);
    int cores = systeminfo.dwNumberOfProcessors;
    workerCount = MIN(MAXTHREADS, cores);
    for (int i = 0; i < workerCount; i++)
    {
        goSignal[i] = CreateEvent(NULL, FALSE, FALSE, 0);
        doneSignal[i] = CreateEvent(NULL, FALSE, FALSE, 0);
    }
    // create and start worker threads
    for (int i = 0; i < workerCount; i++)
    {
         worker[i] = new TileTracer();
         worker[i]->init(accumulator, i);
         worker[i]->start(); //start the thread
    }
    samples = 0;
}

我的线程的init()方法仅在我的标头中定义如下:

void init(vec3* target, int idx) { accumulator = target, threadIdx = idx; }

而start()是:

void Thread::start() 
{
     DWORD tid = 0; 
     m_hThread = (unsigned long*)CreateThread( NULL, 0,    (LPTHREAD_START_ROUTINE)sthread_proc, (Thread*)this, 0, &tid );
     setPriority( Thread::P_NORMAL );
 }

以某种方式(我不知道确切的位置),每个线程都调用以下main方法,该方法用于定义像素的颜色(您不必全部了解):

vec3 TileTracer::Sample(vec3 O, vec3 D, int depth){
  vec3 color(0, 0, 0);
  // trace path extension ray
  float t = 1000.0f, u, v;
  Triangle* tri = 0;
  Scene::mbvh->pool4[0].TraceEmbree(O, D, t, u, v, tri, false);
  totalRays++;
  // handle intersection, if any
  if (tri)
  {
    // determine material color at intersection point
    Material* mat = Scene::matList[tri->material];
    Texture* tex = mat->GetTexture();
    vec3 diffuse;
    if (tex)
    {
        ...
    }
    else diffuse = mat->GetColor();
    vec3 I = O + t * D; //we get exactly to the intersection point on the object

    //we need to store the info of each bounce of the basePath for the offsetPaths
    basePath baseInfo = { O, D, I, tri };
    basePathHits.push_back(baseInfo);

    vec3 L = vec3(-1 + Rand(2.0f), 20, 9 + Rand(2.0f)) - I; //(-1,20,9) is Hard-code of the light position, and I add Rand(2.0f) on X and Z axis
    //so that I have an area light instead of a point light
    float dist = length(L) * 0.99f; //if I cast a ray towards the light source I don't want to hit the source point or the light source
    //otherwise it counts as a shadow even if there is not. So I make the ray a bit shorter by multiplying it for 0.99
    L = normalize(L);
    float ndotl = dot(tri->N, L);
    if (ndotl > 0)
    {
        Triangle* tri = 0;
        totalRays++;
        Scene::mbvh->pool4[0].TraceEmbree(I + L * EPSILON, L, dist, u, v, tri, true);//it just calculates the distance by throwing a ray
        //I am just interested in understanding if I hit something or not
        //if I don't hit anything I calculate the light transport (diffuse * ndotL * lightBrightness * 1/dist^2
        if (!tri) color += diffuse * ndotl * vec3(1000.0f, 1000.0f, 850.0f) * (1.0f / (dist * dist));
    }
    // continue random walk since it is a path tracer (we do it only if we have less than 20 bounces)
    if (depth < 20)
    {
        // russian roulette
        float Psurvival = CLAMP((diffuse.r + diffuse.g + diffuse.b) * 0.33333f, 0.2f, 0.8f);
        if (Rand(1.0f) < Psurvival)
        {
            vec3 R = DiffuseReflectionCosineWeighted(tri->N);//there is weight
            color += diffuse * Sample(I + R * EPSILON, R, depth + 1) * (1.0f / Psurvival);
        }
    }
  }
  return color;
}

现在,您不必确定整个代码,因为我的问题是以下内容:如果您注意到,在最后一个方法中,有以下两条代码行:

basePath baseInfo = { O, D, I, tri };
basePathHits.push_back(baseInfo);

我只是创建一个简单的结构“ basePath”,定义如下:

struct basePath
{
    vec3 O, D, hit;
    Triangle* tri;
};

然后将其存储在代码开头定义的struct向量中:

vector<basePath> basePathHits;

问题在于,这似乎带来了例外。的确,如果我尝试存储这些信息(以后需要在代码中使用),程序将崩溃,并给我一个例外:

Template.exe中0x0FD4FAC1(msvcr120d.dll)的未处理异常:0xC0000005:访问冲突读取位置0x3F4C1BC1。

在另一些时间中,没有进行任何更改,错误有所不同,它是以下内容:

在此处输入图片说明

同时,在不存储这些信息的情况下,一切工作正常。同样,如果将核心数设置为1,则一切正常。那么,为什么多线程不允许我这样做呢?如果这些还不够,请随时询问更多信息。

阿特金斯

尝试对您的代码进行以下更改:

//we need to store the info of each bounce of the basePath for the offsetPaths
basePath baseInfo = { O, D, I, tri }; 
static std::mutex myMutex;
myMutex.lock();
basePathHits.push_back(baseInfo);
myMutex.unlock();

如果那消除了异常,则问题是访问的同步性不佳basePathHits(即多个线程push_back同时调用)。您需要仔细考虑什么是最佳解决方案,以最小化同步对性能的影响。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章