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