我坚持这个,似乎无法弄清楚发生了什么。对于后台,我试图将一个结构体传递给3个pthreads,然后在线程中修改该结构,然后将每个结构存储回主线程,并将每个结构得到的部分结果加起来以加速这部分我的代码似乎是性能的主要瓶颈。我在用C编写的另一个项目中使用了与此非常类似的代码,但是当我将它复制到这个C ++程序并修改它以适应这个问题时,我遇到了一些奇怪的错误。
首先,我必须制作一些我不必在C中制作的演员表,以便进行编译。由于我在类中包含thread_work函数作为方法,因此它将类型视为(void *(AIShell :: *)(void *),因此我需要将其转换为(void *(*)(void *),它允许它编译和运行,但它给了我一个编译器警告。我把它作为方法而不仅仅是一个函数包含的原因是我可以从这个中调用另一个类方法,所以它是必需的。是否有任何方式我都应该修改我的代码以使其消失,或者这只是在类中使用我的线程函数的一个不幸的副作用?
AIShell.cpp: In member function ‘double AIShell::heuristic(int**)’:
AIShell.cpp:173:78: warning: converting from ‘void* (AIShell::*)(void*)’ to ‘void* (*)(void*)’ [-Wpmf-conversions]
th = pthread_create(&new_threads[i], &attr, (void * (*)(void *)) &AIShell::thread_work, (void *) (se+i));
其次,最重要的是我在运行代码时遇到了段错误。我已经缩小了问题发生的位置,每当我尝试访问我传入线程的结构成员时(即执行se-> start_count),它就会发生在我的thread_work函数中:
125 struct start_end
126 {
127 int ** board;
128 int start_col;
129 int end_col;
130 int start_row;
131 int end_row;
132 double total;
133 };
134
135 void * AIShell::thread_work(void * arg)
136 {
137 struct start_end * se = (struct start_end *) malloc(sizeof(struct start_end));
138 se = (struct start_end *) arg;
139 printf("\nse->total = %lg; se->start_row = %d; se->start_col = %d\n\n", se->total, se->start_row, se->start_c ol);
140 fflush(stdout);
141 for (int row = se->start_row; row != se->end_row; row++)
142 {
143 for (int col = se->start_col; col != se->end_col; col++)
144 {
145 se->total += check8(se->board, col, row);
146 }
147 }
148 printf("asdfasdfasfdasdfasdfasdfasdfasdfasdfasdf\n");
149 fflush(stdout);
150 pthread_exit((void *)se);
151 }
当它到达代码的这部分时,这是每个线程运行的代码,它最初在第141行开始时失败,但在第139行添加print语句后,它在那里失败,这证实了问题在于引用结构成员。
但是,如果我添加"&"之前" arg"在138行,所以它看起来像这样:
138 se = (struct start_end *) &arg;
它不会再发生段错误,但它会获得垃圾值,这会破坏我以后的一些代码。据我所知,我在将结构传递给线程之前正确地为结构赋值,所以我不确定这里发生了什么。
此代码是充当"主线程"的方法。初始化结构,产生其他线程,并且应该从每个线程中获取结果并将它们相加以获得最终结果。它也充当了这个本身的线程所以我在这里使用了类似的代码段,我在上面的函数中做了所以我将使用我的所有资源;)
153 double AIShell::heuristic(int ** board)
154 {
155 pthread_t new_threads[3] = {0};
156 pthread_attr_t attr;
157 int th;
158 long t;
159 struct start_end * se;
160 se = (struct start_end *) malloc(3*sizeof(struct start_end));
161
162 pthread_attr_init(&attr);
163 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
164
165 for (int i = 0; i <3; i ++)
166 {
167 (se+i)->board = copy(board);
168 (se+i)->start_row = numRows/4*i;
169 (se+i)->end_row = numRows/4*(i+1);
170 (se+i)->start_col = numCols/4*i;
171 (se+i)->end_col = numCols/4*(i+1);
172 (se+i)->total = 0;
173 th = pthread_create(&new_threads[i], &attr, (void * (*)(void *)) &AIShell::thread_work, (void *) (se+i));
174 if (th)
175 {
176 perror("pthread_create");
177 exit(1);
178 }
179 }
180
181
182 int start_row = numRows/4*3;
183 int end_row = numRows;
184 int start_col = numCols/4*3;
185 int end_col = numCols;
186 int total = 0;
187
188 for (int row = start_row; row != end_row; row++)
189 {
190 for (int col = start_col; col != end_col; col++)
191 {
192 total += check8(board, col, row);
193 }
194 }
195
196 for (int i = 0; i != 3; i++)
197 {
198 th = pthread_join(new_threads[i], (void **) (se+i));
199 if (th)
200 {
201 perror("pthread_join");
202 exit(1);
203 }
204 }
205
206 for (int i = 0; i != 3; i++)
207 {
208 total += (se+i)->total;
209 free((se+i));
210 }
211
212 pthread_attr_destroy(&attr);
213
214 free(se);
215
216 return total;
217 }
我意识到这样做是非常&#34; C&#34;我和我可以用#34; new&#34;或者其他什么,但正如我所说,我改编了来自&#34; C&#34;在这个&#34; C ++&#34;中使用的项目项目,并希望这样做而不必重写所有内容。我也不是肯定的我正在释放&#34;正确的,但它还没有在我的代码中到达那里,所以这更像是次要问题。所以尽管如此,有没有人看到我在这里做错了什么?我尝试了很多东西,似乎无法让它发挥作用:/