I need to calculate PI using multiple threads for my homework. The problem is -- when using more than one thread, most of the time the sum is calculated incorrectly (smaller than it should be). I've spent quite some time on figuring it out, so maybe I'm overlooking something obvious. Hoping for your help.
P.S. There was a question about the same task. However, my mistake is different.
Here is my code.
#include <stdio.h>
#include <Windows.h>
#include <ctime>
#define THREAD_COUNT 2
#define N 10000000
#define BLOCK_SIZE 43087
typedef struct {
unsigned startPos;
int threadInd;
double threadSum;
bool isCalculating;
} ThreadArg;
HANDLE* threads;
HANDLE* events;
DWORD WINAPI ThreadProc(LPVOID);
void calculate(double* sum, unsigned start);
int main() {
unsigned cursor = 0;
ThreadArg* params = NULL;
threads = NULL;
if (THREAD_COUNT > 1) {
params = (ThreadArg*)malloc(sizeof(ThreadArg)*(THREAD_COUNT - 1));
threads = (HANDLE*)malloc(sizeof(HANDLE)*(THREAD_COUNT - 1));
events = (HANDLE*)malloc(sizeof(HANDLE)*(THREAD_COUNT - 1));
}
for (int i = 0; i < THREAD_COUNT - 1; ++i) {
ThreadArg arg;
arg.isCalculating = true;
arg.startPos = cursor;
arg.threadInd = i;
arg.threadSum = 0;
params[i] = arg;
threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, (LPVOID)(¶ms[i]), CREATE_SUSPENDED, 0);
events[i] = CreateEvent(NULL, TRUE, TRUE, NULL);
cursor += BLOCK_SIZE;
}
unsigned startTime = clock();
for (int i = 0; i < THREAD_COUNT - 1; ++i) {
ResumeThread(threads[i]);
}
double mainSum = 0;
while (cursor < N) {
for (int i = 0; i < THREAD_COUNT - 1; ++i) {
if (!params[i].isCalculating) {
params[i].startPos = cursor;
SetEvent(events[i]);
cursor += BLOCK_SIZE;
}
}
calculate(&mainSum, cursor);
cursor += BLOCK_SIZE;
}
bool allFinished;
do {
allFinished = true;
for (int i = 0; i < THREAD_COUNT - 1; ++i) {
if (params[i].isCalculating) {
allFinished = false;
break;
}
}
} while(!allFinished);
for (int i = 0; i < THREAD_COUNT - 1; ++i) {
mainSum += params[i].threadSum;
CloseHandle(threads[i]);
}
printf("Time: %d\n", clock() - startTime);
printf("PI = %.7f\n", mainSum/N);
free(threads);
free(params);
system("pause");
}
DWORD WINAPI ThreadProc(LPVOID lParam) {
ThreadArg* param = (ThreadArg*)lParam;
while (true) {
ResetEvent(events[param->threadInd]);
calculate(¶m->threadSum, param->startPos);
InterlockedDecrement((LONG*)¶m->isCalculating);
WaitForSingleObject(events[param->threadInd], INFINITE);
InterlockedIncrement((LONG*)¶m->isCalculating);
}
}
void calculate(double* sum, unsigned start) {
int endLoop = start + BLOCK_SIZE;
double x;
for (unsigned i = start; i < endLoop; ++i) {
if (i < N) {
x = (i + 0.5) / N;
*sum += 4 / (1 + x*x);
} else break;
}
}
you not need events at all. working thread never must wait. all can be done with interlocked operations.
class CALC_TASK
{
C_ASSERT(sizeof(double)==sizeof(__int64));
union {
double _sum;
__int64 _value;
};
double _step;
LONG _startPos, _maxPos, _blockSize;
static double calculate(LONG i, LONG count, double step)
{
double x, sum = 0.0;
do
{
x = (i-- - 0.5) * step;
sum += 4.0 / (1.0 + x*x);
} while (--count);
return step * sum;
}
void add(double x)
{
union {
double sum;
__int64 value;
};
union {
double new_sum;
__int64 new_value;
};
sum = _sum;
for ( ; ; value = new_value)
{
new_sum = sum + x;
new_value = _InterlockedCompareExchange64(&_value, new_value, value);
if (new_value == value)
{
return;
}
}
}
BOOL getBlock(LONG& pos, LONG& count)
{
LONG startPos, newPos, curPos;
for (startPos = _startPos ; startPos < _maxPos; startPos = curPos)
{
if ((newPos = startPos + _blockSize) > _maxPos)
{
newPos = _maxPos;
}
curPos = _InterlockedCompareExchange(&_startPos, newPos, startPos);
if (curPos == startPos)
{
pos = newPos, count = newPos - startPos;
return TRUE;
}
}
return FALSE;
}
void calculateEx()
{
LONG i, count;
double step = _step;
while (getBlock(i, count))
{
add(calculate(i, count, step));
}
}
public:
double getsum()
{
return _sum;
}
CALC_TASK(LONG maxPos, LONG blockSize)
{
_startPos = 0, _blockSize = blockSize, _maxPos = maxPos, _sum = 0.0, _step = 1.0 / (double)maxPos;
}
static DWORD CALLBACK ThreadProc(PVOID pct)
{
reinterpret_cast<CALC_TASK*>(pct)->calculateEx();
return 0;
}
};
double test(LONG maxPos, LONG blockSize)
{
SYSTEM_INFO si;
GetNativeSystemInfo(&si);
PHANDLE phThreads = 0;
ULONG nThreads = 0;
CALC_TASK ct(maxPos, blockSize);
if (1 < si.dwNumberOfProcessors)
{
ULONG n = si.dwNumberOfProcessors - 1;
phThreads = (HANDLE*)alloca(n * sizeof(HANDLE));
do
{
if (*phThreads = CreateThread(NULL, PAGE_SIZE, CALC_TASK::ThreadProc, &ct, 0, 0))
{
nThreads++, phThreads++;
}
} while (--n);
}
CALC_TASK::ThreadProc(&ct);
if (nThreads)
{
WaitForMultipleObjects(nThreads, phThreads - nThreads, TRUE, INFINITE);
do
{
CloseHandle(*--phThreads);
} while (--nThreads);
}
return ct.getsum();
}
void testEx()
{
ULONG dwStart = GetTickCount();
double d = test(0x10000000, 0x8000);
dwStart = GetTickCount() - dwStart;
DbgPrint("pi = %.15f, %u milliseconds\n", d, dwStart);
}
in my test with 8 core/treads it take ~ 0.5 second for 0x10000000 steps. with single thread this take ~3.5 seconds.
as alternative you can use openMP
double calculateOMP(int num_steps)
{
double x, sum = 0.0, step = 1.0 / (double) num_steps;
#pragma omp parallel for reduction(+:sum) private(x)
for (int i = num_steps; i > 0; --i)
{
x = (i - 0.5) * step;
sum += 4.0 / (1.0 + x*x);
}
return step * sum;
}
for this you need use /openmp option and add vcomp.lib to linker input
Related
ran into a problem regarding fprintf, we want to write a double array into our file for every loop in our main's while loop, however when this loop goes higher than 10 it simply stops fprintf'ing.
The function in question is "store_trash_file". Also the program is controlled by a few defines at top.
Day_max = controls the amount of loops in our while loop
SIZE = with higher SIZE it seems it will fprintf less, and with a smaller it will fprintf more lines.
Ill be putting up the entire code, so u can run it, perhaps keep an eye on the create directories function, as it will make folders and some txts
Any help is much appreciated
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <conio.h>
#include <io.h>
#include <process.h>
#define MARGIN 70
#define MARGIN2 30
#define NAREA 4
#define NSUBAREA 4
#define SIZE 20
#define DAY_MAX 20
#define AREAS_PER_TRUCK 4
#define LOWER1 6
#define LOWER2 8
#define LOWER3 10
#define UPPER1 8
#define UPPER2 10
#define UPPER3 12
typedef struct subarea
{
int co2_cost, time, emptied_subarea_counter, lower_random, upper_random, activity_level;
double average, total_trash_subarea_avg, sensorData[SIZE], sensorDataTotal[SIZE];
} subarea;
typedef struct area
{
subarea *subarea_array[NAREA + 1];
double average, total_trash_area_avg;
int emptied_area_counter;
} area;
void simulated_days(area *area_dynamic, area *area_static);
void average_trash(area *area);
void sensor_data_start(area *area, double start_var);
void compare_trash_to_empty(area *area_array[NAREA + 1], int *area_number_p);
void empty_trash(area *area, int *co2_counter_p, int *time_counter_p);
void store_trash_file(area *area_array[NAREA + 1]);
void create_areas(area *area_array[NAREA + 1]);
void empty_trash_static(area *area, int *co2_counter_static_p, int *time_counter_static_p);
void create_directories();
void make_txt_file(char file_name[30], char file_name2[30]);
int main(void)
{
int co2_counter = 0, time_counter = 0;
int co2_counter_static = 0, time_counter_static = 0;
int day_counter = 0;
int area_number;
int garbage_truck_amount = 0;
double *area_array_avg[DAY_MAX][NAREA];
double *subarea_array_avg[DAY_MAX][NAREA * NSUBAREA];
double *trashcan_array_avg[DAY_MAX][NAREA * NSUBAREA * SIZE];
area *area_array[NAREA + 1];
area *area_array_static[NAREA + 1];
srand(time(NULL));
for (int i = NAREA; i > 0; i -= AREAS_PER_TRUCK)
{
garbage_truck_amount++;
}
printf("Garbage trucks: %d\n", garbage_truck_amount);
create_areas(area_array);
create_areas(area_array_static);
create_directories();
int running = 1;
while (running)
{
for (int i = 1; i < NAREA + 1; i++)
{
simulated_days(area_array[i], area_array_static[i]);
average_trash(area_array[i]);
average_trash(area_array_static[i]);
}
for (int i = 1; i < NAREA + 1; i++)
{
for (int j = 0; j < NSUBAREA; j++)
{
printf("area array: %lf\n", area_array[i]->subarea_array[j]->average);
printf("area array static: %lf\n", area_array_static[i]->subarea_array[j]->average);
}
}
for (int i = 0; i < garbage_truck_amount; i++)
{
compare_trash_to_empty(area_array, &area_number);
empty_trash(area_array[area_number], &co2_counter, &time_counter);
for (int j = 1; j < NAREA + 1; j++)
{
average_trash(area_array[j]);
}
}
if (day_counter > 1 && day_counter % 14 == 0)
{
for (int i = 1; i < NAREA + 1; i++)
{
empty_trash_static(area_array_static[i], &co2_counter_static, &time_counter_static);
average_trash(area_array_static[i]);
}
}
store_trash_file(area_array);
printf("Day: %d\n", day_counter + 1);
for (int i = 0; i < NSUBAREA; i++)
{
for (int j = 1; j < NAREA + 1; j++)
{
printf("%lf\t", area_array[j]->subarea_array[i]->average);
printf("%lf\t", area_array_static[j]->subarea_array[i]->average);
}
printf("\n");
}
printf("\n");
day_counter++;
if(day_counter == DAY_MAX)
{
running = 0;
}
}
}
void simulated_days(area *area_dynamic, area *area_static)
{
for (int i = 0; i < NSUBAREA; i++)
{
for (int j = 0; j < SIZE; j++)
{
int x = ((rand() % (area_dynamic->subarea_array[i]->upper_random - area_dynamic->subarea_array[i]->lower_random + 1)) + area_dynamic->subarea_array[i]->lower_random);
area_dynamic->subarea_array[i]->sensorData[j] += x;
area_dynamic->subarea_array[i]->sensorDataTotal[j] += x;
area_static->subarea_array[i]->sensorData[j] += x;
area_static->subarea_array[i]->sensorDataTotal[j] += x;
}
}
}
void average_trash(area *area)
{
double sum[NSUBAREA];
double sum_total[NSUBAREA];
double area_trash_sum = 0;
double area_trash_sum_total = 0;
for (int i = 0; i < NSUBAREA; i++)
{
sum[i] = 0;
sum_total[i] = 0;
}
for (int i = 0; i < NSUBAREA; i++)
{
for (int j = 0; j < SIZE; j++)
{
sum[i] += area->subarea_array[i]->sensorData[j];
sum_total[i] += area->subarea_array[i]->sensorDataTotal[j];
}
area->subarea_array[i]->average = sum[i] / SIZE;
area->subarea_array[i]->total_trash_subarea_avg = sum_total[i] / SIZE;
}
for (int i = 0; i < NSUBAREA; i++)
{
area_trash_sum += area->subarea_array[i]->average;
area_trash_sum_total += area->subarea_array[i]->total_trash_subarea_avg;
}
area->average = area_trash_sum / NSUBAREA;
area->total_trash_area_avg = area_trash_sum_total / NSUBAREA;
}
void sensor_data_start(area *area, double start_var)
{
for (int i = 0; i < NSUBAREA; i++)
{
for (int j = 0; j < SIZE; j++)
{
area->subarea_array[i]->sensorData[j] = start_var;
area->subarea_array[i]->sensorDataTotal[j] = start_var;
}
}
}
void compare_trash_to_empty(area *area_array[NAREA + 1], int *area_number_p)
{
int highBlock = 0;
for (int i = 1; i < NAREA + 1; i++)
{
if (area_array[i]->average >= MARGIN)
{
if (area_array[i]->average > area_array[highBlock]->average)
{
highBlock = i;
}
}
}
*area_number_p = highBlock;
printf("\nhighblock %d\n", highBlock);
}
void empty_trash(area *area, int *co2_counter_p, int *time_counter_p)
{
for (int i = 0; i < NSUBAREA; i++)
{
if (area->subarea_array[i]->average > MARGIN2)
{
*co2_counter_p += area->subarea_array[i]->co2_cost;
*time_counter_p += area->subarea_array[i]->time;
area->subarea_array[i]->average = 0;
area->subarea_array[i]->emptied_subarea_counter++;
for (int j = 0; j < SIZE; j++)
{
if (area->subarea_array[i]->sensorData[j] <= 100)
{
area->subarea_array[i]->sensorData[j] = 0;
}
else if (area->subarea_array[i]->sensorData[j] > 100)
{
area->subarea_array[i]->sensorData[j] -= 100;
}
}
}
}
area->emptied_area_counter++;
}
void store_trash_file(area *area_array[NAREA + 1])
{
// int xcount = 0;
// int ycount = 0;
// double area_array_avg[NAREA];
// double subarea_array_avg[NAREA * NSUBAREA];
// double trashcan_array_avg[NAREA * NSUBAREA * SIZE];
FILE *output_filepointer;
char *dirname2 = "C:\\Users\\jacob\\Documents\\software\\projekter\\p1\\kode\\intelligenttrash\\data\\area";
char newdirname[150];
char newdirname2[150];
char newdirname3[150];
for (int i = 1; i < NAREA + 1; i++)
{
// area_array_avg[i - 1] = (area_array[i]->total_trash_area_avg);
snprintf(newdirname, 150, "%s%d\\area_average_total.txt", dirname2, i);
output_filepointer = fopen(newdirname, "a");
fprintf(output_filepointer, "%lf ", area_array[i]->total_trash_area_avg);
for (int j = 0; j < NSUBAREA; j++)
{
// subarea_array_avg[j + (ycount * NSUBAREA)] = (area_array[i]->subarea_array[j]->total_trash_subarea_avg);
snprintf(newdirname2, 150, "%s%d%s%d\\subarea_average_total.txt", dirname2, i, "\\subarea", j);
output_filepointer = fopen(newdirname2, "a");
fprintf(output_filepointer, "%lf ", area_array[i]->subarea_array[j]->total_trash_subarea_avg);
for (int z = 0; z < SIZE; z++)
{
// trashcan_array_avg[z + (xcount * SIZE)] = (area_array[i]->subarea_array[j]->sensorDataTotal[z]);
snprintf(newdirname3, 150, "%s%d%s%d\\trashcan_trash.txt", dirname2, i, "\\subarea", j);
output_filepointer = fopen(newdirname3, "a");
fprintf(output_filepointer, "%lf ", area_array[i]->subarea_array[j]->sensorDataTotal[z]);
}
// xcount++;
fprintf(output_filepointer, "\n");
output_filepointer = fopen(newdirname2, "a");
fprintf(output_filepointer, "\n");
}
// ycount++;
output_filepointer = fopen(newdirname, "a");
fprintf(output_filepointer, "\n");
}
fclose(output_filepointer);
}
void create_areas(area *area_array[NAREA + 1])
{
int percentage_added[3][2] = {{LOWER1, UPPER1}, {LOWER2, UPPER2}, {LOWER3, UPPER3}};
int activity_level;
for (int i = 0; i < NAREA + 1; i++)
{
area_array[i] = malloc(sizeof(area));
for (int j = 0; j < NSUBAREA; j++)
{
activity_level = (rand() % 3);
area_array[i]->subarea_array[j] = malloc(sizeof(subarea));
area_array[i]->subarea_array[j]->co2_cost = 50;
area_array[i]->subarea_array[j]->time = 50;
area_array[i]->subarea_array[j]->average = 0;
area_array[i]->subarea_array[j]->emptied_subarea_counter = 0;
area_array[i]->subarea_array[j]->total_trash_subarea_avg = 0;
area_array[i]->subarea_array[j]->lower_random = percentage_added[activity_level][0];
area_array[i]->subarea_array[j]->upper_random = percentage_added[activity_level][1];
area_array[i]->subarea_array[j]->activity_level = activity_level;
}
sensor_data_start(area_array[i], 0);
area_array[i]->average = 0;
area_array[i]->total_trash_area_avg = 0;
area_array[i]->emptied_area_counter = 0;
}
}
void empty_trash_static(area *area, int *co2_counter_static_p, int *time_counter_static_p)
{
for (int i = 0; i < NSUBAREA; i++)
{
*co2_counter_static_p += area->subarea_array[i]->co2_cost;
*time_counter_static_p += area->subarea_array[i]->time;
area->subarea_array[i]->average = 0;
area->subarea_array[i]->emptied_subarea_counter++;
for (int j = 0; j < SIZE; j++)
{
if (area->subarea_array[i]->sensorData[j] <= 100)
{
area->subarea_array[i]->sensorData[j] = 0;
}
else if (area->subarea_array[i]->sensorData[j] > 100)
{
area->subarea_array[i]->sensorData[j] -= 100;
}
}
}
area->emptied_area_counter++;
}
void create_directories()
{
int check;
char *dirname1 = "C:\\Users\\jacob\\Documents\\software\\projekter\\p1\\kode\\intelligenttrash\\data";
char *dirname2 = "C:\\Users\\jacob\\Documents\\software\\projekter\\p1\\kode\\intelligenttrash\\data\\area";
mkdir(dirname1);
for (int i = 1; i < NAREA + 1; i++)
{
char newdirname[100];
char newdirname2[100];
snprintf(newdirname, 100, "%s%d", dirname2, i);
mkdir(newdirname);
for (int j = 1; j < NSUBAREA + 1; j++)
{
snprintf(newdirname2, 100, "%s%d%s%d", dirname2, i, "\\subarea", j);
mkdir(newdirname2);
}
}
}
void make_txt_file(char file_name[30], char file_name2[30])
{
FILE *output_filepointer;
char *dirname2 = "C:\\Users\\jacob\\Documents\\software\\projekter\\p1\\kode\\intelligenttrash\\data\\area";
char newdirname[100];
char newdirname2[100];
for (int i = 1; i < NAREA + 1; i++)
{
if (file_name != "none")
{
snprintf(newdirname, 100, "%s%d\\%s.txt", dirname2, i, file_name);
output_filepointer = fopen(newdirname, "a");
}
for (int j = 1; j < NSUBAREA + 1; j++)
{
if (file_name2 != "none")
{
snprintf(newdirname2, 100, "%s%d%s%d\\%s.txt", dirname2, i, "\\subarea", j, file_name2);
output_filepointer = fopen(newdirname2, "a");
}
}
}
fclose(output_filepointer);
}
I am writing a scheduling algorithm while studying the Operating System.
And 'fopen_s' was used to receive information about the process from a 'txt' file.
First, I checked the function's output with 'errno_t', and it was normal with '0'.
However, if I try to execute it, an error such as an image appears and cannot proceed. Where did the error occur?
This code was written in Visual Studio 2017 using the c language.
This is 'process.txt'. (All are integers.)
1 1 0 10 3
1 2 0 1 1
1 3 0 2 4
1 4 0 5 2
2 5 0 5 2
2 6 0 4 3
2 7 0 1 2
2 8 0 7 1
3 9 0 5 2
3 10 0 4 3
3 11 0 1 4
3 12 0 6 1
This is the core code that causes the error.
int main()
{
sem_init(&semaphore, 0, 1);
q1 = (Process *)malloc(sizeof(Process) * 100);
q2 = (Process *)malloc(sizeof(Process) * 100);
q3 = (Process *)malloc(sizeof(Process) * 100);
FILE *fpp = NULL;
errno_t err = fopen_s(&fpp, "sample.txt", "r");
if (fpp = NULL)
{
printf("OPEN ERROR\n");
return 0;
}
while (!feof(fpp))
{
fscanf_s(fpp, "%d %d %d %d %d",
&class_num, &sub_id, &sub_arrive_time, &sub_burst, &sub_priority);
if (class_num == 1)
{
q1[i_q1].id = sub_id;
q1[i_q1].arrive_time = sub_arrive_time;
q1[i_q1].burst = sub_burst;
q1[i_q1].priority = sub_priority;
i_q1++;
}
else if (class_num = 2)
{
q2[i_q2].id = sub_id;
q2[i_q2].arrive_time = sub_arrive_time;
q2[i_q2].burst = sub_burst;
q2[i_q2].priority = sub_priority;
i_q2++;
}
else if (class_num = 3)
{
q3[i_q3].id = sub_id;
q3[i_q3].arrive_time = sub_arrive_time;
q3[i_q3].burst = sub_burst;
q3[i_q3].priority = sub_priority;
i_q3++;
}
p_count++;
}//초기화 완료
pthread_create(&thread[idx], NULL, MLQS, NULL);//별도의 함수 만들어서 넣기
pthread_join(thread[idx], NULL);
fclose(fpp);
free(q1);
free(q2);
free(q3);
system("pause");
return 0;
}
This is the full code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <pthread.h>
#include <semaphore.h>
#define TRUE 1
#define FALSE 0
typedef struct _process {
int id;
int arrive_time;
int waiting_time;
int return_time;
int turnaround_time;
int response_time;
int burst;
int priority;
int completed;
}Process;
//쓰레드 동기화를 동기화를 위한 semaphore
sem_t semaphore;
int process_count = 0;
int p_count = 0;
int i_q1 = 0;
int i_q2 = 0;
int i_q3 = 0;
int class_num;
int sub_id;
int sub_arrive_time;
int sub_burst;
int sub_priority;
Process *q1;
Process *q2;
Process *q3;
int idx = 0;
pthread_t thread[5];
int time_quantum = 2;
//프로세스 초기화
void p_init(Process p[], int length)
{
int i;
for (i = 0; i < length; i++)
{
p[i].waiting_time = 0;
p[i].return_time = 0;
p[i].response_time = 0;
p[i].completed = FALSE;
}
}
int all_completed(Process *p1, Process *p2, Process *p3, int q1_len, int q2_len, int q3_len)
{
int i;
for (i = 0; i < q1_len; i++)
{
if (p1[i].completed == FALSE)
return FALSE;
}
for (i = 0; i < q2_len; i++)
{
if (p2[i].completed == FALSE)
return FALSE;
}
for (i = 0; i < q2_len; i++)
{
if (p3[i].completed == FALSE)
return FALSE;
}
return TRUE;
}
void print_table(Process p[], int n)
{
int i;
// 반복문에서 사용할 변수 선언
puts("\t+-----+------------+-------------+----------+-------------+-----------------+--------------+-----------------+");
puts("\t| PID | Burst Time | Arrive Time | Priority | Return Time | Response Time | Waiting Time | Turnaround Time |");
puts("\t+-----+------------+-------------+----------+-------------+-----------------+--------------+-----------------+");
/* 프로세스 갯수만큼 반복하며 포맷을 맞추어 출력 */
for (i = 0; i < n; i++)
{
printf("\t| %3d | %3d | %3d | %3d | %3d | %3d | %3d | %3d |\n",
p[i].id, p[i].burst, p[i].arrive_time, p[i].priority, p[i].return_time, p[i].response_time, p[i].waiting_time, p[i].turnaround_time);
puts("\t+-----+------------+-------------+----------+-------------+-----------------+--------------+-----------------+");
}
puts("\n");
}
// 반환 시간을 비교하는 함수
int compare_by_return_time(const void *a, const void *b)
{
Process *pA = (Process *)a;
Process *pB = (Process *)b;
/* pA의 반환 시간이 작을 경우 */
if (pA->return_time < pB->return_time)
return -1;
/* ptA의 반환 시간이 클 경우 */
else if (pA->return_time > pB->return_time)
return 1;
/* 반환 시간이 같을 경우 -> 존재 X */
else
return 0;
}
// 반환 시간을 퀵 소트 기반으로 정렬한다.
void quick_sort_by_return_time(Process p[], int len)
{
qsort(p, len, sizeof(Process), compare_by_return_time);
}
// 우선 순위를 비교하는 함수
int compare_by_priority(Process *a, Process *b)
{
Process *pA = (Process *)a;
Process *pB = (Process *)b;
if (a->priority == b->priority) {
if (a->burst != b->burst) {
if (a->burst < b->burst)
return -1;
else
return 1;
}
else
return 0;
}
else {
if (a->priority < b->priority)
return -1;
else if (a->priority > b->priority)
return 1;
}
}
void quick_sort_by_priority_time()
{
qsort(q1, i_q1, sizeof(Process), compare_by_priority);
}
void gantt_chart(Process p[], int len)
{
int i, j; // 반복문에 사용할 변수
printf("\t ");
for (i = 0; i < len; i++)
{
for (j = 0; j < p[i].burst; j++)
printf("--");
printf(" ");
}
printf("\n\t|");
for (i = 0; i < len; i++)
{
for (j = 0; j < p[i].burst - 1; j++)
printf(" ");
printf("%d", p[i].id);
for (j = 0; j < p[i].burst - 1; j++)
printf(" ");
printf("|");
}
printf("\n\t ");
for (i = 0; i < len; i++)
{
for (j = 0; j < p[i].burst; j++)
printf("--");
printf(" ");
}
printf("\n\t");
printf("0");
for (i = 0; i < len; i++)
{
for (j = 0; j < p[i].burst; j++)
printf(" ");
if (p[i].return_time > 9)
printf("\b");
printf("%d", p[i].return_time);
}
printf("\n");
}
//**************************************************//
// Q1 : Non-preemptive Priority Scheduling Algorithm
// 알고리즘 시간 계산 함수
void Cal_for_npps(Process p[], int len)
{
int i, j; // 반복문에 사용할 변수
int check; // 모든 프로세스 완료 여부 확인
int min; // Priority가 가장 높은 index 저장
int time = 0; // 현재 시간
p[0].return_time = p[0].burst;
p[0].turnaround_time = p[0].return_time - p[0].arrive_time;
p[0].response_time = 0;
p[0].completed = TRUE;
time = p[0].burst;
while (TRUE)//모든 프로세스 완료 시 종료
{
min = INT_MAX;
check = FALSE;
for (i = 1; i < len; i++)//Priority가 가장 높은 프로세스 탐색
{
if ((p[min].priority > p[i].priority) && (p[i].completed == FALSE))
{//현재 Priority보다 작은 Priority 가졌지만 실행되지 않았다면 갱신
min = i;
check = TRUE;
}
}
if (check == FALSE)//모든 프로세스 완료 시 반복문 탈출
break;
p[min].response_time = time - p[min].arrive_time;
p[min].return_time = time + p[min].burst;
p[min].turnaround_time = p[min].return_time - p[min].arrive_time;
p[min].waiting_time = time - p[min].arrive_time;
p[min].completed = TRUE;
time += p[min].burst;
}
}
void *NPPS(void *arg)
{
int i; // 반복문에 사용할 변수
int total_waiting_time = 0;
int total_turnaround_time = 0;
int total_response_time = 0;
p_init(q1, i_q1);
quick_sort_by_priority_time();
Cal_for_npps(q1, i_q1);
for (i = 0; i < i_q1; i++)
{
total_waiting_time += q1[i].waiting_time;
total_turnaround_time += q1[i].turnaround_time;
total_response_time += q1[i].response_time;
}
quick_sort_by_return_time(q1, i_q1);
printf("\tNon-preemptive Priority Scheduling Algorithm\n\n");
gantt_chart(q1, i_q1);
printf("\n\tAverage Waiting Time : %-2.2lf\n", (double)total_waiting_time / (double)i_q1);
printf("\tAverage Turnaround Time : %-2.2lf\n", (double)total_turnaround_time / (double)i_q1);
printf("\tAverage Response Time : %-2.2lf\n\n", (double)total_response_time / (double)i_q1);
print_table(q1, i_q1);
}
//**************************************************//
// Q2 : HRN(Highest Response-Ratio Next)
void *HRN(void *arg)
{
int i, j; // 반복문에 사용할 변수
int time, locate; // 현재 시간과 프로세스 위치
int total_burst_time = 0;
int total_waiting_time = 0;
int total_turnaround_time = 0;
int total_response_time = 0;
float hrr, temp; // 우선순위 저장
p_init(q2, i_q2);
for (i = 0; i < i_q2; i++)
{
total_burst_time += q2[i].burst;
}
for (time = q2[0].arrive_time; time < total_burst_time;)
{
hrr = -99999;
for (i = 0; i < i_q2; i++)// Priority가 가장 높은 프로세스 탐색
{
if (q2[i].completed != TRUE)
{
temp = (q2[i].burst + (time - q2[i].arrive_time)) / q2[i].burst;
if (hrr < temp)//우선순위 갱신
{
hrr = temp;
locate = i;
}
}
}
time += q2[locate].burst;
q2[locate].waiting_time = time - q2[locate].arrive_time - q2[locate].burst;
q2[locate].turnaround_time = time - q2[locate].arrive_time;
q2[locate].return_time = q2[locate].turnaround_time + q2[locate].arrive_time;
q2[locate].response_time = q2[locate].waiting_time;
q2[locate].completed = TRUE;
total_waiting_time += q2[locate].waiting_time;
total_turnaround_time += q2[locate].turnaround_time;
total_response_time += q2[locate].response_time;
}
quick_sort_by_return_time(q2, i_q2);
printf("\tHighest Response Ratio Next Scheduling Algorithm\n\n");
gantt_chart(q2, i_q2);
printf("\n\tAverage Waiting Time : %-2.2lf\n", (double)total_waiting_time / (double)i_q2);
printf("\tAverage Turnaround Time : %-2.2lf\n", (double)total_turnaround_time / (double)i_q2);
printf("\tAverage Response Time : %-2.2lf\n\n", (double)total_response_time / (double)i_q2);
print_table(q2, i_q2);
}
void cal_for_sjf(Process *p, int len)
{
int i, j; // 반복문에 사용할 변수
int cur_time = 0; // 현재 시간
int min = 0; // 최소 시간을 갖는 인덱스 저장
p[0].completed = TRUE;
p[0].return_time = p[0].burst;
p[0].turnaround_time = p[0].burst - p[0].arrive_time;
p[0].waiting_time = 0;
cur_time = p[0].burst;
for (i = 1; i < len; i++)
{
for (j = 1; j < len; j++)
{
if (p[j].completed == TRUE)
continue;
else
{
min = j;
break;
}
}
for (j = 1; j < len; j++)
{
if ((p[j].completed == FALSE) && (p[j].burst < p[min].burst))
{
min = j;
}
}
p[min].waiting_time = cur_time - p[min].arrive_time;
p[min].completed = TRUE;
cur_time += p[min].burst;
p[min].return_time = cur_time;
p[min].turnaround_time = p[min].return_time - p[min].arrive_time;
}
}
void *SJF(void *arg)
{
int i;
int total_waiting_time = 0;
int total_turnaround_time = 0;
int total_response_time = 0;
p_init(q3, i_q3);
cal_for_sjf(q3, i_q3);
for (i = 0; i < i_q3; i++)
{
q3[i].return_time = q3[i].turnaround_time + q3[i].arrive_time;
q3[i].response_time = q3[i].waiting_time;
total_waiting_time += q3[i].waiting_time;
total_turnaround_time += q3[i].turnaround_time;
total_response_time += q3[i].response_time;
}
printf("\tSJF Scheduling Algorithms\n\n");
quick_sort_by_return_time(q3, i_q3);
gantt_chart(q3, i_q3);
printf("\n\tAverage Waiting Time : %-2.2lf\n", (double)total_waiting_time / (double)i_q3);
printf("\tAverage Turnaround Time : %-2.2lf\n", (double)total_turnaround_time / (double)i_q3);
printf("\tAverage Response Time : %-2.2lf\n\n", (double)total_response_time / (double)i_q3);
print_table(q3, i_q3);
}
void *MLQS(void *arg)
{
idx++;
while (all_completed(q1, q2, q3, i_q1, i_q2, i_q3)) {
sem_wait(&semaphore);
if (idx == 1) {
pthread_create(&thread[idx], NULL, NPPS, NULL);
pthread_join(thread[idx], NULL);
}
else if (idx == 2) {
pthread_create(&thread[idx], NULL, HRN, NULL);
pthread_join(thread[idx], NULL);
}
else if (idx == 3) {
pthread_create(&thread[idx], NULL, SJF, NULL);
pthread_join(thread[idx], NULL);
}
idx++;
sem_post(&semaphore);
if (idx > 3)
idx = 1;
}
}
int main()
{
sem_init(&semaphore, 0, 1);
q1 = (Process *)malloc(sizeof(Process) * 100);
q2 = (Process *)malloc(sizeof(Process) * 100);
q3 = (Process *)malloc(sizeof(Process) * 100);
FILE *fpp = NULL;
errno_t err = fopen_s(&fpp, "sample.txt", "r");
if (fpp = NULL)
{
printf("OPEN ERROR\n");
return 0;
}
while (!feof(fpp))
{
fscanf_s(fpp, "%d %d %d %d %d",
&class_num, &sub_id, &sub_arrive_time, &sub_burst, &sub_priority);
if (class_num == 1)
{
q1[i_q1].id = sub_id;
q1[i_q1].arrive_time = sub_arrive_time;
q1[i_q1].burst = sub_burst;
q1[i_q1].priority = sub_priority;
i_q1++;
}
else if (class_num = 2)
{
q2[i_q2].id = sub_id;
q2[i_q2].arrive_time = sub_arrive_time;
q2[i_q2].burst = sub_burst;
q2[i_q2].priority = sub_priority;
i_q2++;
}
else if (class_num = 3)
{
q3[i_q3].id = sub_id;
q3[i_q3].arrive_time = sub_arrive_time;
q3[i_q3].burst = sub_burst;
q3[i_q3].priority = sub_priority;
i_q3++;
}
p_count++;
}//초기화 완료
pthread_create(&thread[idx], NULL, MLQS, NULL);//별도의 함수 만들어서 넣기
pthread_join(thread[idx], NULL);
fclose(fpp);
free(q1);
free(q2);
free(q3);
system("pause");
return 0;
}
Beside all the issues mentioned in the comments:
if (fpp = NULL)
assigns NULL to ffp instead of comparing it (and the condition is always false). You mean
if (fpp == NULL)
I am trying to build an efficient concurrent hash map using pthreads, C.
Following is my implementation
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <stdint.h>
#include <limits.h>
#include <stdio.h>
#include <linux/limits.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#define ENTRIES_PER_BUCKET 3
struct Bucket
{
pthread_mutex_t mutex;
void **keys;
int *vals;
struct Bucket *next;
};
struct Concurrent_Map
{
struct Bucket *buckets;
map_keys_equality *keys_eq;
map_key_hash *khash;
int capacity;
};
int concurrent_map_allocate /*# <t> #*/ (map_keys_equality *keq, map_key_hash *khash,
unsigned capacity,
struct Concurrent_Map **map_out)
{
struct Concurrent_Map *old_map_val = *map_out;
struct Concurrent_Map *map_alloc = malloc(sizeof(struct Concurrent_Map));
if (map_alloc == NULL)
{
return 0;
}
*map_out = (struct Concurrent_Map *)map_alloc;
struct Bucket *buckets_alloc = (struct Bucket *)malloc(sizeof(struct Bucket) * (int)capacity);
if (buckets_alloc == NULL)
{
free(map_alloc);
*map_out = old_map_val;
return 0;
}
(*map_out)->buckets = buckets_alloc;
(*map_out)->capacity = capacity;
(*map_out)->keys_eq = keq;
(*map_out)->khash = khash;
unsigned i;
for (i = 0; i < capacity; i++)
{
if (pthread_mutex_init(&((*map_out)->buckets[i].mutex), NULL) == 0)
{
void **key_alloc = malloc(sizeof(void *) * (ENTRIES_PER_BUCKET));
if (key_alloc != NULL)
{
(*map_out)->buckets[i].keys = key_alloc;
int k;
for (k = 0; k < ENTRIES_PER_BUCKET; k++)
{
(*map_out)->buckets[i].keys[k] = NULL;
}
}
int *vals_alloc = malloc(sizeof(int) * (ENTRIES_PER_BUCKET));
if (vals_alloc != NULL)
{
(*map_out)->buckets[i].vals = vals_alloc;
int k;
for (k = 0; k < ENTRIES_PER_BUCKET; k++)
{
(*map_out)->buckets[i].vals[k] = -1;
}
}
(*map_out)->buckets[i].next = NULL;
}
}
// todo exceptions in allocation
return 1;
}
static unsigned loop(unsigned k, unsigned capacity)
{
unsigned g = k % capacity;
unsigned res = (g + capacity) % capacity;
return res;
}
int concurrent_map_get(struct Concurrent_Map *map, void *key, int *value_out)
{
map_key_hash *khash = map->khash;
unsigned hash = khash(key);
unsigned start = loop(hash, map->capacity);
unsigned bucket_index = loop(start + 0, map->capacity);
if (bucket_index < map->capacity)
{
struct Bucket *bucket = &(map->buckets[bucket_index]);
pthread_mutex_t mutex = bucket->mutex;
pthread_mutex_lock(&mutex);
int j;
do
{
for (j = 0; j < ENTRIES_PER_BUCKET; j++)
{
int val = bucket->vals[j];
if (map->keys_eq(bucket->keys[j], key))
{
if (bucket->vals[j] == val)
{
*value_out = val;
return 1;
}
else
{
*value_out = -1;
return 0;
}
}
}
if (bucket->next != NULL)
{
bucket = (bucket->next);
}
else
{
break;
pthread_mutex_unlock(&mutex);
}
pthread_mutex_unlock(&mutex);
} while (1);
}
*value_out = -1;
return 0;
}
int concurrent_map_put(struct Concurrent_Map *map, void *key, int value)
{
map_key_hash *khash = map->khash;
unsigned hash = khash(key);
unsigned start = loop(hash, map->capacity);
unsigned bucket_index = loop(start + 0, map->capacity);
struct Bucket *bucket = &(map->buckets[bucket_index]);
int j;
do
{
pthread_mutex_t mutex = bucket->mutex;
int j;
pthread_mutex_lock(&mutex);
for (j = 0; j < ENTRIES_PER_BUCKET; j++)
{
if (map->keys_eq(bucket->keys[j], key))
{
pthread_mutex_unlock(&mutex);
return 0;
}
else if (bucket->keys[j] == NULL)
{
bucket->vals[j] = value;
bucket->keys[j] = key;
pthread_mutex_unlock(&mutex);
return 1;
}
}
if (bucket->next == NULL)
{
// allocate a new bucket
struct Bucket *new_bucket = malloc(sizeof(struct Bucket));
if (pthread_mutex_init(&(new_bucket->mutex), NULL) == 0)
{
void **key_alloc = malloc(sizeof(void *) * (ENTRIES_PER_BUCKET));
if (key_alloc != NULL)
{
new_bucket->keys = key_alloc;
int k;
for (k = 0; k < ENTRIES_PER_BUCKET; k++)
{
new_bucket->keys[k] = NULL;
}
}
int *vals_alloc = malloc(sizeof(int) * (ENTRIES_PER_BUCKET));
if (vals_alloc != NULL)
{
new_bucket->vals = vals_alloc;
int k;
for (k = 0; k < ENTRIES_PER_BUCKET; k++)
{
new_bucket->vals[k] = -1;
}
}
bucket->next = new_bucket;
}
}
pthread_mutex_unlock(&mutex);
bucket = bucket->next;
} while (1);
return 0;
}
int concurrent_map_erase(struct Concurrent_Map *map, void *key, void **trash)
{
map_key_hash *khash = map->khash;
unsigned hash = khash(key);
unsigned start = loop(hash, map->capacity);
unsigned bucket_index = loop(start + 0, map->capacity);
struct Bucket *bucket = &(map->buckets[bucket_index]);
int j;
do
{
pthread_mutex_t mutex = bucket->mutex;
int j;
pthread_mutex_lock(&mutex);
for (j = 0; j < ENTRIES_PER_BUCKET; j++)
{
if (map->keys_eq(bucket->keys[j], key))
{
bucket->vals[j] = -1;
bucket->keys[j] = NULL;
pthread_mutex_unlock(&mutex);
return 1;
}
}
pthread_mutex_unlock(&mutex);
if (bucket->next != NULL)
{
bucket = (bucket->next);
}
else
{
break;
}
} while (1);
return 0;
}
int concurrent_map_size(struct Concurrent_Map *map)
{
int num_buckets = 0;
struct Bucket *buckets = map->buckets;
unsigned i;
for (i = 0; i < map->capacity; i++)
{
struct Bucket bucket = buckets[i];
do
{
num_buckets++;
if (bucket.next != NULL)
{
bucket = *(bucket.next);
}
else
{
break;
}
} while (1);
}
return num_buckets * ENTRIES_PER_BUCKET;
}
struct FlowId
{
int src_port;
int dst_port;
int src_ip;
int dst_ip;
int internal_device;
int protocol;
};
bool FlowId_eq(void *a, void *b)
{
if (a == NULL || b == NULL)
{
return false;
}
struct FlowId *id1 = a;
struct FlowId *id2 = b;
return (id1->src_port == id2->src_port) && (id1->dst_port == id2->dst_port) && (id1->src_ip == id2->src_ip) && (id1->dst_ip == id2->dst_ip) && (id1->internal_device == id2->internal_device) && (id1->protocol == id2->protocol);
}
unsigned FlowId_hash(void *obj)
{
struct FlowId *id = obj;
unsigned hash = 0;
hash = __builtin_ia32_crc32si(hash, id->src_port);
hash = __builtin_ia32_crc32si(hash, id->dst_port);
hash = __builtin_ia32_crc32si(hash, id->src_ip);
hash = __builtin_ia32_crc32si(hash, id->dst_ip);
hash = __builtin_ia32_crc32si(hash, id->internal_device);
hash = __builtin_ia32_crc32si(hash, id->protocol);
return hash;
}
struct Concurrent_Map *concurrent_map;
#define NUM_THREADS 2
#define NUM_PACKETS 10000000
void *expirator(void *arg)
{
// printf("Thread started executing\n");
unsigned i = 0;
int error = 0;
unsigned packet_count = NUM_PACKETS / NUM_THREADS;
while (i < packet_count)
{
i++;
struct FlowId *id = malloc(sizeof(struct FlowId));
struct FlowId *id1 = malloc(sizeof(struct FlowId));
id->dst_ip = 1;
id->src_ip = 1;
id->internal_device = 1;
id->protocol = 1;
id->src_port = 1;
id->dst_port = rand() % 65536;
id1->dst_ip = 1;
id1->src_ip = 1;
id1->internal_device = 1;
id1->protocol = 1;
id1->src_port = 1;
id1->dst_port = rand() % 65536;
int external_port = rand() % 65536;
int external;
concurrent_map_erase(concurrent_map, id, NULL);
concurrent_map_put(concurrent_map, id, external_port);
concurrent_map_get(concurrent_map, id, &external);
if (external_port != external)
{
error++;
}
else
{
}
}
return NULL;
}
int main()
{
clock_t begin = clock();
concurrent_map_allocate(FlowId_eq, FlowId_hash, 65536, &(concurrent_map));
pthread_t *threads = malloc(sizeof(pthread_t) * NUM_THREADS);
int i;
for (i = 0; i < NUM_THREADS; i++)
{
if (pthread_create(&threads[i], NULL, expirator, NULL) != 0)
{
printf("Error creating threads");
exit(0);
}
}
for (i = 0; i < NUM_THREADS; i++)
{
if (pthread_join(threads[i], NULL) != 0)
{
printf("Error joining threads");
exit(0);
}
}
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("%lf\n", time_spent);
return 0;
}
Here is how to run this program.
gcc concurrent_map.c -o test-concurrent-new -lpthread -msse4.2 -O3
Then I measure the execution time for a fixed workload and following are the time values I observed.
1: 3.29
2: 6.687811
3: 5.88
4: 6.23
5: 6.38
6: 6.52
7: 6.74
8: 6.82
It seems that when the number of threads is increased the execution time increases and remains almost same.
I profiled this code using Mutrace, which looks for mutex contention. It turns out that
No mutex contended according to filtering parameters.
I checked the number of cache misses, and it turned out that number of cache misses are roughly equal when the number of threads is modified.
Why does not the execution time decrease when the number of threads increase?
I am running this on a 32 core machine
rand() is usually not suited for multi threaded execution. Instead use rand_r().
Also use linux time tool for timing the application.
Your workload generation imposes a huge overhead, and I assume it is the bottleneck here, not the concurrent hash map
I need to write a iterative function for this recursive function.
int funcRec(int n){
if(n>1) {
return 2*funcRec(n - 1) + 3*funcRec(n - 2);
}else{
return n;
}
}
Try this one
int funcIter(int n) {
int value0 = 0;
int value1 = 1;
int res = n;
for (int i = 2; i <= n; i++) {
res = 2 * value1 + 3 * value0;
value0 = value1;
value1 = res;
}
return res;
}
I have a function that returns a pointer to an array. I'm running it in a loop and free() seems to be giving me problems. I'm not sure where, but it appears that somewhere in the main loop the memory that I'm trying to free is being used. I'm using Xcode 3.2.1 in 10.6 | Debug | x86_64 build.
The program will run through the main loop one time; the second time it encounters the free() it gives me the following error:
malloc: *** error for object 0x100100180: incorrect checksum for freed object -
object was probably modified after being freed.
Can someone point out (no pun intended) what I'm doing wrong with pointers here?
Here is the program:
int main(int argc, char **argv) {
int *partition;
int lowerLimit;
int upperLimit;
// snip ... got lowerLimit and upperLimit from console arguments
// this is the 'main loop':
for (int i = lowerLimit; i <= upperLimit; i += 2) {
partition = goldbachPartition(i);
printOutput(partition[0], partition[1], i);
free(partition); // I get problems on the second iteration here
}
return 0;
}
int *goldbachPartition(int x) {
int solved = 0;
int y, z;
int *primes;
int *result;
result = intAlloc(2);
primes = atkinsPrimes(x);
for (int i = intCount(primes)-1; i >= 0; i--) {
y = primes[i];
for (int j = 0; j < y; j++) {
z = primes[j];
if (z + y >= x) {
break;
}
}
if (z + y == x) {
solved = 1;
result[0] = y;
result[1] = z;
break;
} else if (y == z) {
result[0] = 0;
result[1] = 0;
break;
}
}
free(primes);
return result;
}
int *atkinsPrimes(int limit) {
int *primes;
int *initialPrimes;
int *filtered;
int *results;
int counter = 0;
int sqrtLimit;
int xLimit;
int resultsSize;
primes = intAlloc(limit+1);
intFillArray(primes, limit+1, 0);
sqrtLimit = floor(sqrt(limit));
xLimit = floor(sqrt((limit+1) / 2));
// these loops are part of the Atkins Sieve implementation
for (int x = 1; x < xLimit; x++) {
int xx = x*x;
for (int y = 1; y < sqrtLimit; y++) {
int yy = y*y;
int n = 3*xx + yy;
if (n <= limit && n % 12 == 7) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
n += xx;
if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
if (x > y) {
n -= xx + 2*yy;
if (n <= limit && n % 12 == 11) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
}
}
}
for (int n = 5; n < limit; n++) {
if (primes[n] == 1) {
for (int k = n*n; k < limit; k += n*n) {
primes[k] = 0;
}
}
}
initialPrimes = intAlloc(2);
if (limit >= 2) {
initialPrimes[counter++] = 2;
}
if (limit >= 3) {
initialPrimes[counter++] = 3;
}
filtered = intFilterArrayKeys(primes, limit+1);
results = intMergeArrays(initialPrimes, filtered, counter, trueCount(primes, limit+1));
resultsSize = counter + trueCount(primes, limit+1);
free(primes);
free(initialPrimes);
free(filtered);
results[resultsSize] = 0;
return results;
}
int trueCount(int *subject, int arraySize) {
int count = 0;
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
count++;
}
}
return count;
}
int intCount(int *subject) {
// warning: expects 0 terminated array.
int count = 0;
while (*subject++ != 0) {
count++;
}
return count;
}
void intFillArray(int *subject, int arraySize, int value) {
for (int i = 0; i < arraySize; i++) {
subject[i] = value;
}
}
int *intFilterArrayKeys(int *subject, int arraySize) {
int *filtered;
int count = 0;
filtered = intAlloc(trueCount(subject, arraySize));
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
filtered[count++] = i;
}
}
return filtered;
}
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2) {
int *merge;
int count = 0;
merge = intAlloc(arraySize1 + arraySize2);
for (int i = 0; i < arraySize1; i++) {
merge[count++] = subject1[i];
}
for (int i = 0; i < arraySize2; i++) {
merge[count++] = subject2[i];
}
return merge;
}
int *intAlloc(int amount) {
int *ptr;
ptr = (int *)malloc(amount * sizeof(int));
if (ptr == NULL) {
printf("Error: NULL pointer\n");
}
return ptr;
}
void printOutput(int num1, int num2, int rep) {
if (num1 == 0) {
printf("%d: No solution\n", rep);
exit(0);
} else {
printf("%d = %d + %d\n", rep, num1, num2);
}
}
Why is intAlloc not returning int* ?
int *intAlloc(int amount) {
int *ptr;
ptr = (int *)malloc(amount * sizeof(int));
if(ptr == NULL) {
printf("Error: NULL pointer\n");
exit(1);
}
return ptr; //like this
}
EDIT (after your update):
On atkinsPrimes() where is filtered being intAlloc()ed?
int *atkinsPrimes(int limit) {
int *primes;
int *initialPrimes;
int *filtered;
int *results;
int resultsSize;
primes = intAlloc(limit+1);
// ...
initialPrimes = intAlloc(2);
// ...
resultsSize = counter + trueCount(primes, limit+1);
free(primes);
free(initialPrimes);
free(filtered); // Where was it intAlloc()ed?
results[resultsSize] = 0; // make the array 0-terminated to make it easier to work with
return results;
}
EDIT (after your N-th update):
This is a compilable version of your code. It ran smooth on my machine, no crashes. Compiled with g++ (due to declarations of variables inside the for statement):
g++ (Debian 4.3.2-1.1) 4.3.2
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int *goldbachPartition(int x);
int *atkinsPrimes(int limit);
int trueCount(int *subject, int arraySize);
int intCount(int *subject) ;
void intFillArray(int *subject, int arraySize, int value);
int *intFilterArrayKeys(int *subject, int arraySize);
int *intAlloc(int amount);
void printOutput(int num1, int num2, int rep) ;
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2);
int main(int argc, char **argv) {
if (argc < 3) {
printf("Usage: ./program <lower> <upper>\n");
return 0;
}
int *partition;
int lowerLimit = atoi(argv[1]);
int upperLimit = atoi(argv[2]);
// snip ... got lowerLimit and upperLimit from console arguments
// this is the 'main loop':
for (int i = lowerLimit; i <= upperLimit; i += 2) {
partition = goldbachPartition(i);
printOutput(partition[0], partition[1], i);
free(partition); // I get problems on the second iteration here
}
return 0;
}
int *goldbachPartition(int x) {
int solved = 0;
int y, z;
int *primes;
int *result;
result = intAlloc(2);
primes = atkinsPrimes(x);
for (int i = intCount(primes)-1; i >= 0; i--) {
y = primes[i];
for (int j = 0; j < y; j++) {
z = primes[j];
if (z + y >= x) {
break;
}
}
if (z + y == x) {
solved = 1;
result[0] = y;
result[1] = z;
break;
} else if (y == z) {
result[0] = 0;
result[1] = 0;
break;
}
}
free(primes);
return result;
}
int *atkinsPrimes(int limit) {
int *primes;
int *initialPrimes;
int *filtered;
int *results;
int counter = 0;
int sqrtLimit;
int xLimit;
int resultsSize;
primes = intAlloc(limit+1);
intFillArray(primes, limit+1, 0);
sqrtLimit = floor(sqrt(limit));
xLimit = floor(sqrt((limit+1) / 2));
for (int x = 1; x < xLimit; x++) {
int xx = x*x;
for (int y = 1; y < sqrtLimit; y++) {
int yy = y*y;
int n = 3*xx + yy;
if (n <= limit && n % 12 == 7) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
n += xx;
if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
if (x > y) {
n -= xx + 2*yy;
if (n <= limit && n % 12 == 11) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
}
}
}
for (int n = 5; n < limit; n++) {
if (primes[n] == 1) {
for (int k = n*n; k < limit; k += n*n) {
primes[k] = 0;
}
}
}
initialPrimes = intAlloc(2);
if (limit >= 2) {
initialPrimes[counter++] = 2;
}
if (limit >= 3) {
initialPrimes[counter++] = 3;
}
filtered = intFilterArrayKeys(primes, limit+1);
results = intMergeArrays(initialPrimes, filtered, counter, trueCount(primes, limit+1));
resultsSize = counter + trueCount(primes, limit+1);
free(primes);
free(initialPrimes);
free(filtered);
results[resultsSize] = 0;
return results;
}
int trueCount(int *subject, int arraySize) {
int count = 0;
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
count++;
}
}
return count;
}
int intCount(int *subject) {
// warning: expects 0 terminated array.
int count = 0;
while (*subject++ != 0) {
count++;
}
return count;
}
void intFillArray(int *subject, int arraySize, int value) {
for (int i = 0; i < arraySize; i++) {
subject[i] = value;
}
}
int *intFilterArrayKeys(int *subject, int arraySize) {
int *filtered;
int count = 0;
filtered = intAlloc(trueCount(subject, arraySize));
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
filtered[count++] = i;
}
}
return filtered;
}
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2) {
int *merge;
int count = 0;
merge = intAlloc(arraySize1 + arraySize2);
for (int i = 0; i < arraySize1; i++) {
merge[count++] = subject1[i];
}
for (int i = 0; i < arraySize2; i++) {
merge[count++] = subject2[i];
}
return merge;
}
int *intAlloc(int amount) {
int *ptr;
ptr = (int *)malloc(amount * sizeof(int));
if (ptr == NULL) {
printf("Error: NULL pointer\n");
}
return ptr;
}
void printOutput(int num1, int num2, int rep) {
if (num1 == 0) {
printf("%d: No solution\n", rep);
exit(0);
} else {
printf("%d = %d + %d\n", rep, num1, num2);
}
}
Since you are still omitting some source, I can only imagine that the problem is hidden there.
EDIT: (my last update)
To assist your debugging, you should replace your main() function by the one below:
int main(int argc, char **argv)
{
int *primes = NULL;
primes = atkinsPrimes(44); // Evil magic number
free(primes);
return 0;
}
Having a minimal example to reproduce the behavior you pointed out is much better then the whole thing. Have fun with atkinsPrimes(44)