MultiThreading RayTracer генерирует странные артефакты с плоскостью - PullRequest
0 голосов
/ 11 мая 2018

В настоящее время я использую многопоточность на моем RayTracer, и в одном из моих тестовых примеров начали появляться странные артефакты изображения. Другие три, кажется, работают нормально. Я покажу изображения.

Обычная одиночная резьба:

Z-single-thread.jpg

triangle.jpg

Многопоточность:

image.jpg

triangles-_MT.jpg

Многопоточность, другой прогон:

plane.jpg

triangle.jpg

Что я делаю - это переключаю пиксели между двумя потоками. Поток 0 получает пар пикселей (0,2,4,6), а поток 1 получает пикселей (1,3,5,9)

Как можно видеть, существует много легких зеленовато-голубоватых артефактов и вариаций между двумя многопоточными прогонами, такими как расположение и количество маленьких точек, таких как артефакты, плюс цвет треугольника.

Я отправляю программу для печати переменных данных, и вот что я получил:

ST:

БОТО x: 402 y 405

БОТО x: 403 y 405

BOTO x: 404 y 405

......

......

БОТО x: 405 y 407

BOTO x: 406 y 407

BOTO x: 407 y 407

Теперь это результат бега на 1 ° MT:

BOTO x: 403 y 405 thread_id: 1

BOTO x: 403 y 405 thread_id: 1

BOTO x: 403 y 405 thread_id: 1

BOTO x: 403 y 405 thread_id: 1

....

....

BOTO x: 403 y 405 thread_id: 1

BOTO x: 403 y 405 thread_id: 1

BOTO x: 403 y 405 thread_id: 1

BOTO x: 403 y 405 thread_id: 1

А это 2 ° бега:

БОТО x: 401 y 405

БОТО x: 403 y 405

BOTO x: 405 y 405

......

......

BOTO x: 404 y 407

BOTO x: 406 y 407

BOTO x: 408 y 407

Итак, у меня есть MT-код, который каждый раз выполняется по-разному, как показывали разные изображения. Прогон 2 ° MT выполняется правильно (без повторяющихся сообщений о координатах экрана) для координат экрана, которые я показал, как в случае ST, но показал то же поведение в отношении других координат.

Более странным является то, что если просто отправить код установки MT для выполнения того же алгоритма, что и в версии ST, или, другими словами, для визуализации одного и того же изображения дважды, проблема не устраняется. И немного меняется.

ST-_MT1.jpg

ST-_MT2.jpg

Как видно, выполнение одного и того же кода с помощью MT иногда приводит к появлению "чистой" области в начале, и треугольник темнеет (хотя я думаю, что такое же может случиться с исходным кодом MT, особенно с "темным" "треугольник")

Буду признателен за любые предложения о том, как мне попытаться диагностировать проблему, потому что я не знаю, каков ее источник, связан ли код установки MT или проблема с алгоритмом. Я бы поспорил в коде установки MT, так как это я изменил алгоритм на ту же версию ST, и все еще есть проблемы. Тем не менее, проблемы немного изменились, поэтому я потерян здесь.

Код алгоритма RT, связанный с поддержкой MT:

 void RayTracer::draw_multithread (Image *image, Scene *scene, int thread_id) {

  float inv_div=0.5;
  int ctr=0;
  int y=0;
  int initial_x=0;
  if (thread_id==1) {
    cout << "thread_1" << endl;
  ctr=1024*384;
  y=384;
  inv_div=1;
  }

 //if (thread_id==1)
  // return;

 for (; y<(float)image->getHeight()*inv_div; y++) {
   //float px = px_inicial;
   //py = py + ystep;
   for (int x=initial_x; x<image->getWidth(); x++) {
   ....
   .....
      b [ctr] = min (blue*255.0f,255.0f);
      c [ctr] = min (green*255.0f,255.0f);
      d [ctr] = min (red*255.0f,255.0f);
      ctr++;
   }
 }
pthread_exit (NULL);   
}

MT code:

pthread_t threads [2];
thread_data td_array [2];
void *status;
TGAManager tgaManager ("z.tga",true);
if (tgaManager.isFileOpen()) {
   tgaManager.writeHeadersData (image);
   RayTracer rt (image.getHeight() * image.getWidth(),1);
   int rc;
   for (int i=0; i<2; i++) {
      //cout << "main() : creating thread, " << i << endl;
      td_array[i].thread_id=i;
      td_array[i].rt_ptr = &rt;
      td_array[i].img_ptr = &image;
      td_array[i].scene_ptr = &scene;
     //cout << "td_array.thread_index: " << td_array[i].thread_id << endl;
     rc = pthread_create (&threads[i], NULL, RayTracer::run_thread, &td_array[i]);
   }
   if (rc) {
     cout << "Error:unable to create thread," << rc << endl;
     exit(-1);
   }
   for (int i=0; i<2; i++ ) {
     rc = pthread_join(threads[i], &status);
     if (rc) {
        cout << "Error:unable to join," << rc << endl;
        exit(-1);
     }
   }

for (int i=0; i<image.getWidth() * image.getHeight(); i++) {
  tgaManager.file_writer.put (rt.b[i]);
  tgaManager.file_writer.put (rt.c[i]);
  tgaManager.file_writer.put (rt.d[i]);
}
tgaManager.closeFile(1);
rt.deleteImgPtr (true);
}

Для более подробной информации: https://gitlab.com/asmf2/asmfrt/blob/master/RayTracer.cpp (последний метод снизу вверх) и https://gitlab.com/asmf2/asmfrt/blob/master/main.cpp

...