- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
旁注:我开始学习如何使用 pthreads 并且我开始理解这个概念。我一直在这里使用这个示例脚本(用 C++ 编写)来管理带线程的合并排序:https://www.geeksforgeeks.org/merge-sort-using-multi-threading/
因为我是用 C 而不是 C++ 编写自己的合并排序,所以我重写了这个示例脚本来测试并注意到了一个问题。对于 20 个元素的数组,我决定使用 15 个,而不是 MAX 20
。我注意到排序/合并无效(但有点接近),我无法弄清楚为什么......此外,我更改了代码以使用不同数量的线程而不是 THREAD_MAX 4
,因此我可以将其更改为 5 或 10 个线程。
会不会是 Merge 产生了无效的结果?我在下面的 main() 中对其进行了评论。
我的 C++ 到 C 的转换如下:
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
// number of elements in array
#define MAX 15
// number of threads
#define THREAD_MAX 4
//using namespace std;
// array of size MAX
int a[MAX];
int part = 0;
// merge function for merging two parts
void merge(int low, int mid, int high)
{
int* left = (int*) malloc( (mid - low + 1) * sizeof(int));
int* right = (int*) malloc( (high - mid) * sizeof(int));
// n1 is size of left part and n2 is size
// of right part
int n1 = mid - low + 1,
n2 = high - mid,
i, j;
// storing values in left part
for (i = 0; i < n1; i++)
left[i] = a[i + low];
// storing values in right part
for (i = 0; i < n2; i++)
right[i] = a[i + mid + 1];
int k = low;
i = j = 0;
// merge left and right in ascending order
while (i < n1 && j < n2) {
if (left[i] <= right[j])
a[k++] = left[i++];
else
a[k++] = right[j++];
}
// insert remaining values from left
while (i < n1) {
a[k++] = left[i++];
}
// insert remaining values from right
while (j < n2) {
a[k++] = right[j++];
}
free(left);
free(right);
}
// merge sort function
void merge_sort(int low, int high)
{
// calculating mid point of array
int mid = low + (high - low) / 2;
if (low < high) {
// calling first half
merge_sort(low, mid);
// calling second half
merge_sort(mid + 1, high);
// merging the two halves
merge(low, mid, high);
}
}
// thread function for multi-threading
void* merge_sort123(void* arg)
{
// which part out of 4 parts
int thread_part = part++;
// calculating low and high
int low = thread_part * (MAX / THREAD_MAX);
int high = (thread_part + 1) * (MAX / THREAD_MAX) - 1;
// evaluating mid point
int mid = low + (high - low) / 2;
if (low < high) {
merge_sort(low, mid);
merge_sort(mid + 1, high);
merge(low, mid, high);
}
return 0;
}
// Driver Code
int main()
{
// generating random values in array
for (int i = 0; i < MAX; i++){
a[i] = rand() % 100;
// printf("%d ", a[i]);
}
pthread_t threads[THREAD_MAX];
// creating 4 threads
for (int i = 0; i < THREAD_MAX; i++)
pthread_create(&threads[i], NULL, merge_sort123,
(void*)NULL);
// joining all 4 threads
for (int i = 0; i < THREAD_MAX; i++)
pthread_join(threads[i], NULL);
///////////////////////////////////////////////////////////////
// --- THIS MAY BE THE PART WHERE THE MERGING IS INVALID --- //
///////////////////////////////////////////////////////////////
// merging the final 4 parts
merge(0, (MAX / 2 - 1) / 2, MAX / 2 - 1);
merge(MAX / 2, MAX/2 + (MAX-1-MAX/2)/2, MAX - 1);
merge(0, (MAX - 1)/2, MAX - 1);
// displaying sorted array
printf("\n\nSorted array: ");
for (int i = 0; i < MAX; i++)
printf ("%d ", a[i]);
printf("\n");
return 0;
}
最佳答案
正如我在热门评论中提到的,原始代码存在一些问题。
上述竞争条件。
merge
底部 [似乎] 缺少 delete
事实上数组元素的数量必须是线程数量的倍数。否则,最后一个线程的范围将计算不正确。
主线程中的最终合并对于 4 个线程是固定/硬连线的。
一个通用的解决方案是可能的。但是,除非数组大小非常大,否则它不会节省太多时间,所以它主要用于练习多线程[我相信这就是你想要的]。请参阅:Multithreaded quicksort or mergesort
使用控制结构将多个参数传递给线程会更容易。对于一般的多线程来说,这是一种很好的技术。
主线程可以用每个线程的数组范围预填充它。它稍后可以使用这些控制结构来概括最终合并。
这是一个清理过的版本,适用于任意数组大小和任意数量的线程:
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
int opt_a;
int opt_t;
int opt_r;
// number of elements in array
//#define MAX 15
//#define MAX 16
int MAX;
// number of threads
//#define THREAD_MAX 4
int THREAD_MAX;
//using namespace std;
// array of size MAX
int *a;
// thread control parameters
struct tsk {
int tsk_no;
int tsk_low;
int tsk_high;
};
// merge function for merging two parts
void
merge(int low, int mid, int high)
{
// n1 is size of left part and n2 is size of right part
int n1 = mid - low + 1;
int n2 = high - mid;
int *left = malloc(n1 * sizeof(int));
int *right = malloc(n2 * sizeof(int));
int i;
int j;
// storing values in left part
for (i = 0; i < n1; i++)
left[i] = a[i + low];
// storing values in right part
for (i = 0; i < n2; i++)
right[i] = a[i + mid + 1];
int k = low;
i = j = 0;
// merge left and right in ascending order
while (i < n1 && j < n2) {
if (left[i] <= right[j])
a[k++] = left[i++];
else
a[k++] = right[j++];
}
// insert remaining values from left
while (i < n1)
a[k++] = left[i++];
// insert remaining values from right
while (j < n2)
a[k++] = right[j++];
free(left);
free(right);
}
// merge sort function
void
merge_sort(int low, int high)
{
// calculating mid point of array
int mid = low + (high - low) / 2;
if (low < high) {
// calling first half
merge_sort(low, mid);
// calling second half
merge_sort(mid + 1, high);
// merging the two halves
merge(low, mid, high);
}
}
// thread function for multi-threading
void *
merge_sort123(void *arg)
{
struct tsk *tsk = arg;
int low;
int high;
// calculating low and high
low = tsk->tsk_low;
high = tsk->tsk_high;
// evaluating mid point
int mid = low + (high - low) / 2;
if (low < high) {
merge_sort(low, mid);
merge_sort(mid + 1, high);
merge(low, mid, high);
}
return 0;
}
// Driver Code
int
main(int argc, char **argv)
{
char *cp;
struct tsk *tsk;
--argc;
++argv;
MAX = 15;
THREAD_MAX = 4;
// use new/general algorithm by default
opt_a = 1;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'M': // array count
MAX = atoi(cp + 2);
break;
case 'T': // thread count
THREAD_MAX = atoi(cp + 2);
break;
case 'a': // change algorithm
opt_a = !opt_a;
break;
case 'r': // do _not_ use rand -- use linear increment
opt_r = !opt_r;
break;
case 't': // tracing
opt_t = !opt_t;
break;
default:
break;
}
}
// allocate the array
a = malloc(sizeof(int) * MAX);
// generating random values in array
if (opt_t)
printf("ORIG:");
for (int i = 0; i < MAX; i++) {
if (opt_r)
a[i] = MAX - i;
else
a[i] = rand() % 100;
if (opt_t)
printf(" %d", a[i]);
}
if (opt_t)
printf("\n");
pthread_t threads[THREAD_MAX];
struct tsk tsklist[THREAD_MAX];
int len = MAX / THREAD_MAX;
if (opt_t)
printf("THREADS:%d MAX:%d LEN:%d\n", THREAD_MAX, MAX, len);
int low = 0;
for (int i = 0; i < THREAD_MAX; i++, low += len) {
tsk = &tsklist[i];
tsk->tsk_no = i;
if (opt_a) {
tsk->tsk_low = low;
tsk->tsk_high = low + len - 1;
if (i == (THREAD_MAX - 1))
tsk->tsk_high = MAX - 1;
}
else {
tsk->tsk_low = i * (MAX / THREAD_MAX);
tsk->tsk_high = (i + 1) * (MAX / THREAD_MAX) - 1;
}
if (opt_t)
printf("RANGE %d: %d %d\n", i, tsk->tsk_low, tsk->tsk_high);
}
// creating 4 threads
for (int i = 0; i < THREAD_MAX; i++) {
tsk = &tsklist[i];
pthread_create(&threads[i], NULL, merge_sort123, tsk);
}
// joining all 4 threads
for (int i = 0; i < THREAD_MAX; i++)
pthread_join(threads[i], NULL);
// show the array values for each thread
if (opt_t) {
for (int i = 0; i < THREAD_MAX; i++) {
tsk = &tsklist[i];
printf("SUB %d:", tsk->tsk_no);
for (int j = tsk->tsk_low; j <= tsk->tsk_high; ++j)
printf(" %d", a[j]);
printf("\n");
}
}
// merging the final 4 parts
if (opt_a) {
struct tsk *tskm = &tsklist[0];
for (int i = 1; i < THREAD_MAX; i++) {
struct tsk *tsk = &tsklist[i];
merge(tskm->tsk_low, tsk->tsk_low - 1, tsk->tsk_high);
}
}
else {
merge(0, (MAX / 2 - 1) / 2, MAX / 2 - 1);
merge(MAX / 2, MAX / 2 + (MAX - 1 - MAX / 2) / 2, MAX - 1);
merge(0, (MAX - 1) / 2, MAX - 1);
}
// displaying sorted array
printf("\n\nSorted array:");
for (int i = 0; i < MAX; i++)
printf(" %d", a[i]);
printf("\n");
return 0;
}
关于c - 在 C 中使用 PThreads 合并排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52767944/
我正在尝试对每个条目有多个值的关联数组进行排序。 例如 [0] => stdClass Object ( [type] => node [sid] => 158 [score] => 0.059600
我在 mysql 中有“日期”列以这种格式保存日期 2014 年 9 月 17 日(日-月-年) 我需要对它们进行升序排序,所以我使用了这个命令: SELECT * FROM table ORDER
我目前正在将 MySQL 存储过程重写为 MS SQL 存储过程,但遇到了问题。 在 MySQL 存储过程中,有一个游标,它根据最近的日期 (effdate) 选择一个值并将其放入变量 (thestt
我想要 gwt r.QuestionId- 排序。但是我得到未排序的 QuestionId 尽管我提到了 QuestionId ASC 的顺序。 SELECT r.QuestionId,
我有一个关于在 scandir 函数中排序的基本问题。到目前为止,我阅读了 POSIX readdir 的手册页,但没有找到有关订购保证的具体信息。 但是当我遍历大目录(无法更改,只读)时,我在多个系
基本上我必须从 SQL 数据库中构建项目列表,但是用户可以选择对 7 个过滤器的任意组合进行过滤,也可以选择要排序的列以及按方向排序。 正如您可以想象的那样,这会以大量不同的组合进行编码,并且数据集非
我有两张 table 。想象第一个是一个目录,包含很多文件(第二个表)。 第二个表(文件)包含修改日期。 现在,我想选择所有目录并按修改日期 ASC 对它们进行排序(因此,最新的修改最上面)。我不想显
我想先根据用户的状态然后根据用户名来排序我的 sql 请求。该状态由 user_type 列设置: 1=活跃,2=不活跃,3=创始人。 我会使用此请求来执行此操作,但它不起作用,因为我想在“活跃”成员
在 C++ 中,我必须实现一个“类似 Excel/Access”(引用)的查询生成器,以允许对数据集进行自定义排序。如果您在 Excel 中使用查询构建器或 SQL 中的“ORDER BY a, b,
我面临这样的挑战: 检索按字段 A 排序的文档 如果字段 B 存在/不为空 . 否则 按字段排序 C. 在 SQL 世界中,我会做两个查询并创建一个 UNION SELECT,但我不知道如何从 Mon
我想对源列表执行以下操作: map 列表 排序 折叠 排序 展开 列表 其中一些方法(例如map和toList)是可链接的,因为它们返回非空对象。但是,sort 方法返回 void,因为它对 List
我制作了一个用于分析 Windows 日志消息编号的脚本。 uniq -c 数字的输出很难预测,因为根据数字的大小会有不同的空白。此时,我手动删除了空白。 这是对消息进行排序和计数的命令: cat n
我有以下词典: mydict1 = {1: 11, 2: 4, 5: 1, 6: 1} mydict2 = {1: 1, 5: 1} 对于它们中的每一个,我想首先按值(降序)排序,然后按键(升序)排序
我刚刚开始使用泛型,目前在对多个字段进行排序时遇到问题。 案例: 我有一个 PeopleList 作为 TObjectList我希望能够通过一次选择一个排序字段,但尽可能保留以前的排序来制作类似 Ex
有没有办法在 sql 中组合 ORDER BY 和 IS NULL 以便我可以在列不为空时按列排序,但如果它为null,按另一列排序? 最佳答案 类似于: ORDER BY CASE WHEN
我有一个包含 2 列“id”和“name”的表。 id 是常规的自动增量索引,name 只是 varchar。 id name 1 john 2 mary 3 pop 4 mary 5 j
场景 网站页面有一个带有分页、过滤、排序功能的表格 View 。 表中的数据是从REST API服务器获取的,数据包含数百万条记录。 数据库 REST API 服务器 Web 服务器 浏览器 问
假设我有一本字典,其中的键(单词)和值(分数)如下: GOD 8 DONG 16 DOG 8 XI 21 我想创建一个字典键(单词)的 NSArray,首先按分数排序,然后按字
如何在 sphinx 上通过 sql 命令选择前 20 行按标题 WEIGHT 排序,接下来 20 行按标题 ASC 排序(总共 40 个结果),但不要给出重复的标题输出。 我尝试了这个 sql 命令
我有一个奇怪的问题,当从 SQLite 数据库中选择信息并根据日期排序时,返回的结果无效。 我的SQL语句是这样的: Select pk from usersDates order by dateti
我是一名优秀的程序员,十分优秀!