ncurses - mvwprintw generates whitespace - c

I have a ncurses project, where I use mvwprintw to print a long string to a window.
mvwprintw(traceview_window_flatprofile, 1, 0, "%s", flatprofile_as_str());
the result looks like this:
% self children self children
time time time calls /call /call name
39.86 886 µs 0 ns 32 27697 ns 0 ns addr_translate [13]
25.69 571 µs 1454 µs 1 571 µs 1454 µs main [0]
7.02 156 µs 0 ns 1 156 µs 0 ns addr_fini [66]
6.28 139 µs 55006 ns 1 139 µs 55006 ns addr_init [2]
3.83 85094 ns 21956 ns 2 42547 ns 10978 ns flatprofile_snprintf [43]
2.08 46150 ns 0 ns 1 46150 ns 0 ns addr_read_symbol_table [3]
When I print the same string to stderr, using
fprintf(stderr, "%s\n", flatprofile_as_str());
the result looks like:
% self children self children
time time time calls /call /call name
39.86 886 µs 0 ns 32 27697 ns 0 ns addr_translate [13]
25.69 571 µs 1454 µs 1 571 µs 1454 µs main [0]
7.02 156 µs 0 ns 1 156 µs 0 ns addr_fini [66]
6.28 139 µs 55006 ns 1 139 µs 55006 ns addr_init [2]
3.83 85094 ns 21956 ns 2 42547 ns 10978 ns flatprofile_snprintf [43]
2.08 46150 ns 0 ns 1 46150 ns 0 ns addr_read_symbol_table [3]
Do you know what could cause this difference?
EDIT: in addition to the answer below, the following question solves a related issue.
How to make ncurses display UTF-8 chars correctly in C?

The difference seems to be caused by the special character µ i am not quite sure how you can fix it but you will probably have to adjust your flatprofile_as_str() function.
I remember having a similar problem with special chars from utf-8 and i solved it by using this function to count not the bytes but the actual lenght of a string:
int strlen_utf8(char *s) {
int i = 0, j = 0;
while (s[i]) {
if ((s[i] & 0xc0) != 0x80) j++;
i++;
}
return j;
}

Related

How to turn an array of arrays into a matrix in Julia?

I want to turn a array of arrays into a matrix. To illustrate; let the array of arrays be:
[ [1,2,3], [4,5,6], [7,8,9]]
I would like to turn this into the 3x3 matrix:
[1 2 3
4 5 6
7 8 9]
How would you do this in Julia?
There are several ways of doing this. For instance, something along the lines of vcat(transpose.(a)...) will work as a one-liner
julia> a = [[1,2,3], [4,5,6], [7,8,9]]
3-element Vector{Vector{Int64}}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
julia> vcat(transpose.(a)...)
3×3 Matrix{Int64}:
1 2 3
4 5 6
7 8 9
though note that
Since your inner arrays are column-vectors as written, you need to transpose them all before you can vertically concatenate (aka vcat) them (either that or horizontally concatenate and then transpose the whole result after, i.e., transpose(hcat(a...))), and
The splatting operator ... which makes this one-liner work will not be very efficient when applied to Arrays in general, and especially not when applied to larger arrays-of-arrays.
Performance-wise for larger arrays-of-arrays, it will likely actually be hard to beat preallocating a result of the right size and then simply filling with a loop, e.g.
result = similar(first(a), length(a), length(first(a)))
for i=1:length(a)
result[i,:] = a[i] # Aside: `=` is actually slightly faster than `.=` here, though either will have the same practical result in this case
end
Some quick benchmarks for reference:
julia> using BenchmarkTools
julia> #benchmark vcat(transpose.($a)...)
BechmarkTools.Trial: 10000 samples with 405 evaluations.
Range (min … max): 241.289 ns … 3.994 μs ┊ GC (min … max): 0.00% … 92.59%
Time (median): 262.836 ns ┊ GC (median): 0.00%
Time (mean ± σ): 289.105 ns ± 125.940 ns ┊ GC (mean ± σ): 2.06% ± 4.61%
▁▆▇█▇▆▅▅▅▄▄▄▄▃▂▂▂▃▃▂▂▁▁▁▂▄▃▁▁ ▁ ▁ ▂
████████████████████████████████▇▆▅▆▆▄▆▆▆▄▄▃▅▅▃▄▆▄▁▃▃▃▅▄▁▃▅██ █
241 ns Histogram: log(frequency) by time 534 ns <
Memory estimate: 320 bytes, allocs estimate: 5.
julia> #benchmark for i=1:length($a)
$result[i,:] = $a[i]
end
BechmarkTools.Trial: 10000 samples with 993 evaluations.
Range (min … max): 33.966 ns … 124.918 ns ┊ GC (min … max): 0.00% … 0.00%
Time (median): 36.710 ns ┊ GC (median): 0.00%
Time (mean ± σ): 39.795 ns ± 7.566 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
▄▄██▄▅▃ ▅▃ ▄▁▂ ▂▁▂▅▂▁ ▄▂▁ ▂
██████████████▇██████▆█▇▆███▆▇███▇▆▆▅▆▅▅▄▄▅▄▆▆▆▄▁▃▄▁▃▄▅▅▃▁▄█ █
34 ns Histogram: log(frequency) by time 77.7 ns <
Memory estimate: 0 bytes, allocs estimate: 0.
In general, filling column-by-column (if possible) will be faster than filling row-by-row as we have done here, since Julia is column-major.
Expanding on #cbk's answer, another (slightly more efficient) one-liner is
julia> transpose(reduce(hcat, a))
3×3 transpose(::Matrix{Int64}) with eltype Int64:
1 2 3
4 5 6
7 8 9
[1 2 3; 4 5 6; 7 8 9]
# or
reshape(1:9, 3, 3)' # remember that ' makes the transpose of a Matrix

What is the behavior of iscntrl?

The function iscntrl is standardized. Unfortuneately on C99 we have:
The iscntrl function tests for any control character
Considering the prototype which is int iscntrl(int c); I am expecting something like true for 0..31 and perhaps 127 too. However in the following:
#include <stdio.h>
#include <ctype.h>
int main()
{
int i;
printf("The ASCII value of all control characters are ");
for (i=0; i<=1024; ++i)
{
if (iscntrl(i)!=0)
printf("%d ", i);
}
return 0;
}
I get this output:
The ASCII value of all control characters are 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 127 264 288 308 310 320 334
336 346 348 372 374 390 398 404 406 412 420 428 436 444 452 458 460 466 468 474
476 484 492 500 506 512 518 530 536 542 638 644 656 662 668 682 688 694 700 706
708 714 716 718 760 774 780 782 788 798 826 834 836 846 854 856 864 866 874 876
882 888 890 892 898 900 908 962 968 970 988 994 1000
So I am wondering how this function is implemented behind the scene. I tried to search on the standard library, but the answer is not obvious.
https://github.com/bminor/glibc/search?q=iscntrl&unscoped_q=iscntrl
Any ideas?
You are invoking undefined behavior by passing improper values to iscntrl().
Per 7.4 Character handling <ctype.h>, paragraph 1:
The header <ctype.h> declares several functions useful for classifying and mapping characters. In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

LMDB random writes really slow for large data (~1MB/s)

