gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 23:00:46 25 4
gpt4 key购买 nike

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

我的 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() 方法在我的 header 中简单定义如下:

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 );
}

不知何故(我不知 Prop 体在哪里),每个线程调用以下主要方法,该方法用于定义像素的颜色(您不必全部理解):

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;
}

现在,您不必完全理解整个代码,因为我的问题如下:如果您注意到,在最后一个方法中有以下 2 行代码:

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

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

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

然后我将它存储在代码开头定义的结构 vector 中:

vector<basePath> basePathHits;

问题是这似乎带来了一个异常(exception)。事实上,如果我尝试存储这些信息,我稍后需要在我的代码中使用,程序会崩溃并给出异常:

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

其他时候,不做任何更改,错误是不同的,如下所示:

enter image description here

虽然没有存储这些信息,但一切都完美无缺。同样,如果我将核心数设置为 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)。您需要仔细考虑最好的解决方案是什么,以尽量减少同步对性能的影响。

关于c++ - 多线程返回未处理的异常用于存储信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32905634/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com