【发布时间】:2015-12-30 13:45:41
【问题描述】:
我会尽可能清楚地解释我的问题。我有一个必须处理的多线程框架。这是一个路径跟踪器渲染器。当我尝试存储我的线程提供的一些信息时,它给了我错误。尽量避免发布所有代码,我将逐步解释我的意思:
我的 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;
}
现在,您不必完全理解整个代码,因为我的问题如下:如果您注意到,在最后一种方法中有以下 2 行代码:
basePath baseInfo = { O, D, I, tri };
basePathHits.push_back(baseInfo);
我只是创建了一个简单的结构“basePath”,定义如下:
struct basePath
{
vec3 O, D, hit;
Triangle* tri;
};
我将它存储在我的代码开头定义的结构向量中:
vector<basePath> basePathHits;
问题是这似乎带来了异常。事实上,如果我尝试存储这些信息,我稍后需要在我的代码中,程序崩溃给我一个异常:
Template.exe 中 0x0FD4FAC1 (msvcr120d.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0x3F4C1BC1。
其他时候,不做任何改变,错误是不同的,它是以下一个:
虽然不存储这些信息,但一切正常。同样,如果我将核心数设置为 1,一切正常。那么,为什么多线程不允许我这样做呢?如果这些还不够,请随时询问更多信息。
【问题讨论】:
-
您是否尝试按“重试”并进入调试器? 在您的代码中 发生崩溃的位置是什么?你检查过所有相关变量的值吗?
-
basePathHits是在所有线程之间共享,还是每个线程都有自己的版本?如果它是共享的,你是否在尝试push_back之前同步访问它(它看起来不像你)?
标签: c++ multithreading exception-handling