I am testing LMDB performance with the benchmark given in http://www.lmdb.tech/bench/ondisk/. And I noticed that LMDB random writes are really slow when the data goes beyond memory.
I am using a machine with 4GB DRAM with Intel PCIE SSD. The key size is 10 bytes and value size is 1KB. The benchmark code is given in http://www.lmdb.tech/bench/ondisk/, and the command line I used is "./db_bench_mdb --benchmarks=fillrandbatch --threads=1 --stats_interval=1024 --num=10000000 --value_size=1000 --use_existing_db=0 ".
For the first 1GB of data written, the average write rate is 140MB/s. The rate then drops significantly to 40MB/s for the first 2GB. At the end of the test, in which 10M values are written, the average rate is just 3MB/s, and the instant rate is 1MB/s. I know LMDB is not optimized for writes, but I didn't expect it to be this slow, given that I have a really high-end Intel SSD.
I also notice that the way LMDB access the SSD is really strange. At the beginning of the test, it writes the SSD at around 400MB/s, but performs no read, which is expected. But as we write more and more data, LMDB starts to read the SSD. As time goes on, the read throughput rises while the write throughput drops significantly. At the end of test, LMDB is constantly reading at around 190MB/s, while occationally issuing 100MB writes at around 10-20 second intervals.
1. Is it normal for LMDB to have such low write throughput (1MB/s at the end of test) for data stored on SSD?
2. Why is LMDB reading more data than it is writing (about 20MB data read per 1MB written) at the end of the test?
To my understanding, although we have more data than the DRAM can hold, the branch nodes of the B-tree should still be in the DRAM. So for every write, the only pages that we need to fetch from SSD is the leaf nodes. And when we write the leaf node, we might also need to write its parents. So there should be more writes than reads. But it turns out LMDB is reading much more than writing. I think it might be the reason why it is so slow at the end. But I really cannot understand why.
For your reference, here is part of the log given by the benchmark:
2018/03/12-10:36:30 ... thread 0: (1024,1024) ops and (54584.2,54584.2) ops/second in (0.018760,0.018760) seconds
2018/03/12-10:36:30 ... thread 0: (1024,2048) ops and (111231.8,73231.8) ops/second in (0.009206,0.027966) seconds
2018/03/12-10:36:30 ... thread 0: (1024,3072) ops and (125382.6,85019.2) ops/second in (0.008167,0.036133) seconds
2018/03/12-10:36:30 ... thread 0: (1024,4096) ops and (206202.2,99661.8) ops/second in (0.004966,0.041099) seconds
2018/03/12-10:36:30 ... thread 0: (1024,5120) ops and (259634.9,113669.2) ops/second in (0.003944,0.045043) seconds
2018/03/12-10:36:30 ... thread 0: (1024,6144) ops and (306495.1,126984.1) ops/second in (0.003341,0.048384) seconds
2018/03/12-10:36:30 ... thread 0: (1024,7168) ops and (339185.2,139447.1) ops/second in (0.003019,0.051403) seconds
2018/03/12-10:36:30 ... thread 0: (1024,8192) ops and (384240.2,151512.9) ops/second in (0.002665,0.054068) seconds
2018/03/12-10:36:30 ... thread 0: (1024,9216) ops and (385252.1,162465.2) ops/second in (0.002658,0.056726) seconds
2018/03/12-10:36:30 ... thread 0: (1024,10240) ops and (371553.0,172152.9) ops/second in (0.002756,0.059482) seconds
...
2018/03/12-10:36:37 ... thread 0: (1024,993280) ops and (70127.4,142518.0) ops/second in (0.014602,6.969505) seconds
2018/03/12-10:36:37 ... thread 0: (1024,994304) ops and (199415.8,142559.9) ops/second in (0.005135,6.974640) seconds
2018/03/12-10:36:37 ... thread 0: (1024,995328) ops and (75953.1,142431.4) ops/second in (0.013482,6.988122) seconds
2018/03/12-10:36:37 ... thread 0: (1024,996352) ops and (200823.7,142474.0) ops/second in (0.005099,6.993221) seconds
2018/03/12-10:36:37 ... thread 0: (1024,997376) ops and (71975.8,142330.8) ops/second in (0.014227,7.007448) seconds
2018/03/12-10:36:37 ... thread 0: (1024,998400) ops and (62117.1,142142.6) ops/second in (0.016485,7.023933) seconds
2018/03/12-10:36:37 ... thread 0: (1024,999424) ops and (36366.2,141720.2) ops/second in (0.028158,7.052091) seconds
2018/03/12-10:36:37 ... thread 0: (1024,1000448) ops and (61914.3,141533.5) ops/second in (0.016539,7.068630) seconds
2018/03/12-10:36:37 ... thread 0: (1024,1001472) ops and (60985.1,141342.6) ops/second in (0.016791,7.085421) seconds
2018/03/12-10:36:37 ... thread 0: (1024,1002496) ops and (60466.5,141149.8) ops/second in (0.016935,7.102356) seconds
2018/03/12-10:36:37 ... thread 0: (1024,1003520) ops and (60189.3,140956.3) ops/second in (0.017013,7.119369) seconds
2018/03/12-10:36:37 ... thread 0: (1024,1004544) ops and (61731.4,140772.1) ops/second in (0.016588,7.135957) seconds
...
2018/03/12-10:40:15 ... thread 0: (1024,3236864) ops and (5620.5,14373.0) ops/second in (0.182189,225.203790) seconds
2018/03/12-10:40:15 ... thread 0: (1024,3237888) ops and (6098.5,14366.9) ops/second in (0.167911,225.371701) seconds
2018/03/12-10:40:15 ... thread 0: (1024,3238912) ops and (5469.5,14359.5) ops/second in (0.187221,225.558922) seconds
2018/03/12-10:40:15 ... thread 0: (1024,3239936) ops and (5593.9,14352.4) ops/second in (0.183056,225.741978) seconds
2018/03/12-10:40:16 ... thread 0: (1024,3240960) ops and (5806.9,14345.7) ops/second in (0.176342,225.918320) seconds
2018/03/12-10:40:16 ... thread 0: (1024,3241984) ops and (5332.9,14338.1) ops/second in (0.192016,226.110336) seconds
2018/03/12-10:40:16 ... thread 0: (1024,3243008) ops and (5532.3,14330.9) ops/second in (0.185096,226.295432) seconds
2018/03/12-10:40:16 ... thread 0: (1024,3244032) ops and (6108.8,14324.8) ops/second in (0.167626,226.463058) seconds
2018/03/12-10:40:16 ... thread 0: (1024,3245056) ops and (6074.7,14318.6) ops/second in (0.168567,226.631625) seconds
2018/03/12-10:40:17 ... thread 0: (1024,3246080) ops and (5615.2,14311.6) ops/second in (0.182362,226.813987) seconds
2018/03/12-10:40:17 ... thread 0: (1024,3247104) ops and (5529.3,14304.5) ops/second in (0.185194,226.999181) seconds
2018/03/12-10:40:17 ... thread 0: (1024,3248128) ops and (5846.2,14298.0) ops/second in (0.175156,227.174337) seconds
2018/03/12-10:40:17 ... thread 0: (1024,3249152) ops and (5741.5,14291.2) ops/second in (0.178351,227.352688) seconds
2018/03/12-10:40:17 ... thread 0: (1024,3250176) ops and (5640.2,14284.3) ops/second in (0.181555,227.534243) seconds
...
2018/03/12-11:30:39 ... thread 0: (1024,9988096) ops and (1917.2,3074.3) ops/second in (0.534112,3248.860552) seconds
2018/03/12-11:30:39 ... thread 0: (1024,9989120) ops and (1858.9,3074.1) ops/second in (0.550851,3249.411403) seconds
2018/03/12-11:30:40 ... thread 0: (1024,9990144) ops and (1922.8,3073.9) ops/second in (0.532557,3249.943960) seconds
2018/03/12-11:30:40 ... thread 0: (1024,9991168) ops and (1857.2,3073.7) ops/second in (0.551382,3250.495342) seconds
2018/03/12-11:30:41 ... thread 0: (1024,9992192) ops and (1851.3,3073.5) ops/second in (0.553130,3251.048472) seconds
2018/03/12-11:30:41 ... thread 0: (1024,9993216) ops and (1941.0,3073.3) ops/second in (0.527568,3251.576040) seconds
2018/03/12-11:30:42 ... thread 0: (1024,9994240) ops and (1923.1,3073.2) ops/second in (0.532461,3252.108501) seconds
2018/03/12-11:30:42 ... thread 0: (1024,9995264) ops and (1987.6,3073.0) ops/second in (0.515200,3252.623701) seconds
2018/03/12-11:30:43 ... thread 0: (1024,9996288) ops and (1931.2,3072.8) ops/second in (0.530233,3253.153934) seconds
2018/03/12-11:30:43 ... thread 0: (1024,9997312) ops and (1918.9,3072.6) ops/second in (0.533633,3253.687567) seconds
2018/03/12-11:30:44 ... thread 0: (1024,9998336) ops and (1999.0,3072.4) ops/second in (0.512246,3254.199813) seconds
2018/03/12-11:30:44 ... thread 0: (1024,9999360) ops and (1853.3,3072.2) ops/second in (0.552533,3254.752346) seconds
fillrandbatch : 325.508 micros/op 3072 ops/sec; 3.0 MB/s
And here is the read/write rate dumpped from iostat at 1s interval:
Device tps MB_read/s MB_wrtn/s MB_read MB_wrtn
sdb 73.00 0.12 25.52 0 25
sdb 531.00 0.00 495.21 0 495
sdb 15089.00 0.00 488.77 0 488
sdb 27431.00 0.01 463.55 0 463
sdb 13093.00 0.00 478.77 0 478
sdb 53676.00 0.00 413.79 0 413
sdb 16781.00 0.00 483.60 0 483
sdb 22267.00 0.00 323.32 0 323
sdb 23945.00 0.00 164.55 0 164
sdb 22867.00 0.00 152.25 0 152
sdb 22038.00 0.00 146.39 0 146
sdb 23825.00 0.00 263.61 0 263
...
sdb 20866.00 85.81 76.90 85 76
sdb 7684.00 101.75 115.19 101 115
sdb 3707.00 154.48 0.00 154 0
sdb 4349.00 181.41 0.00 181 0
sdb 4373.00 184.70 0.00 184 0
sdb 4329.00 185.04 0.00 185 0
sdb 4338.00 182.30 0.01 182 0
sdb 4364.00 184.27 0.00 184 0
sdb 5310.00 177.32 4.99 177 4
sdb 32130.00 99.07 119.70 99 119
sdb 27010.00 103.26 99.25 103 99
sdb 11109.00 67.18 99.96 67 99
sdb 3931.00 172.51 0.00 172 0
sdb 4112.00 171.28 0.00 171 0
sdb 4202.00 183.03 0.00 183 0
sdb 4119.00 183.79 0.00 183 0
sdb 4232.00 182.77 0.02 182 0
sdb 4224.00 185.90 0.00 185 0
sdb 4304.00 186.17 0.00 186 0
sdb 4279.00 188.83 0.00 188 0
sdb 4087.00 184.38 0.00 184 0
sdb 7758.00 163.86 16.70 163 16
sdb 21309.00 68.95 80.11 68 80
sdb 21166.00 81.66 78.42 81 78
sdb 19328.00 71.56 71.55 71 71
sdb 20836.00 89.08 76.52 89 76
sdb 3211.00 112.01 82.21 112 82
sdb 3939.00 173.40 0.00 173 0
sdb 3992.00 178.03 0.00 178 0
sdb 4251.00 181.49 0.00 181 0
sdb 4148.00 185.63 0.00 185 0
sdb 4094.00 184.12 0.01 184 0
sdb 4241.00 187.38 0.00 187 0
sdb 4044.00 186.60 0.00 186 0
sdb 4049.00 185.47 0.00 185 0
sdb 4247.00 189.17 0.00 189 0
...
sdb 17457.00 105.45 64.05 105 64
sdb 16736.00 82.12 62.35 82 62
sdb 12074.00 108.76 66.21 108 66
sdb 2232.00 194.44 0.00 194 0
sdb 2171.00 187.27 0.02 187 0
sdb 2322.00 197.91 0.00 197 0
sdb 2311.00 194.65 0.00 194 0
sdb 2240.00 187.93 0.00 187 0
sdb 2189.00 191.38 0.00 191 0
sdb 2266.00 192.33 0.01 192 0
sdb 2312.00 198.95 0.00 198 0
sdb 2310.00 199.84 0.00 199 0
sdb 2350.00 198.83 0.00 198 0
sdb 2275.00 198.31 0.00 198 0
sdb 3952.00 185.05 6.79 185 6
sdb 15842.00 59.89 59.67 59 59
sdb 16676.00 88.24 61.79 88 61
sdb 14768.00 75.94 55.00 75 54
sdb 5677.00 141.71 35.03 141 35
sdb 2135.00 184.78 0.04 184 0
sdb 2301.00 197.18 0.00 197 0
sdb 2334.00 198.81 0.00 198 0
sdb 2304.00 198.83 0.00 198 0
sdb 2348.00 198.67 0.00 198 0
sdb 2352.00 198.42 0.01 198 0
sdb 2373.00 199.32 0.00 199 0
sdb 2363.00 197.55 0.00 197 0
sdb 2289.00 198.71 0.00 198 0
sdb 2246.00 189.31 0.00 189 0
sdb 2357.00 198.64 0.01 198 0
sdb 2338.00 197.96 0.00 197 0
sdb 6292.00 177.60 16.56 177 16
sdb 19374.00 93.72 72.16 93 72
sdb 16873.00 101.38 62.01 101 62
sdb 16960.00 98.99 76.84 98 76
sdb 2299.00 189.32 6.16 189 6
sdb 2285.00 195.82 0.00 195 0
sdb 2346.00 198.25 0.00 198 0
sdb 2325.00 198.91 0.00 198 0
sdb 2353.00 197.72 0.02 197 0
sdb 2320.00 198.82 0.00 198 0
sdb 2327.00 200.05 0.00 200 0
sdb 2340.00 198.35 0.00 198 0
sdb 2322.00 199.29 0.00 199 0
sdb 2316.00 197.43 0.01 197 0
sdb 690.00 51.17 0.00 51 0
With the help of #Howard Chu, I have identified the problem.
The excessive reads were caused by OS read-ahead. By default, when we read a page, the OS will prefetch the pages following that page into memory. However, this is usually undesirable in a DB, since we are usually doing random read. So we need to disable read-ahead to get optimal performance for random read.
For the benchmark, there is a command line option --readahead=0, which in turn sets MDB_NORDAHEAD option for LMDB.
After disabling read-ahead, the instant write rate grew from 1MB/s to 8MB/s at the end of the test. And the read/write amount observed in iostat is almost identical.

Implementation of merge sort using threads and fork

Problem: I'm trying to implement Merge Sort in the following way, I have a Parent and two children. the first child will use the merge sort on his own, the second child will implement this the following way: create 2 threads, first one will sort the first half of the array, the second one will sort the rest. Then, after calling the merge sort, he will create again 2 threads for the first half, and 2 threads for the rest, and so on, until we end up in the base case and we finish. In the end, I want to check how much faster the second child implemented the merge sort than the first child.
My question: I've created 2 childs, the first child is implementing the sort merge and everything is fine. the second child - I was able to create only 2 threads, instead of much more (then 2 for each half, and so on), and in the end it neither prints the array nor the date of its finish.
This is the code for the second child:
if((id2 = fork()) == 0 && id1 != 0)
{
printf("Child2: \n");
ans1 = pthread_create ( &thread1 , NULL , mergeSort ,(arr3, (arr_size / 2) - 1 ,arr_size - 1 )) ;
ans2 = pthread_create ( &thread2 , NULL , mergeSort ,(arr3, 0, (arr_size / 2)- 1 )) ;
ans3 = pthread_create ( &thread3 , NULL , printArray ,(arr3, arr_size) ) ;
execl("/bin/date", "date",0);
if ( ans1 != 0 || ans2 != 0 || ans3 != 0) {
printf ( " \n can't create threads " ) ;
exit(0) ;
}
pthread_join ( thread1 , NULL ) ;
pthread_join ( thread2 , NULL ) ;
pthread_join ( thread3 , NULL ) ;
}
I'm using UNIX, and for compiling:
gcc -lpthread prog.c
for executing:
./a.out
This is the whole code:
/* C program for Merge Sort */
#include<stdlib.h>
#include<stdio.h>
#include <pthread.h>
#define N 100
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l+(r-l)/2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m+1, r);
merge(arr, l, m, r);
}
}
/* UTILITY FUNCTIONS */
/* Function to print an array */
void printArray(int A[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}
/* Driver program to test above functions */
int main()
{
int min = -1000, max = 1000;
int arr[10], arr2[10], arr3[10];
int i,r;
int arr_size = sizeof(arr)/sizeof(arr[0]);
int id1,id2;
//Threads init
pthread_t thread1 , thread2, thread3;
int ans1, ans2, ans3;
for( i = 0; i < arr_size; i++){
r = rand() % (max - min + 1);
arr[i] = r;
arr2[i] = r;
arr3[i] = r;
}
//printf("Before: \n");
if((id1 = fork()) == 0)
{
printf("Child1: \n");
mergeSort(arr2, 0, arr_size - 1);
printArray(arr2, arr_size);
execl("/bin/date", "date",0);
}
if((id2 = fork()) == 0 && id1 != 0)
{
printf("Child2: \n");
ans1 = pthread_create ( &thread1 , NULL , mergeSort ,(arr3, (arr_size / 2) - 1 ,arr_size - 1 )) ;
ans2 = pthread_create ( &thread2 , NULL , mergeSort ,(arr3, 0, (arr_size / 2)- 1 )) ;
ans3 = pthread_create ( &thread3 , NULL , printArray ,(arr3, arr_size) ) ;
execl("/bin/date", "date",0);
if ( ans1 != 0 || ans2 != 0 || ans3 != 0) {
printf ( " \n can't create threads " ) ;
exit(0) ;
}
pthread_join ( thread1 , NULL ) ;
pthread_join ( thread2 , NULL ) ;
pthread_join ( thread3 , NULL ) ;
}
wait();
if(id1 != 0 && id2 != 0){
printf("Given array is \n");
printArray(arr, arr_size);
printf("Father:\n");
mergeSort(arr, 0, arr_size - 1);
printArray(arr, arr_size);
execl("/bin/date", "date",0);
printf("\nSorted array is \n");
//printf("After: \n");
}
return 0;
}
EDITED CODE:
/* C program for Merge Sort */
#include<stdlib.h>
#include<stdio.h>
#include <pthread.h>
#include <time.h>
#define N 100
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l+(r-l)/2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m+1, r);
merge(arr, l, m, r);
}
}
void* mergeSort2(void* args)
{
int* newArgs = (int*)args;
int l = newArgs[1];
int r = newArgs[2];
pthread_t thread1 , thread2;
int ans1, ans2;
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = (r+l)/2;
int newArgs1[3] = {newArgs[0], l, m};
int newArgs2[3] = {newArgs[0], m+1, r};
ans1 = pthread_create ( &thread1 , NULL , mergeSort2 ,(void*)newArgs1);
ans1 = pthread_create ( &thread2 , NULL , mergeSort2 ,(void*)newArgs2);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
merge(newArgs[0], l, m, r);
}
}
/* UTILITY FUNCTIONS */
/* Function to print an array */
void printArray(int A[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}
static void print_timestamp(void)
{
time_t now = time(0);
struct tm *utc = gmtime(&now);
char iso8601[32];
strftime(iso8601, sizeof(iso8601), "%Y-%m-%d %H:%M:%S", utc);
printf("%s\n", iso8601);
}
/* Driver program to test above functions */
int main()
{
int min = -1000, max = 1000;
int arr[10], arr2[10], arr3[10];
int i,r;
int arr_size = sizeof(arr)/sizeof(arr[0]);
int id1,id2;
int args[3] ={arr3, 0, arr_size - 1};
struct timeval tvalBefore, tvalAfter;
struct timeval tvalBefore1, tvalAfter1;
//Threads init
pthread_t thread1;
int ans1;
srand(time(NULL));
for( i = 0; i < arr_size; i++){
r = rand() % (max - min + 1);
arr[i] = r;
arr2[i] = r;
arr3[i] = r;
}
//printf("Before: \n");
if((id1 = fork()) == 0)
{
gettimeofday (&tvalBefore, NULL);
//Operation to do
printf("Child1: \n");
mergeSort(arr2, 0, arr_size - 1);
printArray(arr2, arr_size);
print_timestamp();
gettimeofday (&tvalAfter, NULL);
// Changed format to long int (%ld), changed time calculation
printf("Time in microseconds for sorting CHILD 1: %ld microseconds\n",
((tvalAfter.tv_sec - tvalBefore.tv_sec)*1000000L
+tvalAfter.tv_usec) - tvalBefore.tv_usec
); // Added semicolon
}
else if((id2 = fork()) == 0)
{
printf("Child2: \n");
//Start Timer
gettimeofday (&tvalBefore1, NULL);
//Operation to do
ans1 = pthread_create ( &thread1 , NULL , mergeSort2 ,(void*)args);
pthread_join ( thread1 , NULL ) ;
print_timestamp();
gettimeofday (&tvalAfter1, NULL);
// Changed format to long int (%ld), changed time calculation
printf("Time in microseconds for sorting CHILD 2: %ld microseconds\n",
((tvalAfter1.tv_sec - tvalBefore1.tv_sec)*1000000L
+tvalAfter1.tv_usec) - tvalBefore1.tv_usec
); // Added semicolon
}
else{
wait();
wait();
gettimeofday (&tvalBefore, NULL);
//Operation to do
printf("Given array is \n");
printArray(arr, arr_size);
printf("Father:\n");
mergeSort(arr, 0, arr_size - 1);
printArray(arr, arr_size);
print_timestamp();
gettimeofday (&tvalAfter, NULL);
// Changed format to long int (%ld), changed time calculation
printf("Time in microseconds for sorting Father: %ld microseconds\n",
((tvalAfter.tv_sec - tvalBefore.tv_sec)*1000000L
+tvalAfter.tv_usec) - tvalBefore.tv_usec
); // Added semicolon
}
return 0;
}
You have several problems:
as noted in comments and Jonathan's answer, you call exec and replace your whole process image before your threads complete (and possibly before they actually start, since they may not have been given their first timeslice yet)
if you move that, you still have the problem that your printArray function was run in parallel to your sort threads, instead of afterwards
if you fix that, you still have the problem that your printArray thread was started improperly (with a likely invalid input pointer), for the same reason as for the sorting threads, described in more detail below
if you fix the printing, your sorting thread invocation is completely wrong (much detail follows below)
if you fix the thread invocation, your code still doesn't do what you claim you wanted: to keep starting new child threads for smaller and smaller sub-ranges of your input array
Let's start with the prototype of pthread_create, the declaration of your thread function, and the thread creation call:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
this requires a function of shape void* start_routine(void *) as its third argument. However, you have
void mergeSort(int arr[], int l, int r) { ... }
which will nevertheless be called with only the first argument having a defined value. I'm amazed your compiler didn't warn about this.
Now, consider your the fourth argument to pthread_create in the following call:
ans1 = pthread_create(&thread1, NULL,
mergeSort,
(arr3, (arr_size / 2) - 1 ,arr_size - 1 )) ;
it takes the expression (arr3, (arr_size / 2) - 1 ,arr_size - 1 ). However, C doesn't have tuple types, and even if it did they wouldn't be convertible to void*. Instead this uses the comma operator , to discard the results of the first two expressions, and so you're actually using the integer value of arr_size - 1 as a pointer argument.
I'd expect it to crash when it tries to start the child thread - you didn't say how your program failed, but a SEGV would be common. You can catch these in a debugger, but it'll be somewhere inside the pthread library code, so it might not help much.
A sane solution for your problem would look something like this un-tested and never-compiled sample code:
/* use this for the fourth argument to pthread_create */
struct Range {
int *array;
int left;
int right;
pthread_t thread;
};
void mergeSortRange(Range *r) {
const int width = (right - left);
const int mid = left + (width/2);
if (width > THRESHOLD) {
/* wide enough to be worth a child thread */
Range left = { r->array, r->left, mid };
Range right = { r->array, mid+1, r->right };
pthread_create(&left.thread, NULL,
mergeSortRangeThreadFunction,
&left);
mergeSortRange(&right);
pthread_join(left.thread);
mergeSortedHalved(r->array, r->left, mid, r->right);
} else {
regularSingleThreadedMergeSort(r->array, r->left, r->right);
}
}
/* this is what you pass to pthread_create */
void* mergeSortRangeThreadFunction(void *data) {
Range *r = (Range *)data;
mergeSortRange(r);
return data;
}
although, even with THRESHOLD set to something good, it's better to use a thread pool than to start & stop threads repeatedly.
Finally, of course, you don't need to use recursion to start these threads and populate these Range structures - you could just create an array of size/THRESHOLD + 1 range descriptors, create one thread per core, and then figure out some logic for deciding when you're allowed to merge two consecutive ranges.
Program stops because of calls to execl()
You have:
…
ans3 = pthread_create ( &thread3 , NULL , printArray ,(arr3, arr_size) ) ;
execl("/bin/date", "date",0);
if ( ans1 != 0 || ans2 != 0 || ans3 != 0) {
…
The execl() replaces your process and all its threads with date, which produces its output and exits. You can't time-stamp your work like that!
You probably need to call time() or a higher-resolution timing mechanism, and then localtime() or gmtime() to create a broken-down time, and then strftime() to format it as you want, and finally printf() or similar to print the result. That all belongs in a function, of course, not in your code.
#include <stdio.h>
#include <time.h>
static void print_timestamp(void)
{
time_t now = time(0);
struct tm *utc = gmtime(&now);
char iso8601[32];
strftime(iso8601, sizeof(iso8601), "%Y-%m-%dT%H:%M:%S", utc);
printf("%s\n", iso8601);
}
Where you have execl(), call print_timestamp() instead.
Or, more simply, use system() instead of execl():
system("/bin/date");
This is a grotesquely heavyweight way of reporting the time, but it has the merit of simplicity.
Sub-second resolution times
I need to determine the time in milliseconds.
It depends on your platform, but on POSIX-ish systems you can use clock_gettime() or gettimeofday() to get sub-second timing.
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
static void print_timestamp(void) // UTC to seconds
{
time_t now = time(0);
struct tm *utc = gmtime(&now);
char iso8601[32];
strftime(iso8601, sizeof(iso8601), "%Y-%m-%dT%H:%M:%S", utc);
printf("%s\n", iso8601);
}
static void print_utc_ms(void) // UTC to milliseconds
{
struct timeval tv;
gettimeofday(&tv, 0);
struct tm *utc = gmtime(&tv.tv_sec);
char iso8601[32];
strftime(iso8601, sizeof(iso8601), "%Y-%m-%dT%H:%M:%S", utc);
printf("%s.%.3d\n", iso8601, tv.tv_usec / 1000);
}
static void print_local_us(void) // Local time to microseconds
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts); // CLOCK_MONOTONIC has merits too
struct tm *lmt = localtime(&ts.tv_sec);
char iso8601[32];
strftime(iso8601, sizeof(iso8601), "%Y-%m-%dT%H:%M:%S", lmt);
printf("%s.%.6ld\n", iso8601, ts.tv_nsec / 1000L);
}
int main(void)
{
print_timestamp();
print_utc_ms();
print_local_us();
return 0;
}
Example output:
2017-05-05T16:04:14
2017-05-05T16:04:14.268
2017-05-05T09:04:14.268975
NB: Once you've fixed your code so it isn't using execl(), there may still be other problems to resolve — there probably are other problems to fix. But fixing this is a key step to getting your threads to run to completion.
Creating working code
Taking the revised code from the question, applying basic 'cleanliness' to it (making sure it compiles cleanly under stringent warning options), the program seems to work. The 'array of int' approach to passing a pointer and two int values doesn't work on a 64-bit system, so I created a struct Sort to contain the information. I also moved the 'start clock' and 'stop clock' calls to gettimeofday() closer to the code being measured (no printing in the calling code in the way). I added headers needed on macOS Sierra 10.12.4 (GCC 7.1.0). The code also prints the input data before it sorts any of it. The cleanup work was basically 'around' the sort code; the core sorting algorithms were not changed at all.
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h> // gettimeofday()
#include <unistd.h> // fork()
#include <sys/wait.h> // wait()
#define N 100
struct Sort
{
int *data;
int lo;
int hi;
};
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
static
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
static
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l + (r - l) / 2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
static
void *mergeSort2(void *args)
{
struct Sort *newargs = args;
int *data = newargs->data;
int l = newargs->lo;
int r = newargs->hi;
pthread_t thread1, thread2;
int ans1, ans2;
if (l < r)
{
int m = (r + l) / 2;
struct Sort newArgs1 = {data, l, m};
struct Sort newArgs2 = {data, m + 1, r};
ans1 = pthread_create(&thread1, NULL, mergeSort2, &newArgs1);
ans2 = pthread_create(&thread2, NULL, mergeSort2, &newArgs2);
if (ans1 != 0 || ans2 != 0)
exit(1);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
merge(data, l, m, r);
}
return 0;
}
/* UTILITY FUNCTIONS */
/* Function to print an array */
static
void printArray(int A[], int size)
{
for (int i = 0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}
static void print_timestamp(void)
{
time_t now = time(0);
struct tm *utc = gmtime(&now);
char iso8601[32];
strftime(iso8601, sizeof(iso8601), "%Y-%m-%d %H:%M:%S", utc);
printf("%s\n", iso8601);
}
/* Driver program to test above functions */
int main(void)
{
int min = -1000, max = 1000;
int arr[10], arr2[10], arr3[10];
int i, r;
int arr_size = sizeof(arr) / sizeof(arr[0]);
int id1, id2;
struct Sort args = { arr3, 0, arr_size - 1};
struct timeval tvalBefore, tvalAfter;
struct timeval tvalBefore1, tvalAfter1;
// Threads init
pthread_t thread1;
int ans1;
srand(time(NULL));
for (i = 0; i < arr_size; i++)
{
r = rand() % (max - min + 1);
arr[i] = r;
arr2[i] = r;
arr3[i] = r;
}
printf("Given array is \n");
printArray(arr, arr_size);
fflush(stdout);
if ((id1 = fork()) == 0)
{
printf("Child1: \n");
gettimeofday(&tvalBefore, NULL);
mergeSort(arr2, 0, arr_size - 1);
gettimeofday(&tvalAfter, NULL);
printArray(arr2, arr_size);
print_timestamp();
printf("Time in microseconds for sorting CHILD 1: %ld microseconds\n",
((tvalAfter.tv_sec - tvalBefore.tv_sec) * 1000000L
+ tvalAfter.tv_usec) - tvalBefore.tv_usec);
}
else if ((id2 = fork()) == 0)
{
printf("Child2: \n");
gettimeofday(&tvalBefore1, NULL);
ans1 = pthread_create(&thread1, NULL, mergeSort2, &args);
if (ans1 == 0)
pthread_join( thread1, NULL );
gettimeofday(&tvalAfter1, NULL);
print_timestamp();
printArray(arr3, arr_size);
printf("Time in microseconds for sorting CHILD 2: %ld microseconds\n",
((tvalAfter1.tv_sec - tvalBefore1.tv_sec) * 1000000L
+ tvalAfter1.tv_usec) - tvalBefore1.tv_usec);
}
else
{
wait(0);
wait(0);
printf("Parent:\n");
gettimeofday(&tvalBefore, NULL);
mergeSort(arr, 0, arr_size - 1);
gettimeofday(&tvalAfter, NULL);
printArray(arr, arr_size);
print_timestamp();
printf("Time in microseconds for sorting Parent: %ld microseconds\n",
((tvalAfter.tv_sec - tvalBefore.tv_sec) * 1000000L
+ tvalAfter.tv_usec) - tvalBefore.tv_usec);
}
return 0;
}
Compilation (source in ms83.c):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition ms83.c -o ms83
$
Example run 1:
Given array is
574 494 441 870 1121 800 1864 1819 889 242
Child1:
242 441 494 574 800 870 889 1121 1819 1864
2017-05-05 21:31:23
Time in microseconds for sorting CHILD 1: 10 microseconds
Child2:
2017-05-05 21:31:23
242 441 494 574 800 870 889 1121 1819 1864
Time in microseconds for sorting CHILD 2: 3260 microseconds
Parent:
242 441 494 574 800 870 889 1121 1819 1864
2017-05-05 21:31:23
Time in microseconds for sorting Parent: 7 microseconds
Example run 2:
Given array is
150 562 748 1685 889 1859 1807 1904 863 1675
Child1:
150 562 748 863 889 1675 1685 1807 1859 1904
2017-05-05 21:31:40
Time in microseconds for sorting CHILD 1: 11 microseconds
Child2:
2017-05-05 21:31:40
150 562 748 863 889 1675 1685 1807 1859 1904
Time in microseconds for sorting CHILD 2: 4745 microseconds
Parent:
150 562 748 863 889 1675 1685 1807 1859 1904
2017-05-05 21:31:40
Time in microseconds for sorting Parent: 7 microseconds
Note that the threading solution is three orders of magnitude slower than the non-threading code.
When I tried increasing the array size from 10 to 10,000, the threaded child did not complete. That means thread creation failed somewhere. The error reporting is defective (I was being lazy). Switching to 500 entries yielded:
Given array is
1984 1436 713 1349 855 1296 559 1647 567 1153 1156 1395 865 1380 840 1253 714 1396 333 404 538 1468 1381 489 1274 34 697 1484 1742 756 1221 1717 331 532 746 842 1235 1179 1185 1547 1372 1305 138 404 76 762 605 61 1242 1075 1896 203 1173 844 1582 1356 1044 1760 1635 1833 1595 1651 1892 1842 1508 727 357 221 878 967 1665 1783 1927 1655 1110 220 711 371 1785 401 188 1132 1947 1214 5 1414 1065 730 826 807 1155 654 1745 1993 1215 741 1721 1509 604 16 139 804 1773 690 1673 861 1657 566 969 1891 1718 1801 200 1817 235 711 372 319 507 483 1332 968 1138 246 1082 1074 1569 1774 488 358 1713 350 583 381 418 300 1011 416 563 748 1858 837 1678 1336 1516 1177 1449 1664 1991 1465 1159 1653 1724 311 1360 902 1182 1768 1471 1606 1813 1925 825 122 1647 1790 1575 323 153 33 1825 1343 1183 1707 1724 1839 1190 1936 442 1370 206 1530 1142 561 952 478 25 1666 382 1092 418 720 1864 652 313 1878 1268 993 1446 1881 893 1416 319 577 1147 688 1155 726 1336 1354 1419 217 1236 213 1715 101 946 1450 135 297 1962 1405 455 924 26 569 755 64 1459 1636 395 1417 138 924 1360 893 1216 1231 1546 1104 252 697 1602 1794 1565 1945 1738 941 1813 1829 714 280 369 1861 1466 1195 1284 1936 78 1988 145 1541 1927 833 135 913 1214 405 23 1107 390 242 309 964 1311 724 284 342 1550 1394 759 1860 28 1369 1417 362 747 1732 26 1791 646 1817 1392 666 762 1297 945 507 58 928 1972 811 170 1660 1811 1969 573 242 1297 74 581 1513 1258 1311 547 627 942 1965 945 343 1633 197 843 249 77 320 611 1674 303 1346 148 533 1800 259 916 1498 1058 365 973 451 1143 1121 1033 126 595 726 1232 894 1584 878 1076 1796 257 531 144 740 1033 630 471 919 773 1276 1523 1195 475 667 40 91 1336 350 1650 970 1712 542 1927 168 1107 917 1271 649 1006 1428 20 1341 1283 774 1781 1427 1342 316 1317 1162 1333 991 1288 1853 1917 210 1589 1744 1942 962 557 1444 396 1330 378 625 1776 179 434 290 870 961 1365 226 605 1842 1629 1421 1883 108 102 1068 671 1086 692 1053 45 660 1746 1351 399 1308 833 42 1219 491 248 503 499 3 1965 1043 1452 604 1736 1974 675 14 1491 1757 1116 1520 1540 983 108 15 1030 742 1535 423 1802 1622 1401 1801 167 824 230 404 1722 814 1222 1626 1177 1772 1645 27 1061 1848 1031 1659 1725 1862 959 362 728 1644 957 934 1160 1862 915 995 1201 119 1191 259 963 1889
Child1:
3 5 14 15 16 20 23 25 26 26 27 28 33 34 40 42 45 58 61 64 74 76 77 78 91 101 102 108 108 119 122 126 135 135 138 138 139 144 145 148 153 167 168 170 179 188 197 200 203 206 210 213 217 220 221 226 230 235 242 242 246 248 249 252 257 259 259 280 284 290 297 300 303 309 311 313 316 319 319 320 323 331 333 342 343 350 350 357 358 362 362 365 369 371 372 378 381 382 390 395 396 399 401 404 404 404 405 416 418 418 423 434 442 451 455 471 475 478 483 488 489 491 499 503 507 507 531 532 533 538 542 547 557 559 561 563 566 567 569 573 577 581 583 595 604 604 605 605 611 625 627 630 646 649 652 654 660 666 667 671 675 688 690 692 697 697 711 711 713 714 714 720 724 726 726 727 728 730 740 741 742 746 747 748 755 756 759 762 762 773 774 804 807 811 814 824 825 826 833 833 837 840 842 843 844 855 861 865 870 878 878 893 893 894 902 913 915 916 917 919 924 924 928 934 941 942 945 945 946 952 957 959 961 962 963 964 967 968 969 970 973 983 991 993 995 1006 1011 1030 1031 1033 1033 1043 1044 1053 1058 1061 1065 1068 1074 1075 1076 1082 1086 1092 1104 1107 1107 1110 1116 1121 1132 1138 1142 1143 1147 1153 1155 1155 1156 1159 1160 1162 1173 1177 1177 1179 1182 1183 1185 1190 1191 1195 1195 1201 1214 1214 1215 1216 1219 1221 1222 1231 1232 1235 1236 1242 1253 1258 1268 1271 1274 1276 1283 1284 1288 1296 1297 1297 1305 1308 1311 1311 1317 1330 1332 1333 1336 1336 1336 1341 1342 1343 1346 1349 1351 1354 1356 1360 1360 1365 1369 1370 1372 1380 1381 1392 1394 1395 1396 1401 1405 1414 1416 1417 1417 1419 1421 1427 1428 1436 1444 1446 1449 1450 1452 1459 1465 1466 1468 1471 1484 1491 1498 1508 1509 1513 1516 1520 1523 1530 1535 1540 1541 1546 1547 1550 1565 1569 1575 1582 1584 1589 1595 1602 1606 1622 1626 1629 1633 1635 1636 1644 1645 1647 1647 1650 1651 1653 1655 1657 1659 1660 1664 1665 1666 1673 1674 1678 1707 1712 1713 1715 1717 1718 1721 1722 1724 1724 1725 1732 1736 1738 1742 1744 1745 1746 1757 1760 1768 1772 1773 1774 1776 1781 1783 1785 1790 1791 1794 1796 1800 1801 1801 1802 1811 1813 1813 1817 1817 1825 1829 1833 1839 1842 1842 1848 1853 1858 1860 1861 1862 1862 1864 1878 1881 1883 1889 1891 1892 1896 1917 1925 1927 1927 1927 1936 1936 1942 1945 1947 1962 1965 1965 1969 1972 1974 1984 1988 1991 1993
2017-05-05 21:43:11
Time in microseconds for sorting CHILD 1: 62 microseconds
Child2:
2017-05-05 21:43:11
3 5 14 15 16 20 23 25 26 26 27 28 33 34 40 42 45 58 61 64 74 76 77 78 91 101 102 108 108 119 122 126 135 135 138 138 139 144 145 148 153 167 168 170 179 188 197 200 203 206 210 213 217 220 221 226 230 235 242 242 246 248 249 252 257 259 259 280 284 290 297 300 303 309 311 313 316 319 319 320 323 331 333 342 343 350 350 357 358 362 362 365 369 371 372 378 381 382 390 395 396 399 401 404 404 404 405 416 418 418 423 434 442 451 455 471 475 478 483 488 489 491 499 503 507 507 531 532 533 538 542 547 557 559 561 563 566 567 569 573 577 581 583 595 604 604 605 605 611 625 627 630 646 649 652 654 660 666 667 671 675 688 690 692 697 697 711 711 713 714 714 720 724 726 726 727 728 730 740 741 742 746 747 748 755 756 759 762 762 773 774 804 807 811 814 824 825 826 833 833 837 840 842 843 844 855 861 865 870 878 878 893 893 894 902 913 915 916 917 919 924 924 928 934 941 942 945 945 946 952 957 959 961 962 963 964 967 968 969 970 973 983 991 993 995 1006 1011 1030 1031 1033 1033 1043 1044 1053 1058 1061 1065 1068 1074 1075 1076 1082 1086 1092 1104 1107 1107 1110 1116 1121 1132 1138 1142 1143 1147 1153 1155 1155 1156 1159 1160 1162 1173 1177 1177 1179 1182 1183 1185 1190 1191 1195 1195 1201 1214 1214 1215 1216 1219 1221 1222 1231 1232 1235 1236 1242 1253 1258 1268 1271 1274 1276 1283 1284 1288 1296 1297 1297 1305 1308 1311 1311 1317 1330 1332 1333 1336 1336 1336 1341 1342 1343 1346 1349 1351 1354 1356 1360 1360 1365 1369 1370 1372 1380 1381 1392 1394 1395 1396 1401 1405 1414 1416 1417 1417 1419 1421 1427 1428 1436 1444 1446 1449 1450 1452 1459 1465 1466 1468 1471 1484 1491 1498 1508 1509 1513 1516 1520 1523 1530 1535 1540 1541 1546 1547 1550 1565 1569 1575 1582 1584 1589 1595 1602 1606 1622 1626 1629 1633 1635 1636 1644 1645 1647 1647 1650 1651 1653 1655 1657 1659 1660 1664 1665 1666 1673 1674 1678 1707 1712 1713 1715 1717 1718 1721 1722 1724 1724 1725 1732 1736 1738 1742 1744 1745 1746 1757 1760 1768 1772 1773 1774 1776 1781 1783 1785 1790 1791 1794 1796 1800 1801 1801 1802 1811 1813 1813 1817 1817 1825 1829 1833 1839 1842 1842 1848 1853 1858 1860 1861 1862 1862 1864 1878 1881 1883 1889 1891 1892 1896 1917 1925 1927 1927 1927 1936 1936 1942 1945 1947 1962 1965 1965 1969 1972 1974 1984 1988 1991 1993
Time in microseconds for sorting CHILD 2: 83377 microseconds
Parent:
3 5 14 15 16 20 23 25 26 26 27 28 33 34 40 42 45 58 61 64 74 76 77 78 91 101 102 108 108 119 122 126 135 135 138 138 139 144 145 148 153 167 168 170 179 188 197 200 203 206 210 213 217 220 221 226 230 235 242 242 246 248 249 252 257 259 259 280 284 290 297 300 303 309 311 313 316 319 319 320 323 331 333 342 343 350 350 357 358 362 362 365 369 371 372 378 381 382 390 395 396 399 401 404 404 404 405 416 418 418 423 434 442 451 455 471 475 478 483 488 489 491 499 503 507 507 531 532 533 538 542 547 557 559 561 563 566 567 569 573 577 581 583 595 604 604 605 605 611 625 627 630 646 649 652 654 660 666 667 671 675 688 690 692 697 697 711 711 713 714 714 720 724 726 726 727 728 730 740 741 742 746 747 748 755 756 759 762 762 773 774 804 807 811 814 824 825 826 833 833 837 840 842 843 844 855 861 865 870 878 878 893 893 894 902 913 915 916 917 919 924 924 928 934 941 942 945 945 946 952 957 959 961 962 963 964 967 968 969 970 973 983 991 993 995 1006 1011 1030 1031 1033 1033 1043 1044 1053 1058 1061 1065 1068 1074 1075 1076 1082 1086 1092 1104 1107 1107 1110 1116 1121 1132 1138 1142 1143 1147 1153 1155 1155 1156 1159 1160 1162 1173 1177 1177 1179 1182 1183 1185 1190 1191 1195 1195 1201 1214 1214 1215 1216 1219 1221 1222 1231 1232 1235 1236 1242 1253 1258 1268 1271 1274 1276 1283 1284 1288 1296 1297 1297 1305 1308 1311 1311 1317 1330 1332 1333 1336 1336 1336 1341 1342 1343 1346 1349 1351 1354 1356 1360 1360 1365 1369 1370 1372 1380 1381 1392 1394 1395 1396 1401 1405 1414 1416 1417 1417 1419 1421 1427 1428 1436 1444 1446 1449 1450 1452 1459 1465 1466 1468 1471 1484 1491 1498 1508 1509 1513 1516 1520 1523 1530 1535 1540 1541 1546 1547 1550 1565 1569 1575 1582 1584 1589 1595 1602 1606 1622 1626 1629 1633 1635 1636 1644 1645 1647 1647 1650 1651 1653 1655 1657 1659 1660 1664 1665 1666 1673 1674 1678 1707 1712 1713 1715 1717 1718 1721 1722 1724 1724 1725 1732 1736 1738 1742 1744 1745 1746 1757 1760 1768 1772 1773 1774 1776 1781 1783 1785 1790 1791 1794 1796 1800 1801 1801 1802 1811 1813 1813 1817 1817 1825 1829 1833 1839 1842 1842 1848 1853 1858 1860 1861 1862 1862 1864 1878 1881 1883 1889 1891 1892 1896 1917 1925 1927 1927 1927 1936 1936 1942 1945 1947 1962 1965 1965 1969 1972 1974 1984 1988 1991 1993
2017-05-05 21:43:11
Time in microseconds for sorting Parent: 51 microseconds
Different runs showed dramatic variations in the processing time for child 2. I observed the values: 83,377; 73,929; 78,977; 83,977; 94,159; 81,526 microseconds.
You might get some benefit from threading with large data sets sorted by a small number of threads (say 10,000 rows of data, but only 8 threads, each sorting 1250 rows of data), but probably not even then. As you increase the number of threads beyond the number of cores on the system, you get less and less benefit from the multiple threads.

My program returns the wrong values

I am making a program that will calculate the minimum and maximum cost of flight (supposed to be a simple program to practice for an exam) using a separate function to calculate the cost of the flight.
the code is this:
#include<stdio.h>
#include<limits.h>
float cost(float k, int ck, int n)
{
int x;
x = (k*ck)/n;
return x;
}
main()
{
int cont=1, n, nv, costmax = 0, costmin = INT_MAX, ck;
float k;
printf("Introduce the number of flights: \n");
scanf("%d", &nv);
for(cont=1; cont <= nv; cont++)
{
printf("Introduce the number of passangers on flight %d:\n", cont);
scanf("%d", &n);
printf("Introduce the number of distance on flight %d:\n", cont);
scanf("%d", &k);
if(k < 500)
{
ck=50;
}
if(k > 500)
{
ck=80;
}
cost(k,ck,n);
if(cost(k, ck, n) < costmin)
{
costmin = cost(k, ck, n);
}
if(cost(k, ck, n) > costmax)
{
costmax = cost(k, ck, n);
}
}
printf("\nMinimum cost = %d \n", costmin);
printf("\nMaximum cost = %d \n", costmax);
}
and we're supposed to use a text file to input the data
156 397 798 375 489 901 937 519 797 205 883 247 1186 738 860 967 550 887 743 753 906 582 819 665 1112 231 1009 761 921 634 686 591 1027 646 1161 424 668 413 1190 423 840 381 431 559 455 496 1105 489 848 775 456 637 664 760 412 689 639 752 669 312 940 955 706 726 579 556 655 335 902 755 665 431 1093 627 569 310 647 327 943 354 647 733 979 711 504 443 509 266 833 856 667 603 1101 670 688 898 498 669 1149 601 808 934 718 880 1053 977 556 719 1012 286 665 882 456 623 437 632 475 320 494 672 775 548 678 935 984 464 1188 641 749 816 1191 528 1092 203 770 923 1153 220 929 321 789 350 720 745 694 790 687 669 826 372 1029 392 839 932 462 806 882 539 524 797 1084 516 449 218 1048 638 751 889 448 479 465 633 1123 862 904 383 494 472 1117 365 415 889 765 670 941 341 929 876 575 940 565 967 850 473 1119 632 953 904 815 316 409 364 959 287 848 584 574 998 915 826 558 877 858 376 817 591 1068 443 447 428 1081 823 1122 373 852 598 995 735 1028 313 623 820 981 505 753 529 574 433 699 875 1032 833 1068 765 949 691 1145 358 505 251 617 417 945 694 889 323 1028 986 567 269 605 337 1153 926 590 607 803 202 1101 232 771 855 759 776 1011 878 884 393 636 230 1098 788 1140 447 1076 537 1077 734 724 266 635 232 406 752 628 743 848 537 490 598 913 416 855 640 634 209 1172 329 705 249 881 882 817
The program doesn't present any errors or warnings when compiling, but when I run it, it says that the minimum cost and the maximum cost are 0...
I've been checking everything over and over and can't find what's wrong.
Any ideas?
BTW, I'm using a linux machine to run the program, don't know if it makes a difference...
Compile with the -Wall flag, this will help you to catch errors by yourself.
Using gcc:
% gcc t.c -Wall
t.c:9:1: warning: return type defaults to ‘int’ [-Wreturn-type]
main()
^
t.c: In function ‘main’:
t.c:20:9: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘float *’ [-Wformat=]
scanf("%d", &k);
^
t.c:41:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
Using clang:
% clang t.c -Wall
t.c:9:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
main()
^~~~
t.c:20:21: warning: format specifies type 'int *' but the argument has type 'float *' [-Wformat]
scanf("%d", &k);
~~ ^~
%f
2 warnings generated.
Clang suggests you to replace:
scanf("%d", &k);
to
scanf("%f", &k);
And even if it's not as critical, you forgot to define the return type of the main function. Both compilers have replaced it to int but you should also return something at the end of your program.
Finally, as suggested in the comments, you can also use -Wextra. I would also recommend you, while the projects are small enough and that you are still learning, to respect the "0 warning" policy. That will help you to prevent bugs.
Since k is a float, this is wrong:
scanf("%d", &k);
You need:
if (scanf("%f", &k) != 1)
break;
This uses the correct format and checks for errors. A basic debugging technique is to print out the values you've just read to ensure that the program got what you think it should have gotten.
There are other problems too. This code is redundant:
cost(k,ck,n);
if(cost(k, ck, n) < costmin)
{
costmin = cost(k, ck, n);
}
if(cost(k, ck, n) > costmax)
{
costmax = cost(k, ck, n);
}
You call the function up to 5 times to get the same answer each time. The first call you ignore altogether. You should probably use something like:
float new_cost = cost(k,ck,n);
if (new_cost < costmin)
costmin = new_cost;
if (new_cost > costmax)
costmax = cost_max;
You should also use an explicit return type for main():
int main(void)
Normally, 'passengers' is spelled with one 'a' and two 'e's.
It isn't entirely clear whether the cost() function is written appropriately. It takes one float and two int values and combines them and assigns the result to an int before returning that as a float. As written, it will work. Whether that's what you want is another matter. Since costmin and costmax are of type int, there's another level of uncertainty about what's the best type for these values.
Also, generally avoid trailing blanks in your output. A space before \n is almost always … well, if not wrong, superfluous. I'd go for almost always wrong, though. (But it is good that you end messages with a newline — that's a worse problem than trailing blanks, but prevalent in the world of C on Windows.)
Firstly, I see no reading from file. All your readings are from console (stdin).
Also, you are calling the cost function too many times, and sometimes you take no benefit from it, like here:
}
cost(k,ck,n); //<--
if(cost(k, ck, n) < costmin)
I suggest you replace indicated call with:
float c = cost(k, ck, n);
and then use c for checking/assingments instead of calling cost() all over again.
Also, you are assigning a float value to an int in multiple places:
costmax = cost(k, ck, n);
costmin = cost(k, ck, n);
In some places, you use "%d" in scanf and printf for reading/printing a float. You should use "%f".

Resources